├── sample ├── dummy.txt ├── src │ └── main │ │ └── java │ │ └── org │ │ └── reflection_no_reflection │ │ └── generator │ │ └── sample │ │ ├── B.java │ │ ├── A.java │ │ └── Main.java └── build.gradle ├── sample-exploded ├── dummy.txt ├── src │ ├── main │ │ └── java │ │ │ └── org │ │ │ └── reflection_no_reflection │ │ │ └── sample │ │ │ ├── B.java │ │ │ ├── A.java │ │ │ ├── Main.java │ │ │ └── NoReflectionFieldFinderImpl.java │ └── test │ │ └── java │ │ └── org │ │ └── reflection_no_reflection │ │ └── sample │ │ ├── ReflectionFieldTest.java │ │ ├── NoReflectionFieldTest.java │ │ └── FieldTest.java └── build.gradle ├── common-lib ├── .gitignore ├── src │ ├── test │ │ └── java │ │ │ └── org │ │ │ └── reflection_no_reflection │ │ │ ├── PerformanceTest.java │ │ │ └── ClassApiTest.java │ └── main │ │ └── java │ │ └── org │ │ └── reflection_no_reflection │ │ ├── Package.java │ │ ├── Invokable.java │ │ ├── GenericDeclaration.java │ │ ├── FieldFinder.java │ │ ├── GenericDeclarationImpl.java │ │ ├── runtime │ │ ├── Module.java │ │ └── BaseReflector.java │ │ ├── visit │ │ ├── ClassPoolVisitor.java │ │ ├── ClassPoolVisitStrategy.java │ │ └── dump │ │ │ └── JavaDumperClassPoolVisitor.java │ │ ├── package-info.java │ │ ├── TypeVariableImpl.java │ │ ├── TypeVariable.java │ │ ├── Member.java │ │ ├── Annotation.java │ │ └── Field.java ├── build.gradle └── pom.xml~ ├── .travis.yml ├── assets └── prism.jpg ├── processor ├── .settings │ ├── org.eclipse.core.resources.prefs │ └── org.eclipse.jdt.core.prefs ├── build.gradle └── src │ └── test │ └── java │ └── org │ └── reflection_no_reflection │ └── processor │ ├── ClassPoolTest.java │ ├── InterfaceTest.java │ ├── ConstructorParameterTest.java │ ├── AbstractRnRTest.java │ ├── ProcessorTest.java │ ├── GenericsTest.java │ ├── InnerClassTest.java │ ├── FieldArrayTest.java │ ├── FieldTest.java │ ├── MethodParameterTest.java │ ├── ClassTest.java │ ├── MethodTest.java │ └── ConstructorTest.java ├── processor-sample ├── .settings │ ├── org.eclipse.core.resources.prefs │ └── org.eclipse.jdt.core.prefs ├── build.gradle └── src │ ├── test │ └── java │ │ └── org │ │ └── reflection_no_reflection │ │ └── generator │ │ └── sample │ │ └── SampleProcessorTest.java │ └── main │ └── java │ └── org │ └── reflection_no_reflection │ └── generator │ └── sample │ └── SampleProcessor.java ├── generator ├── src │ ├── main │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── javax.annotation.processing.Processor │ │ └── java │ │ │ └── org │ │ │ └── reflection_no_reflection │ │ │ └── generator │ │ │ ├── introspector │ │ │ ├── IntrospectorUtil.java │ │ │ ├── IntrospectorConstructorInvokerCreator.java │ │ │ ├── IntrospectorMethodInvokerCreator.java │ │ │ ├── IntrospectorFieldSetterMethodCreator.java │ │ │ └── IntrospectorDumperClassPoolVisitor.java │ │ │ ├── annotation │ │ │ └── AnnotationCreatorClassPoolVisitor.java │ │ │ └── Generator.java │ └── test │ │ └── java │ │ └── org │ │ └── reflection_no_reflection │ │ └── generator │ │ ├── annotation │ │ └── AnnotationTest.java │ │ ├── introspector │ │ └── IntrospectorTest.java │ │ ├── GeneratorTest.java │ │ └── module │ │ └── ModuleTest.java └── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── generator-integration-tests ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── src │ ├── main │ │ └── java │ │ │ └── org │ │ │ └── reflection_no_reflection │ │ │ └── generator │ │ │ └── sample │ │ │ ├── AnnotationTestCase.java │ │ │ ├── ConstructorTestCase.java │ │ │ ├── Foo.java │ │ │ ├── FieldTestCase.java │ │ │ └── MethodTestCase.java │ └── test │ │ └── java │ │ └── org │ │ └── reflection_no_reflection │ │ └── generator │ │ └── sample │ │ ├── AnnotationTest.java │ │ ├── ConstructorTest.java │ │ ├── ClassTest.java │ │ └── FieldTest.java ├── build.gradle ├── gradlew.bat └── gradlew ├── settings.gradle ├── .gitignore ├── gradle.properties ├── overview.html ├── README.md ├── gradlew.bat ├── gradlew └── LICENSE /sample/dummy.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sample-exploded/dummy.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /common-lib/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk7 4 | 5 | script: 6 | - ./gradlew check 7 | -------------------------------------------------------------------------------- /assets/prism.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanenicolas/reflection-no-reflection/HEAD/assets/prism.jpg -------------------------------------------------------------------------------- /processor/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | -------------------------------------------------------------------------------- /processor-sample/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | -------------------------------------------------------------------------------- /generator/src/main/resources/META-INF/services/javax.annotation.processing.Processor: -------------------------------------------------------------------------------- 1 | org.reflection_no_reflection.generator.Generator 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanenicolas/reflection-no-reflection/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /sample-exploded/src/main/java/org/reflection_no_reflection/sample/B.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.sample; 2 | 3 | public class B { 4 | } 5 | -------------------------------------------------------------------------------- /sample/src/main/java/org/reflection_no_reflection/generator/sample/B.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.sample; 2 | 3 | public class B { 4 | } 5 | -------------------------------------------------------------------------------- /common-lib/src/test/java/org/reflection_no_reflection/PerformanceTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection; 2 | 3 | public class PerformanceTest { 4 | //TODO 5 | } 6 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/Package.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection; 2 | 3 | /** 4 | * @author SNI. 5 | */ 6 | public class Package { 7 | } 8 | -------------------------------------------------------------------------------- /common-lib/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | dependencies { 4 | compile files("${System.properties['java.home']}/../lib/tools.jar") 5 | testCompile 'junit:junit:4.11' 6 | } 7 | 8 | -------------------------------------------------------------------------------- /generator-integration-tests/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanenicolas/reflection-no-reflection/HEAD/generator-integration-tests/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/Invokable.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection; 2 | 3 | public interface Invokable { 4 | Class[] getParameterTypes(); 5 | Class[] getExceptionTypes(); 6 | } 7 | -------------------------------------------------------------------------------- /sample-exploded/src/main/java/org/reflection_no_reflection/sample/A.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.sample; 2 | 3 | import javax.inject.Inject; 4 | 5 | public class A { 6 | @Inject public B b; 7 | @Inject int c; 8 | } 9 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include "common-lib" 2 | include "processor" 3 | include "processor-sample" 4 | include "generator" 5 | include "generator-integration-tests" 6 | //if (!hasProperty('boostrap')) { 7 | // include "sample" 8 | //} 9 | //include "sample-exploded" 10 | -------------------------------------------------------------------------------- /generator-integration-tests/src/main/java/org/reflection_no_reflection/generator/sample/AnnotationTestCase.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.sample; 2 | 3 | public class AnnotationTestCase { 4 | @SuppressWarnings("unused") 5 | public String a; 6 | } 7 | -------------------------------------------------------------------------------- /sample/src/main/java/org/reflection_no_reflection/generator/sample/A.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.sample; 2 | 3 | import javax.inject.Inject; 4 | 5 | public class A { 6 | @Inject public B b; 7 | 8 | @Inject public void m() {} 9 | } 10 | -------------------------------------------------------------------------------- /sample-exploded/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | repositories { 4 | mavenCentral() 5 | mavenLocal() 6 | } 7 | 8 | dependencies { 9 | compile project(':common-lib') 10 | compile 'javax.inject:javax.inject:1' 11 | 12 | testCompile 'junit:junit:4.11' 13 | } 14 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/GenericDeclaration.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @author SNI. 7 | */ 8 | public interface GenericDeclaration { 9 | public TypeVariable[] getTypeParameters(); 10 | } 11 | -------------------------------------------------------------------------------- /processor/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.6 6 | -------------------------------------------------------------------------------- /processor-sample/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.6 6 | -------------------------------------------------------------------------------- /generator-integration-tests/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat May 30 05:55:14 PDT 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-bin.zip 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Dec 13 10:18:29 EST 2014 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-bin.zip 7 | org.gradle.daemon=false 8 | -------------------------------------------------------------------------------- /generator-integration-tests/src/main/java/org/reflection_no_reflection/generator/sample/ConstructorTestCase.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.sample; 2 | 3 | import javax.inject.Inject; 4 | 5 | public class ConstructorTestCase { 6 | int a; 7 | 8 | @Inject public ConstructorTestCase() {a = 3;} 9 | } 10 | -------------------------------------------------------------------------------- /processor/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | repositories { 4 | mavenCentral() 5 | mavenLocal() 6 | } 7 | 8 | dependencies { 9 | compile project(':common-lib') 10 | testCompile 'junit:junit:4.10' 11 | testCompile 'org.easytesting:fest:1.0.7' 12 | testCompile 'com.google.testing.compile:compile-testing:0.4' 13 | } 14 | -------------------------------------------------------------------------------- /generator-integration-tests/src/main/java/org/reflection_no_reflection/generator/sample/Foo.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.sample; 2 | 3 | import javax.inject.Inject; 4 | 5 | public class Foo extends Bar implements Qurtz { 6 | @Inject Foo foo; 7 | @Inject Bar bar; 8 | } 9 | 10 | class Bar { 11 | } 12 | 13 | interface Qurtz { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/FieldFinder.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection; 2 | 3 | import java.lang.annotation.Annotation; 4 | import java.util.Collection; 5 | 6 | /** 7 | * Defines the behaviour of member finders. 8 | * @author SNI 9 | */ 10 | public interface FieldFinder { 11 | 12 | public Collection getAllFields(Class annotationClass, Class clazz); 13 | } 14 | -------------------------------------------------------------------------------- /generator/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | repositories { 4 | mavenCentral() 5 | mavenLocal() 6 | } 7 | 8 | dependencies { 9 | compile project(':common-lib') 10 | compile project(':processor') 11 | compile 'javax.inject:javax.inject:1' 12 | compile 'com.squareup:javapoet:1.0.0' 13 | testCompile 'junit:junit:4.10' 14 | testCompile 'org.easytesting:fest:1.0.7' 15 | testCompile 'com.google.testing.compile:compile-testing:0.4' 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | 19 | # Local configuration file (sdk path, etc) 20 | local.properties 21 | 22 | # Proguard folder generated by Eclipse 23 | proguard/ 24 | 25 | # Log Files 26 | *.log 27 | 28 | #plantuml files 29 | doc-files/ 30 | 31 | #intelliJ 32 | .idea/ 33 | *.iml 34 | *.ipr 35 | *.iws 36 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/GenericDeclarationImpl.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection; 2 | 3 | import java.util.Map; 4 | 5 | public class GenericDeclarationImpl implements GenericDeclaration { 6 | private TypeVariable[] typeParameters; 7 | 8 | public TypeVariable[] getTypeParameters() { 9 | return typeParameters; 10 | } 11 | 12 | public void setTypeParameters(TypeVariable[] typeParameters) { 13 | this.typeParameters = typeParameters; 14 | }} 15 | -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | 3 | repositories { 4 | mavenCentral() 5 | 6 | // NOTE: This is only needed when developing the plugin! 7 | mavenLocal() 8 | } 9 | } 10 | 11 | apply plugin: 'java' 12 | apply plugin: 'application' 13 | 14 | mainClassName = "Main" 15 | 16 | repositories { 17 | mavenCentral() 18 | mavenLocal() 19 | } 20 | 21 | configurations { 22 | provided 23 | } 24 | 25 | dependencies { 26 | provided project(':processor-sample') 27 | compile project(':common-lib') 28 | compile 'javax.inject:javax.inject:1' 29 | } 30 | -------------------------------------------------------------------------------- /processor-sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | repositories { 4 | mavenCentral() 5 | mavenLocal() 6 | } 7 | 8 | dependencies { 9 | compile project(':common-lib') 10 | compile project(':processor') 11 | compile 'javax.inject:javax.inject:1' 12 | testCompile 'junit:junit:4.10' 13 | testCompile 'org.easytesting:fest:1.0.7' 14 | testCompile 'com.google.testing.compile:compile-testing:0.4' 15 | } 16 | 17 | compileJava { 18 | //enable incremental compilation 19 | options.compilerArgs = ["-processor", "org.reflection_no_reflection.processor.Processor"] 20 | } 21 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/runtime/Module.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.runtime; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.Set; 6 | import org.reflection_no_reflection.*; 7 | import org.reflection_no_reflection.Class; 8 | 9 | /** 10 | * A module contains classes that can be loaded into memory. 11 | */ 12 | @SuppressWarnings("unused") 13 | public interface Module { 14 | Set getClassSet(); 15 | 16 | Map> getMapAnnotationNameToNameOfClassesContainingAnnotation(); 17 | 18 | Class loadClass(String className); 19 | } 20 | -------------------------------------------------------------------------------- /generator-integration-tests/src/main/java/org/reflection_no_reflection/generator/sample/FieldTestCase.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.sample; 2 | 3 | import javax.inject.Inject; 4 | 5 | public class FieldTestCase { 6 | @Inject public String a; 7 | @Inject public Foo foo; 8 | @Inject public byte c; 9 | @Inject public short d; 10 | @Inject public int e; 11 | @Inject public long f; 12 | @Inject public float g; 13 | @Inject public double h; 14 | @Inject public char i; 15 | @Inject public boolean j; 16 | 17 | @Inject public String[] k; 18 | 19 | //TODO generics, arrays 1&2D, static 20 | //oosh final 21 | //private 22 | } 23 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | version=1.0.0-SNAPSHOT 2 | GROUP=org.reflection_no_reflection 3 | 4 | POM_DESCRIPTION=Full fledge optimized replacement for java core reflection API 5 | POM_URL=https://github.com/stephannicolas/reflection-no-reflection/ 6 | POM_SCM_URL=https://github.com/stephannicolas/reflection-no-reflection/ 7 | POM_SCM_CONNECTION=scm:git@github.com/stephannicolas/reflection-no-reflection.git 8 | POM_SCM_DEV_CONNECTION=scm:git@github.com:stephannicolas/reflection-no-reflection.git 9 | POM_LICENCE_NAME=The Apache Software License, Version 2.0 10 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt 11 | POM_LICENCE_DIST=repo 12 | POM_DEVELOPER_ID=SNI 13 | POM_DEVELOPER_NAME=Stéphane NICOLAS -------------------------------------------------------------------------------- /overview.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | See below, this document describes an overview of the 4 | Reflection No Reflection library. 5 |
6 | 7 | 8 | 19 |

You can now browse each package to find more on the role of each component.

20 | -------------------------------------------------------------------------------- /sample/src/main/java/org/reflection_no_reflection/generator/sample/Main.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.sample; 2 | 3 | import org.reflection_no_reflection.Class; 4 | import org.reflection_no_reflection.Field; 5 | 6 | /** 7 | * @author SNI. 8 | */ 9 | public class Main { 10 | 11 | public static void main(String[] args) { 12 | Class.loadModule(new org.reflection_no_reflection.sample.Module()); 13 | try { 14 | final Class classFoo = Class.forName("A"); 15 | final Field[] fields = classFoo.getFields(); 16 | System.out.println(fields[0].getName()); //should be B 17 | } catch (ClassNotFoundException e) { 18 | e.printStackTrace(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/visit/ClassPoolVisitor.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.visit; 2 | 3 | import org.reflection_no_reflection.Annotation; 4 | import org.reflection_no_reflection.Class; 5 | import org.reflection_no_reflection.Field; 6 | import org.reflection_no_reflection.Method; 7 | 8 | /** 9 | * @author SNI. 10 | */ 11 | public interface ClassPoolVisitor { 12 | void visit(org.reflection_no_reflection.Class clazz); 13 | 14 | void visit(Field field); 15 | 16 | void visit(Method method); 17 | 18 | void visit(Annotation annotation); 19 | 20 | void visitAnnotationMethod(Annotation annotation, Method method); 21 | 22 | void endVisit(Class aClass); 23 | 24 | void endVisit(Annotation annotation); 25 | } 26 | -------------------------------------------------------------------------------- /sample-exploded/src/test/java/org/reflection_no_reflection/sample/ReflectionFieldTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.sample; 2 | 3 | import org.reflection_no_reflection.Field; 4 | import org.reflection_no_reflection.reflection.ReflectionField; 5 | 6 | /** 7 | * A proof of concept to retrieve core java reflection fields 8 | * and test them via the RNR framework. 9 | * @author SNI 10 | */ 11 | public class ReflectionFieldTest extends FieldTest { 12 | 13 | @Override 14 | public Field getInstance(Class clazz, String fieldName) { 15 | switch (fieldName) { 16 | case "b": 17 | return new ReflectionField(getOriginalFieldB()); 18 | case "c": 19 | return new ReflectionField(getOriginalFieldC()); 20 | } 21 | throw new RuntimeException("No such field:" + fieldName); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /processor/src/test/java/org/reflection_no_reflection/processor/ClassPoolTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.processor; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | import org.reflection_no_reflection.Class; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | /** 11 | * @author SNI. 12 | */ 13 | public class ClassPoolTest { 14 | 15 | @Before 16 | public void setup() { 17 | Class.clearAllClasses(); 18 | } 19 | 20 | @Test 21 | public void classesAreSingletons() throws ClassNotFoundException { 22 | assertThat((Class) Class.forNameSafe("foo"), is((Class) Class.forName("foo"))); 23 | } 24 | 25 | @Test(expected = ClassNotFoundException.class) 26 | public void classNotFound() throws ClassNotFoundException { 27 | Class.forName("foo"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /generator-integration-tests/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | repositories { 4 | mavenCentral() 5 | mavenLocal() 6 | } 7 | 8 | dependencies { 9 | compile project(':common-lib') 10 | compile project(':generator') 11 | compile 'javax.inject:javax.inject:1' 12 | testCompile 'junit:junit:4.10' 13 | } 14 | 15 | task wrapper(type: Wrapper) { 16 | gradleVersion = '2.4' 17 | } 18 | 19 | tasks.withType(JavaCompile) { 20 | sourceCompatibility = "1.7" 21 | targetCompatibility = "1.7" 22 | } 23 | 24 | compileJava { 25 | doFirst { 26 | options.compilerArgs = [ 27 | '-AtargetAnnotatedClasses=javax.inject.Inject,java.lang.SuppressWarnings', 28 | '-AmaxLevel=1', 29 | '-AtargetPackageName=org.reflection_no_reflection.generator.sample.gen', 30 | '-Aintrospector.includes=.*', 31 | '-Aintrospector.excludes=java\\..*,javax.inject.Inject' 32 | ] 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /sample-exploded/src/test/java/org/reflection_no_reflection/sample/NoReflectionFieldTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.sample; 2 | 3 | import javax.inject.Inject; 4 | import org.reflection_no_reflection.Field; 5 | import org.reflection_no_reflection.no_reflection.AnnotationDatabaseFinder; 6 | 7 | /** 8 | * Proof of Concept of RNR field testings. 9 | * @author SNI 10 | */ 11 | public class NoReflectionFieldTest extends FieldTest { 12 | 13 | @Override 14 | public Field getInstance(Class clazz, String fieldName) { 15 | switch (fieldName) { 16 | case "b": 17 | return new NoReflectionFieldFinderImpl((AnnotationDatabaseFinder)null).getAllFields(Inject.class, A.class).get(0); 18 | case "c": 19 | return new NoReflectionFieldFinderImpl((AnnotationDatabaseFinder)null).getAllFields(Inject.class, A.class).get(1); 20 | } 21 | throw new RuntimeException("No such field " + fieldName); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * See below, this document describes an overview of the 3 | * common-library. 4 | * 5 | * The common-lib provides high level classes used by RnR clients. 6 | * Those high level classes have different implementations. One of them 7 | * is based on the java core reflection library and the other one 8 | * is based on RnR. 9 | * 10 | * @author SNI 11 | */ 12 | /* 13 | * @startuml doc-files/common-lib-overview.png 14 | * title Overview of common-lib 15 | * org.RnR.Field <|-- org.RnR.reflection.ReflectionField 16 | * org.RnR.Field <|-- org.RnR.no_reflection.NoReflectionField 17 | * org.RnR.FieldFinder <|-- org.RnR.reflection.ReflectionFieldFinder 18 | * org.RnR.FieldFinder <|-- org.RnR.no_reflection.NoReflectionFieldFinder 19 | * package org.RnR { 20 | * class Field 21 | * note top : Provides the same API as java.lang.Field 22 | * class FieldFinder 23 | * } 24 | * @enduml 25 | */ 26 | package org.reflection_no_reflection; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Reflection No Reflection [![Build Status](https://travis-ci.org/stephanenicolas/reflection-no-reflection.svg?branch=master)](https://travis-ci.org/stephanenicolas/reflection-no-reflection) 2 | ------------------------ 3 | 4 | 5 | 6 | All credits of the library logo to [Tracey Sarsfield](http://www.traceysarsfield.com/gallery.html), we use this picture with her kind permission. 7 | 8 | Reflection No Reflection is a proof of concept to create an API that is 100% compatible with the Java core reflection API, but without any reflection. 9 | 10 | We hope to create a new technology that can improve all reflection based libraries for Android and Java. 11 | 12 | The main idea is to create a reflection compatible API using annotation processing and byte code weaving. 13 | 14 | This project has been initiated by the Android Groupon team, 2014. 15 | 16 | * [Javadoc](http://stephanenicolas.github.io/reflection-no-reflection/) 17 | * [Wiki](https://github.com/stephanenicolas/reflection-no-reflection/wiki) 18 | -------------------------------------------------------------------------------- /processor/src/test/java/org/reflection_no_reflection/processor/InterfaceTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.processor; 2 | 3 | import java.util.Set; 4 | import org.junit.Test; 5 | import org.reflection_no_reflection.Class; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class InterfaceTest extends AbstractRnRTest { 11 | 12 | @Test 13 | public void mapsSimpleAnnotatedClass() throws ClassNotFoundException { 14 | javaSourceCode("test.Foo", // 15 | "package test;", // 16 | "@Deprecated", // 17 | "public interface Foo {}" // 18 | ); 19 | 20 | setTargetAnnotations("java.lang.Deprecated"); 21 | assertJavaSourceCompileWithoutError(); 22 | 23 | final Set annotatedClasses = getProcessedClasses(); 24 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 25 | assertThat(annotatedClasses.contains(Class.forName("test.Foo")), is(true)); 26 | assertThat(Class.forName("test.Foo").isInterface(), is(true)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /common-lib/pom.xml~: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | annotationprocessing 6 | 3.0-alpha-SNAPSHOT 7 | jar 8 | annotationprocessing 9 | 10 | 11 | org.roboguice 12 | roboguice-aggregator 13 | 3.0-alpha-SNAPSHOT 14 | 15 | 16 | 17 | 1.7 18 | 19 | 20 | 21 | 22 | org.apache.velocity 23 | velocity 24 | ${velocity.version} 25 | 26 | 27 | 28 | 29 | 30 | 31 | maven-compiler-plugin 32 | 3.1 33 | 34 | 1.6 35 | 1.6 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /generator-integration-tests/src/main/java/org/reflection_no_reflection/generator/sample/MethodTestCase.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.sample; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import javax.inject.Inject; 6 | 7 | public class MethodTestCase { 8 | int a; 9 | @Inject public void simpleMethod() {a=3;} 10 | 11 | @Inject public String methodReturningString() {return "foo";} 12 | 13 | @Inject public int methodReturningInt() {return 3;} 14 | 15 | @Inject public int[] methodReturningIntArray() {return new int[] {3};} 16 | 17 | @Inject public void methodWithPrimitiveParam(int a) {this.a=3;} 18 | 19 | @Inject public void methodWithObjectParam(String s) {a=3;} 20 | 21 | //if there is no int after the array, then we are in the same case as 22 | // a varargs for method invocation for reflection 23 | @Inject public void methodWithArrayNotLastParam(String[] s, int b) {a=3;} 24 | 25 | @Inject public void methodWithArrayLastParam(String[] s) {a=3;} 26 | 27 | @Inject public void methodWithVarArgsParam(String... s) {a=3;} 28 | 29 | @Inject public void methodWithGenericsParam(ArrayList s) {a=3;} 30 | 31 | @Inject public void methodWithInterfaceParam(List s) {a=3;} 32 | 33 | @Inject public void methodWithException() throws Exception {a=3;} 34 | 35 | //@Inject public T methodWithGenericsType(T t) throws Exception {return t;} 36 | 37 | //TODO 38 | //all primitives return types & params 39 | //static, final, abstract 40 | //generics param and return types (wildcard, intersection and upperbounds) 41 | //private 42 | //generics methods 43 | } 44 | -------------------------------------------------------------------------------- /processor/src/test/java/org/reflection_no_reflection/processor/ConstructorParameterTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.processor; 2 | 3 | import java.lang.reflect.Modifier; 4 | import java.util.Set; 5 | import org.junit.Test; 6 | import org.reflection_no_reflection.Class; 7 | import org.reflection_no_reflection.Constructor; 8 | 9 | import static org.hamcrest.MatcherAssert.assertThat; 10 | import static org.hamcrest.core.Is.is; 11 | 12 | public class ConstructorParameterTest extends AbstractRnRTest { 13 | 14 | @Test 15 | public void mapsConstructorWithAnnotatedParams() throws ClassNotFoundException { 16 | javaSourceCode("test.Foo", // 17 | "package test;", // 18 | "public class Foo {",// 19 | "protected Foo(@Deprecated String a) {}", // 20 | "}" // 21 | ); 22 | 23 | setTargetAnnotations(new String[] {"java.lang.Deprecated"}); 24 | assertJavaSourceCompileWithoutError(); 25 | 26 | final Set annotatedClasses = getProcessedClasses(); 27 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 28 | 29 | final Class expectedParamType = Class.forName("java.lang.String"); 30 | final Class aClass = Class.forName("test.Foo"); 31 | assertThat(aClass.getConstructors().size(), is(1)); 32 | 33 | final Constructor Constructor = (Constructor) aClass.getConstructors().get(0); 34 | final Constructor expected = new Constructor(aClass, new Class[] {expectedParamType}, new Class[0], Modifier.PROTECTED); 35 | assertThat(Constructor, is(expected)); 36 | assertThat(Constructor.getModifiers(), is(Modifier.PROTECTED)); 37 | 38 | //TODO test annotations of params 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /generator/src/test/java/org/reflection_no_reflection/generator/annotation/AnnotationTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.annotation; 2 | 3 | import com.google.common.base.Joiner; 4 | import com.google.testing.compile.JavaFileObjects; 5 | import java.util.Arrays; 6 | import javax.tools.JavaFileObject; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.reflection_no_reflection.generator.Generator; 10 | 11 | import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; 12 | import static org.truth0.Truth.ASSERT; 13 | 14 | public class AnnotationTest { 15 | 16 | protected javax.annotation.processing.Processor processor; 17 | protected JavaFileObject javaSourceCode; 18 | 19 | @Before 20 | public void setup() { 21 | processor = new Generator(); 22 | javaSourceCode = null; 23 | } 24 | 25 | @Test 26 | public void test() { 27 | //TODO 28 | javaSourceCode("test.Foo", // 29 | "package test;", // 30 | "public class Foo {",// 31 | "@javax.inject.Inject String s;", // 32 | "}" // 33 | ); 34 | 35 | assertJavaSourceCompileWithoutError(); 36 | } 37 | 38 | protected void javaSourceCode(String fullyQualifiedName, String... source) { 39 | javaSourceCode = JavaFileObjects.forSourceString(fullyQualifiedName, Joiner.on('\n').join(source)); 40 | } 41 | 42 | protected Iterable rnrProcessors() { 43 | return Arrays.asList(processor); 44 | } 45 | 46 | protected void assertJavaSourceCompileWithoutError() { 47 | ASSERT.about(javaSource()) 48 | .that(javaSourceCode) 49 | .processedWith(rnrProcessors()) 50 | .compilesWithoutError(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /generator/src/test/java/org/reflection_no_reflection/generator/introspector/IntrospectorTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.introspector; 2 | 3 | import com.google.common.base.Joiner; 4 | import com.google.testing.compile.JavaFileObjects; 5 | import java.util.Arrays; 6 | import javax.tools.JavaFileObject; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.reflection_no_reflection.generator.Generator; 10 | 11 | import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; 12 | import static org.truth0.Truth.ASSERT; 13 | 14 | public class IntrospectorTest { 15 | 16 | protected javax.annotation.processing.Processor processor; 17 | protected JavaFileObject javaSourceCode; 18 | 19 | @Before 20 | public void setup() { 21 | processor = new Generator(); 22 | javaSourceCode = null; 23 | } 24 | 25 | @Test 26 | public void test() { 27 | //TODO 28 | javaSourceCode("test.Foo", // 29 | "package test;", // 30 | "public class Foo {",// 31 | "@javax.inject.Inject String s;", // 32 | "}" // 33 | ); 34 | 35 | assertJavaSourceCompileWithoutError(); 36 | } 37 | 38 | protected void javaSourceCode(String fullyQualifiedName, String... source) { 39 | javaSourceCode = JavaFileObjects.forSourceString(fullyQualifiedName, Joiner.on('\n').join(source)); 40 | } 41 | 42 | protected Iterable rnrProcessors() { 43 | return Arrays.asList(processor); 44 | } 45 | 46 | protected void assertJavaSourceCompileWithoutError() { 47 | ASSERT.about(javaSource()) 48 | .that(javaSourceCode) 49 | .processedWith(rnrProcessors()) 50 | .compilesWithoutError(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /generator-integration-tests/src/test/java/org/reflection_no_reflection/generator/sample/AnnotationTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.sample; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | import org.reflection_no_reflection.Annotation; 6 | import org.reflection_no_reflection.Class; 7 | import org.reflection_no_reflection.Field; 8 | import org.reflection_no_reflection.runtime.Module; 9 | 10 | import static org.hamcrest.CoreMatchers.notNullValue; 11 | import static org.hamcrest.core.Is.is; 12 | import static org.junit.Assert.assertNotNull; 13 | import static org.junit.Assert.assertNull; 14 | import static org.junit.Assert.assertThat; 15 | 16 | public class AnnotationTest { 17 | 18 | @Before 19 | public void setUp() throws Exception { 20 | Class.clearAllClasses(); 21 | Module module = new org.reflection_no_reflection.generator.sample.gen.ModuleImpl(); 22 | Class.loadModule(module); 23 | } 24 | 25 | @Test 26 | public void shouldReflectAnnotation() throws ClassNotFoundException { 27 | //GIVEN 28 | 29 | //WHEN 30 | Class classFoo = Class.forName("org.reflection_no_reflection.generator.sample.AnnotationTestCase"); 31 | 32 | //THEN 33 | final Field[] fields = classFoo.getFields(); 34 | final Field field = fields[0]; 35 | assertThat(field.getName(), is("a")); 36 | assertThat(field.getType().getName(), is("java.lang.String")); 37 | //fails assertThat(field.RnrAnnotations().length, is(1)); 38 | //TODO solve which annotation to return RnR or runtime reflect 39 | assertThat(field.getAnnotation((Class)Class.forName("java.lang.SuppressWarnings")), notNullValue()); 40 | assertThat(field.getAnnotation((Class)Class.forName("java.lang.SuppressWarnings")).value()[0], is("unused")); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /processor/src/test/java/org/reflection_no_reflection/processor/AbstractRnRTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.processor; 2 | 3 | import com.google.common.base.Joiner; 4 | import com.google.testing.compile.JavaFileObjects; 5 | import java.util.Arrays; 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | import javax.annotation.processing.AbstractProcessor; 9 | import javax.tools.JavaFileObject; 10 | import org.junit.Before; 11 | import org.reflection_no_reflection.*; 12 | import org.reflection_no_reflection.Class; 13 | 14 | import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; 15 | import static org.truth0.Truth.ASSERT; 16 | 17 | public class AbstractRnRTest { 18 | 19 | protected AbstractProcessor processor; 20 | protected JavaFileObject javaSourceCode; 21 | 22 | @Before 23 | public void setup() { 24 | processor = new Processor(); 25 | javaSourceCode = null; 26 | } 27 | 28 | protected void javaSourceCode(String fullyQualifiedName, String... source) { 29 | javaSourceCode = JavaFileObjects.forSourceString(fullyQualifiedName, Joiner.on('\n').join(source)); 30 | } 31 | 32 | protected void setTargetAnnotations(String... annotations) { 33 | ((Processor)processor).setTargetAnnotatedClasses(new HashSet<>(Arrays.asList(annotations))); 34 | } 35 | 36 | protected void setMaxLevel(int maxLevel) { 37 | ((Processor)processor).setMaxLevel(maxLevel); 38 | } 39 | 40 | protected Iterable rnrProcessors() { 41 | return Arrays.asList(processor); 42 | } 43 | 44 | protected void assertJavaSourceCompileWithoutError() { 45 | ASSERT.about(javaSource()) 46 | .that(javaSourceCode) 47 | .processedWith(rnrProcessors()) 48 | .compilesWithoutError(); 49 | } 50 | 51 | protected Set getProcessedClasses() { 52 | return ((Processor)processor).getAnnotatedClassSet(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/runtime/BaseReflector.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.runtime; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | 5 | /** 6 | * @author SNI. 7 | */ 8 | public class BaseReflector { 9 | 10 | public void setObjectField(Object instance, String fieldName, Object value) { 11 | throw new UnsupportedOperationException(); 12 | } 13 | 14 | public void setByteField(Object instance, String fieldName, byte value) { 15 | throw new UnsupportedOperationException(); 16 | } 17 | 18 | public void setShortField(Object instance, String fieldName, short value) { 19 | throw new UnsupportedOperationException(); 20 | } 21 | 22 | public void setIntField(Object instance, String fieldName, int value) { 23 | throw new UnsupportedOperationException(); 24 | } 25 | 26 | public void setLongField(Object instance, String fieldName, long value) { 27 | throw new UnsupportedOperationException(); 28 | } 29 | 30 | public void setFloatField(Object instance, String fieldName, float value) { 31 | throw new UnsupportedOperationException(); 32 | } 33 | 34 | public void setDoubleField(Object instance, String fieldName, double value) { 35 | throw new UnsupportedOperationException(); 36 | } 37 | 38 | public void setCharField(Object instance, String fieldName, char value) { 39 | throw new UnsupportedOperationException(); 40 | } 41 | 42 | public void setBooleanField(Object instance, String fieldName, boolean value) { 43 | throw new UnsupportedOperationException(); 44 | } 45 | 46 | public Object invokeMethod(Object instance, String methodName, String signature, Object...params) throws InvocationTargetException { 47 | throw new UnsupportedOperationException(); 48 | } 49 | 50 | public T newInstance(String signature, Object...params) throws InvocationTargetException { 51 | throw new UnsupportedOperationException(); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/TypeVariableImpl.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection; 2 | 3 | import java.lang.reflect.Type; 4 | 5 | /** 6 | * TypeVariable is the common superinterface for type variables of kinds. 7 | * A type variable is created the first time it is needed by a reflective 8 | * method, as specified in this package. If a type variable t is referenced 9 | * by a type (i.e, class, interface or annotation type) T, and T is declared 10 | * by the nth enclosing class of T (see JLS 8.1.2), then the creation of t 11 | * requires the resolution (see JVMS 5) of the ith enclosing class of T, 12 | * for i = 0 to n, inclusive. Creating a type variable must not cause the 13 | * creation of its bounds. Repeated creation of a type variable has no effect. 14 | * 15 | *

Multiple objects may be instantiated at run-time to 16 | * represent a given type variable. Even though a type variable is 17 | * created only once, this does not imply any requirement to cache 18 | * instances representing the type variable. However, all instances 19 | * representing a type variable must be equal() to each other. 20 | * As a consequence, users of type variables must not rely on the identity 21 | * of instances of classes implementing this interface. 22 | * 23 | * @param the type of generic declaration that declared the 24 | * underlying type variable. 25 | * @since 1.5 26 | */ 27 | public class TypeVariableImpl implements TypeVariable { 28 | private String name; 29 | private D genericDeclaration; 30 | 31 | public Type[] getBounds() { 32 | return new Type[0]; 33 | } 34 | 35 | public D getGenericDeclaration() { 36 | return genericDeclaration; 37 | } 38 | 39 | public void setGenericDeclaration(D genericDeclaration) { 40 | this.genericDeclaration = genericDeclaration; 41 | } 42 | 43 | public String getName() { 44 | return name; 45 | } 46 | 47 | public void setName(String name) { 48 | this.name = name; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /processor-sample/src/test/java/org/reflection_no_reflection/generator/sample/SampleProcessorTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.sample; 2 | 3 | import com.google.common.base.Joiner; 4 | import com.google.testing.compile.JavaFileObjects; 5 | import java.util.Arrays; 6 | import javax.tools.JavaFileObject; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | 10 | import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; 11 | import static org.truth0.Truth.ASSERT; 12 | 13 | public class SampleProcessorTest { 14 | 15 | protected javax.annotation.processing.Processor processor; 16 | protected JavaFileObject javaSourceCode; 17 | 18 | @Before 19 | public void setup() { 20 | processor = new SampleProcessor(); 21 | javaSourceCode = null; 22 | } 23 | 24 | @Test 25 | public void test() { 26 | javaSourceCode("test.Foo", // 27 | "package test;", // 28 | "public class Foo {",// 29 | "@javax.inject.Inject private String s;", // 30 | "@javax.inject.Inject private void m() {};", // 31 | "@javax.inject.Inject private int n() {return 0;};", // 32 | "@javax.inject.Inject private void p(java.util.List s) {};", // 33 | "}" // 34 | ); 35 | 36 | assertJavaSourceCompileWithoutError(); 37 | } 38 | 39 | protected void javaSourceCode(String fullyQualifiedName, String... source) { 40 | javaSourceCode = JavaFileObjects.forSourceString(fullyQualifiedName, Joiner.on('\n').join(source)); 41 | } 42 | 43 | protected Iterable rnrProcessors() { 44 | return Arrays.asList(processor); 45 | } 46 | 47 | protected void assertJavaSourceCompileWithoutError() { 48 | ASSERT.about(javaSource()) 49 | .that(javaSourceCode) 50 | .processedWith(rnrProcessors()) 51 | .compilesWithoutError(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /processor/src/test/java/org/reflection_no_reflection/processor/ProcessorTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.processor; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashSet; 5 | import javax.lang.model.element.Modifier; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import static org.hamcrest.MatcherAssert.assertThat; 10 | import static org.hamcrest.core.Is.is; 11 | 12 | /** 13 | * @author SNI. 14 | */ 15 | public class ProcessorTest { 16 | 17 | Processor processor; 18 | 19 | @Before 20 | public void setup() { 21 | processor = new Processor(); 22 | } 23 | 24 | @Test 25 | public void testSimpleModifiers() { 26 | assertThat(convert(Modifier.PUBLIC), is(java.lang.reflect.Modifier.PUBLIC)); 27 | assertThat(convert(Modifier.PRIVATE), is(java.lang.reflect.Modifier.PRIVATE)); 28 | assertThat(convert(Modifier.PROTECTED), is(java.lang.reflect.Modifier.PROTECTED)); 29 | assertThat(convert(Modifier.FINAL), is(java.lang.reflect.Modifier.FINAL)); 30 | assertThat(convert(Modifier.STATIC), is(java.lang.reflect.Modifier.STATIC)); 31 | assertThat(convert(Modifier.VOLATILE), is(java.lang.reflect.Modifier.VOLATILE)); 32 | assertThat(convert(Modifier.SYNCHRONIZED), is(java.lang.reflect.Modifier.SYNCHRONIZED)); 33 | assertThat(convert(Modifier.ABSTRACT), is(java.lang.reflect.Modifier.ABSTRACT)); 34 | } 35 | 36 | @Test 37 | public void testCompundModifiers() { 38 | assertThat(convert(Modifier.PUBLIC, Modifier.FINAL), is(java.lang.reflect.Modifier.FINAL + java.lang.reflect.Modifier.PUBLIC)); 39 | assertThat(convert(Modifier.PROTECTED, Modifier.STATIC), is(java.lang.reflect.Modifier.STATIC + java.lang.reflect.Modifier.PROTECTED)); 40 | assertThat(convert(Modifier.PRIVATE, Modifier.SYNCHRONIZED), is(java.lang.reflect.Modifier.PRIVATE + java.lang.reflect.Modifier.SYNCHRONIZED)); 41 | } 42 | 43 | private int convert(Modifier... modifier) { 44 | return processor.convertModifiersFromAnnotationProcessing(new HashSet(Arrays.asList(modifier))); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /generator/src/test/java/org/reflection_no_reflection/generator/GeneratorTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator; 2 | 3 | import com.google.common.base.Joiner; 4 | import com.google.testing.compile.JavaFileObjects; 5 | import java.util.Arrays; 6 | import javax.tools.JavaFileObject; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | 10 | import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; 11 | import static org.truth0.Truth.ASSERT; 12 | 13 | //TODO here we could have test that extend the tests of the processor 14 | //we will do exactly the same test 15 | //on the ClassPool in the processor (during annotation processing) 16 | //AND on the ClassPool generated by the generator (during runtime) 17 | //+ test for field setters & getters, methods invocation, and constructor invocation 18 | public class GeneratorTest { 19 | 20 | protected javax.annotation.processing.Processor processor; 21 | protected JavaFileObject javaSourceCode; 22 | 23 | @Before 24 | public void setup() { 25 | processor = new Generator(); 26 | javaSourceCode = null; 27 | } 28 | 29 | @Test 30 | public void test() { 31 | //TODO 32 | javaSourceCode("test.Foo", // 33 | "package test;", // 34 | "public class Foo {",// 35 | "@javax.inject.Inject String s;", // 36 | "}" // 37 | ); 38 | 39 | assertJavaSourceCompileWithoutError(); 40 | } 41 | 42 | protected void javaSourceCode(String fullyQualifiedName, String... source) { 43 | javaSourceCode = JavaFileObjects.forSourceString(fullyQualifiedName, Joiner.on('\n').join(source)); 44 | } 45 | 46 | protected Iterable rnrProcessors() { 47 | return Arrays.asList(processor); 48 | } 49 | 50 | protected void assertJavaSourceCompileWithoutError() { 51 | ASSERT.about(javaSource()) 52 | .that(javaSourceCode) 53 | .processedWith(rnrProcessors()) 54 | .compilesWithoutError(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /processor-sample/src/main/java/org/reflection_no_reflection/generator/sample/SampleProcessor.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.sample; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | import javax.annotation.processing.AbstractProcessor; 7 | import javax.annotation.processing.ProcessingEnvironment; 8 | import javax.annotation.processing.RoundEnvironment; 9 | import javax.lang.model.element.TypeElement; 10 | import org.reflection_no_reflection.Class; 11 | import org.reflection_no_reflection.processor.Processor; 12 | import org.reflection_no_reflection.visit.dump.JavaDumperClassPoolVisitor; 13 | 14 | /** 15 | * An annotation processor sample that demonstrates how to use the RNR annotation processor. 16 | */ 17 | public class SampleProcessor extends AbstractProcessor { 18 | 19 | private Processor processor = new Processor(); 20 | 21 | @Override 22 | public synchronized void init(ProcessingEnvironment processingEnv) { 23 | //comma separated list of injected classes 24 | processor.init(processingEnv); 25 | processor.setTargetAnnotatedClasses(new HashSet<>(Arrays.asList(javax.inject.Inject.class.getName()))); 26 | processor.setMaxLevel(1); 27 | } 28 | 29 | @Override 30 | public boolean process(Set annotations, RoundEnvironment roundEnv) { 31 | boolean processed = processor.process(annotations, roundEnv); 32 | 33 | if (!roundEnv.processingOver()) { 34 | return processed; 35 | } 36 | //HashSet annotatedClassSet = new HashSet<>(processor.getAnnotatedClassSet()); 37 | 38 | JavaDumperClassPoolVisitor dumper = new JavaDumperClassPoolVisitor(); 39 | Class.visit(dumper); 40 | final StringBuffer buffer = dumper.getBuffer(); 41 | 42 | System.out.println("Dumping all collected data: \n"); 43 | System.out.println(buffer); 44 | return processed; 45 | } 46 | 47 | @Override 48 | public Set getSupportedAnnotationTypes() { 49 | return processor.getSupportedAnnotationTypes(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /generator/src/main/java/org/reflection_no_reflection/generator/introspector/IntrospectorUtil.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.introspector; 2 | 3 | import com.squareup.javapoet.ArrayTypeName; 4 | import com.squareup.javapoet.ClassName; 5 | import com.squareup.javapoet.TypeName; 6 | import org.reflection_no_reflection.*; 7 | 8 | public class IntrospectorUtil { 9 | 10 | public TypeName getClassName(org.reflection_no_reflection.Class clazz) { 11 | return getClassName(clazz.getName()); 12 | } 13 | 14 | public TypeName getClassName(String className) { 15 | if (className.endsWith("[]")) { 16 | final String componentName = className.substring(0, className.lastIndexOf('[')); 17 | return ArrayTypeName.of(getClassName(componentName)); 18 | } else if (className.contains(".")) { 19 | final String packageName = className.substring(0, className.lastIndexOf('.')); 20 | final String simpleName = className.substring(className.lastIndexOf('.')+1); 21 | return ClassName.get(packageName, simpleName); 22 | } else { 23 | //for primitives 24 | switch (className) { 25 | case "short" : 26 | return TypeName.get(short.class); 27 | case "byte" : 28 | return TypeName.get(byte.class); 29 | case "int" : 30 | return TypeName.get(int.class); 31 | case "long" : 32 | return TypeName.get(long.class); 33 | case "float" : 34 | return TypeName.get(float.class); 35 | case "double" : 36 | return TypeName.get(double.class); 37 | case "boolean" : 38 | return TypeName.get(boolean.class); 39 | case "char" : 40 | return TypeName.get(char.class); 41 | } 42 | throw new RuntimeException("Impossible to get typename for " + className); 43 | } 44 | } 45 | 46 | public String createCapitalizedName(String fieldName) { 47 | return Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/visit/ClassPoolVisitStrategy.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.visit; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.Collections; 6 | import java.util.Comparator; 7 | import java.util.List; 8 | import org.reflection_no_reflection.Annotation; 9 | import org.reflection_no_reflection.Class; 10 | import org.reflection_no_reflection.Field; 11 | import org.reflection_no_reflection.Method; 12 | 13 | /** 14 | * @author SNI. 15 | */ 16 | public class ClassPoolVisitStrategy { 17 | 18 | public void visit(Collection classCollection, ClassPoolVisitor classPoolVisitor) { 19 | List classList = sortClassesByLevel(classCollection); 20 | for (Class aClass : classList) { 21 | classPoolVisitor.visit(aClass); 22 | 23 | for (Field field : aClass.getFields()) { 24 | for (java.lang.annotation.Annotation annotation : field.getAnnotations()) { 25 | visitAnnotation((Annotation)annotation, classPoolVisitor); 26 | } 27 | 28 | classPoolVisitor.visit(field); 29 | } 30 | 31 | for (Object method : aClass.getMethods()) { 32 | for (java.lang.annotation.Annotation annotation : ((Method) method).getAnnotations()) { 33 | visitAnnotation(annotation, classPoolVisitor); 34 | } 35 | classPoolVisitor.visit((Method) method); 36 | } 37 | classPoolVisitor.endVisit(aClass); 38 | } 39 | } 40 | 41 | private List sortClassesByLevel(Collection classCollection) { 42 | List classList = new ArrayList<>(classCollection); 43 | Collections.sort(classList, new Comparator() { 44 | @Override public int compare(Class o1, Class o2) { 45 | return o1.getLevel() - o2.getLevel(); 46 | } 47 | }); 48 | return classList; 49 | } 50 | 51 | private void visitAnnotation(java.lang.annotation.Annotation annotation, ClassPoolVisitor classPoolVisitor) { 52 | Annotation rnrAnnotation = (Annotation) annotation; 53 | List methods = rnrAnnotation.getMethods(); 54 | classPoolVisitor.visit(rnrAnnotation); 55 | for (int i = 0; i < methods.size(); i++) { 56 | Method method = methods.get(i); 57 | classPoolVisitor.visitAnnotationMethod(rnrAnnotation, method); 58 | } 59 | classPoolVisitor.endVisit(rnrAnnotation); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /processor/src/test/java/org/reflection_no_reflection/processor/GenericsTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.processor; 2 | 3 | import java.lang.reflect.Modifier; 4 | import java.util.Set; 5 | import org.junit.Test; 6 | import org.reflection_no_reflection.Annotation; 7 | import org.reflection_no_reflection.Class; 8 | import org.reflection_no_reflection.Field; 9 | import org.reflection_no_reflection.GenericDeclaration; 10 | 11 | import static org.hamcrest.MatcherAssert.assertThat; 12 | import static org.hamcrest.core.Is.is; 13 | import static org.hamcrest.core.IsNull.notNullValue; 14 | 15 | public class GenericsTest extends AbstractRnRTest { 16 | 17 | @Test 18 | public void mapsSimpleAnnotatedGenericField() throws ClassNotFoundException { 19 | javaSourceCode("test.Foo", // 20 | "package test;", // 21 | "import java.util.List;", // 22 | "public class Foo {",// 23 | "@Deprecated private List s;", // 24 | "}" // 25 | ); 26 | 27 | setTargetAnnotations(new String[] {"java.lang.Deprecated"}); 28 | assertJavaSourceCompileWithoutError(); 29 | 30 | final Set annotatedClasses = getProcessedClasses(); 31 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 32 | 33 | final Class aClass = Class.forName("test.Foo"); 34 | assertThat(aClass.getFields().length, is(1)); 35 | 36 | final Field aField = aClass.getFields()[0]; 37 | final Field expected = new Field("s", Class.forName("java.util.List"), aClass, Modifier.PRIVATE, null); 38 | assertThat(aField, is(expected)); 39 | assertThat(aField.getType(), is((Class) Class.forName("java.util.List"))); 40 | final GenericDeclaration genericInfo = aField.getType().getGenericInfo(); 41 | assertThat(genericInfo, notNullValue()); 42 | assertThat(genericInfo.getTypeParameters().length, is(1)); 43 | assertThat(genericInfo.getTypeParameters()[0].getName(), is("java.lang.String")); 44 | 45 | assertThat(aField.getModifiers(), is(Modifier.PRIVATE)); 46 | 47 | final Annotation[] annotations = (Annotation[]) aField.getAnnotations(); 48 | assertThat(annotations.length, is(1)); 49 | 50 | final Class deprecatedAnnotationClass = Class.forName("java.lang.Deprecated"); 51 | assertThat(annotations[0].rnrAnnotationType(), is(deprecatedAnnotationClass)); 52 | assertThat(((Annotation) aField.getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType(), is(deprecatedAnnotationClass)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /generator-integration-tests/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/TypeVariable.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection; 2 | 3 | import java.lang.reflect.Type; 4 | 5 | /** 6 | * TypeVariable is the common superinterface for type variables of kinds. 7 | * A type variable is created the first time it is needed by a reflective 8 | * method, as specified in this package. If a type variable t is referenced 9 | * by a type (i.e, class, interface or annotation type) T, and T is declared 10 | * by the nth enclosing class of T (see JLS 8.1.2), then the creation of t 11 | * requires the resolution (see JVMS 5) of the ith enclosing class of T, 12 | * for i = 0 to n, inclusive. Creating a type variable must not cause the 13 | * creation of its bounds. Repeated creation of a type variable has no effect. 14 | * 15 | *

Multiple objects may be instantiated at run-time to 16 | * represent a given type variable. Even though a type variable is 17 | * created only once, this does not imply any requirement to cache 18 | * instances representing the type variable. However, all instances 19 | * representing a type variable must be equal() to each other. 20 | * As a consequence, users of type variables must not rely on the identity 21 | * of instances of classes implementing this interface. 22 | * 23 | * @param the type of generic declaration that declared the 24 | * underlying type variable. 25 | * @since 1.5 26 | */ 27 | public interface TypeVariable { 28 | /** 29 | * Returns an array of {@code Type} objects representing the 30 | * upper bound(s) of this type variable. Note that if no upper bound is 31 | * explicitly declared, the upper bound is {@code Object}. 32 | * 33 | *

For each upper bound B:

  • if B is a parameterized 34 | * type or a type variable, it is created, (see {@link 35 | * java.lang.reflect.ParameterizedType ParameterizedType} for the 36 | * details of the creation process for parameterized types). 37 | *
  • Otherwise, B is resolved.
38 | * 39 | * @return an array of {@code Type}s representing the upper 40 | * bound(s) of this type variable 41 | */ 42 | Type[] getBounds(); 43 | 44 | /** 45 | * Returns the {@code GenericDeclaration} object representing the 46 | * generic declaration declared this type variable. 47 | * 48 | * @return the generic declaration declared for this type variable. 49 | * @since 1.5 50 | */ 51 | D getGenericDeclaration(); 52 | 53 | /** 54 | * Returns the name of this type variable, as it occurs in the source code. 55 | * 56 | * @return the name of this type variable, as it appears in the source code 57 | */ 58 | String getName(); 59 | } 60 | -------------------------------------------------------------------------------- /sample-exploded/src/main/java/org/reflection_no_reflection/sample/Main.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.sample; 2 | 3 | import java.util.Collection; 4 | import javax.inject.Inject; 5 | import org.reflection_no_reflection.Field; 6 | import org.reflection_no_reflection.FieldFinder; 7 | import org.reflection_no_reflection.no_reflection.AnnotationDatabaseFinder; 8 | import org.reflection_no_reflection.reflection.ReflectionFieldFinder; 9 | 10 | public class Main { 11 | 12 | public static final int ITERATIONS = 1000000; 13 | 14 | public static void main(String[] args) throws IllegalAccessException { 15 | A a = new A(); 16 | 17 | long timeWithReflection; 18 | long timeWithoutReflection; 19 | 20 | System.out.println("--- Via Reflection"); 21 | long startTime = System.currentTimeMillis(); 22 | for (int i = 0; i < ITERATIONS; i++) 23 | usingReflection(a); 24 | long endTime = System.currentTimeMillis(); 25 | timeWithReflection = endTime - startTime; 26 | 27 | System.out.println("--- Via No Reflection"); 28 | startTime = System.currentTimeMillis(); 29 | for (int i = 0; i < ITERATIONS; i++) 30 | usingNoReflection(a); 31 | endTime = System.currentTimeMillis(); 32 | timeWithoutReflection = endTime - startTime; 33 | 34 | System.out.println("With Reflection ---> " + timeWithReflection + " ms"); 35 | System.out.println("With No Relection ---> " + timeWithoutReflection + " ms"); 36 | } 37 | 38 | private static void usingNoReflection(A a) throws IllegalAccessException { 39 | FieldFinder fieldFinder; 40 | Collection allFields; 41 | fieldFinder = new NoReflectionFieldFinderImpl((AnnotationDatabaseFinder)null); 42 | allFields = fieldFinder.getAllFields(Inject.class, A.class); 43 | for (Field field : allFields) { 44 | //System.out.println("Field: " + field.getName() + ":" + field.getType().getName() + " -- " + field.getAnnotation(Inject.class)); 45 | //System.out.println("Field: " + field.getName() + ":" + field.getType().getName() + " -- " + field.get(a)); 46 | field.get(a); 47 | } 48 | } 49 | 50 | private static void usingReflection(A a) throws IllegalAccessException { 51 | FieldFinder fieldFinder = new ReflectionFieldFinder(); 52 | Collection allFields = fieldFinder.getAllFields(Inject.class, A.class); 53 | for (Field field : allFields) { 54 | //System.out.println("Field: " + field.getName() + ":" + field.getType().getName() + " -- " + field.getAnnotation(Inject.class)); 55 | //System.out.println("Field: " + field.getName() + ":" + field.getType().getName() + " -- " + field.get(a)); 56 | field.get(a); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /generator-integration-tests/src/test/java/org/reflection_no_reflection/generator/sample/ConstructorTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.sample; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Modifier; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import javax.inject.Inject; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.reflection_no_reflection.Class; 11 | import org.reflection_no_reflection.Constructor; 12 | import org.reflection_no_reflection.Method; 13 | import org.reflection_no_reflection.runtime.Module; 14 | 15 | import static org.hamcrest.CoreMatchers.sameInstance; 16 | import static org.hamcrest.core.Is.is; 17 | import static org.junit.Assert.assertNotNull; 18 | import static org.junit.Assert.assertThat; 19 | 20 | public class ConstructorTest { 21 | 22 | public static final String CONSTRUCTOR_TEST_CASE_CLASS_NAME = "org.reflection_no_reflection.generator.sample.ConstructorTestCase"; 23 | 24 | @Before 25 | public void setUp() throws Exception { 26 | Class.clearAllClasses(); 27 | Module module = new org.reflection_no_reflection.generator.sample.gen.ModuleImpl(); 28 | Class.loadModule(module); 29 | } 30 | 31 | @Test 32 | public void shouldDetectAllConstructors() throws ClassNotFoundException { 33 | //GIVEN 34 | 35 | //WHEN 36 | Class classFoo = (Class) Class.forName("org.reflection_no_reflection.generator.sample.ConstructorTestCase"); 37 | 38 | //THEN 39 | assertNotNull(classFoo); 40 | 41 | final List> constructors = classFoo.getConstructors(); 42 | assertNotNull(constructors); 43 | assertThat(constructors.size(), is(1)); 44 | } 45 | 46 | @Test 47 | public void shouldDetectAnnotationsOfConstructor() throws ClassNotFoundException { 48 | //GIVEN 49 | 50 | //WHEN 51 | Class classFoo = (Class) Class.forName("org.reflection_no_reflection.generator.sample.ConstructorTestCase"); 52 | 53 | //THEN 54 | final List> constructors = classFoo.getConstructors(); 55 | final Constructor constructor = constructors.get(0); 56 | assertThat(constructor.getAnnotation(Inject.class).annotationType(), sameInstance((java.lang.Class) Inject.class)); 57 | } 58 | 59 | @Test 60 | public void shouldReflectSimpleConstructor() throws ClassNotFoundException, InvocationTargetException, InstantiationException { 61 | //GIVEN 62 | 63 | //WHEN 64 | Class classFoo = (Class) Class.forName("org.reflection_no_reflection.generator.sample.ConstructorTestCase"); 65 | 66 | //THEN 67 | final List> constructors = classFoo.getConstructors(); 68 | final Constructor constructor = constructors.get(0); 69 | assertThat(constructor.getName(), is("ConstructorTestCase")); 70 | ConstructorTestCase methodTestCase = constructor.newInstance(); 71 | assertThat(methodTestCase.a, is(3)); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/visit/dump/JavaDumperClassPoolVisitor.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.visit.dump; 2 | 3 | import org.reflection_no_reflection.Annotation; 4 | import org.reflection_no_reflection.Field; 5 | import org.reflection_no_reflection.Method; 6 | import org.reflection_no_reflection.visit.ClassPoolVisitor; 7 | 8 | /** 9 | * @author SNI. 10 | */ 11 | public class JavaDumperClassPoolVisitor implements ClassPoolVisitor { 12 | private static final String CLASS_SEPARATOR = "\n"; 13 | private static final String INDENT = "\t"; 14 | private StringBuffer buffer = new StringBuffer(); 15 | 16 | @Override 17 | public void visit(org.reflection_no_reflection.Class aClass) { 18 | buffer.append(CLASS_SEPARATOR); 19 | buffer.append(aClass.getLevel()); 20 | buffer.append(":"); 21 | if(aClass.isAnnotation()) { 22 | buffer.append("@"); 23 | } 24 | if(aClass.isInterface()) { 25 | buffer.append("interface "); 26 | } 27 | if(aClass.isArray()) { 28 | buffer.append("[]"); 29 | } 30 | buffer.append(aClass.getName()); 31 | buffer.append(" {"); 32 | if (aClass.getFields().length != 0 || !aClass.getMethods().isEmpty()) { 33 | buffer.append(" \n"); 34 | } 35 | } 36 | 37 | @Override 38 | public void endVisit(org.reflection_no_reflection.Class aClass) { 39 | buffer.append("}\n"); 40 | } 41 | 42 | @Override 43 | public void visit(Field field) { 44 | buffer.append(INDENT); 45 | buffer.append(field.getType().getName()); 46 | buffer.append(" "); 47 | buffer.append(field.getName()); 48 | buffer.append("\n"); 49 | } 50 | 51 | @Override 52 | public void visit(Method method) { 53 | buffer.append(INDENT); 54 | buffer.append(method.getReturnType().getName()); 55 | buffer.append(" "); 56 | buffer.append(method.getName()); 57 | buffer.append("()"); 58 | buffer.append("\n"); 59 | } 60 | 61 | @Override 62 | public void visit(Annotation annotation) { 63 | buffer.append(INDENT); 64 | buffer.append("@"); 65 | buffer.append(annotation.rnrAnnotationType().getName()); 66 | if (!annotation.getMethods().isEmpty()) { 67 | buffer.append("("); 68 | } 69 | } 70 | 71 | @Override 72 | public void visitAnnotationMethod(Annotation annotation, Method method) { 73 | final String methodName = method.getName(); 74 | buffer.append(" "); 75 | buffer.append(method.getReturnType().getName()); 76 | buffer.append(" "); 77 | buffer.append(methodName); 78 | buffer.append(" = "); 79 | try { 80 | buffer.append(annotation.getValue(methodName)); 81 | } catch (NoSuchMethodException e) { 82 | throw new RuntimeException("Not associated value for method " + methodName); 83 | } 84 | } 85 | 86 | @Override 87 | public void endVisit(Annotation annotation) { 88 | if (!annotation.getMethods().isEmpty()) { 89 | buffer.append(" )"); 90 | } 91 | buffer.append("\n"); 92 | } 93 | 94 | public StringBuffer getBuffer() { 95 | return buffer; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/Member.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection; 2 | 3 | import java.lang.reflect.AnnotatedElement; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | public abstract class Member implements AnnotatedElement { 8 | 9 | protected Member() {} 10 | 11 | public abstract Class getDeclaringClass(); 12 | public abstract String getName(); 13 | 14 | private List rnRAnnotationList; 15 | private List annotationImplList; 16 | 17 | @SuppressWarnings({"unused", "called by generated code"}) 18 | public void setAnnotationImplList(List annotationImplList) { 19 | this.annotationImplList = annotationImplList; 20 | } 21 | 22 | public void setRnRAnnotationList(List rnRAnnotationList) { 23 | this.rnRAnnotationList = rnRAnnotationList; 24 | } 25 | 26 | 27 | public A getAnnotation(Class annotationType) { 28 | return getAnnotation(annotationType.getName()); 29 | } 30 | 31 | public A getAnnotation(java.lang.Class annotationType) { 32 | return getAnnotation(annotationType.getName()); 33 | } 34 | 35 | public A getAnnotation(String annotationClassNane) { 36 | //processor annotations 37 | if (rnRAnnotationList != null) { 38 | for (Annotation annotation : rnRAnnotationList) { 39 | if (annotation.rnrAnnotationType().getName().equals(annotationClassNane)) { 40 | return (A) annotation; 41 | } 42 | } 43 | } 44 | 45 | //generator annotations 46 | if( annotationImplList!= null) { 47 | for (java.lang.annotation.Annotation annotation : annotationImplList) { 48 | if (annotation.annotationType().getName().equals(annotationClassNane)) { 49 | return (A) annotation; 50 | } 51 | } 52 | } 53 | 54 | return null; 55 | } 56 | 57 | public java.lang.annotation.Annotation[] getAnnotations() { 58 | if (rnRAnnotationList == null && annotationImplList == null) { 59 | return new java.lang.annotation.Annotation[0]; 60 | } else if (rnRAnnotationList !=null ) { 61 | return rnRAnnotationList.toArray(new Annotation[rnRAnnotationList.size()]); 62 | } else { 63 | return annotationImplList.toArray(new java.lang.annotation.Annotation[annotationImplList.size()]); //not implemented 64 | } 65 | } 66 | 67 | public boolean isAnnotationPresent(Class annotationType) { 68 | return false; //not implemented 69 | } 70 | 71 | public boolean isAnnotationPresent(java.lang.Class annotationClass) { 72 | return false; //not implemented 73 | } 74 | 75 | private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; 76 | 77 | /** 78 | * TODO what should this really return ? 79 | * @since 1.5 80 | */ 81 | public java.lang.annotation.Annotation[] getDeclaredAnnotations() { 82 | //TODO catch what the difference should be 83 | return getAnnotations(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /processor/src/test/java/org/reflection_no_reflection/processor/InnerClassTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.processor; 2 | 3 | import java.util.Set; 4 | import org.junit.Test; 5 | import org.reflection_no_reflection.Class; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | import static org.hamcrest.core.IsNull.notNullValue; 10 | 11 | public class InnerClassTest extends AbstractRnRTest { 12 | 13 | @Test 14 | public void mapsSimpleAnnotatedInnerClass() throws ClassNotFoundException { 15 | javaSourceCode("test.Foo", // 16 | "package test;", // 17 | "public class Foo {", // 18 | "@Deprecated", // 19 | "public class Bar {}", // 20 | "}" // 21 | ); 22 | 23 | setTargetAnnotations("java.lang.Deprecated"); 24 | assertJavaSourceCompileWithoutError(); 25 | 26 | final Set annotatedClasses = getProcessedClasses(); 27 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo.Bar")), is(true)); 28 | assertThat(annotatedClasses.contains(Class.forName("test.Foo.Bar")), is(true)); 29 | final Class deprecatedAnnotationClass = Class.forNameSafe("java.lang.Deprecated"); 30 | assertThat(Class.forName("test.Foo.Bar").getAnnotation(deprecatedAnnotationClass), notNullValue()); 31 | } 32 | 33 | @Test 34 | public void mapsStaticAnnotatedInnerClass() throws ClassNotFoundException { 35 | javaSourceCode("test.Foo", // 36 | "package test;", // 37 | "public class Foo {", // 38 | "@Deprecated", // 39 | "public static class Bar {}", // 40 | "}" // 41 | ); 42 | 43 | setTargetAnnotations("java.lang.Deprecated"); 44 | assertJavaSourceCompileWithoutError(); 45 | 46 | final Set annotatedClasses = getProcessedClasses(); 47 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo.Bar")), is(true)); 48 | assertThat(annotatedClasses.contains(Class.forName("test.Foo.Bar")), is(true)); 49 | final Class deprecatedAnnotationClass = Class.forNameSafe("java.lang.Deprecated"); 50 | assertThat(Class.forName("test.Foo.Bar").getAnnotation(deprecatedAnnotationClass), notNullValue()); 51 | } 52 | 53 | @Test 54 | public void mapsPrivateAnnotatedInnerClass() throws ClassNotFoundException { 55 | javaSourceCode("test.Foo", // 56 | "package test;", // 57 | "public class Foo {", // 58 | "@Deprecated", // 59 | "private class Bar {}", // 60 | "}" // 61 | ); 62 | 63 | setTargetAnnotations("java.lang.Deprecated"); 64 | assertJavaSourceCompileWithoutError(); 65 | 66 | final Set annotatedClasses = getProcessedClasses(); 67 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo.Bar")), is(true)); 68 | assertThat(annotatedClasses.contains(Class.forName("test.Foo.Bar")), is(true)); 69 | final Class deprecatedAnnotationClass = Class.forNameSafe("java.lang.Deprecated"); 70 | assertThat(Class.forName("test.Foo.Bar").getAnnotation(deprecatedAnnotationClass), notNullValue()); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/Annotation.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * Base class of all the annotation classes inside the RNR framework. 10 | * This class is a keystone of RNR. It has a little twist and we aim to document it here. 11 | * 12 | * The only thing to remember is that: at processing-time (when you use RNR to write an annotation processor), 13 | * the annotations you manipulation are instances of the present class and they will fault on #annotationType, 14 | * you probably wanna call #rnrAnnotationType. 15 | * 16 | 17 | * Thoughts: normally annotations have an annotationType method that returns a Class. But in RNR, they 18 | * should return RNR classes. At processing time, true classes don't exist and we would not be able 19 | * to manipulation annotations if we only had this API. We thus added the rnrAnnotationType method. 20 | * 21 | * Deeper thoughts: At runtime, we will need to provide true implementations 22 | * of annotations (for instance to answer the getAnnotation(Class A) method). True annotations means to implement 23 | * the java.lang.annoation.Annotation interface (yes, it is an interface and yes, you can implement it). 24 | * This will be achieved via the AnnotationImpl class. 25 | * The processing-time and runtime annotation APIs cannot be reconciliated. One must return a true class for runtime 26 | * and the other must return a RNR class. 27 | * 28 | * We have tried many patterns to make this clear. But actually, adding this little method rnrAnnotationType for 29 | * annotation used at processing-time only is the minimum-disturbing API we have found. Yeah, this is a brain-knot lib. :) 30 | * @author SNI 31 | */ 32 | public class Annotation implements java.lang.annotation.Annotation { 33 | 34 | /** The class name of this annotation type. */ 35 | private Class annotationType; 36 | private Map mapMethodToValue = new HashMap<>(); 37 | 38 | /** 39 | * Creates a new annotation. 40 | * 41 | * @param annotationType class of this annotation type. 42 | */ 43 | public Annotation(Class annotationType, Map mapMethodToValue) { 44 | this.annotationType = annotationType; 45 | this.mapMethodToValue = mapMethodToValue; 46 | } 47 | 48 | public String getAnnotationTypeName() { 49 | return annotationType.getName(); 50 | } 51 | 52 | public List getMethods() { 53 | return new ArrayList<>(mapMethodToValue.keySet()); 54 | } 55 | 56 | public Method getMethod(String methodName) throws NoSuchMethodException { 57 | for (Method method : mapMethodToValue.keySet()) { 58 | if (method.getName().equals(methodName)) { 59 | return method; 60 | } 61 | } 62 | 63 | throw new NoSuchMethodException(methodName); 64 | } 65 | 66 | public Object getValue(String methodName) throws NoSuchMethodException { 67 | final Method method = getMethod(methodName); 68 | Object result = mapMethodToValue.get(method); 69 | 70 | //special cases handling 71 | if (method.getReturnType().getName().equals("java.lang.String[]") 72 | && result instanceof List) { 73 | List temp = (List) result; 74 | if (temp.size() == 1) { 75 | result = ((com.sun.tools.javac.code.Attribute.Constant) temp.get(0)).getValue(); 76 | } 77 | } 78 | return result; 79 | } 80 | 81 | public Class rnrAnnotationType() { 82 | return annotationType; 83 | } 84 | 85 | public java.lang.Class annotationType() { 86 | throw new RuntimeException("This method cannot be called on an RNR annotation during annotation processing. You may want to invoke rnrAnnotationType()."); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /processor/src/test/java/org/reflection_no_reflection/processor/FieldArrayTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.processor; 2 | 3 | import java.lang.reflect.Modifier; 4 | import java.util.Set; 5 | import org.junit.Test; 6 | import org.reflection_no_reflection.Annotation; 7 | import org.reflection_no_reflection.Class; 8 | import org.reflection_no_reflection.Field; 9 | 10 | import static org.hamcrest.MatcherAssert.assertThat; 11 | import static org.hamcrest.core.Is.is; 12 | 13 | public class FieldArrayTest extends AbstractRnRTest { 14 | 15 | @Test 16 | public void mapsAnnotatedObjectArrayField() throws ClassNotFoundException { 17 | javaSourceCode("test.Foo", // 18 | "package test;", // 19 | "public class Foo {",// 20 | "@Deprecated private String[] s;", // 21 | "}" // 22 | ); 23 | 24 | setTargetAnnotations(new String[] {"java.lang.Deprecated"}); 25 | assertJavaSourceCompileWithoutError(); 26 | 27 | final Set annotatedClasses = getProcessedClasses(); 28 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 29 | 30 | final Class aClass = Class.forName("test.Foo"); 31 | assertThat(aClass.getFields().length, is(1)); 32 | 33 | final Field aField = aClass.getFields()[0]; 34 | final Field expected = new Field("s", Class.forName("java.lang.String[]"), aClass, Modifier.PRIVATE, null); 35 | assertThat(aField, is(expected)); 36 | assertThat(aField.getType(), is((Class) Class.forName("java.lang.String[]"))); 37 | assertThat(aField.getType().isArray(), is(true)); 38 | assertThat(aField.getType().getComponentType(), is((Class) Class.forName("java.lang.String"))); 39 | assertThat(aField.getModifiers(), is(Modifier.PRIVATE)); 40 | 41 | final Annotation[] annotations = (Annotation[]) aField.getAnnotations(); 42 | assertThat(annotations.length, is(1)); 43 | 44 | final Class deprecatedAnnotationClass = Class.forName("java.lang.Deprecated"); 45 | assertThat(annotations[0].rnrAnnotationType(), is(deprecatedAnnotationClass)); 46 | assertThat(((Annotation) aField.getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType(), is(deprecatedAnnotationClass)); 47 | 48 | } 49 | 50 | @Test 51 | public void mapsAnnotatedPrimitiveArrayField() throws ClassNotFoundException { 52 | javaSourceCode("test.Foo", // 53 | "package test;", // 54 | "public class Foo {",// 55 | "@Deprecated private int[] s;", // 56 | "}" // 57 | ); 58 | 59 | setTargetAnnotations(new String[] {"java.lang.Deprecated"}); 60 | assertJavaSourceCompileWithoutError(); 61 | 62 | final Set annotatedClasses = getProcessedClasses(); 63 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 64 | 65 | final Class aClass = Class.forName("test.Foo"); 66 | assertThat(aClass.getFields().length, is(1)); 67 | 68 | final Field aField = aClass.getFields()[0]; 69 | final Field expected = new Field("s", Class.forName("int[]"), aClass, Modifier.PRIVATE, null); 70 | assertThat(aField, is(expected)); 71 | assertThat(aField.getType(), is((Class) Class.forName("int[]"))); 72 | assertThat(aField.getType().isArray(), is(true)); 73 | assertThat(aField.getType().getComponentType(), is((Class) Class.forName("int"))); 74 | assertThat(aField.getModifiers(), is(Modifier.PRIVATE)); 75 | 76 | final Annotation[] annotations = (Annotation[]) aField.getAnnotations(); 77 | assertThat(annotations.length, is(1)); 78 | 79 | final Class deprecatedAnnotationClass = Class.forName("java.lang.Deprecated"); 80 | assertThat(annotations[0].rnrAnnotationType(), is(deprecatedAnnotationClass)); 81 | assertThat(((Annotation) aField.getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType(), is(deprecatedAnnotationClass)); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /common-lib/src/main/java/org/reflection_no_reflection/Field.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection; 2 | 3 | import java.lang.reflect.Type; 4 | import java.util.List; 5 | 6 | /** 7 | * This is the base class for all RNR implementation of fields. 8 | * It has the exact same API as Java core reflection fields, and 9 | * can contain extra methods if required. 10 | * Subclass will provide their own implementations of the various field methods. 11 | */ 12 | public class Field extends Member { 13 | 14 | private String name; 15 | private final Class type; 16 | private Class enclosingClass; 17 | private int modifiers; 18 | 19 | public Field(String name, Class type, Class enclosingClass, int modifiers, List annotationList) { 20 | this.name = name; 21 | this.type = type; 22 | this.enclosingClass = enclosingClass; 23 | this.modifiers = modifiers; 24 | setRnRAnnotationList(annotationList); 25 | } 26 | 27 | 28 | public Class getDeclaringClass() { 29 | return enclosingClass; 30 | } 31 | 32 | public Type getGenericType() { 33 | return null; //not implemented 34 | } 35 | 36 | public int getModifiers() { 37 | return modifiers; 38 | } 39 | 40 | public String getName() { 41 | return name; 42 | } 43 | 44 | public Class getType() { 45 | return type; 46 | } 47 | 48 | public int hashCode() { 49 | return 0; //not implemented 50 | } 51 | 52 | public boolean isEnumConstant() { 53 | return false; //not implemented 54 | } 55 | 56 | public boolean isSynthetic() { 57 | return false; //not implemented 58 | } 59 | 60 | public String toGenericString() { 61 | return null; //not implemented 62 | } 63 | 64 | public String toString() { 65 | return null; //not implemented 66 | } 67 | 68 | public static String getTypeName(Class returnType) { 69 | return returnType.toString(); 70 | } 71 | 72 | @Override public boolean equals(Object o) { 73 | if (this == o) { 74 | return true; 75 | } 76 | if (o == null || getClass() != o.getClass()) { 77 | return false; 78 | } 79 | 80 | Field field = (Field) o; 81 | 82 | if (!name.equals(field.name)) { 83 | return false; 84 | } 85 | return enclosingClass.equals(field.enclosingClass); 86 | } 87 | 88 | public void setAccessible(boolean accessible) { 89 | //do nothing 90 | } 91 | 92 | public void set(Object instance, Object value) { 93 | enclosingClass.getReflector().setObjectField(instance, getName(), value); 94 | } 95 | 96 | public void setByte(Object instance, byte value) { 97 | enclosingClass.getReflector().setByteField(instance, getName(), value); 98 | } 99 | 100 | public void setShort(Object instance, short value) { 101 | enclosingClass.getReflector().setShortField(instance, getName(), value); 102 | } 103 | 104 | public void setInt(Object instance, int value) { 105 | enclosingClass.getReflector().setIntField(instance, getName(), value); 106 | } 107 | 108 | public void setLong(Object instance, long value) { 109 | enclosingClass.getReflector().setLongField(instance, getName(), value); 110 | } 111 | 112 | public void setFloat(Object instance, float value) { 113 | enclosingClass.getReflector().setFloatField(instance, getName(), value); 114 | } 115 | 116 | public void setDouble(Object instance, double value) { 117 | enclosingClass.getReflector().setDoubleField(instance, getName(), value); 118 | } 119 | 120 | public void setChar(Object instance, char value) { 121 | enclosingClass.getReflector().setCharField(instance, getName(), value); 122 | } 123 | 124 | public void setBoolean(Object instance, boolean value) { 125 | enclosingClass.getReflector().setBooleanField(instance, getName(), value); 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /sample-exploded/src/main/java/org/reflection_no_reflection/sample/NoReflectionFieldFinderImpl.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.sample; 2 | 3 | import java.lang.annotation.Annotation; 4 | import java.lang.reflect.Modifier; 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import javax.inject.Inject; 9 | import org.reflection_no_reflection.Field; 10 | import org.reflection_no_reflection.no_reflection.AnnotationDatabase; 11 | import org.reflection_no_reflection.no_reflection.AnnotationDatabaseFinder; 12 | import org.reflection_no_reflection.no_reflection.FieldGetterAndSetter; 13 | import org.reflection_no_reflection.no_reflection.NoReflectionFieldFinder; 14 | 15 | /** 16 | * A Proof of Concept for finding fields based on RNR. 17 | * @author SNI 18 | */ 19 | public class NoReflectionFieldFinderImpl extends NoReflectionFieldFinder { 20 | static { 21 | fieldGetterAndSetter = new FieldGetterAndSetterImpl(); 22 | } 23 | 24 | public NoReflectionFieldFinderImpl(AnnotationDatabaseFinder annotationDatabaseFinder) { 25 | super(annotationDatabaseFinder); 26 | } 27 | 28 | public NoReflectionFieldFinderImpl(String[] annotationDatabasePackages) { 29 | super(annotationDatabasePackages); 30 | } 31 | 32 | @Override 33 | public List getAllFields(Class annotationClass, Class clazz) { 34 | List fieldList = new ArrayList(); 35 | if (clazz == A.class) { 36 | List annotationList = new ArrayList<>(); 37 | annotationList.add(new NoReflectionInjectAnnotation()); 38 | Field fieldB = new AnnotationDatabase.LocalNoReflectionField(0, "b", A.class.getName(), B.class.getName(), Modifier.PUBLIC, annotationList); 39 | 40 | annotationList.add(new NoReflectionInjectAnnotation()); 41 | Field fieldC = new AnnotationDatabase.LocalNoReflectionField(1, "c", A.class.getName(), int.class.getName(), 0, annotationList); 42 | fieldList.add(fieldB); 43 | fieldList.add(fieldC); 44 | } 45 | return fieldList; 46 | } 47 | } 48 | 49 | class NoReflectionInjectAnnotation implements Inject { 50 | @Override 51 | public Class annotationType() { 52 | return Inject.class; 53 | } 54 | } 55 | 56 | class FieldGetterAndSetterImpl implements FieldGetterAndSetter { 57 | 58 | public void set(int index, Object object, Object value) throws IllegalAccessException { 59 | switch (index) { 60 | case 0: 61 | ((A) object).b = (B) value; 62 | break; 63 | case 1: 64 | ((A) object).c = (int) value; 65 | break; 66 | default: 67 | throw new IllegalAccessException("No setter for this index:" + index); 68 | } 69 | } 70 | 71 | public void setInt(int index, Object object, int value) throws IllegalAccessException { 72 | switch (index) { 73 | case 0: 74 | throw new IllegalAccessException("Not an int"); 75 | case 1: 76 | ((A) object).c = value; 77 | break; 78 | default: 79 | throw new IllegalAccessException("No setter for this index:" + index); 80 | } 81 | } 82 | 83 | public Object get(int index, Object object) throws IllegalAccessException { 84 | switch (index) { 85 | case 0: 86 | return ((A) object).b; 87 | case 1: 88 | return ((A) object).c; 89 | default: 90 | throw new IllegalAccessException("Not an Object"); 91 | } 92 | } 93 | 94 | public int getInt(int index, Object object) throws IllegalAccessException { 95 | switch (index) { 96 | case 0: 97 | throw new IllegalAccessException("Not an int"); 98 | case 1: 99 | return ((A) object).c; 100 | default: 101 | throw new IllegalAccessException("Not an int"); 102 | } 103 | } 104 | } 105 | 106 | -------------------------------------------------------------------------------- /processor/src/test/java/org/reflection_no_reflection/processor/FieldTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.processor; 2 | 3 | import java.lang.reflect.Modifier; 4 | import java.util.Set; 5 | import org.junit.Test; 6 | import org.reflection_no_reflection.Annotation; 7 | import org.reflection_no_reflection.Class; 8 | import org.reflection_no_reflection.Field; 9 | 10 | import static org.hamcrest.MatcherAssert.assertThat; 11 | import static org.hamcrest.core.Is.is; 12 | 13 | public class FieldTest extends AbstractRnRTest { 14 | 15 | @Test 16 | public void mapsSimpleAnnotatedField() throws ClassNotFoundException { 17 | javaSourceCode("test.Foo", // 18 | "package test;", // 19 | "public class Foo {",// 20 | "@Deprecated private String s;", // 21 | "}" // 22 | ); 23 | 24 | setTargetAnnotations(new String[] {"java.lang.Deprecated"}); 25 | assertJavaSourceCompileWithoutError(); 26 | 27 | final Set annotatedClasses = getProcessedClasses(); 28 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 29 | 30 | final Class aClass = Class.forName("test.Foo"); 31 | assertThat(aClass.getFields().length, is(1)); 32 | 33 | final Field aField = aClass.getFields()[0]; 34 | final Field expected = new Field("s", Class.forName("java.lang.String"), aClass, Modifier.PRIVATE, null); 35 | assertThat(aField, is(expected)); 36 | assertThat(aField.getType(), is((Class) Class.forName("java.lang.String"))); 37 | assertThat(aField.getModifiers(), is(Modifier.PRIVATE)); 38 | 39 | final Annotation[] annotations = (Annotation[]) aField.getAnnotations(); 40 | assertThat(annotations.length, is(1)); 41 | 42 | final Class deprecatedAnnotationClass = Class.forName("java.lang.Deprecated"); 43 | assertThat(annotations[0].rnrAnnotationType(), is(deprecatedAnnotationClass)); 44 | assertThat(((Annotation) aField.getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType(), is(deprecatedAnnotationClass)); 45 | } 46 | 47 | @Test 48 | @SuppressWarnings("foo") 49 | public void mapsAnnotatedFieldWithParams() throws ClassNotFoundException, NoSuchMethodException { 50 | javaSourceCode("test.Foo", // 51 | "package test;", // 52 | "public class Foo {",// 53 | "@SuppressWarnings(\"foo\") private String s;", // 54 | "}" // 55 | ); 56 | 57 | setTargetAnnotations(new String[] {"java.lang.SuppressWarnings"}); 58 | assertJavaSourceCompileWithoutError(); 59 | 60 | final Set annotatedClasses = getProcessedClasses(); 61 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 62 | 63 | final Class aClass = Class.forName("test.Foo"); 64 | assertThat(aClass.getFields().length, is(1)); 65 | 66 | final Field aField = aClass.getFields()[0]; 67 | final Field expected = new Field("s", Class.forName("java.lang.String"), aClass, Modifier.PRIVATE, null); 68 | assertThat(aField, is(expected)); 69 | assertThat(aField.getType(), is((Class) Class.forName("java.lang.String"))); 70 | assertThat(aField.getModifiers(), is(Modifier.PRIVATE)); 71 | 72 | final Annotation[] annotations = (Annotation[]) aField.getAnnotations(); 73 | assertThat(annotations.length, is(1)); 74 | 75 | final Class suppressWarningsAnnotationClass = Class.forName("java.lang.SuppressWarnings"); 76 | assertThat(annotations[0].rnrAnnotationType(), is(suppressWarningsAnnotationClass)); 77 | assertThat(((Annotation) aField.getAnnotation(suppressWarningsAnnotationClass)).rnrAnnotationType(), is(suppressWarningsAnnotationClass)); 78 | assertThat(((Annotation) aField.getAnnotation(suppressWarningsAnnotationClass)).getMethod("value").getReturnType(), is((Class) Class.forName("java.lang.String[]"))); 79 | 80 | final Object value = ((Annotation) aField.getAnnotation(suppressWarningsAnnotationClass)).getValue("value"); 81 | assertThat((String) value, is("foo")); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /processor/src/test/java/org/reflection_no_reflection/processor/MethodParameterTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.processor; 2 | 3 | import java.lang.reflect.Modifier; 4 | import java.util.Set; 5 | import org.junit.Test; 6 | import org.reflection_no_reflection.Class; 7 | import org.reflection_no_reflection.Method; 8 | 9 | import static org.hamcrest.MatcherAssert.assertThat; 10 | import static org.hamcrest.core.Is.is; 11 | 12 | public class MethodParameterTest extends AbstractRnRTest { 13 | 14 | @Test 15 | public void mapsMethodWithAnnotatedParams() throws ClassNotFoundException { 16 | javaSourceCode("test.Foo", // 17 | "package test;", // 18 | "public class Foo {",// 19 | "protected String s(@Deprecated String a) {return a; }", // 20 | "}" // 21 | ); 22 | 23 | setTargetAnnotations(new String[] {"java.lang.Deprecated"}); 24 | assertJavaSourceCompileWithoutError(); 25 | 26 | final Set annotatedClasses = getProcessedClasses(); 27 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 28 | 29 | final Class expectedParamType = Class.forName("java.lang.String"); 30 | final Class aClass = Class.forName("test.Foo"); 31 | assertThat(aClass.getMethods().size(), is(1)); 32 | 33 | final Method method = (Method) aClass.getMethods().get(0); 34 | final Method expected = new Method(aClass, "s", new Class[] {expectedParamType}, Class.forNameSafe("java.lang.String"), new Class[0], Modifier.PROTECTED); 35 | assertThat(method, is(expected)); 36 | assertThat(method.getModifiers(), is(Modifier.PROTECTED)); 37 | 38 | //TODO test annotations of params 39 | } 40 | 41 | @Test 42 | public void mapsMethodWithVarArgs() throws ClassNotFoundException { 43 | javaSourceCode("test.Foo", // 44 | "package test;", // 45 | "public class Foo {",// 46 | "protected void s(@Deprecated String... a) {}", // 47 | "}" // 48 | ); 49 | 50 | setTargetAnnotations(new String[] {"java.lang.Deprecated"}); 51 | assertJavaSourceCompileWithoutError(); 52 | 53 | final Set annotatedClasses = getProcessedClasses(); 54 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 55 | 56 | final Class expectedParamType = Class.forNameSafe("java.lang.String[]"); 57 | final Class aClass = Class.forName("test.Foo"); 58 | assertThat(aClass.getMethods().size(), is(1)); 59 | 60 | final Method method = (Method) aClass.getMethods().get(0); 61 | final Method expected = new Method(aClass, "s", new Class[] {expectedParamType}, Class.forNameSafe("void"), new Class[0], Modifier.PROTECTED); 62 | assertThat(method, is(expected)); 63 | assertThat(method.isVarArgs(), is(true)); 64 | 65 | //TODO test annotations of params 66 | } 67 | 68 | @Test 69 | public void mapsMethodWithInterfaceParam() throws ClassNotFoundException { 70 | javaSourceCode("test.Foo", // 71 | "package test;", // 72 | "public class Foo {",// 73 | "protected void s(@Deprecated java.util.List a) {}", // 74 | "}" // 75 | ); 76 | 77 | setTargetAnnotations(new String[] {"java.lang.Deprecated"}); 78 | assertJavaSourceCompileWithoutError(); 79 | 80 | final Set annotatedClasses = getProcessedClasses(); 81 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 82 | 83 | final Class expectedParamType = Class.forNameSafe("java.util.List"); 84 | final Class aClass = Class.forName("test.Foo"); 85 | assertThat(aClass.getMethods().size(), is(1)); 86 | 87 | final Method method = (Method) aClass.getMethods().get(0); 88 | final Method expected = new Method(aClass, "s", new Class[] {expectedParamType}, Class.forNameSafe("void"), new Class[0], Modifier.PROTECTED); 89 | assertThat(method, is(expected)); 90 | assertThat(method.getParameterTypes()[0].isInterface(), is(true)); 91 | 92 | //TODO test annotations of params 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /common-lib/src/test/java/org/reflection_no_reflection/ClassApiTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection; 2 | 3 | import java.lang.Class; 4 | import java.lang.reflect.Method; 5 | import java.lang.reflect.Modifier; 6 | import org.junit.Test; 7 | 8 | /** 9 | * @author SNI. 10 | */ 11 | public class ClassApiTest { 12 | 13 | private final static boolean DETAIL = false; 14 | 15 | @Test 16 | public void testClassApi() throws Exception { 17 | 18 | final Class reflectionClass = Class.class; 19 | final Class rnrClass = org.reflection_no_reflection.Class.class; 20 | 21 | final long similarityMeasure = getSimilarityMeasure(reflectionClass, rnrClass); 22 | System.out.println("Api compat score for Class: " + similarityMeasure + "%"); 23 | } 24 | 25 | @Test 26 | public void testFieldApi() throws Exception { 27 | 28 | final Class reflectionClass = java.lang.reflect.Field.class; 29 | final Class rnrClass = org.reflection_no_reflection.Field.class; 30 | 31 | final long similarityMeasure = getSimilarityMeasure(reflectionClass, rnrClass); 32 | System.out.println("Api compat score for Field: " + similarityMeasure + "%"); 33 | } 34 | 35 | @Test 36 | public void testMethodApi() throws Exception { 37 | 38 | final Class reflectionClass = java.lang.reflect.Method.class; 39 | final Class rnrClass = org.reflection_no_reflection.Method.class; 40 | 41 | final long similarityMeasure = getSimilarityMeasure(reflectionClass, rnrClass); 42 | System.out.println("Api compat score for Method: " + similarityMeasure + "%"); 43 | } 44 | 45 | private long getSimilarityMeasure(Class reflectionClass, Class rnrClass) { 46 | int equalMethodCount = 0; 47 | int publicMethodCount = 0; 48 | for (Method method : reflectionClass.getMethods()) { 49 | if ((method.getModifiers() & Modifier.PUBLIC) != 0) { 50 | publicMethodCount++; 51 | if (hasSimilarMethod(method, rnrClass)) { 52 | equalMethodCount++; 53 | } else { 54 | if (DETAIL) { 55 | System.out.println(method.getName() + " has no similar methods"); 56 | } 57 | } 58 | } 59 | } 60 | 61 | return Math.round((100 * equalMethodCount) / (double) publicMethodCount); 62 | } 63 | 64 | private boolean hasSimilarMethod(Method method, java.lang.Class rnrClass) { 65 | for (Method rnrMethod : rnrClass.getMethods()) { 66 | final boolean hasSimilarName = rnrMethod.getName().equals(method.getName()); 67 | final boolean hasSimilarReturnType = rnrMethod.getReturnType().getSimpleName().equals(method.getReturnType().getSimpleName()); 68 | final boolean hasSimilarParamTypes = hasSimilarTypes(rnrMethod.getParameterTypes(), method.getParameterTypes()); 69 | if (hasSimilarName) { 70 | if (hasSimilarReturnType) { 71 | if (hasSimilarParamTypes) { 72 | return true; 73 | } else { 74 | if (DETAIL) { 75 | System.out.println("Method of rnrClass : " + rnrClass.getSimpleName() + "#" + method + " has different param types."); 76 | } 77 | } 78 | } else { 79 | if (DETAIL) { 80 | System.out.println("Method of rnrClass : " + rnrClass.getSimpleName() + "#" + method + " has a different return type."); 81 | } 82 | } 83 | } 84 | } 85 | 86 | return false; 87 | } 88 | 89 | private boolean hasSimilarTypes(Class[] parameterTypes, Class[] rnrParameterTypes) { 90 | if (parameterTypes.length != rnrParameterTypes.length) { 91 | return false; 92 | } 93 | 94 | for (int i = 0; i < parameterTypes.length; i++) { 95 | Class parameterType = parameterTypes[i]; 96 | if (!parameterType.getSimpleName().equals(rnrParameterTypes[i].getSimpleName())) { 97 | return false; 98 | } 99 | } 100 | return true; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /generator/src/main/java/org/reflection_no_reflection/generator/introspector/IntrospectorConstructorInvokerCreator.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.introspector; 2 | 3 | import com.squareup.javapoet.ArrayTypeName; 4 | import com.squareup.javapoet.ClassName; 5 | import com.squareup.javapoet.MethodSpec; 6 | import com.squareup.javapoet.ParameterSpec; 7 | import com.squareup.javapoet.TypeName; 8 | import java.lang.reflect.InvocationTargetException; 9 | import javax.lang.model.element.Modifier; 10 | import org.reflection_no_reflection.Class; 11 | import org.reflection_no_reflection.Constructor; 12 | import org.reflection_no_reflection.Method; 13 | 14 | import static org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor.OBJECT_TYPE_NAME; 15 | import static org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor.STRING_TYPE_NAME; 16 | 17 | /** 18 | * @author SNI. 19 | */ 20 | public class IntrospectorConstructorInvokerCreator { 21 | IntrospectorUtil util = new IntrospectorUtil(); 22 | 23 | public MethodSpec createConstructorInvoker(Class aClass) { 24 | ParameterSpec parameterSpec1 = ParameterSpec.builder(STRING_TYPE_NAME, "signature").build(); 25 | TypeName objectVarArgsType = ArrayTypeName.get(Object[].class); 26 | ParameterSpec parameterSpec2 = ParameterSpec.builder(objectVarArgsType, "params").build(); 27 | String packageName = aClass.getName().substring(0, aClass.getName().lastIndexOf('.')); 28 | String className = aClass.getSimpleName(); 29 | MethodSpec.Builder newInstanceMethodBuilder = MethodSpec.methodBuilder("newInstance") 30 | .addModifiers(Modifier.PUBLIC) 31 | .addAnnotation(Override.class) 32 | .addParameter(parameterSpec1) 33 | .addParameter(parameterSpec2) 34 | .returns(ClassName.get(packageName, className)) 35 | .addException(InvocationTargetException.class) 36 | .varargs() 37 | .returns(OBJECT_TYPE_NAME) 38 | .addCode("switch(signature) {\n"); 39 | 40 | for (Object constructorObj : aClass.getConstructors()) { 41 | Constructor constructor = (Constructor) constructorObj; 42 | newInstanceMethodBuilder.addCode(" case($S) :\n", constructor.toString()); 43 | 44 | invokeConstructor(aClass, newInstanceMethodBuilder, constructor); 45 | 46 | } 47 | newInstanceMethodBuilder.addCode(" default :\n"); 48 | newInstanceMethodBuilder.addStatement("throw new InvocationTargetException(new java.lang.NoSuchMethodException(\"constructor:\" + signature + \" not found\"))"); 49 | newInstanceMethodBuilder.addCode("}\n"); 50 | 51 | return newInstanceMethodBuilder.build(); 52 | } 53 | 54 | private void invokeConstructor(Class aClass, MethodSpec.Builder invokeMethodBuilder, Constructor constructor) { 55 | final TypeName enclosingClassName = util.getClassName(aClass); 56 | boolean hasExceptions = constructor.getExceptionTypes().length != 0; 57 | if (hasExceptions) { 58 | invokeMethodBuilder.beginControlFlow("try"); 59 | } 60 | 61 | invokeMethodBuilder.addCode(" return new $T(", enclosingClassName); 62 | addInvocationParameters(invokeMethodBuilder, constructor); 63 | invokeMethodBuilder.addCode(");\n"); 64 | 65 | if (hasExceptions) { 66 | invokeMethodBuilder.endControlFlow(); 67 | invokeMethodBuilder.beginControlFlow("catch(Exception e)"); 68 | invokeMethodBuilder.addStatement("throw new InvocationTargetException(e)"); 69 | invokeMethodBuilder.endControlFlow(); 70 | } 71 | } 72 | 73 | private void addInvocationParameters(MethodSpec.Builder invokeMethodBuilder, Constructor constructor) { 74 | int indexParam = 0; 75 | for (Class paramClass : constructor.getParameterTypes()) { 76 | final boolean isLast = indexParam == constructor.getParameterTypes().length - 1; 77 | System.out.println(constructor.getName()); 78 | if (isLast && paramClass.isArray()) { 79 | invokeMethodBuilder.addCode("($T) params", util.getClassName(paramClass)); 80 | } else { 81 | invokeMethodBuilder.addCode("($T) params[$L]", util.getClassName(paramClass), indexParam); 82 | } 83 | if (!isLast) { 84 | invokeMethodBuilder.addCode(","); 85 | } 86 | indexParam++; 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /generator/src/main/java/org/reflection_no_reflection/generator/introspector/IntrospectorMethodInvokerCreator.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.introspector; 2 | 3 | import com.squareup.javapoet.ArrayTypeName; 4 | import com.squareup.javapoet.MethodSpec; 5 | import com.squareup.javapoet.ParameterSpec; 6 | import com.squareup.javapoet.TypeName; 7 | import java.lang.reflect.InvocationTargetException; 8 | import javax.lang.model.element.Modifier; 9 | import org.reflection_no_reflection.Class; 10 | import org.reflection_no_reflection.Method; 11 | 12 | import static org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor.OBJECT_TYPE_NAME; 13 | import static org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor.STRING_TYPE_NAME; 14 | 15 | /** 16 | * @author SNI. 17 | */ 18 | public class IntrospectorMethodInvokerCreator { 19 | IntrospectorUtil util = new IntrospectorUtil(); 20 | 21 | public MethodSpec createMethodInvoker(Class aClass) { 22 | ParameterSpec parameterSpec1 = ParameterSpec.builder(OBJECT_TYPE_NAME, "instance").build(); 23 | ParameterSpec parameterSpec2 = ParameterSpec.builder(STRING_TYPE_NAME, "methodName").build(); 24 | ParameterSpec parameterSpec3 = ParameterSpec.builder(STRING_TYPE_NAME, "signature").build(); 25 | TypeName objectVarArgsType = ArrayTypeName.get(Object[].class); 26 | ParameterSpec parameterSpec4 = ParameterSpec.builder(objectVarArgsType, "params").build(); 27 | MethodSpec.Builder invokeMethodBuilder = MethodSpec.methodBuilder("invokeMethod") 28 | .addModifiers(Modifier.PUBLIC) 29 | .addAnnotation(Override.class) 30 | .addParameter(parameterSpec1) 31 | .addParameter(parameterSpec2) 32 | .addParameter(parameterSpec3) 33 | .addParameter(parameterSpec4) 34 | .addException(InvocationTargetException.class) 35 | .varargs() 36 | .returns(OBJECT_TYPE_NAME) 37 | .addCode("switch(signature) {\n"); 38 | 39 | for (Object methodObj : aClass.getMethods()) { 40 | Method method = (Method) methodObj; 41 | invokeMethodBuilder.addCode(" case($S) :\n", method.toString()); 42 | 43 | invokeMethod(aClass, invokeMethodBuilder, method); 44 | 45 | } 46 | invokeMethodBuilder.addCode(" default :\n"); 47 | invokeMethodBuilder.addStatement("throw new InvocationTargetException(new java.lang.NoSuchMethodException(\"method:\" + signature + \" not found\"))"); 48 | invokeMethodBuilder.addCode("}\n"); 49 | 50 | return invokeMethodBuilder.build(); 51 | } 52 | 53 | private void invokeMethod(Class aClass, MethodSpec.Builder invokeMethodBuilder, Method method) { 54 | final TypeName enclosingClassName = util.getClassName(aClass); 55 | boolean hasExceptions = method.getExceptionTypes().length != 0; 56 | if (hasExceptions) { 57 | invokeMethodBuilder.beginControlFlow("try"); 58 | } 59 | 60 | if (!method.getReturnType().getName().equals("void")) { 61 | invokeMethodBuilder.addCode(" return (($T) instance).$L(", enclosingClassName, method.getName()); 62 | addInvocationParameters(invokeMethodBuilder, method); 63 | invokeMethodBuilder.addCode(");\n"); 64 | } else { 65 | invokeMethodBuilder.addCode(" (($T) instance).$L(", enclosingClassName, method.getName()); 66 | addInvocationParameters(invokeMethodBuilder, method); 67 | invokeMethodBuilder.addCode(");\n"); 68 | invokeMethodBuilder.addStatement(" return null"); 69 | } 70 | 71 | if (hasExceptions) { 72 | invokeMethodBuilder.endControlFlow(); 73 | invokeMethodBuilder.beginControlFlow("catch(Exception e)"); 74 | invokeMethodBuilder.addStatement("throw new InvocationTargetException(e)"); 75 | invokeMethodBuilder.endControlFlow(); 76 | } 77 | } 78 | 79 | private void addInvocationParameters(MethodSpec.Builder invokeMethodBuilder, Method method) { 80 | int indexParam = 0; 81 | for (Class paramClass : method.getParameterTypes()) { 82 | final boolean isLast = indexParam == method.getParameterTypes().length - 1; 83 | System.out.println(method.getName()); 84 | if (isLast && paramClass.isArray()) { 85 | invokeMethodBuilder.addCode("($T) params", util.getClassName(paramClass)); 86 | } else { 87 | invokeMethodBuilder.addCode("($T) params[$L]", util.getClassName(paramClass), indexParam); 88 | } 89 | if (!isLast) { 90 | invokeMethodBuilder.addCode(","); 91 | } 92 | indexParam++; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /processor/src/test/java/org/reflection_no_reflection/processor/ClassTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.processor; 2 | 3 | import java.util.Set; 4 | import org.junit.Test; 5 | import org.reflection_no_reflection.Annotation; 6 | import org.reflection_no_reflection.Class; 7 | 8 | import static org.hamcrest.MatcherAssert.assertThat; 9 | import static org.hamcrest.core.Is.is; 10 | import static org.hamcrest.core.IsNull.notNullValue; 11 | 12 | public class ClassTest extends AbstractRnRTest { 13 | 14 | @Test 15 | public void mapsSimpleAnnotatedClass() throws ClassNotFoundException { 16 | javaSourceCode("test.Foo", // 17 | "package test;", // 18 | "@Deprecated", // 19 | "public class Foo {}" // 20 | ); 21 | 22 | setTargetAnnotations("java.lang.Deprecated"); 23 | assertJavaSourceCompileWithoutError(); 24 | 25 | final Set annotatedClasses = getProcessedClasses(); 26 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 27 | assertThat(annotatedClasses.contains(Class.forName("test.Foo")), is(true)); 28 | final Class deprecatedAnnotationClass = Class.forNameSafe("java.lang.Deprecated"); 29 | assertThat(Class.forName("test.Foo").getAnnotation(deprecatedAnnotationClass), notNullValue()); 30 | } 31 | 32 | @Test 33 | public void mapsAnnotatedClassWithOtherAnnotations() throws ClassNotFoundException, NoSuchMethodException { 34 | javaSourceCode("test.Foo", // 35 | "package test;", // 36 | "@SuppressWarnings(\"foo\")", // 37 | "@Deprecated", // 38 | "public class Foo {}" // 39 | ); 40 | 41 | setTargetAnnotations("java.lang.Deprecated"); 42 | assertJavaSourceCompileWithoutError(); 43 | 44 | final Set annotatedClasses = getProcessedClasses(); 45 | final Class clazz = Class.forName("test.Foo"); 46 | assertThat(annotatedClasses.contains(clazz), is(true)); 47 | assertThat(annotatedClasses.contains(Class.forName("test.Foo")), is(true)); 48 | final Class deprecatedAnnotationClass = Class.forNameSafe("java.lang.Deprecated"); 49 | assertThat(Class.forName("test.Foo").getAnnotation(deprecatedAnnotationClass), notNullValue()); 50 | assertThat(((Annotation) Class.forName("test.Foo").getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType().isAnnotation(), is(true)); 51 | 52 | final java.lang.annotation.Annotation[] annotations = clazz.getAnnotations(); 53 | assertThat(annotations.length, is(2)); 54 | 55 | final Class suppressWarningsAnnotationClass = Class.forName("java.lang.SuppressWarnings"); 56 | assertThat(((Annotation) clazz.getAnnotation(suppressWarningsAnnotationClass)).rnrAnnotationType(), is(suppressWarningsAnnotationClass)); 57 | assertThat(((Annotation) clazz.getAnnotation(suppressWarningsAnnotationClass)).getMethod("value").getReturnType(), is((Class) Class.forName("java.lang.String[]"))); 58 | assertThat(((Annotation) clazz.getAnnotation(suppressWarningsAnnotationClass)).rnrAnnotationType().isAnnotation(), is(true)); 59 | 60 | final Object value = ((Annotation) clazz.getAnnotation(suppressWarningsAnnotationClass)).getValue("value"); 61 | assertThat((String) value, is("foo")); 62 | } 63 | 64 | @Test 65 | public void superClassIsDefined() throws ClassNotFoundException, NoSuchMethodException { 66 | javaSourceCode("test.Foo", // 67 | "package test;", // 68 | "@SuppressWarnings(\"foo\")", // 69 | "@Deprecated", // 70 | "class Bar {}", // 71 | "@Deprecated", // 72 | "public class Foo extends Bar {}" // 73 | ); 74 | 75 | setTargetAnnotations("java.lang.Deprecated"); 76 | setMaxLevel(1); 77 | assertJavaSourceCompileWithoutError(); 78 | 79 | final Class clazzFoo = Class.forName("test.Foo"); 80 | final Class clazzBar = Class.forName("test.Bar"); 81 | assertThat(clazzFoo.getSuperclass(), notNullValue()); 82 | assertThat(clazzFoo.getSuperclass(), is(clazzBar)); 83 | } 84 | 85 | @Test 86 | public void superInterfaceIsDefined() throws ClassNotFoundException, NoSuchMethodException { 87 | javaSourceCode("test.Foo", // 88 | "package test;", // 89 | "@SuppressWarnings(\"foo\")", // 90 | "@Deprecated", // 91 | "public class Foo implements Bar {}", // 92 | "@Deprecated", // 93 | "interface Bar {}" // 94 | ); 95 | 96 | setTargetAnnotations("java.lang.Deprecated"); 97 | setMaxLevel(1); 98 | assertJavaSourceCompileWithoutError(); 99 | 100 | final Class clazzFoo = Class.forName("test.Foo"); 101 | final Class clazzBar = Class.forName("test.Bar"); 102 | assertThat(clazzFoo.getInterfaces(), notNullValue()); 103 | assertThat(clazzFoo.getInterfaces().length, is(1)); 104 | assertThat(clazzFoo.getInterfaces()[0], is(clazzBar)); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /sample-exploded/src/test/java/org/reflection_no_reflection/sample/FieldTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.sample; 2 | 3 | import java.lang.annotation.Annotation; 4 | import java.lang.reflect.Modifier; 5 | import java.lang.reflect.Type; 6 | import javax.inject.Inject; 7 | import org.hamcrest.core.Is; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.reflection_no_reflection.Field; 11 | 12 | import static org.hamcrest.MatcherAssert.assertThat; 13 | import static org.hamcrest.core.Is.is; 14 | 15 | /** 16 | * Base class for both RNR and core java reflection fields. 17 | * @author SNI 18 | */ 19 | public abstract class FieldTest { 20 | 21 | private java.lang.reflect.Field originalFieldB; 22 | private java.lang.reflect.Field originalFieldC; 23 | private Field fieldB; 24 | private Field fieldC; 25 | 26 | @Before 27 | public void setUp() throws NoSuchFieldException { 28 | originalFieldB = A.class.getDeclaredField("b"); 29 | fieldB = getInstance(A.class, "b"); 30 | originalFieldC = A.class.getDeclaredField("c"); 31 | fieldC = getInstance(A.class, "c"); 32 | } 33 | 34 | public abstract org.reflection_no_reflection.Field getInstance(Class clazz, String fieldName); 35 | 36 | public java.lang.reflect.Field getOriginalFieldB() { 37 | return originalFieldB; 38 | } 39 | 40 | public java.lang.reflect.Field getOriginalFieldC() { 41 | return originalFieldC; 42 | } 43 | 44 | @Test 45 | public void testGetName() throws NoSuchFieldException { 46 | //GIVEN 47 | 48 | //WHEN 49 | String fieldName = fieldB.getName(); 50 | 51 | //THEN 52 | assertThat(fieldName, is(originalFieldB.getName())); 53 | assertThat(fieldName, is("b")); 54 | } 55 | 56 | @Test 57 | public void testGetType() throws NoSuchFieldException { 58 | //GIVEN 59 | 60 | //WHEN 61 | Class fieldType = fieldB.getType(); 62 | 63 | //THEN 64 | assertThat(fieldType, Is.is(originalFieldB.getType())); 65 | assertThat(fieldType, Is.is(B.class)); 66 | } 67 | 68 | @Test 69 | public void testGetGenericType() throws NoSuchFieldException { 70 | //GIVEN 71 | 72 | //WHEN 73 | Type type = fieldB.getGenericType(); 74 | 75 | //THEN 76 | assertThat(type, Is.is(originalFieldB.getType())); 77 | assertThat(type, Is.is(B.class)); 78 | } 79 | 80 | @Test 81 | public void testGetDeclaringClass() throws NoSuchFieldException { 82 | //GIVEN 83 | 84 | //WHEN 85 | Class fieldType = fieldB.getDeclaringClass(); 86 | 87 | //THEN 88 | assertThat(fieldType, Is.is(originalFieldB.getDeclaringClass())); 89 | assertThat(fieldType, Is.is(A.class)); 90 | } 91 | 92 | @Test 93 | public void testGetModifiers() throws NoSuchFieldException { 94 | //GIVEN 95 | 96 | //WHEN 97 | int fieldModifiers = fieldB.getModifiers(); 98 | 99 | //THEN 100 | assertThat(fieldModifiers, is(originalFieldB.getModifiers())); 101 | assertThat(fieldModifiers, is(Modifier.PUBLIC)); 102 | } 103 | 104 | @Test 105 | public void testGetAnnotationInject() throws NoSuchFieldException { 106 | //GIVEN 107 | 108 | //WHEN 109 | Inject fieldAnnotationInject = fieldB.getAnnotation(Inject.class); 110 | 111 | //THEN 112 | assertThat(fieldAnnotationInject, Is.isA(Inject.class)); 113 | } 114 | 115 | @Test 116 | public void testGetAnnotations() throws NoSuchFieldException { 117 | //GIVEN 118 | 119 | //WHEN 120 | Annotation[] annotations = fieldB.getDeclaredAnnotations(); 121 | 122 | //THEN 123 | assertThat(annotations.length, is(1)); 124 | assertThat((Inject) annotations[0], Is.isA(Inject.class)); 125 | } 126 | 127 | @Test 128 | public void testIsAnnotationPresent() throws NoSuchFieldException, IllegalAccessException { 129 | //GIVEN 130 | 131 | //WHEN 132 | A a = new A(); 133 | a.b = new B(); 134 | boolean isInjectpresent = fieldB.isAnnotationPresent(Inject.class); 135 | 136 | //THEN 137 | assertThat(isInjectpresent, Is.is(originalFieldB.isAnnotationPresent(Inject.class))); 138 | assertThat(isInjectpresent, Is.is(true)); 139 | } 140 | 141 | @Test 142 | public void testSet() throws NoSuchFieldException, IllegalAccessException { 143 | //GIVEN 144 | 145 | //WHEN 146 | B newB = new B(); 147 | A a = new A(); 148 | fieldB.set(a, newB); 149 | 150 | //THEN 151 | assertThat(a.b, Is.is((B) originalFieldB.get(a))); 152 | assertThat(a.b, Is.is(newB)); 153 | } 154 | 155 | @Test 156 | public void testGet() throws NoSuchFieldException, IllegalAccessException { 157 | //GIVEN 158 | 159 | //WHEN 160 | A a = new A(); 161 | a.b = new B(); 162 | B b = (B) fieldB.get(a); 163 | 164 | //THEN 165 | assertThat(b, Is.is((B) originalFieldB.get(a))); 166 | assertThat(b, Is.is(a.b)); 167 | } 168 | 169 | @Test 170 | public void testGetInt() throws NoSuchFieldException, IllegalAccessException { 171 | //GIVEN 172 | 173 | //WHEN 174 | A a = new A(); 175 | a.c = 5; 176 | int b = (int) fieldC.getInt(a); 177 | 178 | //THEN 179 | assertThat(b, Is.is(originalFieldC.getInt(a))); 180 | assertThat(b, Is.is(a.c)); 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /generator/src/main/java/org/reflection_no_reflection/generator/annotation/AnnotationCreatorClassPoolVisitor.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.annotation; 2 | 3 | import com.squareup.javapoet.ArrayTypeName; 4 | import com.squareup.javapoet.ClassName; 5 | import com.squareup.javapoet.FieldSpec; 6 | import com.squareup.javapoet.JavaFile; 7 | import com.squareup.javapoet.MethodSpec; 8 | import com.squareup.javapoet.TypeName; 9 | import com.squareup.javapoet.TypeSpec; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import javax.lang.model.element.Modifier; 13 | import org.reflection_no_reflection.Annotation; 14 | import org.reflection_no_reflection.Class; 15 | import org.reflection_no_reflection.Field; 16 | import org.reflection_no_reflection.Method; 17 | import org.reflection_no_reflection.generator.introspector.IntrospectorUtil; 18 | import org.reflection_no_reflection.visit.ClassPoolVisitor; 19 | 20 | /** 21 | * @author SNI. 22 | */ 23 | public class AnnotationCreatorClassPoolVisitor implements ClassPoolVisitor { 24 | IntrospectorUtil util = new IntrospectorUtil(); 25 | 26 | private List> annotationClassList = new ArrayList<>(); 27 | private List javaFiles = new ArrayList<>(); 28 | private String targetPackageName; 29 | 30 | @Override public void visit(org.reflection_no_reflection.Class clazz) { 31 | if (clazz.isAnnotation()) { 32 | annotationClassList.add((Class) clazz); 33 | } 34 | } 35 | 36 | @Override public void visit(Field field) { 37 | 38 | } 39 | 40 | @Override public void visit(Method method) { 41 | 42 | } 43 | 44 | @Override public void visit(Annotation annotation) { 45 | 46 | } 47 | 48 | @Override public void visitAnnotationMethod(Annotation annotation, Method method) { 49 | 50 | } 51 | 52 | @Override public void endVisit(Class aClass) { 53 | 54 | } 55 | 56 | @Override public void endVisit(Annotation annotation) { 57 | 58 | } 59 | 60 | public List getJavaFiles() { 61 | javaFiles.clear(); 62 | for (Class aClass : annotationClassList) { 63 | JavaFile javaFile = buildAnnotationImpl(aClass); 64 | javaFiles.add(javaFile); 65 | } 66 | 67 | return javaFiles; 68 | } 69 | 70 | private JavaFile buildAnnotationImpl(Class annotationClass) { 71 | String aClassName = annotationClass.getName(); 72 | MethodSpec annotationTypeMethod = MethodSpec.methodBuilder("annotationType") 73 | .addModifiers(Modifier.PUBLIC, Modifier.FINAL) 74 | .returns(ClassName.get(java.lang.Class.class)) 75 | .addStatement("return $L.class", aClassName) 76 | .build(); 77 | 78 | TypeSpec.Builder annotationImplType = TypeSpec.classBuilder(annotationClass.getSimpleName() + "$$Impl") 79 | .addModifiers(Modifier.PUBLIC, Modifier.FINAL) 80 | .addSuperinterface(util.getClassName(annotationClass)) 81 | .addMethod(annotationTypeMethod); 82 | 83 | System.out.println("annotation methods " + annotationClass.getMethods().size()); 84 | System.out.println("annotation fields " + annotationClass.getFields().length); 85 | System.out.println("annotation " + annotationClass.toString()); 86 | 87 | for (Method method : annotationClass.getMethods()) { 88 | TypeName type; 89 | if (method.getReturnType().isArray()) { 90 | //important to use the component here as there is no method get(TypeName) 91 | //we fail to be detected as an array (see ArrayTypeName.get implementation) 92 | type = ArrayTypeName.of(util.getClassName(method.getReturnType().getComponentType())); 93 | } else { 94 | type = TypeName.get(method.getReturnType()); 95 | } 96 | FieldSpec field = FieldSpec.builder(type, method.getName(), Modifier.PRIVATE).build(); 97 | annotationImplType.addField(field); 98 | 99 | MethodSpec setterMethod = createSetterMethod(type, method.getName()); 100 | annotationImplType.addMethod(setterMethod); 101 | MethodSpec getterMethod = createGetterMethod(type, method.getName()); 102 | annotationImplType.addMethod(getterMethod); 103 | } 104 | 105 | return JavaFile.builder(targetPackageName, annotationImplType.build()).build(); 106 | } 107 | 108 | private MethodSpec createSetterMethod(TypeName type, String fieldName) { 109 | return createPrefixedMethod("set", fieldName) 110 | .addModifiers(Modifier.PUBLIC) 111 | .addParameter(type, fieldName) 112 | .addStatement("this.$L = $L", fieldName, fieldName) 113 | .build(); 114 | } 115 | 116 | private MethodSpec createGetterMethod(TypeName type, String fieldName) { 117 | return MethodSpec.methodBuilder(fieldName) 118 | .addModifiers(Modifier.PUBLIC) 119 | .returns(type) 120 | .addStatement("return $L", fieldName) 121 | .build(); 122 | } 123 | 124 | private MethodSpec.Builder createPrefixedMethod(String prefix, String fieldName) { 125 | final String capitalizedFieldName = util.createCapitalizedName(fieldName); 126 | String methodName = prefix + capitalizedFieldName; 127 | return MethodSpec.methodBuilder(methodName); 128 | } 129 | 130 | public void setTargetPackageName(String targetPackageName) { 131 | this.targetPackageName = targetPackageName; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /generator-integration-tests/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /processor/src/test/java/org/reflection_no_reflection/processor/MethodTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.processor; 2 | 3 | import java.lang.reflect.Modifier; 4 | import java.util.Set; 5 | import org.junit.Test; 6 | import org.reflection_no_reflection.Annotation; 7 | import org.reflection_no_reflection.Class; 8 | import org.reflection_no_reflection.Method; 9 | 10 | import static org.hamcrest.MatcherAssert.assertThat; 11 | import static org.hamcrest.core.Is.is; 12 | 13 | public class MethodTest extends AbstractRnRTest { 14 | @Test 15 | public void mapsSimpleAnnotatedMethod() throws ClassNotFoundException { 16 | javaSourceCode("test.Foo", // 17 | "package test;", // 18 | "public class Foo {",// 19 | "@Deprecated protected String s() {return \"foo\"; }", // 20 | "}" // 21 | ); 22 | 23 | setTargetAnnotations(new String[] {"java.lang.Deprecated"}); 24 | assertJavaSourceCompileWithoutError(); 25 | 26 | final Set annotatedClasses = getProcessedClasses(); 27 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 28 | 29 | final Class aClass = Class.forName("test.Foo"); 30 | assertThat(aClass.getMethods().size(), is(1)); 31 | 32 | final Method method = (Method) aClass.getMethods().get(0); 33 | final Method expected = new Method(aClass, "s", new Class[0], Class.forNameSafe("java.lang.String"), new Class[0], Modifier.PROTECTED); 34 | assertThat(method, is(expected)); 35 | assertThat(method.getModifiers(), is(Modifier.PROTECTED)); 36 | 37 | final java.lang.annotation.Annotation[] annotations = method.getAnnotations(); 38 | assertThat(annotations.length, is(1)); 39 | 40 | final Class deprecatedAnnotationClass = Class.forName("java.lang.Deprecated"); 41 | assertThat(((Annotation) annotations[0]).rnrAnnotationType(), is(deprecatedAnnotationClass)); 42 | assertThat(((Annotation)method.getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType(), is(deprecatedAnnotationClass)); 43 | } 44 | 45 | @Test 46 | public void mapsSimpleAnnotatedMethodWithParams() throws ClassNotFoundException { 47 | javaSourceCode("test.Foo", // 48 | "package test;", // 49 | "public class Foo {",// 50 | "@Deprecated protected String s(String a) {return a; }", // 51 | "}" // 52 | ); 53 | 54 | setTargetAnnotations(new String[] {"java.lang.Deprecated"}); 55 | assertJavaSourceCompileWithoutError(); 56 | 57 | final Set annotatedClasses = getProcessedClasses(); 58 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 59 | 60 | final Class expectedParamType = Class.forName("java.lang.String"); 61 | final Class aClass = Class.forName("test.Foo"); 62 | assertThat(aClass.getMethods().size(), is(1)); 63 | 64 | final Method method = (Method) aClass.getMethods().get(0); 65 | final Method expected = new Method(aClass, "s", new Class[] {expectedParamType}, Class.forNameSafe("java.lang.String"), new Class[0], Modifier.PROTECTED); 66 | assertThat(method, is(expected)); 67 | assertThat(method.getModifiers(), is(Modifier.PROTECTED)); 68 | 69 | final java.lang.annotation.Annotation[] annotations = method.getAnnotations(); 70 | assertThat(annotations.length, is(1)); 71 | 72 | final Class deprecatedAnnotationClass = Class.forName("java.lang.Deprecated"); 73 | assertThat(((Annotation) annotations[0]).rnrAnnotationType(), is(deprecatedAnnotationClass)); 74 | assertThat(((Annotation)method.getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType(), is(deprecatedAnnotationClass)); 75 | 76 | final Class[] paramTypes = method.getParameterTypes(); 77 | assertThat(paramTypes.length, is(1)); 78 | assertThat(paramTypes[0], is(expectedParamType)); 79 | 80 | assertThat(((Annotation)method.getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType(), is(deprecatedAnnotationClass)); 81 | } 82 | 83 | @Test 84 | public void mapsSimpleAnnotatedMethodWithException() throws ClassNotFoundException { 85 | javaSourceCode("test.Foo", // 86 | "package test;", // 87 | "public class Foo {",// 88 | "@Deprecated protected String s() throws Exception {throw new Exception(); }", // 89 | "}" // 90 | ); 91 | 92 | setTargetAnnotations(new String[] {"java.lang.Deprecated"}); 93 | assertJavaSourceCompileWithoutError(); 94 | 95 | final Set annotatedClasses = getProcessedClasses(); 96 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 97 | 98 | final Class expectedExceptionType = Class.forName("java.lang.Exception"); 99 | final Class aClass = Class.forName("test.Foo"); 100 | assertThat(aClass.getMethods().size(), is(1)); 101 | 102 | final Method method = (Method) aClass.getMethods().get(0); 103 | final Method expected = new Method(aClass, "s", new Class[0], Class.forNameSafe("java.lang.String"), new Class[] {expectedExceptionType}, Modifier.PROTECTED); 104 | assertThat(method, is(expected)); 105 | assertThat(method.getModifiers(), is(Modifier.PROTECTED)); 106 | 107 | final java.lang.annotation.Annotation[] annotations = method.getAnnotations(); 108 | assertThat(annotations.length, is(1)); 109 | 110 | final Class deprecatedAnnotationClass = Class.forName("java.lang.Deprecated"); 111 | assertThat(((Annotation) annotations[0]).rnrAnnotationType(), is(deprecatedAnnotationClass)); 112 | assertThat(((Annotation)method.getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType(), is(deprecatedAnnotationClass)); 113 | 114 | final Class[] exceptionTypes = method.getExceptionTypes(); 115 | assertThat(exceptionTypes.length, is(1)); 116 | assertThat(exceptionTypes[0], is(expectedExceptionType)); 117 | 118 | assertThat(((Annotation)method.getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType(), is(deprecatedAnnotationClass)); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /processor/src/test/java/org/reflection_no_reflection/processor/ConstructorTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.processor; 2 | 3 | import java.lang.reflect.Modifier; 4 | import java.util.Set; 5 | import org.junit.Test; 6 | import org.reflection_no_reflection.Annotation; 7 | import org.reflection_no_reflection.Class; 8 | import org.reflection_no_reflection.Constructor; 9 | 10 | import static org.hamcrest.MatcherAssert.assertThat; 11 | import static org.hamcrest.core.Is.is; 12 | 13 | public class ConstructorTest extends AbstractRnRTest { 14 | 15 | @Test 16 | public void mapsSimpleAnnotatedConstructor() throws ClassNotFoundException { 17 | javaSourceCode("test.Foo", // 18 | "package test;", // 19 | "public class Foo {",// 20 | "@Deprecated protected Foo() {}", // 21 | "}" // 22 | ); 23 | 24 | setTargetAnnotations(new String[] {"java.lang.Deprecated"}); 25 | assertJavaSourceCompileWithoutError(); 26 | 27 | final Set annotatedClasses = getProcessedClasses(); 28 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 29 | 30 | final Class aClass = Class.forName("test.Foo"); 31 | assertThat(aClass.getConstructors().size(), is(1)); 32 | 33 | final Constructor constructor = (Constructor) aClass.getConstructors().get(0); 34 | final Constructor expected = new Constructor(aClass, new Class[0], new Class[0], Modifier.PROTECTED); 35 | assertThat(constructor, is(expected)); 36 | assertThat(constructor.getModifiers(), is(Modifier.PROTECTED)); 37 | 38 | final java.lang.annotation.Annotation[] annotations = constructor.getAnnotations(); 39 | assertThat(annotations.length, is(1)); 40 | 41 | final Class deprecatedAnnotationClass = Class.forName("java.lang.Deprecated"); 42 | assertThat(((Annotation) annotations[0]).rnrAnnotationType(), is(deprecatedAnnotationClass)); 43 | assertThat(((Annotation)constructor.getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType(), is(deprecatedAnnotationClass)); 44 | } 45 | 46 | @Test 47 | public void mapsSimpleAnnotatedConstructorWithParams() throws ClassNotFoundException { 48 | javaSourceCode("test.Foo", // 49 | "package test;", // 50 | "public class Foo {",// 51 | "@Deprecated protected Foo(String a) {}", // 52 | "}" // 53 | ); 54 | 55 | setTargetAnnotations(new String[] {"java.lang.Deprecated"}); 56 | assertJavaSourceCompileWithoutError(); 57 | 58 | final Set annotatedClasses = getProcessedClasses(); 59 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 60 | 61 | final Class expectedParamType = Class.forName("java.lang.String"); 62 | final Class aClass = Class.forName("test.Foo"); 63 | assertThat(aClass.getConstructors().size(), is(1)); 64 | 65 | final Constructor constructor = (Constructor) aClass.getConstructors().get(0); 66 | final Constructor expected = new Constructor(aClass, new Class[] {expectedParamType}, new Class[0], Modifier.PROTECTED); 67 | assertThat(constructor, is(expected)); 68 | assertThat(constructor.getModifiers(), is(Modifier.PROTECTED)); 69 | 70 | final java.lang.annotation.Annotation[] annotations = constructor.getAnnotations(); 71 | assertThat(annotations.length, is(1)); 72 | 73 | final Class deprecatedAnnotationClass = Class.forName("java.lang.Deprecated"); 74 | assertThat(((Annotation) annotations[0]).rnrAnnotationType(), is(deprecatedAnnotationClass)); 75 | assertThat(((Annotation)constructor.getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType(), is(deprecatedAnnotationClass)); 76 | 77 | final Class[] paramTypes = constructor.getParameterTypes(); 78 | assertThat(paramTypes.length, is(1)); 79 | assertThat(paramTypes[0], is(expectedParamType)); 80 | 81 | assertThat(((Annotation)constructor.getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType(), is(deprecatedAnnotationClass)); 82 | } 83 | 84 | @Test 85 | public void mapsSimpleAnnotatedConstructorWithException() throws ClassNotFoundException { 86 | javaSourceCode("test.Foo", // 87 | "package test;", // 88 | "public class Foo {",// 89 | "@Deprecated protected Foo() throws Exception {throw new Exception(); }", // 90 | "}" // 91 | ); 92 | 93 | setTargetAnnotations(new String[] {"java.lang.Deprecated"}); 94 | assertJavaSourceCompileWithoutError(); 95 | 96 | final Set annotatedClasses = getProcessedClasses(); 97 | assertThat(annotatedClasses.contains(Class.forNameSafe("test.Foo")), is(true)); 98 | 99 | final Class expectedExceptionType = Class.forName("java.lang.Exception"); 100 | final Class aClass = Class.forName("test.Foo"); 101 | assertThat(aClass.getConstructors().size(), is(1)); 102 | 103 | final Constructor constructor = (Constructor) aClass.getConstructors().get(0); 104 | final Constructor expected = new Constructor(aClass, new Class[0], new Class[] {expectedExceptionType}, Modifier.PROTECTED); 105 | assertThat(constructor, is(expected)); 106 | assertThat(constructor.getModifiers(), is(Modifier.PROTECTED)); 107 | 108 | final java.lang.annotation.Annotation[] annotations = constructor.getAnnotations(); 109 | assertThat(annotations.length, is(1)); 110 | 111 | final Class deprecatedAnnotationClass = Class.forName("java.lang.Deprecated"); 112 | assertThat(((Annotation) annotations[0]).rnrAnnotationType(), is(deprecatedAnnotationClass)); 113 | assertThat(((Annotation)constructor.getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType(), is(deprecatedAnnotationClass)); 114 | 115 | final Class[] exceptionTypes = constructor.getExceptionTypes(); 116 | assertThat(exceptionTypes.length, is(1)); 117 | assertThat(exceptionTypes[0], is(expectedExceptionType)); 118 | 119 | assertThat(((Annotation)constructor.getAnnotation(deprecatedAnnotationClass)).rnrAnnotationType(), is(deprecatedAnnotationClass)); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /generator/src/test/java/org/reflection_no_reflection/generator/module/ModuleTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.module; 2 | 3 | import com.google.common.base.Joiner; 4 | import com.google.testing.compile.CompileTester; 5 | import com.google.testing.compile.JavaFileObjects; 6 | import java.util.Arrays; 7 | import javax.tools.JavaFileObject; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.reflection_no_reflection.generator.Generator; 11 | 12 | import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; 13 | import static org.truth0.Truth.ASSERT; 14 | 15 | public class ModuleTest { 16 | 17 | protected javax.annotation.processing.Processor processor; 18 | protected JavaFileObject javaSourceCode; 19 | protected JavaFileObject generatedSourceCode; 20 | 21 | @Before 22 | public void setup() { 23 | processor = new Generator(); 24 | javaSourceCode = null; 25 | generatedSourceCode = null; 26 | } 27 | 28 | @Test 29 | public void test() { 30 | javaSourceCode("test.Foo", // 31 | "package test;", // 32 | "public class Foo {",// 33 | "@javax.inject.Inject public String s;", // 34 | "@javax.inject.Inject public void m() {}", // 35 | "@javax.inject.Inject public int n() {return 4;}", // 36 | "}" // 37 | ); 38 | 39 | //generatedSourceCode("org.reflection_no_reflection.generator.sample.gen.ModuleImpl", 40 | // "package org.reflection_no_reflection.generator.sample.gen;", // 41 | // "", // 42 | // "import java.lang.Override;", // 43 | // "import java.util.ArrayList;", // 44 | // "import java.util.HashMap;", // 45 | // "import java.util.HashSet;", // 46 | // "import java.util.List;", // 47 | // "import java.util.Map;", // 48 | // "import java.util.Set;", // 49 | // "import org.reflection_no_reflection.Annotation;", // 50 | // "import org.reflection_no_reflection.Class;", // 51 | // "import org.reflection_no_reflection.Field;", // 52 | // "import org.reflection_no_reflection.runtime.Module;", // 53 | // "import test.Foo$$Reflector;", // 54 | // "", // 55 | // "public final class ModuleImpl implements Module {", // 56 | // " private Set classSet = new HashSet<>();", // 57 | // "", // 58 | // " private Map, Set> mapOfAnnotationTypeToClassesContainingAnnotation = new HashMap<>();", // 59 | // "", // 60 | // " public ModuleImpl() {", // 61 | // " Class c0 = Class.forNameSafe(\"test.Foo\");", // 62 | // " classSet.add(c0);", // 63 | // " Field f0 = new Field(\"s\",Class.forNameSafe(\"java.lang.String\"),c0,1,null);", // 64 | // " c0.addField(f0);", // 65 | // " {", // 66 | // " int indexAnnotation = 0;", // 67 | // " List annotationImplTab = new ArrayList(1);", // 68 | // " Class a0 = Class.forNameSafe(\"javax.inject.Inject\");", // 69 | // " a0.setModifiers(8192);", // 70 | // " classSet.add(a0);", // 71 | // " annotationImplTab.add(new Inject$$Impl());", // 72 | // " indexAnnotation++;", // 73 | // " f0.setAnnotationImplList(annotationImplTab);", // 74 | // " }", // 75 | // " c0.setReflector(new Foo$$Reflector());", // 76 | // " c0.setModifiers(0);", // 77 | // "", // 78 | // " Set s0 = new HashSet();", // 79 | // " s0.add(Class.forNameSafe(\"test.Foo\"));", // 80 | // " mapOfAnnotationTypeToClassesContainingAnnotation.put((Class) Class.forNameSafe(\"javax.inject.Inject\"),s0);", // 81 | // "", // 82 | // " }", // 83 | // "", // 84 | // " @Override", // 85 | // " public Set getClassSet() {", // 86 | // " return classSet;", // 87 | // " }", // 88 | // "", // 89 | // " public Map, Set> getMapOfAnnotationTypeToClassesContainingAnnotation() {", // 90 | // " return mapOfAnnotationTypeToClassesContainingAnnotation;", // 91 | // " }", // 92 | // "}"); 93 | 94 | //assertJavaSourceCompileWithoutErrorAndGenerateExpectedSource(); 95 | assertJavaSourceCompileWithoutError(); 96 | } 97 | 98 | protected void javaSourceCode(String fullyQualifiedName, String... source) { 99 | javaSourceCode = JavaFileObjects.forSourceString(fullyQualifiedName, Joiner.on('\n').join(source)); 100 | } 101 | 102 | protected void generatedSourceCode(String fullyQualifiedName, String... source) { 103 | generatedSourceCode = JavaFileObjects.forSourceString(fullyQualifiedName, Joiner.on('\n').join(source)); 104 | } 105 | 106 | protected Iterable rnrProcessors() { 107 | return Arrays.asList(processor); 108 | } 109 | 110 | protected CompileTester.SuccessfulCompilationClause assertJavaSourceCompileWithoutError() { 111 | return ASSERT.about(javaSource()) 112 | .that(javaSourceCode) 113 | .processedWith(rnrProcessors()) 114 | .compilesWithoutError(); 115 | } 116 | 117 | protected CompileTester.SuccessfulCompilationClause assertJavaSourceCompileWithoutErrorAndGenerateExpectedSource() { 118 | return assertJavaSourceCompileWithoutError() 119 | .and() 120 | .generatesSources(generatedSourceCode); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /generator/src/main/java/org/reflection_no_reflection/generator/introspector/IntrospectorFieldSetterMethodCreator.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.introspector; 2 | 3 | import com.squareup.javapoet.MethodSpec; 4 | import com.squareup.javapoet.ParameterSpec; 5 | import com.squareup.javapoet.TypeName; 6 | import javax.lang.model.element.Modifier; 7 | import org.reflection_no_reflection.*; 8 | import org.reflection_no_reflection.Class; 9 | 10 | import static org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor.BYTE_TYPE_NAME; 11 | import static org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor.SHORT_TYPE_NAME; 12 | import static org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor.INT_TYPE_NAME; 13 | import static org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor.LONG_TYPE_NAME; 14 | import static org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor.FLOAT_TYPE_NAME; 15 | import static org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor.DOUBLE_TYPE_NAME; 16 | import static org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor.CHAR_TYPE_NAME; 17 | import static org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor.BOOLEAN_TYPE_NAME; 18 | import static org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor.OBJECT_TYPE_NAME; 19 | import static org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor.STRING_TYPE_NAME; 20 | 21 | /** 22 | * @author SNI. 23 | */ 24 | public class IntrospectorFieldSetterMethodCreator { 25 | IntrospectorUtil util = new IntrospectorUtil(); 26 | 27 | public MethodSpec createSetObjectFieldMethod(org.reflection_no_reflection.Class aClass) { 28 | return createSetFieldMethod(aClass, OBJECT_TYPE_NAME, "setObjectField", false, new FieldEvaluator() { 29 | @Override public boolean accepts(Class clazz) { 30 | return !clazz.isPrimitive(); 31 | } 32 | }); 33 | } 34 | 35 | public MethodSpec createSetByteFieldMethod(Class aClass) { 36 | return createSetFieldMethod(aClass, BYTE_TYPE_NAME, "setByteField", true, new FieldEvaluator() { 37 | @Override public boolean accepts(Class clazz) { 38 | return clazz.isPrimitive() && clazz == Class.forNameSafe("byte"); 39 | } 40 | }); 41 | } 42 | 43 | public MethodSpec createSetShortFieldMethod(Class aClass) { 44 | return createSetFieldMethod(aClass, SHORT_TYPE_NAME, "setShortField", true, new FieldEvaluator() { 45 | @Override public boolean accepts(Class clazz) { 46 | return clazz.isPrimitive() && clazz == Class.forNameSafe("short"); 47 | } 48 | }); 49 | } 50 | 51 | public MethodSpec createSetIntFieldMethod(Class aClass) { 52 | return createSetFieldMethod(aClass, INT_TYPE_NAME, "setIntField", true, new FieldEvaluator() { 53 | @Override public boolean accepts(Class clazz) { 54 | return clazz.isPrimitive() && clazz == Class.forNameSafe("int"); 55 | } 56 | }); 57 | } 58 | 59 | public MethodSpec createSetLongFieldMethod(Class aClass) { 60 | return createSetFieldMethod(aClass, LONG_TYPE_NAME, "setLongField", true, new FieldEvaluator() { 61 | @Override public boolean accepts(Class clazz) { 62 | return clazz.isPrimitive() && clazz == Class.forNameSafe("long"); 63 | } 64 | }); 65 | } 66 | 67 | public MethodSpec createSetFloatFieldMethod(Class aClass) { 68 | return createSetFieldMethod(aClass, FLOAT_TYPE_NAME, "setFloatField", true, new FieldEvaluator() { 69 | @Override public boolean accepts(Class clazz) { 70 | return clazz.isPrimitive() && clazz == Class.forNameSafe("float"); 71 | } 72 | }); 73 | } 74 | 75 | public MethodSpec createSetDoubleFieldMethod(Class aClass) { 76 | return createSetFieldMethod(aClass, DOUBLE_TYPE_NAME, "setDoubleField", true, new FieldEvaluator() { 77 | @Override public boolean accepts(Class clazz) { 78 | return clazz.isPrimitive() && clazz == Class.forNameSafe("double"); 79 | } 80 | }); 81 | } 82 | 83 | public MethodSpec createSetCharFieldMethod(Class aClass) { 84 | return createSetFieldMethod(aClass, CHAR_TYPE_NAME, "setCharField", true, new FieldEvaluator() { 85 | @Override public boolean accepts(Class clazz) { 86 | return clazz.isPrimitive() && clazz == Class.forNameSafe("char"); 87 | } 88 | }); 89 | } 90 | 91 | public MethodSpec createSetBooleanFieldMethod(Class aClass) { 92 | return createSetFieldMethod(aClass, BOOLEAN_TYPE_NAME, "setBooleanField", true, new FieldEvaluator() { 93 | @Override public boolean accepts(Class clazz) { 94 | return clazz.isPrimitive() && clazz == Class.forNameSafe("boolean"); 95 | } 96 | }); 97 | } 98 | 99 | private MethodSpec createSetFieldMethod(Class aClass, TypeName paramTypeName, String methodName, boolean isPrimitive, FieldEvaluator evaluator) { 100 | boolean hasFieldOfThatType = false; 101 | ParameterSpec parameterSpec1 = ParameterSpec.builder(OBJECT_TYPE_NAME, "instance").build(); 102 | ParameterSpec parameterSpec2 = ParameterSpec.builder(STRING_TYPE_NAME, "name").build(); 103 | ParameterSpec parameterSpec3 = ParameterSpec.builder(paramTypeName, "value").build(); 104 | MethodSpec.Builder setFieldMethodBuilder = MethodSpec.methodBuilder(methodName) 105 | .addModifiers(Modifier.PUBLIC) 106 | .addAnnotation(Override.class) 107 | .addParameter(parameterSpec1) 108 | .addParameter(parameterSpec2) 109 | .addParameter(parameterSpec3) 110 | .addCode("switch(name) {\n"); 111 | 112 | for (Field field : aClass.getFields()) { 113 | if( evaluator.accepts(field.getType())) { 114 | hasFieldOfThatType = true; 115 | final TypeName enclosingClassName = util.getClassName(aClass); 116 | setFieldMethodBuilder 117 | .addCode("case($S) :\n", field.getName()); 118 | TypeName fieldTypeName = util.getClassName(field.getType()); 119 | if (isPrimitive) { 120 | setFieldMethodBuilder.addStatement("(($T) instance).$L = value", enclosingClassName, field.getName()); 121 | } else { 122 | setFieldMethodBuilder.addStatement("(($T) instance).$L = ($T) value", enclosingClassName, field.getName(), fieldTypeName); 123 | } 124 | setFieldMethodBuilder.addStatement("break"); 125 | } 126 | } 127 | 128 | if( !hasFieldOfThatType) { 129 | return null; 130 | } 131 | 132 | setFieldMethodBuilder.addCode("}\n"); 133 | return setFieldMethodBuilder.build(); 134 | } 135 | 136 | interface FieldEvaluator { 137 | boolean accepts(Class clazz); 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /generator/src/main/java/org/reflection_no_reflection/generator/introspector/IntrospectorDumperClassPoolVisitor.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.introspector; 2 | 3 | import com.squareup.javapoet.ClassName; 4 | import com.squareup.javapoet.JavaFile; 5 | import com.squareup.javapoet.MethodSpec; 6 | import com.squareup.javapoet.TypeName; 7 | import com.squareup.javapoet.TypeSpec; 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.Set; 13 | import java.util.regex.Pattern; 14 | import javax.lang.model.element.Modifier; 15 | import org.reflection_no_reflection.Annotation; 16 | import org.reflection_no_reflection.Class; 17 | import org.reflection_no_reflection.Field; 18 | import org.reflection_no_reflection.Method; 19 | import org.reflection_no_reflection.visit.ClassPoolVisitor; 20 | 21 | /** 22 | * @author SNI. 23 | */ 24 | public class IntrospectorDumperClassPoolVisitor implements ClassPoolVisitor { 25 | 26 | private List javaFiles = new ArrayList<>(); 27 | private List> classList = new ArrayList<>(); 28 | 29 | private Map, Set>> mapAnnotationTypeToClassContainingAnnotation = new HashMap<>(); 30 | public static final ClassName BASE_REFLECTOR_TYPE_NAME = ClassName.get("org.reflection_no_reflection.runtime", "BaseReflector"); 31 | public static final ClassName CLASS_TYPE_NAME = ClassName.get("org.reflection_no_reflection", "Class"); 32 | public static final ClassName OBJECT_TYPE_NAME = ClassName.get("java.lang", "Object"); 33 | public static final TypeName BYTE_TYPE_NAME = TypeName.get(byte.class); 34 | public static final TypeName SHORT_TYPE_NAME = TypeName.get(short.class); 35 | public static final TypeName INT_TYPE_NAME = TypeName.get(int.class); 36 | public static final TypeName LONG_TYPE_NAME = TypeName.get(long.class); 37 | public static final TypeName FLOAT_TYPE_NAME = TypeName.get(float.class); 38 | public static final TypeName DOUBLE_TYPE_NAME = TypeName.get(double.class); 39 | public static final TypeName CHAR_TYPE_NAME = TypeName.get(char.class); 40 | public static final TypeName BOOLEAN_TYPE_NAME = TypeName.get(boolean.class); 41 | public static final ClassName STRING_TYPE_NAME = ClassName.get("java.lang", "String"); 42 | private List includes; 43 | private List excludes; 44 | 45 | @Override 46 | public void visit(Class clazz) { 47 | //TODO add all protected java & android packages 48 | String className = clazz.getName(); 49 | boolean shouldIncludeClass = filter(className); 50 | System.out.println("Introspector for class:" + className + "=" + shouldIncludeClass); 51 | if (shouldIncludeClass) { 52 | classList.add(clazz); 53 | } 54 | } 55 | 56 | public boolean filter(String className) { 57 | if (className.indexOf('.') == -1) { 58 | return false; 59 | } 60 | 61 | boolean inIncludes = false; 62 | for (Pattern include : includes) { 63 | if (include.matcher(className).find()) { 64 | inIncludes = true; 65 | break; 66 | } 67 | } 68 | 69 | if (!inIncludes) { 70 | return false; 71 | } 72 | 73 | for (Pattern exclude : excludes) { 74 | if (exclude.matcher(className).find()) { 75 | return false; 76 | } 77 | } 78 | return true; 79 | } 80 | 81 | @Override public void visit(Field field) { 82 | 83 | } 84 | 85 | @Override public void visit(Method method) { 86 | 87 | } 88 | 89 | @Override public void visit(Annotation annotation) { 90 | 91 | } 92 | 93 | @Override public void visitAnnotationMethod(Annotation annotation, Method method) { 94 | 95 | } 96 | 97 | @Override public void endVisit(Class aClass) { 98 | 99 | } 100 | 101 | @Override public void endVisit(Annotation annotation) { 102 | 103 | } 104 | 105 | public Map, Set>> getMapAnnotationTypeToClassContainingAnnotation() { 106 | return mapAnnotationTypeToClassContainingAnnotation; 107 | } 108 | 109 | public List getJavaFiles() { 110 | javaFiles.clear(); 111 | for (Class aClass : classList) { 112 | JavaFile javaFile = buildReflector(aClass); 113 | javaFiles.add(javaFile); 114 | } 115 | 116 | return javaFiles; 117 | } 118 | 119 | private JavaFile buildReflector(Class aClass) { 120 | IntrospectorFieldSetterMethodCreator setterCreator = new IntrospectorFieldSetterMethodCreator(); 121 | IntrospectorMethodInvokerCreator methodInvokerCreator = new IntrospectorMethodInvokerCreator(); 122 | IntrospectorConstructorInvokerCreator constructorInvokerCreator = new IntrospectorConstructorInvokerCreator(); 123 | final MethodSpec setObjectFieldMethod = setterCreator.createSetObjectFieldMethod(aClass); 124 | final MethodSpec setByteFieldMethod = setterCreator.createSetByteFieldMethod(aClass); 125 | final MethodSpec setShortFieldMethod = setterCreator.createSetShortFieldMethod(aClass); 126 | final MethodSpec setIntFieldMethod = setterCreator.createSetIntFieldMethod(aClass); 127 | final MethodSpec setLongFieldMethod = setterCreator.createSetLongFieldMethod(aClass); 128 | final MethodSpec setFloatFieldMethod = setterCreator.createSetFloatFieldMethod(aClass); 129 | final MethodSpec setDoubleFieldMethod = setterCreator.createSetDoubleFieldMethod(aClass); 130 | final MethodSpec setCharFieldMethod = setterCreator.createSetCharFieldMethod(aClass); 131 | final MethodSpec setBooleanFieldMethod = setterCreator.createSetBooleanFieldMethod(aClass); 132 | 133 | final MethodSpec methodInvokerMethod = methodInvokerCreator.createMethodInvoker(aClass); 134 | final MethodSpec constructorInvokerMethod = constructorInvokerCreator.createConstructorInvoker(aClass); 135 | 136 | TypeSpec.Builder reflectorType = TypeSpec.classBuilder(aClass.getSimpleName() + "$$Reflector") 137 | .addModifiers(Modifier.PUBLIC, Modifier.FINAL) 138 | .superclass(BASE_REFLECTOR_TYPE_NAME); 139 | 140 | doAddMethod(reflectorType, setObjectFieldMethod); 141 | doAddMethod(reflectorType, setByteFieldMethod); 142 | doAddMethod(reflectorType, setShortFieldMethod); 143 | doAddMethod(reflectorType, setIntFieldMethod); 144 | doAddMethod(reflectorType, setLongFieldMethod); 145 | doAddMethod(reflectorType, setFloatFieldMethod); 146 | doAddMethod(reflectorType, setDoubleFieldMethod); 147 | doAddMethod(reflectorType, setCharFieldMethod); 148 | doAddMethod(reflectorType, setBooleanFieldMethod); 149 | doAddMethod(reflectorType, methodInvokerMethod); 150 | doAddMethod(reflectorType, constructorInvokerMethod); 151 | final String aClassName = aClass.getName(); 152 | return JavaFile.builder(aClassName.substring(0, aClassName.lastIndexOf('.')), reflectorType.build()).build(); 153 | } 154 | 155 | private void doAddMethod(TypeSpec.Builder reflectorType, MethodSpec methodSpec) { 156 | if (methodSpec != null) { 157 | reflectorType.addMethod(methodSpec); 158 | } 159 | } 160 | 161 | public void setIncludes(List includes) { 162 | this.includes = includes; 163 | } 164 | 165 | public void setExcludes(List excludes) { 166 | this.excludes = excludes; 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /generator/src/main/java/org/reflection_no_reflection/generator/Generator.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator; 2 | 3 | import com.squareup.javapoet.JavaFile; 4 | import java.io.IOException; 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.HashSet; 8 | import java.util.List; 9 | import java.util.Set; 10 | import java.util.regex.Pattern; 11 | import javax.annotation.processing.AbstractProcessor; 12 | import javax.annotation.processing.ProcessingEnvironment; 13 | import javax.annotation.processing.RoundEnvironment; 14 | import javax.annotation.processing.SupportedOptions; 15 | import javax.lang.model.SourceVersion; 16 | import javax.lang.model.element.TypeElement; 17 | import org.reflection_no_reflection.Class; 18 | import org.reflection_no_reflection.generator.annotation.AnnotationCreatorClassPoolVisitor; 19 | import org.reflection_no_reflection.generator.introspector.IntrospectorDumperClassPoolVisitor; 20 | import org.reflection_no_reflection.generator.module.ModuleDumperClassPoolVisitor; 21 | import org.reflection_no_reflection.processor.Processor; 22 | import org.reflection_no_reflection.visit.ClassPoolVisitStrategy; 23 | 24 | /** 25 | * An annotation processor sample that demonstrates how to use the RNR annotation processor. 26 | */ 27 | @SupportedOptions({"targetAnnotatedClasses", "maxLevel","targetPackageName", 28 | "introspector.includes","introspector.excludes"}) 29 | public class Generator extends AbstractProcessor { 30 | 31 | private String targetPackageName = null; 32 | private Processor processor = new Processor(); 33 | private ProcessingEnvironment processingEnv; 34 | 35 | private List introspectorIncludes; 36 | private List introspectorExcludes; 37 | 38 | @Override 39 | public synchronized void init(ProcessingEnvironment processingEnv) { 40 | this.processingEnv = processingEnv; 41 | //comma separated list of injected classes 42 | String annotatedClassesString = processingEnv.getOptions().get("targetAnnotatedClasses"); 43 | if (annotatedClassesString != null) { 44 | processor.setTargetAnnotatedClasses(new HashSet<>(Arrays.asList(annotatedClassesString.split(",")))); 45 | } 46 | 47 | String maxLevelString = processingEnv.getOptions().get("maxLevel"); 48 | if (maxLevelString != null) { 49 | processor.setMaxLevel(Integer.parseInt(maxLevelString)); 50 | } 51 | 52 | //introspector includes and excludes 53 | setIntrospectorIncludes(createPatterns(processingEnv, "introspector.includes")); 54 | setIntrospectorExcludes(createPatterns(processingEnv, "introspector.excludes")); 55 | 56 | String targetPackageNameString = processingEnv.getOptions().get("targetPackageName"); 57 | if (targetPackageNameString != null) { 58 | targetPackageName = targetPackageNameString; 59 | } 60 | 61 | Class.clearAllClasses(); 62 | 63 | processor.init(processingEnv); 64 | System.out.println("RNR Generator created."); 65 | } 66 | 67 | private List createPatterns(ProcessingEnvironment processingEnv, String option) { 68 | String patternString = processingEnv.getOptions().get(option); 69 | List patternList = new ArrayList<>(); 70 | if (patternString != null) { 71 | for (String pattern : patternString.split(",")) { 72 | patternList.add(Pattern.compile(pattern)); 73 | } 74 | } 75 | return patternList; 76 | } 77 | 78 | @Override 79 | public boolean process(Set annotations, RoundEnvironment roundEnv) { 80 | boolean processed = processor.process(annotations, roundEnv); 81 | 82 | if (annotations.isEmpty() || roundEnv.processingOver()) { 83 | //module creation 84 | Set annotatedClassSet = Class.getClassPool(); 85 | IntrospectorDumperClassPoolVisitor reflectorsDumper = new IntrospectorDumperClassPoolVisitor(); 86 | reflectorsDumper.setIncludes(introspectorIncludes); 87 | reflectorsDumper.setExcludes(introspectorExcludes); 88 | ModuleDumperClassPoolVisitor moduleDumper = new ModuleDumperClassPoolVisitor(reflectorsDumper); 89 | moduleDumper.setTargetPackageName(targetPackageName); 90 | moduleDumper.getMapAnnotationTypeToClassContainingAnnotation().putAll(processor.getMapAnnotationTypeToClassContainingAnnotation()); 91 | JavaFile rnRModuleJavaFile = createRnRModuleJavaFile(annotatedClassSet, moduleDumper); 92 | System.out.println("Dumping all collected data: \n"); 93 | printJavaFile(rnRModuleJavaFile); 94 | writeJavaFile(rnRModuleJavaFile); 95 | 96 | //reflectors creation 97 | ClassPoolVisitStrategy visitor = new ClassPoolVisitStrategy(); 98 | visitor.visit(annotatedClassSet, reflectorsDumper); 99 | 100 | for (JavaFile javaFile : reflectorsDumper.getJavaFiles()) { 101 | System.out.println("Dumping reflector: \n"); 102 | printJavaFile(javaFile); 103 | writeJavaFile(javaFile); 104 | } 105 | 106 | //annotation implementations creation 107 | AnnotationCreatorClassPoolVisitor annotationDumper = new AnnotationCreatorClassPoolVisitor(); 108 | annotationDumper.setTargetPackageName(targetPackageName); 109 | ClassPoolVisitStrategy visitor2 = new ClassPoolVisitStrategy(); 110 | final Set annotationClasses = processor.getAnnotationClasses(); 111 | visitor2.visit(annotationClasses, annotationDumper); 112 | 113 | for (JavaFile javaFile : annotationDumper.getJavaFiles()) { 114 | writeJavaFile(javaFile); 115 | System.out.println("Dumping Annotations implementations: \n"); 116 | printJavaFile(javaFile); 117 | } 118 | } 119 | return processed; 120 | } 121 | 122 | private void printJavaFile(JavaFile javaFile) { 123 | String buffer = javaFile.toString(); 124 | System.out.println(buffer); 125 | } 126 | 127 | private void writeJavaFile(JavaFile javaFile) { 128 | try { 129 | javaFile.writeTo(processingEnv.getFiler()); 130 | } catch (IOException e) { 131 | e.printStackTrace(); 132 | } 133 | } 134 | 135 | private JavaFile createRnRModuleJavaFile(Set annotatedClassSet, ModuleDumperClassPoolVisitor dumper) { 136 | ClassPoolVisitStrategy visitor = new ClassPoolVisitStrategy(); 137 | visitor.visit(annotatedClassSet, dumper); 138 | return dumper.getJavaFile(); 139 | } 140 | 141 | @Override 142 | public Set getSupportedAnnotationTypes() { 143 | return processor.getSupportedAnnotationTypes(); 144 | } 145 | 146 | @Override 147 | public SourceVersion getSupportedSourceVersion() { 148 | return processor.getSupportedSourceVersion(); 149 | } 150 | 151 | @Override 152 | public Set getSupportedOptions() { 153 | return processor.getSupportedOptions(); 154 | } 155 | 156 | public void setTargetAnnotatedClasses(Set targetAnnotatedClasses) { 157 | processor.setTargetAnnotatedClasses(targetAnnotatedClasses); 158 | } 159 | 160 | public void setIntrospectorIncludes(List introspectorIncludes) { 161 | this.introspectorIncludes = introspectorIncludes; 162 | } 163 | 164 | public void setIntrospectorExcludes(List introspectorExcludes) { 165 | this.introspectorExcludes = introspectorExcludes; 166 | } 167 | 168 | 169 | } 170 | -------------------------------------------------------------------------------- /generator-integration-tests/src/test/java/org/reflection_no_reflection/generator/sample/ClassTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.sample; 2 | 3 | import org.hamcrest.CoreMatchers; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | import org.reflection_no_reflection.Class; 7 | 8 | import static org.hamcrest.CoreMatchers.is; 9 | import static org.hamcrest.core.IsSame.sameInstance; 10 | import static org.junit.Assert.assertThat; 11 | 12 | public class ClassTest { 13 | 14 | @Before 15 | public void setUp() throws Exception { 16 | Class.clearAllClasses(); 17 | } 18 | 19 | @Test 20 | public void classesShouldBeUnique() throws Exception { 21 | //GIVEN 22 | final Class stringClass = Class.forNameSafe("java.lang.String"); 23 | 24 | //WHEN 25 | final Class stringClass2 = Class.forNameSafe("java.lang.String"); 26 | 27 | //THEN 28 | assertThat(stringClass2, sameInstance(stringClass)); 29 | } 30 | 31 | @Test 32 | public void classPoolContainsClasses() { 33 | //GIVEN 34 | final Class stringClass = Class.forNameSafe("java.lang.String"); 35 | 36 | //WHEN 37 | 38 | //THEN 39 | assertThat(Class.getClassPool().size() >= 1, is(true)); 40 | assertThat(Class.getClassPool().contains(stringClass), is(true)); 41 | } 42 | 43 | @Test 44 | public void classPoolCanBeCleared() throws Exception { 45 | //GIVEN 46 | final Class stringClass = Class.forNameSafe("java.lang.String"); 47 | 48 | //WHEN 49 | Class.clearAllClasses(); 50 | 51 | //THEN 52 | assertThat(Class.getClassPool().size(), is(0)); 53 | } 54 | 55 | @Test(expected = ClassNotFoundException.class) 56 | public void classForNameShouldFailIfClassDoesNotExist() throws Exception { 57 | //GIVEN 58 | //WHEN 59 | Class.forName("foo.bar.Qurtz"); 60 | 61 | //THEN 62 | } 63 | 64 | @Test 65 | public void classForNameSafeShouldNotFailIfClassDoesNotExist() { 66 | //GIVEN 67 | //WHEN 68 | final Class stringClass = Class.forNameSafe("java.lang.String"); 69 | //THEN 70 | } 71 | 72 | @Test 73 | public void primitiveClassesShouldBeWellDefined() { 74 | //GIVEN 75 | //WHEN 76 | final Class shortClass = Class.forNameSafe("short"); 77 | final Class byteClass = Class.forNameSafe("byte"); 78 | final Class intClass = Class.forNameSafe("int"); 79 | final Class longClass = Class.forNameSafe("long"); 80 | final Class floatClass = Class.forNameSafe("float"); 81 | final Class doubleClass = Class.forNameSafe("double"); 82 | final Class charClass = Class.forNameSafe("char"); 83 | final Class booleanClass = Class.forNameSafe("boolean"); 84 | final Class objectClass = Class.forNameSafe("java.lang.Object"); 85 | 86 | //THEN 87 | assertThat(shortClass.getName(),is("short")); 88 | assertThat(byteClass.getName(),is("byte")); 89 | assertThat(intClass.getName(),is("int")); 90 | assertThat(longClass.getName(),is("long")); 91 | assertThat(floatClass.getName(),is("float")); 92 | assertThat(doubleClass.getName(),is("double")); 93 | assertThat(charClass.getName(),is("char")); 94 | assertThat(booleanClass.getName(),is("boolean")); 95 | 96 | assertThat(shortClass.isPrimitive(),is(true)); 97 | assertThat(byteClass.isPrimitive(),is(true)); 98 | assertThat(intClass.isPrimitive(),is(true)); 99 | assertThat(longClass.isPrimitive(),is(true)); 100 | assertThat(floatClass.isPrimitive(),is(true)); 101 | assertThat(doubleClass.isPrimitive(),is(true)); 102 | assertThat(charClass.isPrimitive(),is(true)); 103 | assertThat(booleanClass.isPrimitive(),is(true)); 104 | assertThat(objectClass.isPrimitive(),is(false)); 105 | } 106 | 107 | @Test 108 | public void arrayClassesShouldBeWellDefined() { 109 | //GIVEN 110 | //WHEN 111 | final Class shortArrayClass = Class.forNameSafe("short[]"); 112 | final Class objectArrayClass = Class.forNameSafe("java.lang.Object[]"); 113 | final Class objectClass = Class.forNameSafe("java.lang.Object"); 114 | 115 | //THEN 116 | assertThat(shortArrayClass.getName(),is("short[]")); 117 | assertThat(objectArrayClass.getName(),is("java.lang.Object[]")); 118 | 119 | assertThat(shortArrayClass.isArray(),is(true)); 120 | assertThat(objectArrayClass.isArray(),is(true)); 121 | assertThat(objectClass.isArray(),is(false)); 122 | 123 | assertThat(shortArrayClass.getComponentType(), sameInstance((Class) Class.forNameSafe("short"))); 124 | assertThat(objectArrayClass.getComponentType(),sameInstance(objectClass)); 125 | } 126 | 127 | @Test 128 | public void array2DClassesShouldBeWellDefined() { 129 | //GIVEN 130 | //WHEN 131 | final Class shortArray2DClass = Class.forNameSafe("short[][]"); 132 | final Class objectArray2DClass = Class.forNameSafe("java.lang.Object[][]"); 133 | final Class shortArrayClass = Class.forNameSafe("short[]"); 134 | final Class objectArrayClass = Class.forNameSafe("java.lang.Object[]"); 135 | final Class objectClass = Class.forNameSafe("java.lang.Object"); 136 | 137 | //THEN 138 | assertThat(shortArray2DClass.getName(),is("short[][]")); 139 | assertThat(objectArray2DClass.getName(),is("java.lang.Object[][]")); 140 | 141 | assertThat(shortArray2DClass.isArray(),is(true)); 142 | assertThat(objectArray2DClass.isArray(),is(true)); 143 | 144 | assertThat(shortArray2DClass.getComponentType(), sameInstance(shortArrayClass)); 145 | assertThat(objectArray2DClass.getComponentType(),sameInstance(objectArrayClass)); 146 | assertThat(shortArrayClass.getComponentType(), sameInstance((Class) Class.forNameSafe("short"))); 147 | assertThat(objectArrayClass.getComponentType(),sameInstance(objectClass)); 148 | } 149 | 150 | @Test 151 | public void genericsClassesShouldBeWellDefined() { 152 | //GIVEN 153 | //WHEN 154 | final Class stringList = Class.forNameSafe("java.util.List"); 155 | 156 | //THEN 157 | assertThat(stringList.getName(),is("java.util.List")); 158 | } 159 | 160 | @Test 161 | public void isInstanceOfWorksForDirectInstances() { 162 | //GIVEN 163 | //WHEN 164 | final Class string = Class.forNameSafe("java.lang.String"); 165 | 166 | //THEN 167 | assertThat(string.isInstance("foo"),is(true)); 168 | } 169 | 170 | @Test 171 | public void isInstanceOfWorksForSubClasses() { 172 | //GIVEN 173 | 174 | 175 | //WHEN 176 | final Class fooClass = Class.forNameSafe("org.reflection_no_reflection.generator.sample.Foo"); 177 | final Class barClass = Class.forNameSafe("org.reflection_no_reflection.generator.sample.Bar"); 178 | 179 | //THEN 180 | Foo obj = new Foo(); 181 | assertThat(fooClass.isInstance(obj),is(true)); 182 | assertThat(barClass.isInstance(obj),is(true)); 183 | } 184 | 185 | @Test 186 | public void isInstanceOfWorksForClassesThatImplementInterface() { 187 | //GIVEN 188 | //WHEN 189 | final Class fooClass = Class.forNameSafe("org.reflection_no_reflection.generator.sample.Foo"); 190 | final Class qurtzClass = Class.forNameSafe("org.reflection_no_reflection.generator.sample.Qurtz"); 191 | 192 | //THEN 193 | Foo obj = new Foo(); 194 | assertThat(fooClass.isInstance(obj),is(true)); 195 | assertThat(qurtzClass.isInstance(obj),is(true)); 196 | } 197 | 198 | } 199 | -------------------------------------------------------------------------------- /generator-integration-tests/src/test/java/org/reflection_no_reflection/generator/sample/FieldTest.java: -------------------------------------------------------------------------------- 1 | package org.reflection_no_reflection.generator.sample; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | import org.reflection_no_reflection.Class; 6 | import org.reflection_no_reflection.Field; 7 | import org.reflection_no_reflection.runtime.Module; 8 | 9 | import static org.hamcrest.core.Is.is; 10 | import static org.junit.Assert.assertNotNull; 11 | import static org.junit.Assert.assertNull; 12 | import static org.junit.Assert.assertThat; 13 | 14 | public class FieldTest { 15 | 16 | @Before 17 | public void setUp() throws Exception { 18 | Class.clearAllClasses(); 19 | Module module = new org.reflection_no_reflection.generator.sample.gen.ModuleImpl(); 20 | Class.loadModule(module); 21 | } 22 | 23 | @Test 24 | public void shouldDetectAllFields() throws ClassNotFoundException { 25 | //GIVEN 26 | 27 | //WHEN 28 | Class classFoo = Class.forName("org.reflection_no_reflection.generator.sample.FieldTestCase"); 29 | 30 | //THEN 31 | assertNotNull(classFoo); 32 | 33 | final Field[] fields = classFoo.getFields(); 34 | assertNotNull(fields); 35 | assertThat(fields.length, is(11)); 36 | } 37 | 38 | @Test 39 | public void shouldReflectStringField() throws ClassNotFoundException { 40 | //GIVEN 41 | 42 | //WHEN 43 | Class classFoo = Class.forName("org.reflection_no_reflection.generator.sample.FieldTestCase"); 44 | 45 | //THEN 46 | final Field[] fields = classFoo.getFields(); 47 | final Field field = fields[0]; 48 | assertThat(field.getName(), is("a")); 49 | assertThat(field.getType().getName(), is("java.lang.String")); 50 | FieldTestCase fieldTestCase = new FieldTestCase(); 51 | assertNull(fieldTestCase.a); 52 | field.set(fieldTestCase, "foo"); 53 | assertThat(fieldTestCase.a, is("foo")); 54 | //TODO getter 55 | } 56 | 57 | @Test 58 | public void shouldReflectObjectField() throws ClassNotFoundException { 59 | //GIVEN 60 | 61 | //WHEN 62 | Class classFoo = Class.forName("org.reflection_no_reflection.generator.sample.FieldTestCase"); 63 | 64 | //THEN 65 | final Field[] fields = classFoo.getFields(); 66 | final Field field = fields[1]; 67 | assertThat(field.getName(), is("foo")); 68 | assertThat(field.getType().getName(), is("org.reflection_no_reflection.generator.sample.Foo")); 69 | FieldTestCase fieldTestCase = new FieldTestCase(); 70 | assertNull(fieldTestCase.foo); 71 | field.set(fieldTestCase, new Foo()); 72 | assertNotNull(fieldTestCase.foo); 73 | //TODO getter 74 | } 75 | 76 | @Test 77 | public void shouldReflectByteField() throws ClassNotFoundException { 78 | //GIVEN 79 | 80 | //WHEN 81 | Class classFoo = Class.forName("org.reflection_no_reflection.generator.sample.FieldTestCase"); 82 | 83 | //THEN 84 | final Field[] fields = classFoo.getFields(); 85 | final Field field = fields[2]; 86 | assertThat(field.getName(), is("c")); 87 | assertThat(field.getType().getName(), is("byte")); 88 | FieldTestCase fieldTestCase = new FieldTestCase(); 89 | assertThat(fieldTestCase.c, is((byte) 0)); 90 | field.setByte(fieldTestCase, (byte) 2); 91 | assertThat(fieldTestCase.c, is((byte) 2)); 92 | //TODO getter 93 | } 94 | 95 | @Test 96 | public void shouldReflectShortField() throws ClassNotFoundException { 97 | //GIVEN 98 | 99 | //WHEN 100 | Class classFoo = Class.forName("org.reflection_no_reflection.generator.sample.FieldTestCase"); 101 | 102 | //THEN 103 | final Field[] fields = classFoo.getFields(); 104 | final Field field = fields[3]; 105 | assertThat(field.getName(), is("d")); 106 | assertThat(field.getType().getName(), is("short")); 107 | FieldTestCase fieldTestCase = new FieldTestCase(); 108 | assertThat(fieldTestCase.d, is((short) 0)); 109 | field.setShort(fieldTestCase, (short) 2); 110 | assertThat(fieldTestCase.d, is((short)2)); 111 | //TODO getter 112 | } 113 | 114 | @Test 115 | public void shouldReflectIntField() throws ClassNotFoundException { 116 | //GIVEN 117 | 118 | //WHEN 119 | Class classFoo = Class.forName("org.reflection_no_reflection.generator.sample.FieldTestCase"); 120 | 121 | //THEN 122 | final Field[] fields = classFoo.getFields(); 123 | final Field field = fields[4]; 124 | assertThat(field.getName(), is("e")); 125 | assertThat(field.getType().getName(), is("int")); 126 | FieldTestCase fieldTestCase = new FieldTestCase(); 127 | assertThat(fieldTestCase.e, is(0)); 128 | field.setInt(fieldTestCase, 2); 129 | assertThat(fieldTestCase.e, is(2)); 130 | //TODO getter 131 | } 132 | 133 | @Test 134 | public void shouldReflectLongField() throws ClassNotFoundException { 135 | //GIVEN 136 | 137 | //WHEN 138 | Class classFoo = Class.forName("org.reflection_no_reflection.generator.sample.FieldTestCase"); 139 | 140 | //THEN 141 | final Field[] fields = classFoo.getFields(); 142 | final Field field = fields[5]; 143 | assertThat(field.getName(), is("f")); 144 | assertThat(field.getType().getName(), is("long")); 145 | FieldTestCase fieldTestCase = new FieldTestCase(); 146 | assertThat(fieldTestCase.f, is((long)0)); 147 | field.setLong(fieldTestCase, 2); 148 | assertThat(fieldTestCase.f, is((long)2)); 149 | //TODO getter 150 | } 151 | 152 | @Test 153 | public void shouldReflectFloatField() throws ClassNotFoundException { 154 | //GIVEN 155 | 156 | //WHEN 157 | Class classFoo = Class.forName("org.reflection_no_reflection.generator.sample.FieldTestCase"); 158 | 159 | //THEN 160 | final Field[] fields = classFoo.getFields(); 161 | final Field field = fields[6]; 162 | assertThat(field.getName(), is("g")); 163 | assertThat(field.getType().getName(), is("float")); 164 | FieldTestCase fieldTestCase = new FieldTestCase(); 165 | assertThat(fieldTestCase.g, is((float)0)); 166 | field.setFloat(fieldTestCase, 2f); 167 | assertThat(fieldTestCase.g, is((float)2)); 168 | //TODO getter 169 | } 170 | 171 | 172 | @Test 173 | public void shouldReflectDoubleField() throws ClassNotFoundException { 174 | //GIVEN 175 | 176 | //WHEN 177 | Class classFoo = Class.forName("org.reflection_no_reflection.generator.sample.FieldTestCase"); 178 | 179 | //THEN 180 | final Field[] fields = classFoo.getFields(); 181 | final Field field = fields[7]; 182 | assertThat(field.getName(), is("h")); 183 | assertThat(field.getType().getName(), is("double")); 184 | FieldTestCase fieldTestCase = new FieldTestCase(); 185 | assertThat(fieldTestCase.h, is((double)0)); 186 | field.setDouble(fieldTestCase, 2f); 187 | assertThat(fieldTestCase.h, is((double)2)); 188 | //TODO getter 189 | } 190 | 191 | @Test 192 | public void shouldReflectCharField() throws ClassNotFoundException { 193 | //GIVEN 194 | 195 | //WHEN 196 | Class classFoo = Class.forName("org.reflection_no_reflection.generator.sample.FieldTestCase"); 197 | 198 | //THEN 199 | final Field[] fields = classFoo.getFields(); 200 | final Field field = fields[8]; 201 | assertThat(field.getName(), is("i")); 202 | assertThat(field.getType().getName(), is("char")); 203 | FieldTestCase fieldTestCase = new FieldTestCase(); 204 | assertThat(fieldTestCase.i, is('\u0000')); 205 | field.setChar(fieldTestCase, 'a'); 206 | assertThat(fieldTestCase.i, is('a')); 207 | //TODO getter 208 | } 209 | 210 | @Test 211 | public void shouldReflectBooleanField() throws ClassNotFoundException { 212 | //GIVEN 213 | 214 | //WHEN 215 | Class classFoo = Class.forName("org.reflection_no_reflection.generator.sample.FieldTestCase"); 216 | 217 | //THEN 218 | final Field[] fields = classFoo.getFields(); 219 | final Field field = fields[9]; 220 | assertThat(field.getName(), is("j")); 221 | assertThat(field.getType().getName(), is("boolean")); 222 | FieldTestCase fieldTestCase = new FieldTestCase(); 223 | assertThat(fieldTestCase.j, is(false)); 224 | field.setBoolean(fieldTestCase, true); 225 | assertThat(fieldTestCase.j, is(true)); 226 | //TODO getter 227 | } 228 | 229 | @Test 230 | public void shouldReflectStringArrayField() throws ClassNotFoundException { 231 | //GIVEN 232 | 233 | //WHEN 234 | Class classFoo = Class.forName("org.reflection_no_reflection.generator.sample.FieldTestCase"); 235 | 236 | //THEN 237 | final Field[] fields = classFoo.getFields(); 238 | final Field field = fields[10]; 239 | assertThat(field.getName(), is("k")); 240 | assertThat(field.getType().getName(), is("java.lang.String[]")); 241 | FieldTestCase fieldTestCase = new FieldTestCase(); 242 | assertNull(fieldTestCase.k); 243 | field.set(fieldTestCase, new String[] {"3"}); 244 | assertNotNull(fieldTestCase.k); 245 | assertThat(fieldTestCase.k, is(new String[] {"3"})); 246 | //TODO getter 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | --------------------------------------------------------------------------------