From 0151060e78eaf22235e8d83f370cd4424665e2ea Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Sun, 3 Jun 2012 03:47:01 +0200 Subject: [PATCH 1/3] HttpsClient annotation Signed-off-by: Nabil Hachicha --- .../AndroidAnnotationProcessor.java | 9 +++++++-- .../helper/IdValidatorHelper.java | 7 +++++++ .../helper/TargetAnnotationHelper.java | 13 +++++++++++++ .../androidannotations/rclass/IRClass.java | 2 +- .../functional-test-1-5-tests/pom.xml | 7 +++++++ .../.settings/org.eclipse.jdt.apt.core.prefs | 2 +- .../functional-test-1-5/AndroidManifest.xml | 1 + androidannotations-dependencies/.classpath | 2 +- 8 files changed, 38 insertions(+), 5 deletions(-) diff --git a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/AndroidAnnotationProcessor.java b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/AndroidAnnotationProcessor.java index be03692b7b..94931e8c4c 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/AndroidAnnotationProcessor.java +++ b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/AndroidAnnotationProcessor.java @@ -54,6 +54,7 @@ import com.googlecode.androidannotations.annotations.FragmentByTag; import com.googlecode.androidannotations.annotations.FromHtml; import com.googlecode.androidannotations.annotations.Fullscreen; +import com.googlecode.androidannotations.annotations.HttpsClient; import com.googlecode.androidannotations.annotations.InstanceState; import com.googlecode.androidannotations.annotations.ItemClick; import com.googlecode.androidannotations.annotations.ItemLongClick; @@ -133,6 +134,7 @@ import com.googlecode.androidannotations.processing.FragmentByTagProcessor; import com.googlecode.androidannotations.processing.FromHtmlProcessor; import com.googlecode.androidannotations.processing.FullscreenProcessor; +import com.googlecode.androidannotations.processing.HttpsClientProcessor; import com.googlecode.androidannotations.processing.InstanceStateProcessor; import com.googlecode.androidannotations.processing.ItemClickProcessor; import com.googlecode.androidannotations.processing.ItemLongClickProcessor; @@ -190,6 +192,7 @@ import com.googlecode.androidannotations.validation.FragmentByTagValidator; import com.googlecode.androidannotations.validation.FromHtmlValidator; import com.googlecode.androidannotations.validation.FullscreenValidator; +import com.googlecode.androidannotations.validation.HttpsClientValidator; import com.googlecode.androidannotations.validation.InstanceStateValidator; import com.googlecode.androidannotations.validation.ItemClickValidator; import com.googlecode.androidannotations.validation.ItemLongClickValidator; @@ -291,8 +294,8 @@ FragmentByTag.class, // BeforeTextChange.class, // TextChange.class, // - AfterTextChange.class // -}) + AfterTextChange.class, // + HttpsClient.class }) @SupportedSourceVersion(SourceVersion.RELEASE_6) public class AndroidAnnotationProcessor extends AnnotatedAbstractProcessor { @@ -460,6 +463,7 @@ private ModelValidator buildModelValidator(IRClass rClass, AndroidSystemServices modelValidator.register(new BeforeTextChangeValidator(processingEnv, rClass)); modelValidator.register(new TextChangeValidator(processingEnv, rClass)); modelValidator.register(new AfterTextChangeValidator(processingEnv, rClass)); + modelValidator.register(new HttpsClientValidator(processingEnv, rClass)); return modelValidator; } @@ -538,6 +542,7 @@ private ModelProcessor buildModelProcessor(IRClass rClass, AndroidSystemServices modelProcessor.register(new TextChangeProcessor(processingEnv, rClass)); modelProcessor.register(new BeforeTextChangeProcessor(processingEnv, rClass)); modelProcessor.register(new AfterTextChangeProcessor(processingEnv, rClass)); + modelProcessor.register(new HttpsClientProcessor()); return modelProcessor; } diff --git a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/helper/IdValidatorHelper.java b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/helper/IdValidatorHelper.java index 45d859fb25..141caf6f60 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/helper/IdValidatorHelper.java +++ b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/helper/IdValidatorHelper.java @@ -49,6 +49,13 @@ public void idExists(Element element, Res res, boolean defaultUseName, boolean a idExists(element, res, defaultUseName, allowDefault, valid, idValue); } + public void idExists(Element element, Res res, boolean defaultUseName, boolean allowDefault, IsValid valid, String methodName) { + + Integer idValue = annotationHelper.extractAnnotationValue(element, methodName); + + idExists(element, res, defaultUseName, allowDefault, valid, idValue); + } + public void idsExists(Element element, Res res, IsValid valid) { int[] idsValues = annotationHelper.extractAnnotationValue(element); diff --git a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/helper/TargetAnnotationHelper.java b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/helper/TargetAnnotationHelper.java index 90f1b777ed..536e15624d 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/helper/TargetAnnotationHelper.java +++ b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/helper/TargetAnnotationHelper.java @@ -48,6 +48,19 @@ public T extractAnnotationValue(Element element) { } } + @SuppressWarnings("unchecked") + public T extractAnnotationValue(Element element, String methodName) { + Annotation annotation = element.getAnnotation(target); + + Method method; + try { + method = annotation.getClass().getMethod(methodName); + return (T) method.invoke(annotation); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + public DeclaredType extractAnnotationClassValue(Element element) { AnnotationMirror annotationMirror = findAnnotationMirror(element, target); diff --git a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/rclass/IRClass.java b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/rclass/IRClass.java index 46ca74e137..6cb0b65436 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/rclass/IRClass.java +++ b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/rclass/IRClass.java @@ -18,7 +18,7 @@ public interface IRClass { public enum Res { - LAYOUT, ID, STRING, ARRAY, COLOR, ANIM, BOOL, DIMEN, DRAWABLE, INTEGER, MOVIE, MENU; + LAYOUT, ID, STRING, ARRAY, COLOR, ANIM, BOOL, DIMEN, DRAWABLE, INTEGER, MOVIE, MENU, RAW; public String rName() { return toString().toLowerCase(); } diff --git a/AndroidAnnotations/functional-test-1-5-tests/pom.xml b/AndroidAnnotations/functional-test-1-5-tests/pom.xml index a08842b740..4979f3a950 100644 --- a/AndroidAnnotations/functional-test-1-5-tests/pom.xml +++ b/AndroidAnnotations/functional-test-1-5-tests/pom.xml @@ -46,6 +46,13 @@ junit test + + + bouncycastle + bcprov-jdk16 + 140 + + diff --git a/AndroidAnnotations/functional-test-1-5/.settings/org.eclipse.jdt.apt.core.prefs b/AndroidAnnotations/functional-test-1-5/.settings/org.eclipse.jdt.apt.core.prefs index ef6fa98563..82e4e67c34 100644 --- a/AndroidAnnotations/functional-test-1-5/.settings/org.eclipse.jdt.apt.core.prefs +++ b/AndroidAnnotations/functional-test-1-5/.settings/org.eclipse.jdt.apt.core.prefs @@ -1,5 +1,5 @@ eclipse.preferences.version=1 org.eclipse.jdt.apt.aptEnabled=true -org.eclipse.jdt.apt.genSrcDir=.apt_generated +org.eclipse.jdt.apt.genSrcDir=.apt_generatedd org.eclipse.jdt.apt.processorOptions/trace=true org.eclipse.jdt.apt.reconcileEnabled=true diff --git a/AndroidAnnotations/functional-test-1-5/AndroidManifest.xml b/AndroidAnnotations/functional-test-1-5/AndroidManifest.xml index 015f6ff043..0a7f9d9802 100644 --- a/AndroidAnnotations/functional-test-1-5/AndroidManifest.xml +++ b/AndroidAnnotations/functional-test-1-5/AndroidManifest.xml @@ -63,6 +63,7 @@ + diff --git a/androidannotations-dependencies/.classpath b/androidannotations-dependencies/.classpath index d05ca50cfe..539a980637 100644 --- a/androidannotations-dependencies/.classpath +++ b/androidannotations-dependencies/.classpath @@ -3,6 +3,6 @@ - + From afc3e43292d3a73d44b709246d01fb9ea9d53613 Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Sun, 3 Jun 2012 04:22:04 +0200 Subject: [PATCH 2/3] HttpsClient Annotation Signed-off-by: Nabil Hachicha --- .../annotations/HttpsClient.java | 72 +++++++ .../processing/HttpsClientProcessor.java | 188 ++++++++++++++++++ .../validation/HttpsClientValidator.java | 61 ++++++ .../test15/SSLConnectionTest.java | 70 +++++++ .../functional-test-1-5/res/raw/cacerts.bks | Bin 0 -> 61391 bytes .../test15/SSLConnection.java | 22 ++ 6 files changed, 413 insertions(+) create mode 100644 AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/annotations/HttpsClient.java create mode 100644 AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/HttpsClientProcessor.java create mode 100644 AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/validation/HttpsClientValidator.java create mode 100644 AndroidAnnotations/functional-test-1-5-tests/src/test/java/com/googlecode/androidannotations/test15/SSLConnectionTest.java create mode 100644 AndroidAnnotations/functional-test-1-5/res/raw/cacerts.bks create mode 100644 AndroidAnnotations/functional-test-1-5/src/main/java/com/googlecode/androidannotations/test15/SSLConnection.java diff --git a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/annotations/HttpsClient.java b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/annotations/HttpsClient.java new file mode 100644 index 0000000000..e0be059f60 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/annotations/HttpsClient.java @@ -0,0 +1,72 @@ +/** + * Copyright (C) 2010-2011 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 com.googlecode.androidannotations.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Use this annotation to get an HttpClient instance with the specified KeyStore + * and TrustStore configured to perform an HTTPS request
+ *
+ * + * All the parameters are optional
+ *
+ * + * trustStore: int, Resource id of your trust store file ex + * R.raw.cacerts.bks Typically your servers trusted certificates + * (public key, Root Chain Authority etc)
+ *
+ * + * trustStorePwd: String, Your trust store password (default is + * changeit)
+ *
+ * + * keyStore: int, Resource id of your keystore Usually your private key + * (client certificate)
+ *
+ * + * keyStorePwd: String, Your KeyStore password (default is + * changeit)
+ *
+ * + * hostnameVerif: boolean, Turn on or off strict hostname verification + * (default false) Hostname in certificate (DN) must match the URL.
+ *
+ * + * Note: + * Until ICS, Android accept [Key|Trust]store only in BKS format + * (Bouncycastle Key Store) + * + * @author Nabil Hachicha + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.FIELD) +public @interface HttpsClient { + public static final String DEFAULT_PASSWD = "changeit"; + + int trustStore() default Id.DEFAULT_VALUE; + + String trustStorePwd() default DEFAULT_PASSWD; + + int keyStore() default Id.DEFAULT_VALUE; + + String keyStorePwd() default DEFAULT_PASSWD; + + boolean hostnameVerif() default false; +} \ No newline at end of file diff --git a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/HttpsClientProcessor.java b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/HttpsClientProcessor.java new file mode 100644 index 0000000000..ea3053226a --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/HttpsClientProcessor.java @@ -0,0 +1,188 @@ +/** + * Copyright (C) 2010-2011 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. + * + * @author Nabil Hachicha + */ +package com.googlecode.androidannotations.processing; + +import java.lang.annotation.Annotation; + +import javax.lang.model.element.Element; + +import com.googlecode.androidannotations.annotations.HttpsClient; +import com.googlecode.androidannotations.annotations.Id; +import com.sun.codemodel.JBlock; +import com.sun.codemodel.JCatchBlock; +import com.sun.codemodel.JClass; +import com.sun.codemodel.JCodeModel; +import com.sun.codemodel.JDefinedClass; +import com.sun.codemodel.JExpr; +import com.sun.codemodel.JExpression; +import com.sun.codemodel.JInvocation; +import com.sun.codemodel.JMethod; +import com.sun.codemodel.JMod; +import com.sun.codemodel.JTryBlock; +import com.sun.codemodel.JVar; + +public class HttpsClientProcessor implements ElementProcessor { + + public HttpsClientProcessor() { + } + + @Override + public Class getTarget() { + return HttpsClient.class; + } + + @Override + public void process(Element element, JCodeModel codeModel, EBeansHolder eBeansHolder) { + EBeanHolder holder = eBeansHolder.getEnclosingEBeanHolder(element); + + int trustStoreFile = element.getAnnotation(HttpsClient.class).trustStore(); + String trustStorePwd = element.getAnnotation(HttpsClient.class).trustStorePwd(); + + int keyStoreFile = element.getAnnotation(HttpsClient.class).keyStore(); + String keyStorePwd = element.getAnnotation(HttpsClient.class).keyStorePwd(); + + boolean hostnameVerif = element.getAnnotation(HttpsClient.class).hostnameVerif(); + + boolean useCustomTrustStore = Id.DEFAULT_VALUE != trustStoreFile ? true : false; + boolean useCustomKeyStore = Id.DEFAULT_VALUE != keyStoreFile ? true : false; + + String fieldName = element.getSimpleName().toString(); + JBlock methodBody = holder.init.body(); + + JClass jTypeRetMethod = holder.refClass("org.apache.http.conn.ClientConnectionManager"); + JClass jTypeDefHttp = holder.refClass("org.apache.http.impl.client.DefaultHttpClient"); + JClass jTypeKeyStore = holder.refClass("java.security.KeyStore"); + JClass jTypeRes = holder.refClass("android.content.res.Resources"); + JClass jTypeInputStream = holder.refClass("java.io.InputStream"); + + JDefinedClass jAnonClass = codeModel.anonymousClass(jTypeDefHttp); + + JMethod method = jAnonClass.method(JMod.PROTECTED, jTypeRetMethod, "createClientConnectionManager"); + method.annotate(Override.class); + + JTryBlock jTryBlock = method.body()._try(); + JVar jVarTrusted = null; + JVar jVarKeystore = null; + + if (useCustomKeyStore) { + jVarKeystore = jTryBlock.body().decl(jTypeKeyStore, "keystore"); + jVarKeystore.init(jTypeKeyStore.staticInvoke("getInstance").arg("BKS")); + } + + if (useCustomTrustStore || !useCustomTrustStore && useCustomKeyStore/* + * use + * default + * trust + * store + */) { + jVarTrusted = jTryBlock.body().decl(jTypeKeyStore, "trusted"); + jVarTrusted.init(jTypeKeyStore.staticInvoke("getInstance").arg("BKS")); + + } + + JVar jVarRes = null; + JVar jVarTrstFile = null; + JVar jVarKeyFile = null; + + if (useCustomKeyStore || useCustomTrustStore) { + jVarRes = jTryBlock.body().decl(jTypeRes, "res", JExpr.invoke("getResources")); + } + + if (useCustomKeyStore) { + JInvocation jInvRawKey = jVarRes.invoke("openRawResource").arg(JExpr.lit(keyStoreFile)); + jVarKeyFile = jTryBlock.body().decl(jTypeInputStream, "inKeystore", jInvRawKey); + } + + if (useCustomTrustStore) { + JInvocation jInvRawTrust = jVarRes.invoke("openRawResource").arg(JExpr.lit(trustStoreFile)); + jVarTrstFile = jTryBlock.body().decl(jTypeInputStream, "inTrustStore", jInvRawTrust); + + } else if (useCustomKeyStore) { + JClass jTypeFileInputStream = holder.refClass("java.io.FileInputStream"); + jVarTrstFile = jTryBlock.body().decl(jTypeInputStream, "inTrustStore", JExpr._new(jTypeFileInputStream).arg("/system/etc/security/cacerts.bks")); + } + + // try load + if (useCustomKeyStore || useCustomTrustStore) { + JTryBlock jTryLoad = jTryBlock.body()._try(); + + if (useCustomKeyStore) { + jTryLoad.body().add(JExpr.invoke(jVarKeystore, "load").arg(jVarKeyFile).arg(JExpr.invoke(JExpr.lit(keyStorePwd), "toCharArray"))); + } + + if (useCustomTrustStore || !useCustomTrustStore && useCustomKeyStore) { + jTryLoad.body().add(JExpr.invoke(jVarTrusted, "load").arg(jVarTrstFile).arg(JExpr.invoke(JExpr.lit(trustStorePwd), "toCharArray"))); + } + // finally load + JBlock jFinally = jTryLoad._finally(); + if (useCustomKeyStore) { + jFinally.add(JExpr.invoke(jVarKeyFile, "close")); + } + + if (useCustomTrustStore || !useCustomTrustStore && useCustomKeyStore) { + jFinally.add(JExpr.invoke(jVarTrstFile, "close")); + } + } + + if (null == jVarKeystore && null == jVarTrusted) { + JVar jVarCcm = jTryBlock.body().decl(jTypeRetMethod, "ccm"); + jVarCcm.init(JExpr._super().invoke("createClientConnectionManager")); + + if (!hostnameVerif) { + JClass jTypeSocketFact = holder.refClass("org.apache.http.conn.ssl.SSLSocketFactory"); + JExpression jCast = JExpr.cast(jTypeSocketFact, jVarCcm.invoke("getSchemeRegistry").invoke("getScheme").arg("https").invoke("getSocketFactory")); + JClass jTypeSslFact = holder.refClass("org.apache.http.conn.ssl.SSLSocketFactory"); + jTryBlock.body().add(jCast.invoke("setHostnameVerifier").arg(jTypeSslFact.staticRef("ALLOW_ALL_HOSTNAME_VERIFIER"))); + } + + jTryBlock.body()._return(jVarCcm); + + } else { + JClass jTypeSslFact = holder.refClass("org.apache.http.conn.ssl.SSLSocketFactory"); + JClass jTypeScheme = holder.refClass("org.apache.http.conn.scheme.Scheme"); + JClass jTypeSchemeReg = holder.refClass("org.apache.http.conn.scheme.SchemeRegistry"); + JClass jTypeSingleConnMgr = holder.refClass("org.apache.http.impl.conn.SingleClientConnManager"); + + JVar jVarSslFact = jTryBlock.body().decl(jTypeSslFact, "newSslSocketFactory"); + jVarSslFact.init(JExpr._new(jTypeSslFact).arg(null == jVarKeystore ? JExpr._null() : jVarKeystore).arg(keyStorePwd).arg(null == jVarTrusted ? JExpr._null() : jVarTrusted)); + + if (!hostnameVerif) { + jTryBlock.body().add(JExpr.invoke(jVarSslFact, "setHostnameVerifier").arg(jTypeSslFact.staticRef("ALLOW_ALL_HOSTNAME_VERIFIER"))); + } + + JVar jVarSchemeReg = jTryBlock.body().decl(jTypeSchemeReg, "registry"); + jVarSchemeReg.init(JExpr._new(jTypeSchemeReg)); + jTryBlock.body().add(JExpr.invoke(jVarSchemeReg, "register").arg(JExpr._new(jTypeScheme).arg("https").arg(jVarSslFact).arg(JExpr.lit(443)))); + + JVar jVarCcm = jTryBlock.body().decl(jTypeRetMethod, "ccm"); + jVarCcm.init(JExpr._new(jTypeSingleConnMgr).arg(JExpr.invoke("getParams")).arg(jVarSchemeReg)); + jTryBlock.body()._return(jVarCcm); + } + + // catch block + JClass jTypeException = holder.refClass("java.lang.Exception"); + JCatchBlock jCatchBlock = jTryBlock._catch(jTypeException); + JVar jVarExceptionParam = jCatchBlock.param("e"); + jCatchBlock.body().add(jVarExceptionParam.invoke("printStackTrace")); + jCatchBlock.body()._return(JExpr._super().invoke("createClientConnectionManager")); + + methodBody.assign(JExpr.ref(fieldName), JExpr._new(jAnonClass)); + + } + +} diff --git a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/validation/HttpsClientValidator.java b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/validation/HttpsClientValidator.java new file mode 100644 index 0000000000..be977908a1 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/validation/HttpsClientValidator.java @@ -0,0 +1,61 @@ +/** + * Copyright (C) 2010-2011 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. + * + * @author Nabil Hachicha + */ +package com.googlecode.androidannotations.validation; + +import java.lang.annotation.Annotation; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; + +import com.googlecode.androidannotations.annotations.HttpsClient; +import com.googlecode.androidannotations.helper.IdAnnotationHelper; +import com.googlecode.androidannotations.helper.IdValidatorHelper; +import com.googlecode.androidannotations.model.AnnotationElements; +import com.googlecode.androidannotations.rclass.IRClass; +import com.googlecode.androidannotations.rclass.IRClass.Res; + +public class HttpsClientValidator implements ElementValidator { + + private IdValidatorHelper validatorHelper; + + public HttpsClientValidator(ProcessingEnvironment processingEnv, IRClass rClass) { + IdAnnotationHelper annotationHelper = new IdAnnotationHelper(processingEnv, getTarget(), rClass); + validatorHelper = new IdValidatorHelper(annotationHelper); + } + + @Override + public Class getTarget() { + return HttpsClient.class; + } + + @Override + public boolean validate(Element element, AnnotationElements validatedElements) { + + IsValid valid = new IsValid(); + + validatorHelper.enclosingElementHasEnhancedComponentAnnotation(element, validatedElements, valid); + + validatorHelper.idExists(element, Res.RAW, false, true, valid, "keyStore"); + validatorHelper.idExists(element, Res.RAW, false, true, valid, "trustStore"); + + validatorHelper.isNotPrivate(element, valid); + + return valid.isValid(); + } + +} diff --git a/AndroidAnnotations/functional-test-1-5-tests/src/test/java/com/googlecode/androidannotations/test15/SSLConnectionTest.java b/AndroidAnnotations/functional-test-1-5-tests/src/test/java/com/googlecode/androidannotations/test15/SSLConnectionTest.java new file mode 100644 index 0000000000..6c6713c674 --- /dev/null +++ b/AndroidAnnotations/functional-test-1-5-tests/src/test/java/com/googlecode/androidannotations/test15/SSLConnectionTest.java @@ -0,0 +1,70 @@ +package com.googlecode.androidannotations.test15; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.security.Security; + +import junit.framework.Assert; + +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SocketFactory; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidAnnotationsTestRunner.class) +public class SSLConnectionTest { + + private SSLConnection_ activity; + + @BeforeClass + public static void addSecurityProvider () { + Security.addProvider(new BouncyCastleProvider()); + } + + @Before + public void setup () { + activity = new SSLConnection_(); + activity.onCreate(null); + } + + @Test + public void truststoreProvided () { + assertNotNull(activity.mHttpsClientTest1); + ClientConnectionManager ccm = activity.mHttpsClientTest1.getConnectionManager(); + assertNotNull(ccm); + + Scheme httpsScheme = ccm.getSchemeRegistry().getScheme("https"); + assertNotNull(httpsScheme); + + assertEquals(443, httpsScheme.getDefaultPort()); + SocketFactory socketFactHttps = httpsScheme.getSocketFactory(); + + if (!(socketFactHttps instanceof SSLSocketFactory)) { + Assert.fail("wrong instance should be org.apache.http.conn.ssl.SSLSocketFactory, getting " + socketFactHttps); + } + assertEquals(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER, ((SSLSocketFactory)socketFactHttps).getHostnameVerifier ()); + } + + @Test + public void strictHostnameVerifier () { + assertNotNull(activity.mHttpsClientTest2); + ClientConnectionManager ccm = activity.mHttpsClientTest2.getConnectionManager(); + Scheme httpsScheme = ccm.getSchemeRegistry().getScheme("https"); + SSLSocketFactory socketFactHttps = (SSLSocketFactory)httpsScheme.getSocketFactory(); + + assertEquals(SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER, ((SSLSocketFactory)socketFactHttps).getHostnameVerifier ()); + } + + @Test + public void noOptions () { + assertNotNull(activity.mHttpsClientTest3); + ClientConnectionManager ccm = activity.mHttpsClientTest3.getConnectionManager(); + assertNotNull(ccm); + } +} diff --git a/AndroidAnnotations/functional-test-1-5/res/raw/cacerts.bks b/AndroidAnnotations/functional-test-1-5/res/raw/cacerts.bks new file mode 100644 index 0000000000000000000000000000000000000000..ca45764affbd1a96903c7cf5d78c9678ecc6ca1d GIT binary patch literal 61391 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 b6wS}mb_3UfX|(r3TyV3Z8{q>Nv?cxt;^QLh literal 0 HcmV?d00001 diff --git a/AndroidAnnotations/functional-test-1-5/src/main/java/com/googlecode/androidannotations/test15/SSLConnection.java b/AndroidAnnotations/functional-test-1-5/src/main/java/com/googlecode/androidannotations/test15/SSLConnection.java new file mode 100644 index 0000000000..ed91d6dd8b --- /dev/null +++ b/AndroidAnnotations/functional-test-1-5/src/main/java/com/googlecode/androidannotations/test15/SSLConnection.java @@ -0,0 +1,22 @@ +package com.googlecode.androidannotations.test15; + +import org.apache.http.client.HttpClient; + +import android.app.Activity; + +import com.googlecode.androidannotations.annotations.EActivity; +import com.googlecode.androidannotations.annotations.HttpsClient; + +@EActivity +public class SSLConnection extends Activity { + @HttpsClient(trustStore = R.raw.cacerts) + HttpClient mHttpsClientTest1; + + @HttpsClient(trustStore = R.raw.cacerts, + hostnameVerif=true) + HttpClient mHttpsClientTest2; + + @HttpsClient + HttpClient mHttpsClientTest3; + +} From 96c0a4af99945b2b9e78bb6d133aac0ffa860dea Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Mon, 4 Jun 2012 04:41:45 +0200 Subject: [PATCH 3/3] HttpsClient Annotation Branch --- .../.settings/org.eclipse.jdt.apt.core.prefs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AndroidAnnotations/functional-test-1-5/.settings/org.eclipse.jdt.apt.core.prefs b/AndroidAnnotations/functional-test-1-5/.settings/org.eclipse.jdt.apt.core.prefs index 82e4e67c34..ef6fa98563 100644 --- a/AndroidAnnotations/functional-test-1-5/.settings/org.eclipse.jdt.apt.core.prefs +++ b/AndroidAnnotations/functional-test-1-5/.settings/org.eclipse.jdt.apt.core.prefs @@ -1,5 +1,5 @@ eclipse.preferences.version=1 org.eclipse.jdt.apt.aptEnabled=true -org.eclipse.jdt.apt.genSrcDir=.apt_generatedd +org.eclipse.jdt.apt.genSrcDir=.apt_generated org.eclipse.jdt.apt.processorOptions/trace=true org.eclipse.jdt.apt.reconcileEnabled=true