Merge "JarFile: Optimize getMetaInfEntryNames."
diff --git a/benchmarks/src/benchmarks/regression/JarFileBenchmark.java b/benchmarks/src/benchmarks/regression/JarFileBenchmark.java
index 6e0cb57..1eff10b 100644
--- a/benchmarks/src/benchmarks/regression/JarFileBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/JarFileBenchmark.java
@@ -23,9 +23,8 @@
 
 public class JarFileBenchmark {
     @Param({
-        "/system/framework/bouncycastle.jar",
-        "/system/framework/core.jar",
-        "/system/framework/framework.jar"
+        "/system/framework/core-oj.jar",
+        "/system/priv-app/Phonesky/Phonesky.apk"
     })
     private String filename;
 
diff --git a/ojluni/src/main/java/java/util/jar/JarFile.java b/ojluni/src/main/java/java/util/jar/JarFile.java
index af2cd75..68a6d85 100755
--- a/ojluni/src/main/java/java/util/jar/JarFile.java
+++ b/ojluni/src/main/java/java/util/jar/JarFile.java
@@ -181,19 +181,7 @@
         return manifest;
     }
 
-    private String[] getMetaInfEntryNames() {
-        List<String> list = new ArrayList<String>(8);
-
-        Enumeration<? extends ZipEntry> allEntries = entries();
-        while (allEntries.hasMoreElements()) {
-            ZipEntry ze = allEntries.nextElement();
-            if (ze.getName().startsWith(META_DIR)
-                    && ze.getName().length() > META_DIR.length()) {
-                list.add(ze.getName());
-            }
-        }
-        return list.toArray(new String[list.size()]);
-    }
+    private native String[] getMetaInfEntryNames();
 
     /**
      * Returns the <code>JarEntry</code> for the given entry name or
diff --git a/ojluni/src/main/native/java_util_zip_ZipFile.c b/ojluni/src/main/native/java_util_zip_ZipFile.c
index 2c770af..a57e20e 100644
--- a/ojluni/src/main/native/java_util_zip_ZipFile.c
+++ b/ojluni/src/main/native/java_util_zip_ZipFile.c
@@ -345,6 +345,49 @@
     return JNU_NewStringPlatform(env, msg);
 }
 
+JNIEXPORT jobjectArray JNICALL
+JarFile_getMetaInfEntryNames(JNIEnv *env, jobject obj)
+{
+    jlong zfile = (*env)->GetLongField(env, obj, jzfileID);
+    jzfile *zip;
+    int i, count;
+    jobjectArray result = 0;
+
+    if (zfile == 0) {
+        JNU_ThrowByName(env,
+                        "java/lang/IllegalStateException", "zip file closed");
+        return NULL;
+    }
+    zip = jlong_to_ptr(zfile);
+
+    /* count the number of valid ZIP metanames */
+    count = 0;
+    if (zip->metanames != 0) {
+        for (i = 0; i < zip->metacount; i++) {
+            if (zip->metanames[i] != 0) {
+                count++;
+            }
+        }
+    }
+
+    /* If some names were found then build array of java strings */
+    if (count > 0) {
+        jclass cls = (*env)->FindClass(env, "java/lang/String");
+        result = (*env)->NewObjectArray(env, count, cls, 0);
+        if (result != 0) {
+            for (i = 0; i < count; i++) {
+                jstring str = (*env)->NewStringUTF(env, zip->metanames[i]);
+                if (str == 0) {
+                    break;
+                }
+                (*env)->SetObjectArrayElement(env, result, i, str);
+                (*env)->DeleteLocalRef(env, str);
+            }
+        }
+    }
+    return result;
+}
+
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(ZipFile, getEntry, "(J[BZ)J"),
   NATIVE_METHOD(ZipFile, freeEntry, "(JJ)V"),
@@ -365,8 +408,13 @@
   NATIVE_METHOD(ZipFile, getZipMessage, "(J)Ljava/lang/String;"),
 };
 
+static JNINativeMethod gJarFileMethods[] = {
+  NATIVE_METHOD(JarFile, getMetaInfEntryNames, "()[Ljava/lang/String;"),
+};
+
 void register_java_util_zip_ZipFile(JNIEnv* env) {
   jniRegisterNativeMethods(env, "java/util/zip/ZipFile", gMethods, NELEM(gMethods));
-
   ZipFile_initIDs(env);
+
+  jniRegisterNativeMethods(env, "java/util/jar/JarFile", gJarFileMethods, NELEM(gJarFileMethods));
 }
diff --git a/ojluni/src/main/native/zip_util.c b/ojluni/src/main/native/zip_util.c
index c79f738..a4dbe14 100644
--- a/ojluni/src/main/native/zip_util.c
+++ b/ojluni/src/main/native/zip_util.c
@@ -440,22 +440,19 @@
 
 /*
  * Returns true if the specified entry's name begins with the string
- * "META-INF/" irrespective of case.
+ * "META-INF/".
  */
 static int
 isMetaName(const char *name, int length)
 {
+    static const char kMetaInf[] = "META-INF/";
+    static const int kMetaInfLength = sizeof(kMetaInf) - 1;
     const char *s;
-    if (length < (int)sizeof("META-INF/") - 1)
+    if (length < kMetaInfLength) {
         return 0;
-    for (s = "META-INF/"; *s != '\0'; s++) {
-        char c = *name++;
-        // Avoid toupper; it's locale-dependent
-        if (c >= 'a' && c <= 'z') c += 'A' - 'a';
-        if (*s != c)
-            return 0;
     }
-    return 1;
+
+    return (strncmp(kMetaInf, name, kMetaInfLength) == 0) ? 1 : 0;
 }
 
 /*