Merge "Add tests to demonstrate libcore.io.Base64 behavior"
diff --git a/Docs.mk b/Docs.mk
index 0c52bf5..a163d1f 100644
--- a/Docs.mk
+++ b/Docs.mk
@@ -20,20 +20,11 @@
libart/src/main/java/dalvik \
libart/src/main/java/java \
luni/src/main/java/android \
+ luni/src/main/java/java \
luni/src/main/java/javax \
luni/src/main/java/org/xml/sax \
luni/src/main/java/org/w3c \
xml/src/main/java/org/xmlpull/v1)
-# IcuIteratorWrapper.java references com.ibm.icu.text.BreakIterator,
-# which is renamed by our jarjar rule, and so unrecognizable by javadoc,
-# with annoying error: error: package com.ibm.icu.text does not exist.
-# We don't want to generate doc for this file anyway.
-libcore_to_document += \
- $(filter-out luni/src/main/java/java/text/IcuIteratorWrapper.java,\
- $(call find-files-in-subdirs, libcore, \
- "*.java", \
- luni/src/main/java/java))
-
libcore_docs_include_once := 1
endif # libcore_docs_include_once
diff --git a/benchmarks/src/benchmarks/regression/AnnotatedElementBenchmark.java b/benchmarks/src/benchmarks/regression/AnnotatedElementBenchmark.java
index 6c33968..107767b 100644
--- a/benchmarks/src/benchmarks/regression/AnnotatedElementBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/AnnotatedElementBenchmark.java
@@ -141,7 +141,68 @@
public void timeGetDeclaredAnnotationsOnSubclass(int reps) {
for (int i = 0; i < reps; i++) {
- ExtendsHasThreeAnnotations.class.getAnnotations();
+ ExtendsHasThreeAnnotations.class.getDeclaredAnnotations();
+ }
+ }
+
+
+ // get annotations with enclosing / inner classes
+
+ public void timeGetDeclaredClasses(int reps) {
+ for (int i = 0; i < reps; i++) {
+ AnnotatedElementBenchmark.class.getDeclaredClasses();
+ }
+ }
+
+ public void timeGetDeclaringClass(int reps) {
+ for (int i = 0; i < reps; i++) {
+ HasSmallAnnotation.class.getDeclaringClass();
+ }
+ }
+
+ public void timeGetEnclosingClass(int reps) {
+ Object anonymousClass = new Object() {};
+ for (int i = 0; i < reps; i++) {
+ anonymousClass.getClass().getEnclosingClass();
+ }
+ }
+
+ public void timeGetEnclosingConstructor(int reps) {
+ Object anonymousClass = new Object() {};
+ for (int i = 0; i < reps; i++) {
+ anonymousClass.getClass().getEnclosingConstructor();
+ }
+ }
+
+ public void timeGetEnclosingMethod(int reps) {
+ Object anonymousClass = new Object() {};
+ for (int i = 0; i < reps; i++) {
+ anonymousClass.getClass().getEnclosingMethod();
+ }
+ }
+
+ public void timeGetModifiers(int reps) {
+ for (int i = 0; i < reps; i++) {
+ HasSmallAnnotation.class.getModifiers();
+ }
+ }
+
+ public void timeGetSimpleName(int reps) {
+ for (int i = 0; i < reps; i++) {
+ HasSmallAnnotation.class.getSimpleName();
+ }
+ }
+
+ public void timeIsAnonymousClass(int reps) {
+ Object anonymousClass = new Object() {};
+ for (int i = 0; i < reps; i++) {
+ anonymousClass.getClass().isAnonymousClass();
+ }
+ }
+
+ public void timeIsLocalClass(int reps) {
+ for (int i = 0; i < reps; i++) {
+ HasSmallAnnotation.class.isLocalClass();
}
}
@@ -174,7 +235,7 @@
@Marker
public class HasThreeAnnotations {}
- public class ExtendsHasThreeAnnotations {}
+ public class ExtendsHasThreeAnnotations extends HasThreeAnnotations {}
// the annotations
diff --git a/benchmarks/src/benchmarks/regression/BidiBenchmark.java b/benchmarks/src/benchmarks/regression/BidiBenchmark.java
new file mode 100644
index 0000000..bb5087e
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/BidiBenchmark.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 benchmarks.regression;
+
+import com.google.caliper.SimpleBenchmark;
+
+import java.math.BigDecimal;
+import java.text.AttributedCharacterIterator;
+import java.text.Bidi;
+import java.text.DecimalFormat;
+
+public class BidiBenchmark extends SimpleBenchmark {
+
+ private static final AttributedCharacterIterator charIter =
+ DecimalFormat.getInstance().formatToCharacterIterator(new BigDecimal(Math.PI));
+
+ public void time_createBidiFromIter(int reps) {
+ for (int i = 0; i < reps; i++) {
+ Bidi bidi = new Bidi(charIter);
+ }
+ }
+
+ public void time_createBidiFromCharArray(int reps) {
+ for (int i = 0; i < reps; i++) {
+ Bidi bd = new Bidi(new char[]{'s', 's', 's'}, 0, new byte[]{(byte) 1,
+ (byte) 2, (byte) 3}, 0, 3, Bidi.DIRECTION_RIGHT_TO_LEFT);
+ }
+ }
+
+ public void time_createBidiFromString(int reps) {
+ for (int i = 0; i < reps; i++) {
+ Bidi bidi = new Bidi("Hello", Bidi.DIRECTION_LEFT_TO_RIGHT);
+ }
+ }
+
+ public void time_reorderVisually(int reps) {
+ for (int i = 0; i < reps; i++) {
+ Bidi.reorderVisually(new byte[]{2, 1, 3, 0, 4}, 0,
+ new String[]{"H", "e", "l", "l", "o"}, 0, 5);
+ }
+ }
+
+ public void time_hebrewBidi(int reps) {
+ for (int i = 0; i < reps; i++) {
+ Bidi bd = new Bidi(new char[]{'\u05D0', '\u05D0', '\u05D0'}, 0,
+ new byte[]{(byte) -1, (byte) -2, (byte) -3}, 0, 3,
+ Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
+ bd = new Bidi(new char[]{'\u05D0', '\u05D0', '\u05D0'}, 0,
+ new byte[]{(byte) -1, (byte) -2, (byte) -3}, 0, 3,
+ Bidi.DIRECTION_LEFT_TO_RIGHT);
+ }
+ }
+
+ public void time_complicatedOverrideBidi(int reps) {
+ for (int i = 0; i < reps; i++) {
+ Bidi bd = new Bidi("a\u05D0a\"a\u05D0\"\u05D0a".toCharArray(), 0,
+ new byte[]{0, 0, 0, -3, -3, 2, 2, 0, 3}, 0, 9,
+ Bidi.DIRECTION_RIGHT_TO_LEFT);
+ }
+ }
+
+ public void time_requiresBidi(int reps) {
+ for (int i = 0; i < reps; i++) {
+ Bidi.requiresBidi("\u05D0".toCharArray(), 1, 1); // false.
+ Bidi.requiresBidi("\u05D0".toCharArray(), 0, 1); // true.
+ }
+ }
+
+}
diff --git a/benchmarks/src/benchmarks/regression/IdnBenchmark.java b/benchmarks/src/benchmarks/regression/IdnBenchmark.java
new file mode 100644
index 0000000..9de5261
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/IdnBenchmark.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 Google Inc.
+ *
+ * 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 benchmarks.regression;
+
+import com.google.caliper.SimpleBenchmark;
+
+import java.net.IDN;
+
+public class IdnBenchmark extends SimpleBenchmark {
+
+ public void timeToUnicode(int reps) {
+ for (int i = 0; i < reps; i++) {
+ IDN.toASCII("fass.de");
+ IDN.toASCII("faß.de");
+ IDN.toASCII("fäß.de");
+ IDN.toASCII("a\u200Cb");
+ IDN.toASCII("öbb.at");
+ IDN.toASCII("abc・日本.co.jp");
+ IDN.toASCII("日本.co.jp");
+ IDN.toASCII("x\u0327\u0301.de");
+ IDN.toASCII("σόλοσ.gr");
+ }
+ }
+
+ public void timeToAscii(int reps) {
+ for (int i = 0; i < reps; i++) {
+ IDN.toUnicode("xn--fss-qla.de");
+ IDN.toUnicode("xn--n00d.com");
+ IDN.toUnicode("xn--bb-eka.at");
+ IDN.toUnicode("xn--og-09a.de");
+ IDN.toUnicode("xn--53h.de");
+ IDN.toUnicode("xn--iny-zx5a.de");
+ IDN.toUnicode("xn--abc-rs4b422ycvb.co.jp");
+ IDN.toUnicode("xn--wgv71a.co.jp");
+ IDN.toUnicode("xn--x-xbb7i.de");
+ IDN.toUnicode("xn--wxaikc6b.gr");
+ IDN.toUnicode("xn--wxaikc6b.xn--gr-gtd9a1b0g.de");
+ }
+ }
+
+}
diff --git a/libart/src/main/java/java/lang/Class.java b/libart/src/main/java/java/lang/Class.java
index 0d37cd6..0dc4bc4 100644
--- a/libart/src/main/java/java/lang/Class.java
+++ b/libart/src/main/java/java/lang/Class.java
@@ -37,6 +37,7 @@
import java.io.InputStream;
import java.io.Serializable;
import java.lang.annotation.Annotation;
+import java.lang.annotation.Inherited;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
@@ -53,7 +54,9 @@
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import libcore.reflect.AnnotationAccess;
import libcore.reflect.GenericSignatureParser;
@@ -202,6 +205,9 @@
/** Virtual methods defined in this class; invoked through vtable. */
private transient long virtualMethods;
+ /** Class flags to help the GC with object scanning. */
+ private transient int classFlags;
+
/**
* Total size of the Class instance; used when allocating storage on GC heap.
* See also {@link Class#objectSize}.
@@ -351,7 +357,25 @@
}
@Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
- return AnnotationAccess.getAnnotation(this, annotationType);
+ if (annotationType == null) {
+ throw new NullPointerException("annotationType == null");
+ }
+
+ A annotation = getDeclaredAnnotation(annotationType);
+ if (annotation != null) {
+ return annotation;
+ }
+
+ if (annotationType.isDeclaredAnnotationPresent(Inherited.class)) {
+ for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+ annotation = sup.getDeclaredAnnotation(annotationType);
+ if (annotation != null) {
+ return annotation;
+ }
+ }
+ }
+
+ return null;
}
/**
@@ -361,7 +385,33 @@
* @see #getDeclaredAnnotations()
*/
@Override public Annotation[] getAnnotations() {
- return AnnotationAccess.getAnnotations(this);
+ /*
+ * We need to get the annotations declared on this class, plus the
+ * annotations from superclasses that have the "@Inherited" annotation
+ * set. We create a temporary map to use while we accumulate the
+ * annotations and convert it to an array at the end.
+ *
+ * It's possible to have duplicates when annotations are inherited.
+ * We use a Map to filter those out.
+ *
+ * HashMap might be overkill here.
+ */
+ HashMap<Class<?>, Annotation> map = new HashMap<Class<?>, Annotation>();
+ for (Annotation declaredAnnotation : getDeclaredAnnotations()) {
+ map.put(declaredAnnotation.annotationType(), declaredAnnotation);
+ }
+ for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+ for (Annotation declaredAnnotation : sup.getDeclaredAnnotations()) {
+ Class<? extends Annotation> clazz = declaredAnnotation.annotationType();
+ if (!map.containsKey(clazz) && clazz.isDeclaredAnnotationPresent(Inherited.class)) {
+ map.put(clazz, declaredAnnotation);
+ }
+ }
+ }
+
+ /* Convert annotation values from HashMap to array. */
+ Collection<Annotation> coll = map.values();
+ return coll.toArray(new Annotation[coll.size()]);
}
/**
@@ -734,10 +784,17 @@
*
* @see #getAnnotations()
*/
- @Override public Annotation[] getDeclaredAnnotations() {
- List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
- return result.toArray(new Annotation[result.size()]);
- }
+ @Override public native Annotation[] getDeclaredAnnotations();
+
+ /**
+ * Returns the annotation if it exists.
+ */
+ private native <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass);
+
+ /**
+ * Returns true if the annotation exists.
+ */
+ private native boolean isDeclaredAnnotationPresent(Class<? extends Annotation> annotationClass);
/**
* Returns an array containing {@code Class} objects for all classes,
@@ -793,7 +850,7 @@
* method or constructor.
*/
public Class<?> getDeclaringClass() {
- if (AnnotationAccess.isAnonymousClass(this)) {
+ if (isAnonymousClass()) {
return null;
}
return AnnotationAccess.getEnclosingClass(this);
@@ -1220,7 +1277,23 @@
}
@Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
- return AnnotationAccess.isAnnotationPresent(this, annotationType);
+ if (annotationType == null) {
+ throw new NullPointerException("annotationType == null");
+ }
+
+ if (isDeclaredAnnotationPresent(annotationType)) {
+ return true;
+ }
+
+ if (annotationType.isDeclaredAnnotationPresent(Inherited.class)) {
+ for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+ if (sup.isDeclaredAnnotationPresent(annotationType)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
}
/**
diff --git a/libart/src/main/java/java/lang/ClassLoader.java b/libart/src/main/java/java/lang/ClassLoader.java
index dfbeeb5..860e4a1 100644
--- a/libart/src/main/java/java/lang/ClassLoader.java
+++ b/libart/src/main/java/java/lang/ClassLoader.java
@@ -92,6 +92,11 @@
private Map<String, Package> packages = new HashMap<String, Package>();
/**
+ * Pointer to the class table, only used from within the runtime.
+ */
+ private transient long classTable;
+
+ /**
* To avoid unloading individual classes, {@link java.lang.reflect.Proxy}
* only generates one class for each set of interfaces. This maps sets of
* interfaces to the proxy class that implements all of them. It is declared
diff --git a/libart/src/main/java/java/lang/reflect/Constructor.java b/libart/src/main/java/java/lang/reflect/Constructor.java
index 9711ef4..0dadd8d 100644
--- a/libart/src/main/java/java/lang/reflect/Constructor.java
+++ b/libart/src/main/java/java/lang/reflect/Constructor.java
@@ -36,7 +36,6 @@
import java.lang.annotation.Annotation;
import java.util.Comparator;
import java.util.List;
-import libcore.reflect.AnnotationAccess;
import libcore.reflect.Types;
/**
@@ -97,10 +96,7 @@
* this constructor has no declared exceptions, an empty array will be
* returned.
*/
- public Class<?>[] getExceptionTypes() {
- // TODO: use dex cache to speed looking up class
- return AnnotationAccess.getExceptions(this);
- }
+ public native Class<?>[] getExceptionTypes();
/**
* Returns an array of the {@code Class} objects associated with the
@@ -181,24 +177,23 @@
return super.getGenericExceptionTypes();
}
- @Override public Annotation[] getDeclaredAnnotations() {
- List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
- return result.toArray(new Annotation[result.size()]);
- }
+ @Override public native Annotation[] getDeclaredAnnotations();
@Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
if (annotationType == null) {
throw new NullPointerException("annotationType == null");
}
- return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
+ return isAnnotationPresentNative(annotationType);
}
+ private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
@Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
if (annotationType == null) {
throw new NullPointerException("annotationType == null");
}
- return AnnotationAccess.getDeclaredAnnotation(this, annotationType);
+ return getAnnotationNative(annotationType);
}
+ private native <A extends Annotation> A getAnnotationNative(Class<A> annotationType);
/**
* Returns an array of arrays that represent the annotations of the formal
@@ -209,9 +204,13 @@
* @return an array of arrays of {@code Annotation} instances
*/
public Annotation[][] getParameterAnnotations() {
- return AnnotationAccess.getParameterAnnotations(
- declaringClassOfOverriddenMethod, dexMethodIndex);
+ Annotation[][] parameterAnnotations = getParameterAnnotationsNative();
+ if (parameterAnnotations == null) {
+ parameterAnnotations = new Annotation[getParameterTypes().length][0];
+ }
+ return parameterAnnotations;
}
+ private native Annotation[][] getParameterAnnotationsNative();
/**
* Returns the constructor's signature in non-printable form. This is called
diff --git a/libart/src/main/java/java/lang/reflect/Field.java b/libart/src/main/java/java/lang/reflect/Field.java
index 37f2ad0..06cc0b2 100644
--- a/libart/src/main/java/java/lang/reflect/Field.java
+++ b/libart/src/main/java/java/lang/reflect/Field.java
@@ -36,7 +36,6 @@
import java.lang.annotation.Annotation;
import java.util.Comparator;
import java.util.List;
-import libcore.reflect.AnnotationAccess;
import libcore.reflect.GenericSignatureParser;
import libcore.reflect.Types;
@@ -218,7 +217,7 @@
* instantiated for some reason
*/
public Type getGenericType() {
- String signatureAttribute = AnnotationAccess.getSignature(this);
+ String signatureAttribute = getSignatureAttribute();
Class<?> declaringClass = getDeclaringClass();
ClassLoader cl = declaringClass.getClassLoader();
GenericSignatureParser parser = new GenericSignatureParser(cl);
@@ -230,6 +229,19 @@
return genericType;
}
+ private String getSignatureAttribute() {
+ String[] annotation = getSignatureAnnotation();
+ if (annotation == null) {
+ return null;
+ }
+ StringBuilder result = new StringBuilder();
+ for (String s : annotation) {
+ result.append(s);
+ }
+ return result.toString();
+ }
+ private native String[] getSignatureAnnotation();
+
/**
* Returns the constructor's signature in non-printable form. This is called
* (only) from IO native code and needed for deriving the serialVersionUID
@@ -240,24 +252,23 @@
return Types.getSignature(getType());
}
- @Override public Annotation[] getDeclaredAnnotations() {
- List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
- return result.toArray(new Annotation[result.size()]);
- }
+ @Override public native Annotation[] getDeclaredAnnotations();
@Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
if (annotationType == null) {
throw new NullPointerException("annotationType == null");
}
- return AnnotationAccess.getDeclaredAnnotation(this, annotationType);
+ return getAnnotationNative(annotationType);
}
+ private native <A extends Annotation> A getAnnotationNative(Class<A> annotationType);
@Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
if (annotationType == null) {
throw new NullPointerException("annotationType == null");
}
- return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
+ return isAnnotationPresentNative(annotationType);
}
+ private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
/**
* Returns the value of the field in the specified object. This reproduces
diff --git a/libart/src/main/java/java/lang/reflect/Method.java b/libart/src/main/java/java/lang/reflect/Method.java
index a07ec6f..79287ba 100644
--- a/libart/src/main/java/java/lang/reflect/Method.java
+++ b/libart/src/main/java/java/lang/reflect/Method.java
@@ -36,7 +36,6 @@
import java.lang.annotation.Annotation;
import java.util.Comparator;
import java.util.List;
-import libcore.reflect.AnnotationAccess;
import libcore.reflect.Types;
/**
@@ -148,16 +147,7 @@
*
* @return the declared exception classes
*/
- public Class<?>[] getExceptionTypes() {
- if (getDeclaringClass().isProxy()) {
- return getExceptionTypesNative();
- } else {
- // TODO: use dex cache to speed looking up class
- return AnnotationAccess.getExceptions(this);
- }
- }
-
- private native Class<?>[] getExceptionTypesNative();
+ public native Class<?>[] getExceptionTypes();
/**
* Returns an array of {@code Class} objects associated with the parameter
@@ -250,8 +240,9 @@
if (annotationType == null) {
throw new NullPointerException("annotationType == null");
}
- return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
+ return isAnnotationPresentNative(annotationType);
}
+ private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
/**
* Returns the exception types as an array of {@code Type} instances. If
@@ -288,17 +279,15 @@
return Types.getType(getMethodOrConstructorGenericInfo().genericReturnType);
}
- @Override public Annotation[] getDeclaredAnnotations() {
- List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
- return result.toArray(new Annotation[result.size()]);
- }
+ @Override public native Annotation[] getDeclaredAnnotations();
@Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
if (annotationType == null) {
throw new NullPointerException("annotationType == null");
}
- return AnnotationAccess.getDeclaredAnnotation(this, annotationType);
+ return getAnnotationNative(annotationType);
}
+ private native <A extends Annotation> A getAnnotationNative(Class<A> annotationType);
/**
* Returns an array of arrays that represent the annotations of the formal
@@ -309,9 +298,13 @@
* @return an array of arrays of {@code Annotation} instances
*/
public Annotation[][] getParameterAnnotations() {
- return AnnotationAccess.getParameterAnnotations(
- declaringClassOfOverriddenMethod, dexMethodIndex);
+ Annotation[][] parameterAnnotations = getParameterAnnotationsNative();
+ if (parameterAnnotations == null) {
+ parameterAnnotations = new Annotation[getParameterTypes().length][0];
+ }
+ return parameterAnnotations;
}
+ private native Annotation[][] getParameterAnnotationsNative();
/**
* Returns the default value for the annotation member represented by this
@@ -323,9 +316,7 @@
* if this annotation member is of type {@code Class} and no
* definition can be found
*/
- public Object getDefaultValue() {
- return AnnotationAccess.getDefaultValue(this);
- }
+ public native Object getDefaultValue();
/**
* Returns the result of dynamically invoking this method. Equivalent to
diff --git a/luni/src/main/java/java/lang/reflect/Array.java b/luni/src/main/java/java/lang/reflect/Array.java
index a7dacfe..72e6717 100644
--- a/luni/src/main/java/java/lang/reflect/Array.java
+++ b/luni/src/main/java/java/lang/reflect/Array.java
@@ -371,7 +371,7 @@
} else if (componentType == void.class) {
throw new IllegalArgumentException("Can't allocate an array of void");
}
- throw new AssertionError();
+ throw new AssertionError(componentType.toString());
}
/*
diff --git a/luni/src/main/java/java/net/IDN.java b/luni/src/main/java/java/net/IDN.java
index 4e60209..dd256c2 100644
--- a/luni/src/main/java/java/net/IDN.java
+++ b/luni/src/main/java/java/net/IDN.java
@@ -16,7 +16,7 @@
package java.net;
-import libcore.icu.NativeIDN;
+import com.ibm.icu.text.IDNA;
/**
* Converts internationalized domain names between Unicode and the ASCII Compatible Encoding
@@ -61,7 +61,11 @@
* @throws IllegalArgumentException if {@code input} does not conform to <a href="http://www.ietf.org/rfc/rfc3490.txt">RFC 3490</a>
*/
public static String toASCII(String input, int flags) {
- return NativeIDN.toASCII(input, flags);
+ try {
+ return IDNA.convertIDNToASCII(input, flags).toString();
+ } catch (com.ibm.icu.text.StringPrepParseException e) {
+ throw new IllegalArgumentException("Invalid input to toASCII: " + input, e);
+ }
}
/**
@@ -91,7 +95,28 @@
* or {@code ALLOW_UNASSIGNED | USE_STD3_ASCII_RULES}
*/
public static String toUnicode(String input, int flags) {
- return NativeIDN.toUnicode(input, flags);
+ try {
+ // ICU only translates separators to ASCII for toASCII.
+ // Java expects the translation for toUnicode too.
+ return convertFullStop(IDNA.convertIDNToUnicode(input, flags)).toString();
+ } catch (com.ibm.icu.text.StringPrepParseException e) {
+ // The RI documentation explicitly states that if the conversion was unsuccessful
+ // the original string is returned.
+ return input;
+ }
+ }
+
+ private static boolean isLabelSeperator(char c) {
+ return (c == '\u3002' || c == '\uff0e' || c == '\uff61');
+ }
+
+ private static StringBuffer convertFullStop(StringBuffer input) {
+ for (int i = 0; i < input.length(); i++) {
+ if (isLabelSeperator(input.charAt(i))) {
+ input.setCharAt(i, '.');
+ }
+ }
+ return input;
}
/**
@@ -101,6 +126,6 @@
* @return the Unicode name
*/
public static String toUnicode(String input) {
- return NativeIDN.toUnicode(input, 0);
+ return toUnicode(input, 0);
}
}
diff --git a/luni/src/main/java/java/text/Bidi.java b/luni/src/main/java/java/text/Bidi.java
index d73ea4a..65861a7 100644
--- a/luni/src/main/java/java/text/Bidi.java
+++ b/luni/src/main/java/java/text/Bidi.java
@@ -17,11 +17,6 @@
package java.text;
-import java.awt.font.NumericShaper;
-import java.awt.font.TextAttribute;
-import java.util.ArrayList;
-import java.util.Arrays;
-
/**
* Implements the <a href="http://unicode.org/reports/tr9/">Unicode Bidirectional Algorithm</a>.
*
@@ -58,33 +53,28 @@
*/
public static final int DIRECTION_RIGHT_TO_LEFT = 1;
- /**
- * TODO: if we care about performance, we might just want to use an int[] instead of a Run[].
- */
- static class Run {
- private final int start;
- private final int limit;
- private final int level;
-
- public Run(int start, int limit, int level) {
- this.start = start;
- this.limit = limit;
- this.level = level;
- }
-
- public int getLevel() {
- return level;
- }
-
- public int getLimit() {
- return limit;
- }
-
- public int getStart() {
- return start;
+ private static int translateConstToIcu(int javaInt) {
+ switch (javaInt) {
+ case DIRECTION_DEFAULT_LEFT_TO_RIGHT:
+ return com.ibm.icu.text.Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
+ case DIRECTION_DEFAULT_RIGHT_TO_LEFT:
+ return com.ibm.icu.text.Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT;
+ case DIRECTION_LEFT_TO_RIGHT:
+ return com.ibm.icu.text.Bidi.DIRECTION_LEFT_TO_RIGHT;
+ case DIRECTION_RIGHT_TO_LEFT:
+ return com.ibm.icu.text.Bidi.DIRECTION_RIGHT_TO_LEFT;
+ // If the parameter was unrecognized use LEFT_TO_RIGHT.
+ default:
+ return com.ibm.icu.text.Bidi.DIRECTION_LEFT_TO_RIGHT;
}
}
+ private boolean isUnidirectional() {
+ return icuBidi.getRunCount() == 0;
+ }
+
+ private final com.ibm.icu.text.Bidi icuBidi;
+
/**
* Creates a {@code Bidi} object from the {@code
* AttributedCharacterIterator} of a paragraph text. The RUN_DIRECTION
@@ -114,65 +104,7 @@
throw new IllegalArgumentException("paragraph is null");
}
- int begin = paragraph.getBeginIndex();
- int end = paragraph.getEndIndex();
- int length = end - begin;
- char[] text = new char[length + 1]; // One more char for AttributedCharacterIterator.DONE
-
- if (length != 0) {
- text[0] = paragraph.first();
- } else {
- paragraph.first();
- }
-
- // First check the RUN_DIRECTION attribute.
- int flags = DIRECTION_DEFAULT_LEFT_TO_RIGHT;
- Object direction = paragraph.getAttribute(TextAttribute.RUN_DIRECTION);
- if (direction != null && direction instanceof Boolean) {
- if (direction.equals(TextAttribute.RUN_DIRECTION_LTR)) {
- flags = DIRECTION_LEFT_TO_RIGHT;
- } else {
- flags = DIRECTION_RIGHT_TO_LEFT;
- }
- }
-
- // Retrieve the text and gather BIDI_EMBEDDINGS
- byte[] embeddings = null;
- for (int textLimit = 1, i = 1; i < length; textLimit = paragraph
- .getRunLimit(TextAttribute.BIDI_EMBEDDING)
- - begin + 1) {
- Object embedding = paragraph.getAttribute(TextAttribute.BIDI_EMBEDDING);
- if (embedding != null && embedding instanceof Integer) {
- int embLevel = ((Integer) embedding).intValue();
-
- if (embeddings == null) {
- embeddings = new byte[length];
- }
-
- for (; i < textLimit; i++) {
- text[i] = paragraph.next();
- embeddings[i - 1] = (byte) embLevel;
- }
- } else {
- for (; i < textLimit; i++) {
- text[i] = paragraph.next();
- }
- }
- }
-
- // Apply NumericShaper to the text
- Object numericShaper = paragraph.getAttribute(TextAttribute.NUMERIC_SHAPING);
- if (numericShaper != null && numericShaper instanceof NumericShaper) {
- ((NumericShaper) numericShaper).shape(text, 0, length);
- }
-
- long bidi = 0;
- try {
- bidi = createUBiDi(text, 0, embeddings, 0, length, flags);
- readBidiInfo(bidi);
- } finally {
- ubidi_close(bidi);
- }
+ this.icuBidi = new com.ibm.icu.text.Bidi(paragraph);
}
/**
@@ -214,13 +146,11 @@
if (text == null || text.length - textStart < paragraphLength) {
throw new IllegalArgumentException();
}
-
if (embeddings != null) {
if (embeddings.length - embStart < paragraphLength) {
throw new IllegalArgumentException();
}
}
-
if (textStart < 0) {
throw new IllegalArgumentException("Negative textStart value " + textStart);
}
@@ -231,13 +161,9 @@
throw new IllegalArgumentException("Negative paragraph length " + paragraphLength);
}
- long bidi = 0;
- try {
- bidi = createUBiDi(text, textStart, embeddings, embStart, paragraphLength, flags);
- readBidiInfo(bidi);
- } finally {
- ubidi_close(bidi);
- }
+ this.icuBidi = new com.ibm.icu.text.Bidi(text, textStart, embeddings, embStart,
+ paragraphLength, translateConstToIcu(flags));
+
}
/**
@@ -261,109 +187,18 @@
(paragraph == null ? 0 : paragraph.length()), flags);
}
- // create the native UBiDi struct, need to be closed with ubidi_close().
- private static long createUBiDi(char[] text, int textStart,
- byte[] embeddings, int embStart, int paragraphLength, int flags) {
- char[] realText = null;
- byte[] realEmbeddings = null;
-
- if (text == null || text.length - textStart < paragraphLength) {
- throw new IllegalArgumentException();
- }
- realText = new char[paragraphLength];
- System.arraycopy(text, textStart, realText, 0, paragraphLength);
-
- if (embeddings != null) {
- if (embeddings.length - embStart < paragraphLength) {
- throw new IllegalArgumentException();
- }
- if (paragraphLength > 0) {
- Bidi temp = new Bidi(text, textStart, null, 0, paragraphLength, flags);
- realEmbeddings = new byte[paragraphLength];
- System.arraycopy(temp.offsetLevel, 0, realEmbeddings, 0, paragraphLength);
- for (int i = 0; i < paragraphLength; i++) {
- byte e = embeddings[i];
- if (e < 0) {
- realEmbeddings[i] = (byte) (UBIDI_LEVEL_OVERRIDE - e);
- } else if (e > 0) {
- realEmbeddings[i] = e;
- } else {
- realEmbeddings[i] |= (byte) UBIDI_LEVEL_OVERRIDE;
- }
- }
- }
- }
-
- if (flags > 1 || flags < -2) {
- flags = 0;
- }
-
- long bidi = 0;
- boolean needsDeletion = true;
- try {
- bidi = ubidi_open();
- ubidi_setPara(bidi, realText, paragraphLength, flags, realEmbeddings);
- needsDeletion = false;
- } finally {
- if (needsDeletion) {
- ubidi_close(bidi);
- }
- }
- return bidi;
+ private Bidi(com.ibm.icu.text.Bidi icuBidi) {
+ this.icuBidi = icuBidi;
}
- /* private constructor used by createLineBidi() */
- private Bidi(long pBidi) {
- readBidiInfo(pBidi);
- }
-
- // read info from the native UBiDi struct
- private void readBidiInfo(long pBidi) {
- length = ubidi_getLength(pBidi);
-
- offsetLevel = (length == 0) ? null : ubidi_getLevels(pBidi);
-
- baseLevel = ubidi_getParaLevel(pBidi);
-
- int runCount = ubidi_countRuns(pBidi);
- if (runCount == 0) {
- unidirectional = true;
- runs = null;
- } else if (runCount < 0) {
- runs = null;
- } else {
- runs = ubidi_getRuns(pBidi);
-
- // Simplified case for one run which has the base level
- if (runCount == 1 && runs[0].getLevel() == baseLevel) {
- unidirectional = true;
- runs = null;
- }
- }
-
- direction = ubidi_getDirection(pBidi);
- }
-
- private int baseLevel;
-
- private int length;
-
- private byte[] offsetLevel;
-
- private Run[] runs;
-
- private int direction;
-
- private boolean unidirectional;
-
/**
* Returns whether the base level is from left to right.
*
* @return true if the base level is from left to right.
*/
public boolean baseIsLeftToRight() {
- return baseLevel % 2 == 0 ? true : false;
+ return icuBidi.baseIsLeftToRight();
}
/**
@@ -382,55 +217,36 @@
* than the length of this object's paragraph text.
*/
public Bidi createLineBidi(int lineStart, int lineLimit) {
- if (lineStart < 0 || lineLimit < 0 || lineLimit > length || lineStart > lineLimit) {
+ if (lineStart < 0 || lineLimit < 0 || lineLimit > getLength() || lineStart > lineLimit) {
throw new IllegalArgumentException("Invalid ranges (start=" + lineStart + ", " +
- "limit=" + lineLimit + ", length=" + length + ")");
+ "limit=" + lineLimit + ", length=" + getLength() + ")");
}
- char[] text = new char[this.length];
- Arrays.fill(text, 'a');
- byte[] embeddings = new byte[this.length];
- for (int i = 0; i < embeddings.length; i++) {
- embeddings[i] = (byte) -this.offsetLevel[i];
+ // In the special case where the start and end positions are the same, we return a new bidi
+ // instance which is empty. Note that the default constructor for an empty ICU4J bidi
+ // instance is not the same as passing in empty values. This way allows one to call
+ // .getLength() for example and return a correct value instead of an IllegalStateException
+ // being thrown, which happens in the case of using the empty constructor.
+ if (lineStart == lineLimit) {
+ return new Bidi(new com.ibm.icu.text.Bidi(new char[] {}, 0, new byte[] {}, 0, 0,
+ translateConstToIcu(DIRECTION_LEFT_TO_RIGHT)));
}
- int dir = this.baseIsLeftToRight()
- ? Bidi.DIRECTION_LEFT_TO_RIGHT
- : Bidi.DIRECTION_RIGHT_TO_LEFT;
- long parent = 0;
- try {
- parent = createUBiDi(text, 0, embeddings, 0, this.length, dir);
- if (lineStart == lineLimit) {
- return createEmptyLineBidi(parent);
- }
- return new Bidi(ubidi_setLine(parent, lineStart, lineLimit));
- } finally {
- ubidi_close(parent);
- }
- }
-
- private Bidi createEmptyLineBidi(long parent) {
- // ICU4C doesn't allow this case, but the RI does.
- Bidi result = new Bidi(parent);
- result.length = 0;
- result.offsetLevel = null;
- result.runs = null;
- result.unidirectional = true;
- return result;
+ return new Bidi(icuBidi.createLineBidi(lineStart, lineLimit));
}
/**
* Returns the base level.
*/
public int getBaseLevel() {
- return baseLevel;
+ return icuBidi.getBaseLevel();
}
/**
* Returns the length of the text.
*/
public int getLength() {
- return length;
+ return icuBidi.getLength();
}
/**
@@ -438,9 +254,9 @@
*/
public int getLevelAt(int offset) {
try {
- return offsetLevel[offset] & ~UBIDI_LEVEL_OVERRIDE;
- } catch (RuntimeException e) {
- return baseLevel;
+ return icuBidi.getLevelAt(offset);
+ } catch (IllegalArgumentException e) {
+ return getBaseLevel();
}
}
@@ -448,28 +264,43 @@
* Returns the number of runs in the text, at least 1.
*/
public int getRunCount() {
- return unidirectional ? 1 : runs.length;
+ return isUnidirectional() ? 1 : icuBidi.getRunCount();
}
/**
* Returns the level of the given run.
*/
public int getRunLevel(int run) {
- return unidirectional ? baseLevel : runs[run].getLevel();
+ // Paper over a the ICU4J behaviour of strictly enforcing run must be strictly less than
+ // the number of runs. Done to maintain compatibility with previous C implementation.
+ if (run == getRunCount()) {
+ return getBaseLevel();
+ }
+ return isUnidirectional() ? icuBidi.getBaseLevel() : icuBidi.getRunLevel(run);
}
/**
* Returns the limit offset of the given run.
*/
public int getRunLimit(int run) {
- return unidirectional ? length : runs[run].getLimit();
+ // Paper over a the ICU4J behaviour of strictly enforcing run must be strictly less than
+ // the number of runs. Done to maintain compatibility with previous C implementation.
+ if (run == getRunCount()) {
+ return getBaseLevel();
+ }
+ return isUnidirectional() ? icuBidi.getLength() : icuBidi.getRunLimit(run);
}
/**
* Returns the start offset of the given run.
*/
public int getRunStart(int run) {
- return unidirectional ? 0 : runs[run].getStart();
+ // Paper over a the ICU4J behaviour of strictly enforcing run must be strictly less than
+ // the number of runs. Done to maintain compatibility with previous C implementation.
+ if (run == getRunCount()) {
+ return getBaseLevel();
+ }
+ return isUnidirectional() ? 0 : icuBidi.getRunStart(run);
}
/**
@@ -477,14 +308,14 @@
* direction and the text direction is from left to right.
*/
public boolean isLeftToRight() {
- return direction == UBiDiDirection_UBIDI_LTR;
+ return icuBidi.isLeftToRight();
}
/**
* Returns true if the text direction is mixed.
*/
public boolean isMixed() {
- return direction == UBiDiDirection_UBIDI_MIXED;
+ return icuBidi.isMixed();
}
/**
@@ -492,7 +323,7 @@
* direction and the text direction is from right to left.
*/
public boolean isRightToLeft() {
- return direction == UBiDiDirection_UBIDI_RTL;
+ return icuBidi.isRightToLeft();
}
/**
@@ -519,6 +350,7 @@
*/
public static void reorderVisually(byte[] levels, int levelStart,
Object[] objects, int objectStart, int count) {
+
if (count < 0 || levelStart < 0 || objectStart < 0
|| count > levels.length - levelStart
|| count > objects.length - objectStart) {
@@ -527,17 +359,7 @@
", objectStart=" + objectStart + ", count=" + count + ")");
}
- byte[] realLevels = new byte[count];
- System.arraycopy(levels, levelStart, realLevels, 0, count);
-
- int[] indices = ubidi_reorderVisual(realLevels, count);
-
- ArrayList<Object> result = new ArrayList<Object>(count);
- for (int i = 0; i < count; i++) {
- result.add(objects[objectStart + indices[i]]);
- }
-
- System.arraycopy(result.toArray(), 0, objects, objectStart, count);
+ com.ibm.icu.text.Bidi.reorderVisually(levels, levelStart, objects, objectStart, count);
}
/**
@@ -562,33 +384,13 @@
throw new IllegalArgumentException();
}
- Bidi bidi = new Bidi(text, start, null, 0, limit - start, 0);
- return !bidi.isLeftToRight();
+ return com.ibm.icu.text.Bidi.requiresBidi(text, start, limit);
}
@Override
public String toString() {
return getClass().getName()
- + "[direction: " + direction + " baseLevel: " + baseLevel
- + " length: " + length + " runs: " + Arrays.toString(runs) + "]";
+ + "[direction: " + icuBidi.getDirection() + " baseLevel: " + icuBidi.getBaseLevel()
+ + " length: " + icuBidi.getLength() + " runs: " + icuBidi.getRunCount() + "]";
}
-
- // ICU4C constants.
- private static final int UBIDI_LEVEL_OVERRIDE = 0x80;
- private static final int UBiDiDirection_UBIDI_LTR = 0;
- private static final int UBiDiDirection_UBIDI_RTL = 1;
- private static final int UBiDiDirection_UBIDI_MIXED = 2;
-
- // ICU4C functions.
- private static native long ubidi_open();
- private static native void ubidi_close(long pBiDi);
- private static native void ubidi_setPara(long pBiDi, char[] text, int length, int paraLevel, byte[] embeddingLevels);
- private static native long ubidi_setLine(final long pParaBiDi, int start, int limit);
- private static native int ubidi_getDirection(final long pBiDi);
- private static native int ubidi_getLength(final long pBiDi);
- private static native byte ubidi_getParaLevel(final long pBiDi);
- private static native byte[] ubidi_getLevels(long pBiDi);
- private static native int ubidi_countRuns(long pBiDi);
- private static native Bidi.Run[] ubidi_getRuns(long pBidi);
- private static native int[] ubidi_reorderVisual(byte[] levels, int length);
}
diff --git a/luni/src/main/java/javax/crypto/Cipher.java b/luni/src/main/java/javax/crypto/Cipher.java
index b27ea88..c455119 100644
--- a/luni/src/main/java/javax/crypto/Cipher.java
+++ b/luni/src/main/java/javax/crypto/Cipher.java
@@ -512,8 +512,9 @@
// Try each of the transforms and keep track of the first exception
// encountered.
Exception cause = null;
- for (Transform transform : transforms) {
- if (provider != null) {
+
+ if (provider != null) {
+ for (Transform transform : transforms) {
Provider.Service service = provider.getService(SERVICE, transform.name);
if (service == null) {
continue;
@@ -521,22 +522,40 @@
return tryTransformWithProvider(initParams, transformParts, transform.needToSet,
service);
}
- ArrayList<Provider.Service> services = ENGINE.getServices(transform.name);
- if (services == null || services.isEmpty()) {
- continue;
- }
+ } else {
+ ArrayList<Provider.Service> services = ENGINE.getServices();
for (Provider.Service service : services) {
- if (initParams == null || initParams.key == null
- || service.supportsParameter(initParams.key)) {
- try {
- Engine.SpiAndProvider sap = tryTransformWithProvider(initParams,
- transformParts, transform.needToSet, service);
- if (sap != null) {
- return sap;
+ String serviceAlgorithmUC = service.getAlgorithm().toUpperCase(Locale.US);
+ for (Transform transform : transforms) {
+ // Check that this service offers the algorithm we're after
+ // since none of the services have been filtered yet.
+ boolean matchesAlgorithm = false;
+ if (transform.name.equals(serviceAlgorithmUC)) {
+ matchesAlgorithm = true;
+ } else {
+ for (String alias : Engine.door.getAliases(service)) {
+ if (transform.name.equals(alias.toUpperCase(Locale.US))) {
+ matchesAlgorithm = true;
+ break;
+ }
}
- } catch (Exception e) {
- if (cause == null) {
- cause = e;
+ }
+ if (!matchesAlgorithm) {
+ continue;
+ }
+
+ if (initParams == null || initParams.key == null
+ || service.supportsParameter(initParams.key)) {
+ try {
+ Engine.SpiAndProvider sap = tryTransformWithProvider(initParams,
+ transformParts, transform.needToSet, service);
+ if (sap != null) {
+ return sap;
+ }
+ } catch (Exception e) {
+ if (cause == null) {
+ cause = e;
+ }
}
}
}
diff --git a/luni/src/main/java/libcore/icu/AlphabeticIndex.java b/luni/src/main/java/libcore/icu/AlphabeticIndex.java
deleted file mode 100644
index 322384d..0000000
--- a/luni/src/main/java/libcore/icu/AlphabeticIndex.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * 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 libcore.icu;
-
-import java.util.Locale;
-
-/**
- * Exposes icu4c's AlphabeticIndex.
- */
-public final class AlphabeticIndex {
-
- /**
- * Exposes icu4c's ImmutableIndex (new to icu 51). This exposes a read-only,
- * thread safe snapshot view of an AlphabeticIndex at the moment it was
- * created, and allows for random access to buckets by index.
- */
- public static final class ImmutableIndex {
- private long peer;
-
- private ImmutableIndex(long peer) {
- this.peer = peer;
- }
-
- @Override protected synchronized void finalize() throws Throwable {
- try {
- destroy(peer);
- peer = 0;
- } finally {
- super.finalize();
- }
- }
-
- /**
- * Returns the number of the label buckets in this index.
- */
- public int getBucketCount() {
- return getBucketCount(peer);
- }
-
- /**
- * Returns the index of the bucket in which 's' should appear.
- * Function is synchronized because underlying routine walks an iterator
- * whose state is maintained inside the index object.
- */
- public int getBucketIndex(String s) {
- return getBucketIndex(peer, s);
- }
-
- /**
- * Returns the label for the bucket at the given index (as returned by getBucketIndex).
- */
- public String getBucketLabel(int index) {
- return getBucketLabel(peer, index);
- }
-
- private static native int getBucketCount(long peer);
- private static native int getBucketIndex(long peer, String s);
- private static native String getBucketLabel(long peer, int index);
- }
-
- private long peer;
-
- /**
- * Creates a new AlphabeticIndex for the given locale.
- */
- public AlphabeticIndex(Locale locale) {
- peer = create(locale.toString());
- }
-
- @Override protected synchronized void finalize() throws Throwable {
- try {
- destroy(peer);
- peer = 0;
- } finally {
- super.finalize();
- }
- }
-
- /**
- * Returns the max number of the label buckets allowed in this index.
- */
- public synchronized int getMaxLabelCount() {
- return getMaxLabelCount(peer);
- }
-
- /**
- * Sets the max number of the label buckets in this index.
- * (ICU 51 default is 99)
- */
- public synchronized AlphabeticIndex setMaxLabelCount(int count) {
- setMaxLabelCount(peer, count);
- return this;
- }
-
- /**
- * Adds the index characters from the given locale to the index.
- * The labels are added to those that are already in the index;
- * they do not replace the existing index characters.
- * The collation order for this index is not changed;
- * it remains that of the locale that was originally specified
- * when creating this index.
- */
- public synchronized AlphabeticIndex addLabels(Locale locale) {
- addLabels(peer, locale.toString());
- return this;
- }
-
- /**
- * Adds the index characters in the range between the specified start and
- * end code points, inclusive.
- */
- public synchronized AlphabeticIndex addLabelRange(int codePointStart, int codePointEnd) {
- addLabelRange(peer, codePointStart, codePointEnd);
- return this;
- }
-
- /**
- * Returns the number of the label buckets in this index.
- */
- public synchronized int getBucketCount() {
- return getBucketCount(peer);
- }
-
- /**
- * Returns the index of the bucket in which 's' should appear.
- * Function is synchronized because underlying routine walks an iterator
- * whose state is maintained inside the index object.
- */
- public synchronized int getBucketIndex(String s) {
- return getBucketIndex(peer, s);
- }
-
- /**
- * Returns the label for the bucket at the given index (as returned by getBucketIndex).
- */
- public synchronized String getBucketLabel(int index) {
- return getBucketLabel(peer, index);
- }
-
- /**
- * Returns an ImmutableIndex created from this AlphabeticIndex.
- */
- public synchronized ImmutableIndex getImmutableIndex() {
- return new ImmutableIndex(buildImmutableIndex(peer));
- }
-
- private static native long create(String locale);
- private static native void destroy(long peer);
- private static native int getMaxLabelCount(long peer);
- private static native void setMaxLabelCount(long peer, int count);
- private static native void addLabels(long peer, String locale);
- private static native void addLabelRange(long peer, int codePointStart, int codePointEnd);
- private static native int getBucketCount(long peer);
- private static native int getBucketIndex(long peer, String s);
- private static native String getBucketLabel(long peer, int index);
- private static native long buildImmutableIndex(long peer);
-}
diff --git a/luni/src/main/java/libcore/icu/NativeIDN.java b/luni/src/main/java/libcore/icu/NativeIDN.java
deleted file mode 100644
index db93379..0000000
--- a/luni/src/main/java/libcore/icu/NativeIDN.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * 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 libcore.icu;
-
-public final class NativeIDN {
- public static String toASCII(String s, int flags) {
- return convert(s, flags, true);
- }
-
- public static String toUnicode(String s, int flags) {
- try {
- return convert(s, flags, false);
- } catch (IllegalArgumentException ex) {
- // The RI documentation explicitly states that this method can't fail.
- // ICU4C disagrees, as does the RI in practice.
- // The RI just returns the input string if it can't
- return s;
- }
- }
-
- private static String convert(String s, int flags, boolean toAscii) {
- if (s == null) {
- throw new NullPointerException("s == null");
- }
- return convertImpl(s, flags, toAscii);
- }
- private static native String convertImpl(String s, int flags, boolean toAscii);
-
- private NativeIDN() {}
-}
diff --git a/luni/src/main/java/libcore/icu/TimeZoneNames.java b/luni/src/main/java/libcore/icu/TimeZoneNames.java
index 3413a5d..daa915e 100644
--- a/luni/src/main/java/libcore/icu/TimeZoneNames.java
+++ b/luni/src/main/java/libcore/icu/TimeZoneNames.java
@@ -22,6 +22,7 @@
import java.util.HashMap;
import java.util.Locale;
import java.util.TimeZone;
+import java.util.concurrent.TimeUnit;
import libcore.util.BasicLruCache;
import libcore.util.ZoneInfoDB;
@@ -58,7 +59,7 @@
}
@Override protected String[][] create(Locale locale) {
- long start = System.currentTimeMillis();
+ long start = System.nanoTime();
// Set up the 2D array used to hold the names. The first column contains the Olson ids.
String[][] result = new String[availableTimeZoneIds.length][5];
@@ -66,17 +67,17 @@
result[i][0] = availableTimeZoneIds[i];
}
- long nativeStart = System.currentTimeMillis();
+ long nativeStart = System.nanoTime();
fillZoneStrings(locale.toString(), result);
- long nativeEnd = System.currentTimeMillis();
+ long nativeEnd = System.nanoTime();
internStrings(result);
// Ending up in this method too often is an easy way to make your app slow, so we ensure
// it's easy to tell from the log (a) what we were doing, (b) how long it took, and
// (c) that it's all ICU's fault.
- long end = System.currentTimeMillis();
- long nativeDuration = nativeEnd - nativeStart;
- long duration = end - start;
+ long end = System.nanoTime();
+ long nativeDuration = TimeUnit.NANOSECONDS.toMillis(nativeEnd - nativeStart);
+ long duration = TimeUnit.NANOSECONDS.toMillis(end - start);
System.logI("Loaded time zone names for \"" + locale + "\" in " + duration + "ms" +
" (" + nativeDuration + "ms in ICU)");
return result;
diff --git a/luni/src/main/java/libcore/io/IoBridge.java b/luni/src/main/java/libcore/io/IoBridge.java
index fcb30dd..acf9b39 100644
--- a/luni/src/main/java/libcore/io/IoBridge.java
+++ b/luni/src/main/java/libcore/io/IoBridge.java
@@ -42,6 +42,8 @@
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+
import static android.system.OsConstants.*;
/**
@@ -149,7 +151,7 @@
IoUtils.setBlocking(fd, false);
// 2. call connect(2) non-blocking.
- long finishTimeMs = System.currentTimeMillis() + timeoutMs;
+ long finishTimeNanos = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(timeoutMs);
try {
Libcore.os.connect(fd, inetAddress, port);
IoUtils.setBlocking(fd, true); // 4. set the socket back to blocking.
@@ -164,7 +166,8 @@
// 3. loop using poll(2).
int remainingTimeoutMs;
do {
- remainingTimeoutMs = (int) (finishTimeMs - System.currentTimeMillis());
+ remainingTimeoutMs =
+ (int) TimeUnit.NANOSECONDS.toMillis(finishTimeNanos - System.nanoTime());
if (remainingTimeoutMs <= 0) {
throw new SocketTimeoutException(connectDetail(inetAddress, port, timeoutMs, null));
}
diff --git a/luni/src/main/java/org/apache/harmony/security/fortress/Engine.java b/luni/src/main/java/org/apache/harmony/security/fortress/Engine.java
index 1c794e5..3c929c4 100644
--- a/luni/src/main/java/org/apache/harmony/security/fortress/Engine.java
+++ b/luni/src/main/java/org/apache/harmony/security/fortress/Engine.java
@@ -152,6 +152,14 @@
}
/**
+ * Returns a list of all providers for this type of service or {@code null}
+ * if no matches were found.
+ */
+ public ArrayList<Provider.Service> getServices() {
+ return Services.getServices(serviceName);
+ }
+
+ /**
* Returns a list of all possible matches for a given algorithm. Returns
* {@code null} if no matches were found.
*/
diff --git a/luni/src/main/java/org/apache/harmony/security/fortress/Services.java b/luni/src/main/java/org/apache/harmony/security/fortress/Services.java
index 234f4a2..232b6d2 100644
--- a/luni/src/main/java/org/apache/harmony/security/fortress/Services.java
+++ b/luni/src/main/java/org/apache/harmony/security/fortress/Services.java
@@ -21,7 +21,7 @@
import java.security.Security;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.Locale;
+import java.util.Iterator;
/**
@@ -134,12 +134,37 @@
}
/**
+ * Looks up the requested service by type. The service {@code type} and
+ * should be provided in the same format used when registering a service
+ * with a provider, for example, "KeyFactory". Callers can cache the
+ * returned service information but such caches should be validated against
+ * the result of Service.getCacheVersion() before use. Returns {@code null}
+ * if there are no services of the given {@code type} found.
+ */
+ public static synchronized ArrayList<Provider.Service> getServices(String type) {
+ ArrayList<Provider.Service> services = null;
+ for (Provider p : providers) {
+ Iterator<Provider.Service> i = p.getServices().iterator();
+ while (i.hasNext()) {
+ Provider.Service s = i.next();
+ if (type.equals(s.getType())) {
+ if (services == null) {
+ services = new ArrayList<>(providers.size());
+ }
+ services.add(s);
+ }
+ }
+ }
+ return services;
+ }
+
+ /**
* Looks up the requested service by type and algorithm. The service
* {@code type} and should be provided in the same format used when
- * registering a service with a provider, for example, "KeyFactory.RSA".
- * Callers can cache the returned service information but such caches should
- * be validated against the result of Service.getCacheVersion() before use.
- * Returns {@code null} if there are no services found.
+ * registering a service with a provider, for example, "KeyFactory" and
+ * "RSA". Callers can cache the returned service information but such caches
+ * should be validated against the result of Service.getCacheVersion()
+ * before use. Returns {@code null} if there are no services found.
*/
public static synchronized ArrayList<Provider.Service> getServices(String type,
String algorithm) {
diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp
index 0e30da7..c32e675 100644
--- a/luni/src/main/native/Register.cpp
+++ b/luni/src/main/native/Register.cpp
@@ -47,7 +47,6 @@
REGISTER(register_java_lang_StringToReal);
REGISTER(register_java_lang_System);
REGISTER(register_java_math_NativeBN);
- REGISTER(register_java_text_Bidi);
REGISTER(register_java_util_jar_StrictJarFile);
REGISTER(register_java_util_regex_Matcher);
REGISTER(register_java_util_regex_Pattern);
@@ -55,12 +54,10 @@
REGISTER(register_java_util_zip_CRC32);
REGISTER(register_java_util_zip_Deflater);
REGISTER(register_java_util_zip_Inflater);
- REGISTER(register_libcore_icu_AlphabeticIndex);
REGISTER(register_libcore_icu_ICU);
REGISTER(register_libcore_icu_NativeCollation);
REGISTER(register_libcore_icu_NativeConverter);
REGISTER(register_libcore_icu_NativeDecimalFormat);
- REGISTER(register_libcore_icu_NativeIDN);
REGISTER(register_libcore_icu_TimeZoneNames);
REGISTER(register_libcore_io_AsynchronousCloseMonitor);
REGISTER(register_libcore_io_Memory);
diff --git a/luni/src/main/native/java_text_Bidi.cpp b/luni/src/main/native/java_text_Bidi.cpp
deleted file mode 100644
index 6a3e751..0000000
--- a/luni/src/main/native/java_text_Bidi.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
-#define LOG_TAG "Bidi"
-
-#include "IcuUtilities.h"
-#include "JNIHelp.h"
-#include "JniConstants.h"
-#include "JniException.h"
-#include "ScopedPrimitiveArray.h"
-#include "unicode/ubidi.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <memory>
-
-struct BiDiData {
- BiDiData(UBiDi* biDi) : mBiDi(biDi) {
- }
-
- ~BiDiData() {
- ubidi_close(mBiDi);
- }
-
- UBiDiLevel* embeddingLevels() {
- return reinterpret_cast<UBiDiLevel*>(&mEmbeddingLevels[0]);
- }
-
- void setEmbeddingLevels(jbyte* newEmbeddingLevels) {
- mEmbeddingLevels.reset(newEmbeddingLevels);
- }
-
- UBiDi* uBiDi() {
- return mBiDi;
- }
-
-private:
- UBiDi* mBiDi;
- std::unique_ptr<jbyte[]> mEmbeddingLevels;
-
- // Disallow copy and assignment.
- BiDiData(const BiDiData&);
- void operator=(const BiDiData&);
-};
-
-static BiDiData* biDiData(jlong ptr) {
- return reinterpret_cast<BiDiData*>(static_cast<uintptr_t>(ptr));
-}
-
-static UBiDi* uBiDi(jlong ptr) {
- return reinterpret_cast<BiDiData*>(static_cast<uintptr_t>(ptr))->uBiDi();
-}
-
-static jlong Bidi_ubidi_open(JNIEnv*, jclass) {
- return reinterpret_cast<uintptr_t>(new BiDiData(ubidi_open()));
-}
-
-static void Bidi_ubidi_close(JNIEnv*, jclass, jlong ptr) {
- delete biDiData(ptr);
-}
-
-static void Bidi_ubidi_setPara(JNIEnv* env, jclass, jlong ptr, jcharArray text, jint length, jint paraLevel, jbyteArray newEmbeddingLevels) {
- BiDiData* data = biDiData(ptr);
- // Copy the new embedding levels from the Java heap to the native heap.
- if (newEmbeddingLevels != NULL) {
- jbyte* dst;
- data->setEmbeddingLevels(dst = new jbyte[length]);
- env->GetByteArrayRegion(newEmbeddingLevels, 0, length, dst);
- } else {
- data->setEmbeddingLevels(NULL);
- }
- ScopedCharArrayRO chars(env, text);
- if (chars.get() == NULL) {
- return;
- }
- UErrorCode err = U_ZERO_ERROR;
- ubidi_setPara(data->uBiDi(), chars.get(), length, paraLevel, data->embeddingLevels(), &err);
- maybeThrowIcuException(env, "ubidi_setPara", err);
-}
-
-static jlong Bidi_ubidi_setLine(JNIEnv* env, jclass, jlong ptr, jint start, jint limit) {
- UErrorCode status = U_ZERO_ERROR;
- UBiDi* sized = ubidi_openSized(limit - start, 0, &status);
- if (maybeThrowIcuException(env, "ubidi_openSized", status)) {
- return 0;
- }
- std::unique_ptr<BiDiData> lineData(new BiDiData(sized));
- ubidi_setLine(uBiDi(ptr), start, limit, lineData->uBiDi(), &status);
- maybeThrowIcuException(env, "ubidi_setLine", status);
- return reinterpret_cast<uintptr_t>(lineData.release());
-}
-
-static jint Bidi_ubidi_getDirection(JNIEnv*, jclass, jlong ptr) {
- return ubidi_getDirection(uBiDi(ptr));
-}
-
-static jint Bidi_ubidi_getLength(JNIEnv*, jclass, jlong ptr) {
- return ubidi_getLength(uBiDi(ptr));
-}
-
-static jbyte Bidi_ubidi_getParaLevel(JNIEnv*, jclass, jlong ptr) {
- return ubidi_getParaLevel(uBiDi(ptr));
-}
-
-static jbyteArray Bidi_ubidi_getLevels(JNIEnv* env, jclass, jlong ptr) {
- UErrorCode status = U_ZERO_ERROR;
- const UBiDiLevel* levels = ubidi_getLevels(uBiDi(ptr), &status);
- if (maybeThrowIcuException(env, "ubidi_getLevels", status)) {
- return NULL;
- }
- int len = ubidi_getLength(uBiDi(ptr));
- jbyteArray result = env->NewByteArray(len);
- env->SetByteArrayRegion(result, 0, len, reinterpret_cast<const jbyte*>(levels));
- return result;
-}
-
-static jint Bidi_ubidi_countRuns(JNIEnv* env, jclass, jlong ptr) {
- UErrorCode status = U_ZERO_ERROR;
- int count = ubidi_countRuns(uBiDi(ptr), &status);
- maybeThrowIcuException(env, "ubidi_countRuns", status);
- return count;
-}
-
-/**
- * TODO: if we care about performance, we might just want to use an int[] instead of a Run[].
- */
-static jobjectArray Bidi_ubidi_getRuns(JNIEnv* env, jclass, jlong ptr) {
- UBiDi* ubidi = uBiDi(ptr);
- UErrorCode status = U_ZERO_ERROR;
- int runCount = ubidi_countRuns(ubidi, &status);
- if (maybeThrowIcuException(env, "ubidi_countRuns", status)) {
- return NULL;
- }
- static jmethodID bidiRunConstructor =
- env->GetMethodID(JniConstants::bidiRunClass, "<init>", "(III)V");
- jobjectArray runs = env->NewObjectArray(runCount, JniConstants::bidiRunClass, NULL);
- UBiDiLevel level = 0;
- int start = 0;
- int limit = 0;
- for (int i = 0; i < runCount; ++i) {
- ubidi_getLogicalRun(ubidi, start, &limit, &level);
- jobject run = env->NewObject(JniConstants::bidiRunClass, bidiRunConstructor, start, limit, level);
- env->SetObjectArrayElement(runs, i, run);
- start = limit;
- }
- return runs;
-}
-
-static jintArray Bidi_ubidi_reorderVisual(JNIEnv* env, jclass, jbyteArray javaLevels, jint length) {
- ScopedByteArrayRO levelBytes(env, javaLevels);
- if (levelBytes.get() == NULL) {
- return NULL;
- }
-
- const UBiDiLevel* levels = reinterpret_cast<const UBiDiLevel*>(levelBytes.get());
-
- std::unique_ptr<int[]> indexMap(new int[length]);
- ubidi_reorderVisual(levels, length, &indexMap[0]);
-
- jintArray result = env->NewIntArray(length);
- env->SetIntArrayRegion(result, 0, length, &indexMap[0]);
- return result;
-}
-
-static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Bidi, ubidi_close, "(J)V"),
- NATIVE_METHOD(Bidi, ubidi_countRuns, "(J)I"),
- NATIVE_METHOD(Bidi, ubidi_getDirection, "(J)I"),
- NATIVE_METHOD(Bidi, ubidi_getLength, "(J)I"),
- NATIVE_METHOD(Bidi, ubidi_getLevels, "(J)[B"),
- NATIVE_METHOD(Bidi, ubidi_getParaLevel, "(J)B"),
- NATIVE_METHOD(Bidi, ubidi_getRuns, "(J)[Ljava/text/Bidi$Run;"),
- NATIVE_METHOD(Bidi, ubidi_open, "()J"),
- NATIVE_METHOD(Bidi, ubidi_reorderVisual, "([BI)[I"),
- NATIVE_METHOD(Bidi, ubidi_setLine, "(JII)J"),
- NATIVE_METHOD(Bidi, ubidi_setPara, "(J[CII[B)V"),
-};
-void register_java_text_Bidi(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/text/Bidi", gMethods, NELEM(gMethods));
-}
diff --git a/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp b/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
deleted file mode 100644
index acc247b..0000000
--- a/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "AlphabeticIndex"
-
-#include "IcuUtilities.h"
-#include "JNIHelp.h"
-#include "JniConstants.h"
-#include "JniException.h"
-#include "ScopedIcuLocale.h"
-#include "ScopedJavaUnicodeString.h"
-#include "unicode/alphaindex.h"
-#include "unicode/uniset.h"
-
-static icu::AlphabeticIndex* fromPeer(jlong peer) {
- return reinterpret_cast<icu::AlphabeticIndex*>(static_cast<uintptr_t>(peer));
-}
-
-static jlong AlphabeticIndex_create(JNIEnv* env, jclass, jstring javaLocaleName) {
- UErrorCode status = U_ZERO_ERROR;
- ScopedIcuLocale icuLocale(env, javaLocaleName);
- if (!icuLocale.valid()) {
- return 0;
- }
- icu::AlphabeticIndex* ai = new icu::AlphabeticIndex(icuLocale.locale(), status);
- if (maybeThrowIcuException(env, "AlphabeticIndex", status)) {
- return 0;
- }
- return reinterpret_cast<uintptr_t>(ai);
-}
-
-static void AlphabeticIndex_destroy(JNIEnv*, jclass, jlong peer) {
- delete fromPeer(peer);
-}
-
-static jint AlphabeticIndex_getMaxLabelCount(JNIEnv*, jclass, jlong peer) {
- icu::AlphabeticIndex* ai = fromPeer(peer);
- return ai->getMaxLabelCount();
-}
-
-static void AlphabeticIndex_setMaxLabelCount(JNIEnv* env, jclass, jlong peer, jint count) {
- icu::AlphabeticIndex* ai = fromPeer(peer);
- UErrorCode status = U_ZERO_ERROR;
- ai->setMaxLabelCount(count, status);
- maybeThrowIcuException(env, "AlphabeticIndex::setMaxLabelCount", status);
-}
-
-static void AlphabeticIndex_addLabels(JNIEnv* env, jclass, jlong peer, jstring javaLocaleName) {
- icu::AlphabeticIndex* ai = fromPeer(peer);
- ScopedIcuLocale icuLocale(env, javaLocaleName);
- if (!icuLocale.valid()) {
- return;
- }
- UErrorCode status = U_ZERO_ERROR;
- ai->addLabels(icuLocale.locale(), status);
- maybeThrowIcuException(env, "AlphabeticIndex::addLabels", status);
-}
-
-static void AlphabeticIndex_addLabelRange(JNIEnv* env, jclass, jlong peer,
- jint codePointStart, jint codePointEnd) {
- icu::AlphabeticIndex* ai = fromPeer(peer);
- UErrorCode status = U_ZERO_ERROR;
- ai->addLabels(icu::UnicodeSet(codePointStart, codePointEnd), status);
- maybeThrowIcuException(env, "AlphabeticIndex::addLabels", status);
-}
-
-static jint AlphabeticIndex_getBucketCount(JNIEnv* env, jclass, jlong peer) {
- icu::AlphabeticIndex* ai = fromPeer(peer);
- UErrorCode status = U_ZERO_ERROR;
- jint result = ai->getBucketCount(status);
- if (maybeThrowIcuException(env, "AlphabeticIndex::getBucketCount", status)) {
- return -1;
- }
- return result;
-}
-
-static jint AlphabeticIndex_getBucketIndex(JNIEnv* env, jclass, jlong peer, jstring javaString) {
- icu::AlphabeticIndex* ai = fromPeer(peer);
- ScopedJavaUnicodeString string(env, javaString);
- if (!string.valid()) {
- return -1;
- }
- UErrorCode status = U_ZERO_ERROR;
- jint result = ai->getBucketIndex(string.unicodeString(), status);
- if (maybeThrowIcuException(env, "AlphabeticIndex::getBucketIndex", status)) {
- return -1;
- }
- return result;
-}
-
-static jstring AlphabeticIndex_getBucketLabel(JNIEnv* env, jclass, jlong peer, jint index) {
- if (index < 0) {
- jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "Invalid index: %d", index);
- return NULL;
- }
-
- // Iterate to the nth bucket.
- icu::AlphabeticIndex* ai = fromPeer(peer);
- UErrorCode status = U_ZERO_ERROR;
- ai->resetBucketIterator(status);
- if (maybeThrowIcuException(env, "AlphabeticIndex::resetBucketIterator", status)) {
- return NULL;
- }
- for (jint i = 0; i <= index; ++i) {
- if (!ai->nextBucket(status)) {
- jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "Invalid index: %d", index);
- return NULL;
- }
- if (maybeThrowIcuException(env, "AlphabeticIndex::nextBucket", status)) {
- return NULL;
- }
- }
-
- // Return "" for the underflow/inflow/overflow buckets.
- if (ai->getBucketLabelType() != U_ALPHAINDEX_NORMAL) {
- return env->NewStringUTF("");
- }
-
- const icu::UnicodeString& label(ai->getBucketLabel());
- return env->NewString(label.getBuffer(), label.length());
-}
-
-static jlong AlphabeticIndex_buildImmutableIndex(JNIEnv* env, jclass, jlong peer) {
- icu::AlphabeticIndex* ai = fromPeer(peer);
- UErrorCode status = U_ZERO_ERROR;
- icu::AlphabeticIndex::ImmutableIndex* ii = ai->buildImmutableIndex(status);
- if (maybeThrowIcuException(env, "AlphabeticIndex::buildImmutableIndex", status)) {
- return 0;
- }
- return reinterpret_cast<uintptr_t>(ii);
-}
-
-static icu::AlphabeticIndex::ImmutableIndex* immutableIndexFromPeer(jlong peer) {
- return reinterpret_cast<icu::AlphabeticIndex::ImmutableIndex*>(static_cast<uintptr_t>(peer));
-}
-
-static jint ImmutableIndex_getBucketCount(JNIEnv*, jclass, jlong peer) {
- icu::AlphabeticIndex::ImmutableIndex* ii = immutableIndexFromPeer(peer);
- return ii->getBucketCount();
-}
-
-static jint ImmutableIndex_getBucketIndex(JNIEnv* env, jclass, jlong peer, jstring javaString) {
- icu::AlphabeticIndex::ImmutableIndex* ii = immutableIndexFromPeer(peer);
- ScopedJavaUnicodeString string(env, javaString);
- if (!string.valid()) {
- return -1;
- }
- UErrorCode status = U_ZERO_ERROR;
- jint result = ii->getBucketIndex(string.unicodeString(), status);
- if (maybeThrowIcuException(env, "AlphabeticIndex::ImmutableIndex::getBucketIndex", status)) {
- return -1;
- }
- return result;
-}
-
-static jstring ImmutableIndex_getBucketLabel(JNIEnv* env, jclass, jlong peer, jint index) {
- icu::AlphabeticIndex::ImmutableIndex* ii = immutableIndexFromPeer(peer);
- const icu::AlphabeticIndex::Bucket* bucket = ii->getBucket(index);
- if (bucket == NULL) {
- jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "Invalid index: %d", index);
- return NULL;
- }
-
- // Return "" for the underflow/inflow/overflow buckets.
- if (bucket->getLabelType() != U_ALPHAINDEX_NORMAL) {
- return env->NewStringUTF("");
- }
-
- const icu::UnicodeString& label(bucket->getLabel());
- return env->NewString(label.getBuffer(), label.length());
-}
-
-static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(AlphabeticIndex, create, "(Ljava/lang/String;)J"),
- NATIVE_METHOD(AlphabeticIndex, destroy, "(J)V"),
- NATIVE_METHOD(AlphabeticIndex, getMaxLabelCount, "(J)I"),
- NATIVE_METHOD(AlphabeticIndex, setMaxLabelCount, "(JI)V"),
- NATIVE_METHOD(AlphabeticIndex, addLabels, "(JLjava/lang/String;)V"),
- NATIVE_METHOD(AlphabeticIndex, addLabelRange, "(JII)V"),
- NATIVE_METHOD(AlphabeticIndex, getBucketCount, "(J)I"),
- NATIVE_METHOD(AlphabeticIndex, getBucketIndex, "(JLjava/lang/String;)I"),
- NATIVE_METHOD(AlphabeticIndex, getBucketLabel, "(JI)Ljava/lang/String;"),
- NATIVE_METHOD(AlphabeticIndex, buildImmutableIndex, "(J)J"),
-};
-static JNINativeMethod gImmutableIndexMethods[] = {
- NATIVE_METHOD(ImmutableIndex, getBucketCount, "(J)I"),
- NATIVE_METHOD(ImmutableIndex, getBucketIndex, "(JLjava/lang/String;)I"),
- NATIVE_METHOD(ImmutableIndex, getBucketLabel, "(JI)Ljava/lang/String;"),
-};
-void register_libcore_icu_AlphabeticIndex(JNIEnv* env) {
- jniRegisterNativeMethods(env, "libcore/icu/AlphabeticIndex", gMethods, NELEM(gMethods));
- jniRegisterNativeMethods(env, "libcore/icu/AlphabeticIndex$ImmutableIndex", gImmutableIndexMethods, NELEM(gImmutableIndexMethods));
-}
diff --git a/luni/src/main/native/libcore_icu_NativeIDN.cpp b/luni/src/main/native/libcore_icu_NativeIDN.cpp
deleted file mode 100644
index 43f3ce5..0000000
--- a/luni/src/main/native/libcore_icu_NativeIDN.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "NativeIDN"
-
-#include "JNIHelp.h"
-#include "JniConstants.h"
-#include "ScopedStringChars.h"
-#include "unicode/uidna.h"
-
-static bool isLabelSeparator(const UChar ch) {
- switch (ch) {
- case 0x3002: // ideographic full stop
- case 0xff0e: // fullwidth full stop
- case 0xff61: // halfwidth ideographic full stop
- return true;
- default:
- return false;
- }
-}
-
-static jstring NativeIDN_convertImpl(JNIEnv* env, jclass, jstring javaSrc, jint flags, jboolean toAscii) {
- ScopedStringChars src(env, javaSrc);
- if (src.get() == NULL) {
- return NULL;
- }
- UChar dst[256];
- UErrorCode status = U_ZERO_ERROR;
-
- // We're stuck implementing IDNA-2003 for now since that's what we specify.
- //
- // TODO: Change our spec to IDNA-2008 + UTS-46 compatibility processing if
- // it's safe enough.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
- size_t resultLength = toAscii
- ? uidna_IDNToASCII(src.get(), src.size(), &dst[0], sizeof(dst), flags, NULL, &status)
- : uidna_IDNToUnicode(src.get(), src.size(), &dst[0], sizeof(dst), flags, NULL, &status);
-#pragma GCC diagnostic pop
-
- if (U_FAILURE(status)) {
- jniThrowException(env, "java/lang/IllegalArgumentException", u_errorName(status));
- return NULL;
- }
- if (!toAscii) {
- // ICU only translates separators to ASCII for toASCII.
- // Java expects the translation for toUnicode too.
- // We may as well do this here, while the string is still mutable.
- for (size_t i = 0; i < resultLength; ++i) {
- if (isLabelSeparator(dst[i])) {
- dst[i] = '.';
- }
- }
- }
- return env->NewString(&dst[0], resultLength);
-}
-
-static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(NativeIDN, convertImpl, "(Ljava/lang/String;IZ)Ljava/lang/String;"),
-};
-void register_libcore_icu_NativeIDN(JNIEnv* env) {
- jniRegisterNativeMethods(env, "libcore/icu/NativeIDN", gMethods, NELEM(gMethods));
-}
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index 783a1bb..bfe2380 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -135,9 +135,9 @@
*/
#define NET_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ...) ({ \
return_type _rc = -1; \
+ int _syscallErrno; \
do { \
bool _wasSignaled; \
- int _syscallErrno; \
{ \
int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \
AsynchronousCloseMonitor _monitor(_fd); \
@@ -156,6 +156,10 @@
break; \
} \
} while (_rc == -1); /* _syscallErrno == EINTR && !_wasSignaled */ \
+ if (_rc == -1) { \
+ /* If the syscall failed, re-set errno: throwing an exception might have modified it. */ \
+ errno = _syscallErrno; \
+ } \
_rc; })
/**
@@ -170,9 +174,9 @@
*/
#define IO_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ...) ({ \
return_type _rc = -1; \
+ int _syscallErrno; \
do { \
bool _wasSignaled; \
- int _syscallErrno; \
{ \
int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \
AsynchronousCloseMonitor _monitor(_fd); \
@@ -191,6 +195,10 @@
break; \
} \
} while (_rc == -1); /* && _syscallErrno == EINTR && !_wasSignaled */ \
+ if (_rc == -1) { \
+ /* If the syscall failed, re-set errno: throwing an exception might have modified it. */ \
+ errno = _syscallErrno; \
+ } \
_rc; })
#define NULL_ADDR_OK true
diff --git a/luni/src/main/native/sub.mk b/luni/src/main/native/sub.mk
index ec39596..b227793 100644
--- a/luni/src/main/native/sub.mk
+++ b/luni/src/main/native/sub.mk
@@ -27,7 +27,6 @@
java_lang_StringToReal.cpp \
java_lang_System.cpp \
java_math_NativeBN.cpp \
- java_text_Bidi.cpp \
java_util_jar_StrictJarFile.cpp \
java_util_regex_Matcher.cpp \
java_util_regex_Pattern.cpp \
@@ -35,12 +34,10 @@
java_util_zip_CRC32.cpp \
java_util_zip_Deflater.cpp \
java_util_zip_Inflater.cpp \
- libcore_icu_AlphabeticIndex.cpp \
libcore_icu_ICU.cpp \
libcore_icu_NativeCollation.cpp \
libcore_icu_NativeConverter.cpp \
libcore_icu_NativeDecimalFormat.cpp \
- libcore_icu_NativeIDN.cpp \
libcore_icu_TimeZoneNames.cpp \
libcore_io_AsynchronousCloseMonitor.cpp \
libcore_io_Memory.cpp \
diff --git a/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java b/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java
deleted file mode 100644
index 6c7452d..0000000
--- a/luni/src/test/java/libcore/icu/AlphabeticIndexTest.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * 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 libcore.icu;
-
-import java.util.Locale;
-
-public class AlphabeticIndexTest extends junit.framework.TestCase {
- private static AlphabeticIndex.ImmutableIndex createIndex(Locale locale) {
- return new AlphabeticIndex(locale).addLabels(Locale.US).getImmutableIndex();
- }
-
- private static void assertHasLabel(AlphabeticIndex.ImmutableIndex ii, String string, String expectedLabel) {
- int index = ii.getBucketIndex(string);
- String label = ii.getBucketLabel(index);
- assertEquals(expectedLabel, label);
- }
-
- public void test_en() throws Exception {
- // English [A-Z]
- AlphabeticIndex.ImmutableIndex en = createIndex(Locale.ENGLISH);
- assertHasLabel(en, "Allen", "A");
- assertHasLabel(en, "allen", "A");
- }
-
- public void test_ja() throws Exception {
- AlphabeticIndex.ImmutableIndex ja = createIndex(Locale.JAPANESE);
-
- // Japanese
- // sorts hiragana/katakana, Kanji/Chinese, English, other
- // …, あ, か, さ, た, な, は, ま, や, ら, わ, …
- // hiragana "a"
- assertHasLabel(ja, "Allen", "A");
- assertHasLabel(ja, "\u3041", "\u3042");
- // katakana "a"
- assertHasLabel(ja, "\u30a1", "\u3042");
-
- // Kanji (sorts to inflow section)
- assertHasLabel(ja, "\u65e5", "");
-
- // http://bugs.icu-project.org/trac/ticket/10423 / http://b/10809397
- assertHasLabel(ja, "\u95c7", "");
- assertHasLabel(ja, "\u308f", "わ");
-
- // English
- assertHasLabel(ja, "Smith", "S");
-
- // Chinese (sorts to inflow section)
- assertHasLabel(ja, "\u6c88" /* Shen/Chen */, "");
-
- // Korean Hangul (sorts to overflow section)
- assertHasLabel(ja, "\u1100", "");
- }
-
- public void test_ko() throws Exception {
- // Korean (sorts Korean, then English)
- // …, ᄀ, ᄂ, ᄃ, ᄅ, ᄆ, ᄇ, ᄉ, ᄋ, ᄌ, ᄎ, ᄏ, ᄐ, ᄑ, ᄒ, …
- AlphabeticIndex.ImmutableIndex ko = createIndex(Locale.KOREAN);
- assertHasLabel(ko, "\u1100", "\u3131");
- assertHasLabel(ko, "\u3131", "\u3131");
- assertHasLabel(ko, "\u1101", "\u3131");
- assertHasLabel(ko, "\u1161", "\u314e");
- }
-
- public void test_cs() throws Exception {
- // Czech
- // …, [A-C], Č,[D-H], CH, [I-R], Ř, S, Š, [T-Z], Ž, …
- AlphabeticIndex.ImmutableIndex cs = createIndex(new Locale("cs"));
- assertHasLabel(cs, "Cena", "C");
- assertHasLabel(cs, "Čáp", "\u010c");
- assertHasLabel(cs, "Ruda", "R");
- assertHasLabel(cs, "Řada", "\u0158");
- assertHasLabel(cs, "Selka", "S");
- assertHasLabel(cs, "Šála", "\u0160");
- assertHasLabel(cs, "Zebra", "Z");
- assertHasLabel(cs, "Žába", "\u017d");
- assertHasLabel(cs, "Chata", "CH");
- }
-
- public void test_fr() throws Exception {
- // French: [A-Z] (no accented chars)
- AlphabeticIndex.ImmutableIndex fr = createIndex(Locale.FRENCH);
- assertHasLabel(fr, "Øfer", "O");
- assertHasLabel(fr, "Œster", "O");
- }
-
- public void test_da() throws Exception {
- // Danish: [A-Z], Æ, Ø, Å
- AlphabeticIndex.ImmutableIndex da = createIndex(new Locale("da"));
- assertHasLabel(da, "Ænes", "\u00c6");
- assertHasLabel(da, "Øfer", "\u00d8");
- assertHasLabel(da, "Œster", "\u00d8");
- assertHasLabel(da, "Ågård", "\u00c5");
- }
-
- public void test_de() throws Exception {
- // German: [A-Z] (no ß or umlauted characters in standard alphabet)
- AlphabeticIndex.ImmutableIndex de = createIndex(Locale.GERMAN);
- assertHasLabel(de, "ßind", "S");
- // We no longer split out "S", "Sch", and "St".
- assertHasLabel(de, "Sacher", "S");
- assertHasLabel(de, "Schiller", "S");
- assertHasLabel(de, "Steiff", "S");
- }
-
- public void test_th() throws Exception {
- // Thai (sorts English then Thai)
- // …, ก, ข, ฃ, ค, ฅ, ฆ, ง, จ, ฉ, ช, ซ, ฌ, ญ, ฎ, ฏ, ฐ, ฑ, ฒ, ณ, ด, ต, ถ, ท, ธ, น, บ, ป, ผ, ฝ, พ, ฟ, ภ, ม, ย, ร, ฤ, ล, ฦ, ว, ศ, ษ, ส, ห, ฬ, อ, ฮ, …,
- AlphabeticIndex.ImmutableIndex th = createIndex(new Locale("th"));
- assertHasLabel(th, "\u0e2d\u0e07\u0e04\u0e4c\u0e40\u0e25\u0e47\u0e01", "\u0e2d");
- assertHasLabel(th, "\u0e2a\u0e34\u0e07\u0e2b\u0e40\u0e2a\u0e19\u0e35", "\u0e2a");
- }
-
- public void test_ar() throws Exception {
- // Arabic (sorts English then Arabic)
- // …, ا, ب, ت, ث, ج, ح, خ, د, ذ, ر, ز, س, ش, ص, ض, ط, ظ, ع, غ, ف, ق, ك, ل, م, ن, ه, و, ي, …
- AlphabeticIndex.ImmutableIndex ar = createIndex(new Locale("ar"));
- assertHasLabel(ar, "\u0646\u0648\u0631", /* Noor */ "\u0646");
- }
-
- public void test_he() throws Exception {
- // Hebrew (sorts English then Hebrew)
- // …, א, ב, ג, ד, ה, ו, ז, ח, ט, י, כ, ל, מ, נ, ס, ע, פ, צ, ק, ר, ש, ת, …
- AlphabeticIndex.ImmutableIndex he = createIndex(new Locale("he"));
- assertHasLabel(he, "\u05e4\u05e8\u05d9\u05d3\u05de\u05df", "\u05e4");
- }
-
- public void test_zh_CN() throws Exception {
- // Simplified Chinese (default collator Pinyin): [A-Z]
- AlphabeticIndex.ImmutableIndex zh_CN = createIndex(new Locale("zh", "CN"));
-
- // Jia/Gu: should be, usually, 'J' for name collator and 'G' for apps/other
- assertHasLabel(zh_CN, "\u8d3e", "J");
-
- // Shen/Chen (simplified): should usually be 'S' for names and 'C' for apps/other.
- // icu4c does not specialize for names and defaults to 'C'.
- // Some OEMs prefer to default to 'S'.
- // We allow either to pass CTS since neither choice is right all the time.
- // assertHasLabel(zh_CN, "\u6c88", "C");
- String shenChenLabel = zh_CN.getBucketLabel(zh_CN.getBucketIndex("\u6c88"));
- assertTrue(shenChenLabel.equals("C") || shenChenLabel.equals("S"));
-
- // Shen/Chen (traditional)
- assertHasLabel(zh_CN, "\u700b", "S");
- }
-
- public void test_zh_HK() throws Exception {
- // Traditional Chinese (strokes).
- // …, [1-33, 35, 36, 39, 48]劃, …
- // Shen/Chen
- AlphabeticIndex.ImmutableIndex zh_HK = createIndex(new Locale("zh", "HK"));
- assertHasLabel(zh_HK, "\u6c88", "7\u5283");
- assertHasLabel(zh_HK, "\u700b", "18\u5283");
- // Jia/Gu
- assertHasLabel(zh_HK, "\u8d3e", "10\u5283");
- }
-
- public void test_constructor_NPE() throws Exception {
- try {
- new AlphabeticIndex(null);
- fail();
- } catch (NullPointerException expected) {
- }
- }
-
- public void test_addLabels_NPE() throws Exception {
- AlphabeticIndex ai = new AlphabeticIndex(Locale.US);
- try {
- ai.addLabels(null);
- fail();
- } catch (NullPointerException expected) {
- }
- }
-
- // ICU 51 default max label count is 99. Test to make sure can create an
- // index with a larger number of labels.
- public void test_setMaxLabelCount() throws Exception {
- final int MAX_LABEL_COUNT = 500;
- AlphabeticIndex ai = new AlphabeticIndex(Locale.US)
- .setMaxLabelCount(MAX_LABEL_COUNT)
- .addLabels(Locale.JAPANESE)
- .addLabels(Locale.KOREAN)
- .addLabels(new Locale("th"))
- .addLabels(new Locale("ar"))
- .addLabels(new Locale("he"))
- .addLabels(new Locale("el"))
- .addLabels(new Locale("ru"));
- assertEquals(MAX_LABEL_COUNT, ai.getMaxLabelCount());
- assertEquals(208, ai.getBucketCount());
- AlphabeticIndex.ImmutableIndex ii = ai.getImmutableIndex();
- assertEquals(ai.getBucketCount(), ii.getBucketCount());
- }
-
- public void test_getBucketIndex_NPE() throws Exception {
- AlphabeticIndex.ImmutableIndex ii = createIndex(Locale.US);
- try {
- ii.getBucketIndex(null);
- fail();
- } catch (NullPointerException expected) {
- }
- }
-
- public void test_getBucketLabel_invalid() throws Exception {
- AlphabeticIndex.ImmutableIndex ii = createIndex(Locale.US);
- try {
- ii.getBucketLabel(-1);
- fail();
- } catch (IllegalArgumentException expected) {
- }
-
- try {
- ii.getBucketLabel(123456);
- fail();
- } catch (IllegalArgumentException expected) {
- }
- }
-}
diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java
index f1d6668..1dcc3c6 100644
--- a/luni/src/test/java/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/io/OsTest.java
@@ -426,6 +426,23 @@
checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, false);
}
+ public void test_Ipv4Fallback() throws Exception {
+ // This number of iterations gives a ~60% chance of creating the conditions that caused
+ // http://b/23088314 without making test times too long. On a hammerhead running MRZ37C using
+ // vogar, this test takes about 4s.
+ final int ITERATIONS = 10000;
+ for (int i = 0; i < ITERATIONS; i++) {
+ FileDescriptor mUdpSock = Libcore.os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ try {
+ Libcore.os.bind(mUdpSock, Inet4Address.ANY, 0);
+ } catch(ErrnoException e) {
+ fail("ErrnoException after " + i + " iterations: " + e);
+ } finally {
+ Libcore.os.close(mUdpSock);
+ }
+ }
+ }
+
public void test_unlink() throws Exception {
File f = File.createTempFile("OsTest", "tst");
assertTrue(f.exists());
diff --git a/luni/src/test/java/libcore/java/io/SerializationTest.java b/luni/src/test/java/libcore/java/io/SerializationTest.java
index 32bc402..03e7d94 100644
--- a/luni/src/test/java/libcore/java/io/SerializationTest.java
+++ b/luni/src/test/java/libcore/java/io/SerializationTest.java
@@ -49,7 +49,9 @@
static class FieldMadeTransient implements Serializable {
private static final long serialVersionUID = 0L;
+ @SuppressWarnings("unused")
private transient int transientInt;
+ @SuppressWarnings("unused")
private int nonTransientInt;
}
@@ -64,7 +66,7 @@
+ "374244669656c644d6164655374617469630000000000000000020001490009737461746963496e7"
+ "47870000022b8";
FieldMadeStatic deserialized = (FieldMadeStatic) SerializationTester.deserializeHex(s);
- // The field data is simply ignored if it is static.
+ // The field data must be ignored if it is static.
assertEquals(9999, deserialized.staticInt);
}
@@ -74,73 +76,101 @@
private static int staticInt = 9999;
}
+ public static boolean serializableContainer1InitializedFlag = false;
+ public static boolean unserializable1InitializedFlag = false;
+
+ public static class Unserializable1 {
+ static {
+ SerializationTest.unserializable1InitializedFlag = true;
+ }
+ }
+
+ static class SerializableContainer1 implements Serializable {
+ private static final long serialVersionUID = 0L;
+ private Unserializable1 unserializable = null;
+
+ static {
+ serializableContainer1InitializedFlag = true;
+ }
+ }
+
// We can serialize an object that has an unserializable field providing it is null.
public void testDeserializeNullUnserializableField() throws Exception {
// This was created by creating a new SerializableContainer and not setting the
// unserializable field. A canned serialized form is used so we can tell if the static
// initializers were executed during deserialization.
- // SerializationTester.serializeHex(new SerializableContainer());
- String s = "aced0005737200376c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657"
- + "3742453657269616c697a61626c65436f6e7461696e657200000000000000000200014c000e756e7"
- + "3657269616c697a61626c657400334c6c6962636f72652f6a6176612f696f2f53657269616c697a6"
- + "174696f6e546573742457617353657269616c697a61626c653b787070";
+ // SerializationTester.serializeHex(new SerializableContainer1());
+ String s = "aced0005737200386c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657"
+ + "3742453657269616c697a61626c65436f6e7461696e65723100000000000000000200014c000e7"
+ + "56e73657269616c697a61626c657400124c6a6176612f6c616e672f4f626a6563743b787070";
- serializableContainerInitializedFlag = false;
- wasSerializableInitializedFlag = false;
+ assertFalse(serializableContainer1InitializedFlag);
+ assertFalse(unserializable1InitializedFlag);
- SerializableContainer sc = (SerializableContainer) SerializationTester.deserializeHex(s);
+ SerializableContainer1 sc = (SerializableContainer1) SerializationTester.deserializeHex(s);
assertNull(sc.unserializable);
// Confirm the container was initialized, but the class for the null field was not.
- assertTrue(serializableContainerInitializedFlag);
- assertFalse(wasSerializableInitializedFlag);
+ assertTrue(serializableContainer1InitializedFlag);
+ assertFalse(unserializable1InitializedFlag);
}
- public static boolean serializableContainerInitializedFlag = false;
+ static class Unserializable2 {
+ }
- static class SerializableContainer implements Serializable {
+ static class HasUnserializableField implements Serializable {
private static final long serialVersionUID = 0L;
- private Object unserializable = null;
-
- static {
- serializableContainerInitializedFlag = true;
- }
+ @SuppressWarnings("unused") // Required to make objects unserializable.
+ private Unserializable2 unserializable = new Unserializable2();
}
// We must not serialize an object that has a non-null unserializable field.
public void testSerializeUnserializableField() throws Exception {
- SerializableContainer sc = new SerializableContainer();
- sc.unserializable = new WasSerializable();
+ HasUnserializableField uf = new HasUnserializableField();
try {
- SerializationTester.serializeHex(sc);
+ SerializationTester.serializeHex(uf);
fail();
} catch (NotSerializableException expected) {
}
}
+ public static boolean serializableContainer2InitializedFlag = false;
+
+ @SuppressWarnings("unused") // Required for deserialization test
+ static class SerializableContainer2 implements Serializable {
+ private static final long serialVersionUID = 0L;
+ private WasSerializable unserializable = null;
+
+ static {
+ serializableContainer2InitializedFlag = true;
+ }
+ }
+
// It must not be possible to deserialize an object if a field is no longer serializable.
public void testDeserializeUnserializableField() throws Exception {
- // This was generated by creating a SerializableContainer and setting the unserializable
+ // This was generated by creating a SerializableContainer2 and setting the unserializable
// field to a WasSerializable when it was still Serializable. A canned serialized form is
// used so we can tell if the static initializers were executed during deserialization.
- // SerializableContainer sc = new SerializableContainer();
+ // SerializableContainer2 sc = new SerializableContainer2();
// sc.unserializable = new WasSerializable();
// SerializationTester.serializeHex(sc);
- String s = "aced0005737200376c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657"
- + "3742453657269616c697a61626c65436f6e7461696e657200000000000000000200014c000e756e7"
- + "3657269616c697a61626c657400124c6a6176612f6c616e672f4f626a6563743b7870737200316c6"
- + "962636f72652e6a6176612e696f2e53657269616c697a6174696f6e5465737424576173536572696"
- + "16c697a61626c65000000000000000002000149000169787000000000";
+ String s = "aced0005737200386c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657"
+ + "3742453657269616c697a61626c65436f6e7461696e65723200000000000000000200014c000e7"
+ + "56e73657269616c697a61626c657400334c6c6962636f72652f6a6176612f696f2f53657269616"
+ + "c697a6174696f6e546573742457617353657269616c697a61626c653b7870737200316c6962636"
+ + "f72652e6a6176612e696f2e53657269616c697a6174696f6e546573742457617353657269616c6"
+ + "97a61626c65000000000000000002000149000169787000000000";
- serializableContainerInitializedFlag = false;
- wasSerializableInitializedFlag = false;
+ assertFalse(serializableContainer2InitializedFlag);
+ assertFalse(wasSerializableInitializedFlag);
try {
SerializationTester.deserializeHex(s);
fail();
} catch (InvalidClassException expected) {
}
- // Confirm neither the container nor the contained class was initialized.
- assertFalse(serializableContainerInitializedFlag);
+ // The container class will be initialized to establish the serialVersionUID.
+ assertTrue(serializableContainer2InitializedFlag);
+ // Confirm the contained class was initialized.
assertFalse(wasSerializableInitializedFlag);
}
@@ -196,7 +226,7 @@
+ "e546573742457617353657269616c697a61626c65000000000000000002000149000169787000000"
+ "000";
- wasSerializableInitializedFlag = false;
+ assertFalse(wasSerializableInitializedFlag);
try {
SerializationTester.deserializeHex(s);
fail();
@@ -239,7 +269,7 @@
final String s = "aced0005737200336c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6"
+ "e546573742457617345787465726e616c697a61626c6500000000000000000c0000787078";
- wasExternalizableInitializedFlag = false;
+ assertFalse(wasExternalizableInitializedFlag);
try {
SerializationTester.deserializeHex(s);
fail();
@@ -275,7 +305,7 @@
+ "e5465737424576173456e756d00000000000000001200007872000e6a6176612e6c616e672e456e7"
+ "56d0000000000000000120000787074000556414c5545";
- wasEnumInitializedFlag = false;
+ assertFalse(wasEnumInitializedFlag);
try {
SerializationTester.deserializeHex(s);
fail();
@@ -309,7 +339,7 @@
final String s = "aced00057372002b6c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6"
+ "e54657374245761734f626a656374000000000000000002000149000169787000000000";
- wasObjectInitializedFlag = false;
+ assertFalse(wasObjectInitializedFlag);
try {
SerializationTester.deserializeHex(s);
fail();
diff --git a/luni/src/test/java/libcore/java/nio/charset/CharsetDecoderTest.java b/luni/src/test/java/libcore/java/nio/charset/CharsetDecoderTest.java
index 4fa6e0c..db2be53 100644
--- a/luni/src/test/java/libcore/java/nio/charset/CharsetDecoderTest.java
+++ b/luni/src/test/java/libcore/java/nio/charset/CharsetDecoderTest.java
@@ -85,7 +85,11 @@
private static byte[] encode(String charsetName, String s) throws Exception {
CharsetEncoder encoder = Charset.forName(charsetName).newEncoder();
- return encoder.encode(CharBuffer.wrap(s)).array();
+ ByteBuffer buf = encoder.encode(CharBuffer.wrap(s));
+ byte[] out = new byte[buf.remaining()];
+ buf.get(out);
+ assertEquals(0, buf.remaining());
+ return out;
}
public void testUtf8BytesSplitAcrossMultipleWrites() throws Exception {
diff --git a/luni/src/test/java/libcore/java/text/OldBidiTest.java b/luni/src/test/java/libcore/java/text/OldBidiTest.java
index 45fe258..fbf68ea 100644
--- a/luni/src/test/java/libcore/java/text/OldBidiTest.java
+++ b/luni/src/test/java/libcore/java/text/OldBidiTest.java
@@ -70,4 +70,126 @@
assertEquals(1, bd.getRunStart(1));
assertEquals(2, bd.getRunStart(2));
}
+
+ public void testReorderVisuallyIllegalArguments() {
+ // Negative index.
+ try {
+ Bidi.reorderVisually(new byte[] {}, -1, new Object[] {}, 0, 0);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+
+ try {
+ Bidi.reorderVisually(new byte[] {}, 0, new Object[] {}, -1, 0);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+
+ try {
+ Bidi.reorderVisually(new byte[] {}, 0, new Object[] {}, 0, -1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+
+ // Count > levels.length.
+ try {
+ Bidi.reorderVisually(new byte[] {}, 0, new Object[] {}, 0, 1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+
+ // Count > levels.length - levelStart.
+ try {
+ Bidi.reorderVisually(new byte[] {1, 2, 3}, 2, new Object[] {}, 0, 2);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+ }
+
+ public void testRequiresBidiIllegalArguments() {
+ // Negative param.
+ try {
+ Bidi.requiresBidi(new char[] {}, 0, -1);
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+
+ try {
+ Bidi.requiresBidi(new char[] {}, -1, 0);
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+
+ // Limit > start.
+ try {
+ Bidi.requiresBidi(new char[] {}, 1, 0);
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+
+ // Limit > text.length.
+ try {
+ Bidi.requiresBidi(new char[] {'a', 'b', 'c'}, 0, 4);
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+ }
+
+ public void testCreateLineBidiIllegalArguments() {
+ Bidi bidi = new Bidi("test", Bidi.DIRECTION_LEFT_TO_RIGHT);
+
+ try {
+ bidi.createLineBidi(-1, 0);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+
+ try {
+ bidi.createLineBidi(0, -1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+
+ // Linelimit > getLength().
+ try {
+ bidi.createLineBidi(0, 5);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+
+ // lineStart > lineLimit.
+ try {
+ bidi.createLineBidi(2, 1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+ }
+
+ public void testConstructorIllegalArguments() {
+ try {
+ new Bidi(null, Bidi.DIRECTION_LEFT_TO_RIGHT);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+
+ // text.length - textStart < paragraphLength.
+ try {
+ new Bidi(new char[] {'a', 'b', 'c', 'd', 'e'}, 1, new byte[] {}, 0, 5,
+ Bidi.DIRECTION_LEFT_TO_RIGHT);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ // Expected.
+ }
+ }
+
}
diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
index 13d54b4..bad8a74 100644
--- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
@@ -979,6 +979,76 @@
}
}
+ public void testCipher_getInstance_CorrectPriority_AlgorithmOnlyFirst() throws Exception {
+ Provider mockProviderOnlyAlgorithm = new MockProvider("MockProviderOnlyAlgorithm") {
+ public void setup() {
+ put("Cipher.FOO", MockCipherSpi.AllKeyTypes.class.getName());
+ }
+ };
+ Provider mockProviderFullTransformSpecified = new MockProvider("MockProviderFull") {
+ public void setup() {
+ put("Cipher.FOO/FOO/FOO", MockCipherSpi.AllKeyTypes.class.getName());
+ }
+ };
+
+ Security.addProvider(mockProviderOnlyAlgorithm);
+ Security.addProvider(mockProviderFullTransformSpecified);
+ try {
+ Cipher c = Cipher.getInstance("FOO/FOO/FOO");
+ assertEquals(mockProviderOnlyAlgorithm, c.getProvider());
+ } finally {
+ Security.removeProvider(mockProviderOnlyAlgorithm.getName());
+ Security.removeProvider(mockProviderFullTransformSpecified.getName());
+ }
+ }
+
+ public void testCipher_getInstance_CorrectPriority_FullTransformFirst() throws Exception {
+ Provider mockProviderOnlyAlgorithm = new MockProvider("MockProviderOnlyAlgorithm") {
+ public void setup() {
+ put("Cipher.FOO", MockCipherSpi.AllKeyTypes.class.getName());
+ }
+ };
+ Provider mockProviderFullTransformSpecified = new MockProvider("MockProviderFull") {
+ public void setup() {
+ put("Cipher.FOO/FOO/FOO", MockCipherSpi.AllKeyTypes.class.getName());
+ }
+ };
+
+ Security.addProvider(mockProviderFullTransformSpecified);
+ Security.addProvider(mockProviderOnlyAlgorithm);
+ try {
+ Cipher c = Cipher.getInstance("FOO/FOO/FOO");
+ assertEquals(mockProviderFullTransformSpecified, c.getProvider());
+ } finally {
+ Security.removeProvider(mockProviderOnlyAlgorithm.getName());
+ Security.removeProvider(mockProviderFullTransformSpecified.getName());
+ }
+ }
+
+ public void testCipher_getInstance_CorrectPriority_AliasedAlgorithmFirst() throws Exception {
+ Provider mockProviderAliasedAlgorithm = new MockProvider("MockProviderAliasedAlgorithm") {
+ public void setup() {
+ put("Cipher.BAR", MockCipherSpi.AllKeyTypes.class.getName());
+ put("Alg.Alias.Cipher.FOO", "BAR");
+ }
+ };
+ Provider mockProviderAlgorithmOnly = new MockProvider("MockProviderAlgorithmOnly") {
+ public void setup() {
+ put("Cipher.FOO", MockCipherSpi.AllKeyTypes.class.getName());
+ }
+ };
+
+ Security.addProvider(mockProviderAliasedAlgorithm);
+ Security.addProvider(mockProviderAlgorithmOnly);
+ try {
+ Cipher c = Cipher.getInstance("FOO/FOO/FOO");
+ assertEquals(mockProviderAliasedAlgorithm, c.getProvider());
+ } finally {
+ Security.removeProvider(mockProviderAliasedAlgorithm.getName());
+ Security.removeProvider(mockProviderAlgorithmOnly.getName());
+ }
+ }
+
public void testCipher_getInstance_WrongType_Failure() throws Exception {
Provider mockProviderInvalid = new MockProvider("MockProviderInvalid") {
public void setup() {