Merge "Improve nio IllegalArgumentException detail messages."
diff --git a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
index 8e82ef0..b23adb7 100644
--- a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
+++ b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
@@ -24,6 +24,7 @@
 #include <fcntl.h>
 #include <sys/socket.h>
 #include <unistd.h>
+#include <vector>
 
 #include <jni.h>
 
@@ -154,6 +155,35 @@
 };
 typedef UniquePtr<X509, X509_Delete> Unique_X509;
 
+class X509Chain {
+  public:
+    X509Chain(size_t n) : x509s_(n) {}
+
+    ~X509Chain() {
+        // TODO: C++0x auto
+        for (std::vector<X509*>::const_iterator it = x509s_.begin(); it != x509s_.end(); ++it) {
+            X509_free(*it);
+        }
+    }
+
+    X509*& operator[](size_t n) {
+        return x509s_[n];
+    }
+
+    X509* operator[](size_t n) const {
+        return x509s_[n];
+    }
+
+    X509* release(size_t i) {
+        X509* x = x509s_[i];
+        x509s_[i] = NULL;
+        return x;
+    }
+
+  private:
+    std::vector<X509*> x509s_;
+};
+
 struct X509_NAME_Delete {
     void operator()(X509_NAME* p) const {
         X509_NAME_free(p);
@@ -2968,7 +2998,7 @@
         return;
     }
 
-    Unique_X509 certificatesX509[length];
+    X509Chain certificatesX509(length);
     for (int i = 0; i < length; i++) {
         ScopedLocalRef<jbyteArray> certificate(env,
                 reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(certificates, i)));
@@ -2984,9 +3014,9 @@
             return;
         }
         const unsigned char* tmp = reinterpret_cast<const unsigned char*>(buf.get());
-        certificatesX509[i].reset(d2i_X509(NULL, &tmp, buf.size()));
+        certificatesX509[i] = d2i_X509(NULL, &tmp, buf.size());
 
-        if (certificatesX509[i].get() == NULL) {
+        if (certificatesX509[i] == NULL) {
             ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
             throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error parsing certificate");
             SSL_clear(ssl);
@@ -2995,9 +3025,9 @@
         }
     }
 
-    int ret = SSL_use_certificate(ssl, certificatesX509[0].get());
+    int ret = SSL_use_certificate(ssl, certificatesX509[0]);
     if (ret == 1) {
-        OWNERSHIP_TRANSFERRED(certificatesX509[0]);
+        certificatesX509.release(0);
     } else {
         ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
         throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting certificate");
@@ -3013,7 +3043,7 @@
         return;
     }
     for (int i = 1; i < length; i++) {
-        if (!sk_X509_push(chain.get(), certificatesX509[i].release())) {
+        if (!sk_X509_push(chain.get(), certificatesX509.release(i))) {
             jniThrowOutOfMemoryError(env, "Unable to push certificate");
             JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificate push error", ssl);
             return;