ApiConfigAnnotationReader implements ApiConfigSource { @Override public void loadEndpointClass(ServiceContext serviceContext, Class<?> endpointClass, ApiConfig config) throws ApiConfigException { try { Annotation api = getDeclaredAnnotation(endpointClass, annotationTypes.get("Api")); Annotation apiClass = getDeclaredAnnotation(endpointClass, annotationTypes.get("ApiClass")); if (!readEndpointClass(config, endpointClass, api, apiClass, endpointClass)) { throw new ApiConfigException(endpointClass + " has no @Api annotation."); } } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException e) { throw new ApiConfigException(e); } } ApiConfigAnnotationReader();  ApiConfigAnnotationReader(Map<String, Class<? extends Annotation>> annotationTypes); @Override void loadEndpointClass(ServiceContext serviceContext, Class<?> endpointClass,
      ApiConfig config); @Override void loadEndpointMethods(ServiceContext serviceContext, Class<?> endpointClass,
      ApiClassConfig.MethodConfigMap methodConfigMap); @Override boolean isStaticConfig(ApiConfig config);  }
@Test public void testServiceWithOverridingInterfaceReference() throws Exception { ApiConfig config = createConfig(InterfaceReferenceEndpoint.class); annotationReader.loadEndpointClass(serviceContext, InterfaceReferenceEndpoint.class, config); assertEquals("interfaceBasedApi", config.getName()); assertEquals("v2", config.getVersion()); }
@Test public void testServiceWithSimpleReference() throws Exception { ApiConfig config = createConfig(SimpleReferenceEndpoint.class); annotationReader.loadEndpointClass(serviceContext, SimpleReferenceEndpoint.class, config); assertEquals("api", config.getName()); }
@Test public void testServiceWithApiNameOverride() throws Exception { ApiConfig config = createConfig(Endpoint4.class); annotationReader.loadEndpointClass(serviceContext, Endpoint4.class, config); assertEquals("api4", config.getName()); }
@Test public void testEndpointNoApiAnnotation() throws Exception { ApiConfig config = createConfig(Object.class); try { annotationReader.loadEndpointClass(serviceContext, Object.class, config); fail("No @Api annotation should've caused reader to fail."); } catch (ApiConfigException expected) { assertEquals("class java.lang.Object has no @Api annotation.", expected.getMessage()); } }
@Test public void testAbstract() throws Exception { @Api(isAbstract = AnnotationBoolean.TRUE) class Test {} ApiConfig config = createConfig(Test.class); annotationReader.loadEndpointClass(serviceContext, Test.class, config); assertTrue(config.getIsAbstract()); }
@Test public void testFrontendLimitsRulesNotDuplicatedInInheritance() throws Exception { @Api(frontendLimits = @ApiFrontendLimits( rules = {@ApiFrontendLimitRule(match = "test", qps = 1)})) class Test { } final class Child extends Test { } ApiConfig config = createConfig(Child.class); annotationReader.loadEndpointClass(serviceContext, Child.class, config); assertEquals(1, config.getFrontendLimitsConfig().getRules().size()); }
@Test public void testFrontendLimitsRuleWithSameMatchOverridesParentRule() throws Exception { @Api(frontendLimits = @ApiFrontendLimits( rules = {@ApiFrontendLimitRule(match = "test", qps = 1)})) class Test { } @Api(frontendLimits = @ApiFrontendLimits( rules = {@ApiFrontendLimitRule(match = "test", userQps = 1)})) final class Child extends Test { } ApiConfig config = createConfig(Child.class); annotationReader.loadEndpointClass(serviceContext, Child.class, config); assertEquals(1, config.getFrontendLimitsConfig().getRules().size()); FrontendLimitsRule rule = config.getFrontendLimitsConfig().getRules().get(0); assertEquals("test", rule.getMatch()); assertEquals(-1, rule.getQps()); assertEquals(1, rule.getUserQps()); }
@Test public void testReadParametersInApiNamespace() throws Exception { @Api class ValidNamespaceDefault {} ApiConfig config = createConfig(ValidNamespaceDefault.class); annotationReader.loadEndpointClass(serviceContext, ValidNamespaceDefault.class, config); @Api(namespace = @ApiNamespace(ownerDomain = "domain", ownerName = "")) class BadNamespaceEmptyName {} config = createConfig(BadNamespaceEmptyName.class); annotationReader.loadEndpointClass(serviceContext, BadNamespaceEmptyName.class, config); assertEquals("domain", config.getNamespaceConfig().getOwnerDomain()); @Api(namespace = @ApiNamespace(ownerDomain = "", ownerName = "name")) class BadNamespaceEmptyDomain {} config = createConfig(BadNamespaceEmptyDomain.class); annotationReader.loadEndpointClass(serviceContext, BadNamespaceEmptyDomain.class, config); assertEquals("name", config.getNamespaceConfig().getOwnerName()); @Api(namespace = @ApiNamespace(ownerDomain = "domain", ownerName = "name")) class ValidNamespaceEmptyPackage {} config = createConfig(ValidNamespaceEmptyPackage.class); annotationReader.loadEndpointClass(serviceContext, ValidNamespaceEmptyPackage.class, config); assertEquals("domain", config.getNamespaceConfig().getOwnerDomain()); assertEquals("name", config.getNamespaceConfig().getOwnerName()); @Api(namespace = @ApiNamespace( ownerDomain = "domain", ownerName = "name", packagePath = "package")) class ValidNamespaceFullySpecified {} config = createConfig(ValidNamespaceFullySpecified.class); annotationReader.loadEndpointClass(serviceContext, ValidNamespaceFullySpecified.class, config); assertEquals("domain", config.getNamespaceConfig().getOwnerDomain()); assertEquals("name", config.getNamespaceConfig().getOwnerName()); assertEquals("package", config.getNamespaceConfig().getPackagePath()); }
@Test public void testSimpleInheritanceCycleDetection() throws Exception { @ApiReference(Test1.Test2.class) final class Test1 { @ApiReference(Test1.class) final class Test2 {} } try { ApiConfig config = createConfig(Test1.class); annotationReader.loadEndpointClass(serviceContext, Test1.class, config); fail(); } catch (CyclicApiInheritanceException e) { } }
@Test public void testDeepInheritanceCycleDetection() throws Exception { @ApiReference(Test1.Test2.class) @Api(name = "Test1") final class Test1 { @ApiReference(Test2.Test3.class) final class Test2 { @ApiReference(Test3.Test4.class) @Api(name = "Test3") final class Test3 { @ApiReference(Test4.Test5.class) final class Test4 { @ApiReference(Test5.Test6.class) @Api(name = "Test5") final class Test5 { @ApiReference(Test6.Test7.class) final class Test6 { @ApiReference(Test7.Test8.class) @Api(name = "Test7") final class Test7 { @ApiReference(Test1.class) final class Test8 {} } } } } } } } try { ApiConfig config = createConfig(Test1.class); annotationReader.loadEndpointClass(serviceContext, Test1.class, config); fail(); } catch (CyclicApiInheritanceException e) { } }