Add param interceptors for @Rest by yDelouis · Pull Request #485 · androidannotations/androidannotations · GitHub
Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.net.URI;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;

Expand All @@ -33,6 +34,7 @@ public final class CanonicalNameConstants {
public static final String SQL_EXCEPTION = SQLException.class.getCanonicalName();
public static final String INTEGER = Integer.class.getCanonicalName();
public static final String BOOLEAN = Boolean.class.getCanonicalName();
public static final String ARRAYLIST = ArrayList.class.getCanonicalName();

/*
* Android
Expand Down Expand Up @@ -100,6 +102,7 @@ public final class CanonicalNameConstants {
public static final String HTTP_ENTITY = "org.springframework.http.HttpEntity";
public static final String REST_TEMPLATE = "org.springframework.web.client.RestTemplate";
public static final String HTTP_MESSAGE_CONVERTER = "org.springframework.http.converter.HttpMessageConverter";
public static final String CLIENT_HTTP_REQUEST_INTERCEPTOR = "org.springframework.http.client.ClientHttpRequestInterceptor";

/*
* RoboGuice
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static org.androidannotations.helper.AndroidConstants.LOG_INFO;
import static org.androidannotations.helper.AndroidConstants.LOG_VERBOSE;
import static org.androidannotations.helper.AndroidConstants.LOG_WARN;
import static org.androidannotations.helper.CanonicalNameConstants.CLIENT_HTTP_REQUEST_INTERCEPTOR;
import static org.androidannotations.helper.CanonicalNameConstants.HTTP_MESSAGE_CONVERTER;
import static org.androidannotations.helper.ModelConstants.GENERATION_SUFFIX;

Expand Down Expand Up @@ -1157,4 +1158,41 @@ public void validateConverters(Element element, IsValid valid) {
}

}

public void validateInterceptors(Element element, IsValid valid) {
TypeMirror clientHttpRequestInterceptorType = annotationHelper.typeElementFromQualifiedName(CLIENT_HTTP_REQUEST_INTERCEPTOR).asType();
TypeMirror clientHttpRequestInterceptorTypeErased = annotationHelper.getTypeUtils().erasure(clientHttpRequestInterceptorType);
List<DeclaredType> interceptors = annotationHelper.extractAnnotationClassArrayParameter(element, annotationHelper.getTarget(), "interceptors");
if(interceptors == null) {
return;
}
for (DeclaredType interceptorType : interceptors) {
TypeMirror erasedInterceptorType = annotationHelper.getTypeUtils().erasure(interceptorType);
if (annotationHelper.isSubtype(erasedInterceptorType, clientHttpRequestInterceptorTypeErased)) {
Element interceptorElement = interceptorType.asElement();
if (interceptorElement.getKind().isClass()) {
if (!annotationHelper.isAbstract(interceptorElement)) {
List<ExecutableElement> constructors = ElementFilter.constructorsIn(interceptorElement.getEnclosedElements());
for (ExecutableElement constructor : constructors) {
if (annotationHelper.isPublic(constructor) && constructor.getParameters().isEmpty()) {
return;
}
}
valid.invalidate();
annotationHelper.printAnnotationError(element, "The interceptor class must have a public no argument constructor");
} else {
valid.invalidate();
annotationHelper.printAnnotationError(element, "The interceptor class must not be abstract");
}
} else {
valid.invalidate();
annotationHelper.printAnnotationError(element, "The interceptor class must be a class");
}
} else {
valid.invalidate();
annotationHelper.printAnnotationError(element, "The interceptor class must be a subtype of " + CLIENT_HTTP_REQUEST_INTERCEPTOR);
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static com.sun.codemodel.JExpr._this;
import static com.sun.codemodel.JExpr.invoke;
import static com.sun.codemodel.JExpr.lit;
import static org.androidannotations.helper.CanonicalNameConstants.ARRAYLIST;
import static org.androidannotations.helper.CanonicalNameConstants.REST_TEMPLATE;
import static org.androidannotations.helper.CanonicalNameConstants.STRING;

Expand Down Expand Up @@ -101,6 +102,19 @@ public void process(Element element, JCodeModel codeModel, EBeansHolder eBeansHo
constructorBody.add(invoke(holder.restTemplateField, "getMessageConverters").invoke("add").arg(_new(converterClass)));
}
}

{
// Interceptors
List<DeclaredType> interceptors = annotationHelper.extractAnnotationClassArrayParameter(element, getTarget(), "interceptors");
if (interceptors != null) {
JClass listClass = eBeansHolder.refClass(ARRAYLIST);
constructorBody.add(invoke(holder.restTemplateField, "setInterceptors").arg(_new(listClass)));
for (DeclaredType interceptorType : interceptors) {
JClass interceptorClass = eBeansHolder.refClass(interceptorType.toString());
constructorBody.add(invoke(holder.restTemplateField, "getInterceptors").invoke("add").arg(_new(interceptorClass)));
}
}
}
constructorBody.assign(holder.rootUrlField, lit(typeElement.getAnnotation(Rest.class).rootUrl()));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ public boolean validate(Element element, AnnotationElements validatedElements) {

validatorHelper.validateConverters(element, valid);

validatorHelper.validateInterceptors(element, valid);

return valid.isValid();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* Copyright (C) 2010-2012 eBusiness Information, Excilys Group
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed To in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.androidannotations.rest;

import org.springframework.http.client.ClientHttpRequestInterceptor;

public abstract class AbstractInterceptor implements ClientHttpRequestInterceptor {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Copyright (C) 2010-2012 eBusiness Information, Excilys Group
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed To in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.androidannotations.rest;

import org.androidannotations.annotations.rest.Rest;

@Rest(converters = { AbstractInterceptor.class })
public interface ClientWithAbstractInterceptor {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright (C) 2010-2012 eBusiness Information, Excilys Group
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed To in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.androidannotations.rest;

import org.androidannotations.annotations.rest.Rest;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;

@Rest(converters = { MappingJacksonHttpMessageConverter.class }, interceptors = { Object.class })
public interface ClientWithNonInterceptor {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright (C) 2010-2012 eBusiness Information, Excilys Group
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed To in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.androidannotations.rest;

import org.androidannotations.annotations.rest.Rest;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;

@Rest(converters = { MappingJacksonHttpMessageConverter.class }, interceptors = { ValidInterceptor.class })
public interface ClientWithValidInterceptor {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright (C) 2010-2012 eBusiness Information, Excilys Group
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed To in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.androidannotations.rest;

import org.androidannotations.annotations.rest.Rest;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;

@Rest(converters = { MappingJacksonHttpMessageConverter.class }, interceptors = { WrongConstructorInterceptor.class })
public interface ClientWithWrongConstructorInterceptor {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* Copyright (C) 2010-2012 eBusiness Information, Excilys Group
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed To in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.androidannotations.rest;

import java.io.IOException;

import org.androidannotations.AndroidAnnotationProcessor;
import org.androidannotations.utils.AAProcessorTestHelper;
import org.junit.Before;
import org.junit.Test;

public class RestInterceptorTest extends AAProcessorTestHelper {

@Before
public void setup() {
addManifestProcessorParameter(RestInterceptorTest.class);
addProcessor(AndroidAnnotationProcessor.class);
}

@Test
public void client_with_valid_interceptor_compiles() {
CompileResult result = compileFiles(ClientWithValidInterceptor.class);
assertCompilationSuccessful(result);
}

@Test
public void client_with_abstract_interceptor_does_not_compile() throws IOException {
CompileResult result = compileFiles(ClientWithAbstractInterceptor.class);
assertCompilationErrorOn(ClientWithAbstractInterceptor.class, "@Rest", result);
}

@Test
public void client_with_non_interceptor_does_not_compile() throws IOException {
CompileResult result = compileFiles(ClientWithNonInterceptor.class);
assertCompilationErrorOn(ClientWithNonInterceptor.class, "@Rest", result);
}

@Test
public void client_with_wrong_constructor_interceptor_does_not_compile() throws IOException {
CompileResult result = compileFiles(ClientWithWrongConstructorInterceptor.class);
assertCompilationErrorOn(ClientWithWrongConstructorInterceptor.class, "@Rest", result);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.androidannotations.rest;

import java.io.IOException;

import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

public class ValidInterceptor implements ClientHttpRequestInterceptor {

@Override
public ClientHttpResponse intercept(HttpRequest arg0, byte[] arg1, ClientHttpRequestExecution arg2) throws IOException {
return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Copyright (C) 2010-2012 eBusiness Information, Excilys Group
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed To in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.androidannotations.rest;

import java.io.IOException;

import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

public class WrongConstructorInterceptor implements ClientHttpRequestInterceptor {

public WrongConstructorInterceptor(String someParam) {
this();
}

private WrongConstructorInterceptor() {

}

@Override
public ClientHttpResponse intercept(HttpRequest arg0, byte[] arg1, ClientHttpRequestExecution arg2) throws IOException {
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import org.androidannotations.api.rest.MediaType;

// if defined, the rootUrl will be added as a prefix to every request
@Rest(rootUrl = "http://company.com/ajax/services", converters = { MappingJacksonHttpMessageConverter.class })
@Rest(rootUrl = "http://company.com/ajax/services", converters = { MappingJacksonHttpMessageConverter.class }, interceptors = { RequestInterceptor.class })
public interface MyService {

// url variables are mapped to method parameter names.
Expand Down