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 3f43bc20fa..6c39f1da1f 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; @@ -132,6 +133,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; @@ -188,6 +190,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; @@ -288,7 +291,8 @@ FragmentByTag.class, // BeforeTextChange.class, // TextChange.class, // - AfterTextChange.class // + AfterTextChange.class, // + HttpsClient.class // }) @SupportedSourceVersion(SourceVersion.RELEASE_6) public class AndroidAnnotationProcessor extends AnnotatedAbstractProcessor { @@ -456,6 +460,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; } @@ -533,6 +538,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(rClass)); return modelProcessor; } 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..a8736bce5d --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/annotations/HttpsClient.java @@ -0,0 +1,73 @@ +/** + * 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)
+ *
+ * + * allowAllHostnames: boolean, if true, authorizes any TLS/SSL hostname + * (default true) If false, Hostname in certificate (DN) must match + * the URL.
+ *
+ * + * Note: + * Prior to ICS, Android accepts [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 allowAllHostnames() default true; +} \ No newline at end of file diff --git a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/helper/CanonicalNameConstants.java b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/helper/CanonicalNameConstants.java index 041524a68c..9c095ce393 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/helper/CanonicalNameConstants.java +++ b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/helper/CanonicalNameConstants.java @@ -22,7 +22,7 @@ public final class CanonicalNameConstants { /* - * Java classes + * Java */ public static final String URI = URI.class.getCanonicalName(); public static final String SET = Set.class.getCanonicalName(); @@ -31,7 +31,7 @@ public final class CanonicalNameConstants { public static final String CHAR_SEQUENCE = CharSequence.class.getCanonicalName(); /* - * Android classes + * Android */ public static final String LOG = "android.util.Log"; public static final String PARCELABLE = "android.os.Parcelable"; @@ -74,16 +74,17 @@ public final class CanonicalNameConstants { public static final String BROADCAST_RECEIVER = "android.content.BroadcastReceiver"; public static final String CONTENT_PROVIDER = "android.content.ContentProvider"; public static final String SQLITE_DATABASE = "android.database.sqlite.SQLiteDatabase"; + public static final String KEY_STORE = "java.security.KeyStore"; /* - * Sherlock classes + * Sherlock */ public static final String SHERLOCK_MENU = "com.actionbarsherlock.view.Menu"; public static final String SHERLOCK_MENU_ITEM = "com.actionbarsherlock.view.MenuItem"; public static final String SHERLOCK_MENU_INFLATER = "com.actionbarsherlock.view.MenuInflater"; /* - * SpringFramework classes + * SpringFramework */ public static final String RESPONSE_ENTITY = "org.springframework.http.ResponseEntity"; public static final String HTTP_HEADERS = "org.springframework.http.HttpHeaders"; @@ -113,6 +114,16 @@ public final class CanonicalNameConstants { public static final String ON_CONTENT_VIEW_AVAILABLE_EVENT = "roboguice.activity.event.OnContentViewAvailableEvent"; public static final String ON_CREATE_EVENT = "roboguice.activity.event.OnCreateEvent"; + /* + * HttpClient + */ + public static final String CLIENT_CONNECTION_MANAGER = "org.apache.http.conn.ClientConnectionManager"; + public static final String DEFAULT_HTTP_CLIENT = "org.apache.http.impl.client.DefaultHttpClient"; + public static final String SSL_SOCKET_FACTORY = "org.apache.http.conn.ssl.SSLSocketFactory"; + public static final String SCHEME = "org.apache.http.conn.scheme.Scheme"; + public static final String SCHEME_REGISTRY = "org.apache.http.conn.scheme.SchemeRegistry"; + public static final String SINGLE_CLIENT_CONN_MANAGER = "org.apache.http.impl.conn.SingleClientConnManager"; + private CanonicalNameConstants() { } 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 8b60e792f4..b48b7cde8d 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 e01422f5a3..89fe3ec393 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 @@ -35,13 +35,17 @@ public TargetAnnotationHelper(ProcessingEnvironment processingEnv, Class T extractAnnotationValue(Element element) { + return extractAnnotationValue(element, "value"); + } + + @SuppressWarnings("unchecked") + public T extractAnnotationValue(Element element, String methodName) { Annotation annotation = element.getAnnotation(target); Method method; try { - method = annotation.getClass().getMethod("value"); + method = annotation.getClass().getMethod(methodName); return (T) method.invoke(annotation); } catch (Exception e) { throw new RuntimeException(e); diff --git a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/ClickProcessor.java b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/ClickProcessor.java index 42332dfac4..ecaa46d319 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/ClickProcessor.java +++ b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/ClickProcessor.java @@ -34,7 +34,6 @@ import com.sun.codemodel.JBlock; import com.sun.codemodel.JCodeModel; import com.sun.codemodel.JDefinedClass; -import com.sun.codemodel.JExpr; import com.sun.codemodel.JExpression; import com.sun.codemodel.JFieldRef; import com.sun.codemodel.JInvocation; diff --git a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/EBeansHolder.java b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/EBeansHolder.java index 57762b20c9..7f6ebdf7e9 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/EBeansHolder.java +++ b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/EBeansHolder.java @@ -15,6 +15,8 @@ */ package com.googlecode.androidannotations.processing; +import java.io.FileInputStream; +import java.io.InputStream; import java.io.Serializable; import java.util.HashMap; import java.util.Map; @@ -30,17 +32,20 @@ public class EBeansHolder { public class Classes { /* - * Java classes + * Java */ public final JClass RUNTIME_EXCEPTION = refClass(RuntimeException.class); + public final JClass EXCEPTION = refClass(Exception.class); public final JClass CHAR_SEQUENCE = refClass(CharSequence.class); public final JClass CLASS_CAST_EXCEPTION = refClass(ClassCastException.class); public final JClass SERIALIZABLE = refClass(Serializable.class); public final JClass STRING = refClass(String.class); public final JClass SYSTEM = refClass(System.class); + public final JClass INPUT_STREAM = refClass(InputStream.class); + public final JClass FILE_INPUT_STREAM = refClass(FileInputStream.class); /* - * Android classes + * Android */ public final JClass LOG = refClass(CanonicalNameConstants.LOG); public final JClass BUNDLE = refClass(CanonicalNameConstants.BUNDLE); @@ -76,9 +81,10 @@ public class Classes { public final JClass MOTION_EVENT = refClass(CanonicalNameConstants.MOTION_EVENT); public final JClass ON_TOUCH_LISTENER = refClass(CanonicalNameConstants.ON_TOUCH_LISTENER); public final JClass HANDLER = refClass(CanonicalNameConstants.HANDLER); + public final JClass KEY_STORE = refClass(CanonicalNameConstants.KEY_STORE); /* - * Sherlock classes + * Sherlock */ public final JClass SHERLOCK_MENU = refClass(CanonicalNameConstants.SHERLOCK_MENU); public final JClass SHERLOCK_MENU_ITEM = refClass(CanonicalNameConstants.SHERLOCK_MENU_ITEM); @@ -105,6 +111,16 @@ public class Classes { public final JClass ON_CONTENT_VIEW_AVAILABLE_EVENT = refClass(CanonicalNameConstants.ON_CONTENT_VIEW_AVAILABLE_EVENT); public final JClass ON_CREATE_EVENT = refClass(CanonicalNameConstants.ON_CREATE_EVENT); + /* + * HttpClient + */ + public final JClass CLIENT_CONNECTION_MANAGER = refClass(CanonicalNameConstants.CLIENT_CONNECTION_MANAGER); + public final JClass DEFAULT_HTTP_CLIENT = refClass(CanonicalNameConstants.DEFAULT_HTTP_CLIENT); + public final JClass SSL_SOCKET_FACTORY = refClass(CanonicalNameConstants.SSL_SOCKET_FACTORY); + public final JClass SCHEME = refClass(CanonicalNameConstants.SCHEME); + public final JClass SCHEME_REGISTRY = refClass(CanonicalNameConstants.SCHEME_REGISTRY); + public final JClass SINGLE_CLIENT_CONN_MANAGER = refClass(CanonicalNameConstants.SINGLE_CLIENT_CONN_MANAGER); + } private final Map EBeanHolders = new HashMap(); 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..7bc4b3ffd5 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/HttpsClientProcessor.java @@ -0,0 +1,191 @@ +/** + * 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 static com.sun.codemodel.JExpr._new; +import static com.sun.codemodel.JExpr._null; +import static com.sun.codemodel.JExpr._super; +import static com.sun.codemodel.JExpr.cast; +import static com.sun.codemodel.JExpr.invoke; +import static com.sun.codemodel.JExpr.lit; +import static com.sun.codemodel.JExpr.ref; + +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.googlecode.androidannotations.processing.EBeansHolder.Classes; +import com.googlecode.androidannotations.rclass.IRClass; +import com.googlecode.androidannotations.rclass.IRClass.Res; +import com.googlecode.androidannotations.rclass.IRInnerClass; +import com.sun.codemodel.JBlock; +import com.sun.codemodel.JCatchBlock; +import com.sun.codemodel.JCodeModel; +import com.sun.codemodel.JDefinedClass; +import com.sun.codemodel.JExpression; +import com.sun.codemodel.JFieldRef; +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 { + + private final IRClass rClass; + + public HttpsClientProcessor(IRClass rClass) { + this.rClass = rClass; + } + + @Override + public Class getTarget() { + return HttpsClient.class; + } + + @Override + public void process(Element element, JCodeModel codeModel, EBeansHolder eBeansHolder) { + EBeanHolder holder = eBeansHolder.getEnclosingEBeanHolder(element); + + HttpsClient annotation = element.getAnnotation(HttpsClient.class); + int trustStoreRawId = annotation.trustStore(); + String trustStorePwd = annotation.trustStorePwd(); + + int keyStoreRawId = annotation.keyStore(); + String keyStorePwd = annotation.keyStorePwd(); + + boolean allowAllHostnames = annotation.allowAllHostnames(); + + boolean useCustomTrustStore = Id.DEFAULT_VALUE != trustStoreRawId ? true : false; + boolean useCustomKeyStore = Id.DEFAULT_VALUE != keyStoreRawId ? true : false; + + String fieldName = element.getSimpleName().toString(); + JBlock methodBody = holder.init.body(); + + Classes classes = holder.classes(); + + JDefinedClass jAnonClass = codeModel.anonymousClass(classes.DEFAULT_HTTP_CLIENT); + + JMethod method = jAnonClass.method(JMod.PROTECTED, classes.CLIENT_CONNECTION_MANAGER, "createClientConnectionManager"); + method.annotate(Override.class); + + JTryBlock jTryBlock = method.body()._try(); + JVar jVarTrusted = null; + JVar jVarKeystore = null; + + if (useCustomKeyStore) { + jVarKeystore = jTryBlock.body().decl(classes.KEY_STORE, "keystore"); + jVarKeystore.init(classes.KEY_STORE.staticInvoke("getInstance").arg("BKS")); + } + + if (useCustomTrustStore || !useCustomTrustStore && useCustomKeyStore) { + /* + * use default trust store + */ + jVarTrusted = jTryBlock.body().decl(classes.KEY_STORE, "trusted"); + jVarTrusted.init(classes.KEY_STORE.staticInvoke("getInstance").arg("BKS")); + + } + + JVar jVarRes = null; + JVar jVarTrstFile = null; + JVar jVarKeyFile = null; + + if (useCustomKeyStore || useCustomTrustStore) { + jVarRes = jTryBlock.body().decl(classes.RESOURCES, "res", invoke("getResources")); + } + + IRInnerClass rInnerClass = rClass.get(Res.RAW); + if (useCustomKeyStore) { + JFieldRef rawIdRef = rInnerClass.getIdStaticRef(keyStoreRawId, holder); + JInvocation jInvRawKey = jVarRes.invoke("openRawResource").arg(rawIdRef); + jVarKeyFile = jTryBlock.body().decl(classes.INPUT_STREAM, "inKeystore", jInvRawKey); + } + + if (useCustomTrustStore) { + JFieldRef rawIdRef = rInnerClass.getIdStaticRef(trustStoreRawId, holder); + JInvocation jInvRawTrust = jVarRes.invoke("openRawResource").arg(rawIdRef); + jVarTrstFile = jTryBlock.body().decl(classes.INPUT_STREAM, "inTrustStore", jInvRawTrust); + + } else if (useCustomKeyStore) { + jVarTrstFile = jTryBlock.body().decl(classes.INPUT_STREAM, "inTrustStore", _new(classes.FILE_INPUT_STREAM).arg("/system/etc/security/cacerts.bks")); + } + + // try load + if (useCustomKeyStore || useCustomTrustStore) { + JTryBlock jTryLoad = jTryBlock.body()._try(); + + if (useCustomKeyStore) { + jTryLoad.body().add(invoke(jVarKeystore, "load").arg(jVarKeyFile).arg(invoke(lit(keyStorePwd), "toCharArray"))); + } + + if (useCustomTrustStore || !useCustomTrustStore && useCustomKeyStore) { + jTryLoad.body().add(invoke(jVarTrusted, "load").arg(jVarTrstFile).arg(invoke(lit(trustStorePwd), "toCharArray"))); + } + // finally load + JBlock jFinally = jTryLoad._finally(); + if (useCustomKeyStore) { + jFinally.add(invoke(jVarKeyFile, "close")); + } + + if (useCustomTrustStore || !useCustomTrustStore && useCustomKeyStore) { + jFinally.add(invoke(jVarTrstFile, "close")); + } + } + + if (null == jVarKeystore && null == jVarTrusted) { + JVar jVarCcm = jTryBlock.body().decl(classes.CLIENT_CONNECTION_MANAGER, "ccm"); + jVarCcm.init(_super().invoke("createClientConnectionManager")); + + if (allowAllHostnames) { + JExpression jCast = cast(classes.SSL_SOCKET_FACTORY, jVarCcm.invoke("getSchemeRegistry").invoke("getScheme").arg("https").invoke("getSocketFactory")); + jTryBlock.body().add(jCast.invoke("setHostnameVerifier").arg(classes.SSL_SOCKET_FACTORY.staticRef("ALLOW_ALL_HOSTNAME_VERIFIER"))); + } + + jTryBlock.body()._return(jVarCcm); + + } else { + JVar jVarSslFact = jTryBlock.body().decl(classes.SSL_SOCKET_FACTORY, "newSslSocketFactory"); + jVarSslFact.init(_new(classes.SSL_SOCKET_FACTORY).arg(null == jVarKeystore ? _null() : jVarKeystore).arg(keyStorePwd).arg(null == jVarTrusted ? _null() : jVarTrusted)); + + if (allowAllHostnames) { + jTryBlock.body().add(invoke(jVarSslFact, "setHostnameVerifier").arg(classes.SSL_SOCKET_FACTORY.staticRef("ALLOW_ALL_HOSTNAME_VERIFIER"))); + } + + JVar jVarSchemeReg = jTryBlock.body().decl(classes.SCHEME_REGISTRY, "registry"); + jVarSchemeReg.init(_new(classes.SCHEME_REGISTRY)); + jTryBlock.body().add(invoke(jVarSchemeReg, "register").arg(_new(classes.SCHEME).arg("https").arg(jVarSslFact).arg(lit(443)))); + + JVar jVarCcm = jTryBlock.body().decl(classes.CLIENT_CONNECTION_MANAGER, "ccm"); + jVarCcm.init(_new(classes.SINGLE_CLIENT_CONN_MANAGER).arg(invoke("getParams")).arg(jVarSchemeReg)); + jTryBlock.body()._return(jVarCcm); + } + + // catch block + JCatchBlock jCatchBlock = jTryBlock._catch(classes.EXCEPTION); + JVar jVarExceptionParam = jCatchBlock.param("e"); + jCatchBlock.body().add(jVarExceptionParam.invoke("printStackTrace")); + jCatchBlock.body()._return(_super().invoke("createClientConnectionManager")); + + methodBody.assign(ref(fieldName), _new(jAnonClass)); + + } + +} 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 3f210e35a1..b631ee1c24 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/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/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-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..feed9aa06e --- /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/AndroidManifest.xml b/AndroidAnnotations/functional-test-1-5/AndroidManifest.xml index 68e32206c7..59d6f23e79 100644 --- a/AndroidAnnotations/functional-test-1-5/AndroidManifest.xml +++ b/AndroidAnnotations/functional-test-1-5/AndroidManifest.xml @@ -65,6 +65,7 @@ + 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 0000000000..ca45764aff Binary files /dev/null and b/AndroidAnnotations/functional-test-1-5/res/raw/cacerts.bks differ 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..e15cbbb29d --- /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, allowAllHostnames = false) + HttpClient mHttpsClientTest2; + + @HttpsClient + HttpClient mHttpsClientTest3; + +}