Merge "Remove UntrustedChecker"
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index ef7703e..04c5fcb 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -53,7 +53,7 @@
luni/src/main/java \
ojluni/src/main/resources/
test_resource_dirs := $(call all-core-resource-dirs,test)
-test_src_files := $(call all-test-java-files-under,dalvik dom harmony-tests json luni xml)
+test_src_files := $(call all-test-java-files-under,dalvik dalvik/test-rules dom harmony-tests json luni xml)
ojtest_src_files := $(call all-test-java-files-under,ojluni)
ifeq ($(EMMA_INSTRUMENT),true)
@@ -166,6 +166,24 @@
LOCAL_CORE_LIBRARY := true
include $(BUILD_JAVA_LIBRARY)
+# Build libcore test rules for target
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-java-files-under, dalvik/test-rules/src/main test-rules/src/main)
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_MODULE := core-test-rules
+LOCAL_JAVA_LIBRARIES := core-all core-junit
+LOCAL_STATIC_JAVA_LIBRARIES := junit4-target
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Build libcore test rules for host
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-java-files-under, dalvik/test-rules/src/main test-rules/src/main)
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_MODULE := core-test-rules-hostdex
+LOCAL_JAVA_LIBRARIES := core-oj-hostdex core-libart-hostdex core-junit-hostdex
+LOCAL_STATIC_JAVA_LIBRARIES := junit4-target-hostdex
+include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
+
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(non_openjdk_java_files) $(android_icu4j_src_files)
LOCAL_JAVA_RESOURCE_DIRS := $(android_icu4j_resource_dirs)
@@ -189,8 +207,14 @@
LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVA_LIBRARIES := core-oj core-libart okhttp core-junit junit4-target bouncycastle mockito-target
-LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support sqlite-jdbc mockwebserver nist-pkix-tests
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ core-test-rules \
+ core-tests-support \
+ mockwebserver \
+ nist-pkix-tests \
+ sqlite-jdbc
LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_ERROR_PRONE_FLAGS := -Xep:TryFailThrowable:ERROR
LOCAL_JAVA_LANGUAGE_VERSION := 1.8
LOCAL_MODULE := core-tests
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
@@ -329,14 +353,14 @@
LOCAL_CORE_LIBRARY := true
include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
-# Make the core-tests library.
+# Make the core-tests-hostdex library.
ifeq ($(LIBCORE_SKIP_TESTS),)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(test_src_files)
LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVA_LIBRARIES := core-oj-hostdex core-libart-hostdex okhttp-hostdex bouncycastle-hostdex core-junit-hostdex junit4-target-hostdex core-tests-support-hostdex mockito-api-hostdex
- LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host
+ LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host core-test-rules-hostdex
LOCAL_JAVACFLAGS := $(local_javac_flags)
LOCAL_MODULE_TAGS := optional
LOCAL_JAVA_LANGUAGE_VERSION := 1.8
@@ -416,6 +440,7 @@
-title "libcore" \
-proofread $(OUT_DOCS)/$(LOCAL_MODULE)-proofread.txt \
-todo ../$(LOCAL_MODULE)-docs-todo.html \
+ -knowntags ./libcore/known_oj_tags.txt \
-hdf android.whichdoc offline
LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
diff --git a/NativeCode.mk b/NativeCode.mk
index 7c3efbc..85bd4a0 100644
--- a/NativeCode.mk
+++ b/NativeCode.mk
@@ -80,7 +80,7 @@
core_shared_libraries := $(LOCAL_SHARED_LIBRARIES)
core_static_libraries := $(LOCAL_STATIC_LIBRARIES)
libart_cflags := $(LOCAL_CFLAGS) -Wall -Wextra -Werror
-core_cppflags += -std=gnu++11 -DU_USING_ICU_NAMESPACE=0
+core_cppflags += -DU_USING_ICU_NAMESPACE=0
# TODO(narayan): Prune down this list of exclusions once the underlying
# issues have been fixed. Most of these are small changes except for
# -Wunused-parameter.
@@ -169,6 +169,7 @@
LOCAL_C_INCLUDES += libcore/include
LOCAL_SHARED_LIBRARIES += libnativehelper_compat_libc++
LOCAL_MODULE_TAGS := optional
+LOCAL_STRIP_MODULE := keep_symbols
LOCAL_MODULE := libjavacoretests
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
LOCAL_CXX_STL := libc++
diff --git a/benchmarks/src/benchmarks/CloneBenchmark.java b/benchmarks/src/benchmarks/CloneBenchmark.java
new file mode 100644
index 0000000..d05fb3d
--- /dev/null
+++ b/benchmarks/src/benchmarks/CloneBenchmark.java
@@ -0,0 +1,1071 @@
+/*
+ * Copyright (C) 2016 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;
+
+public class CloneBenchmark {
+ static class CloneableObject implements Cloneable {
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+ }
+
+ static class CloneableManyFieldObject implements Cloneable {
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+ Object o1 = new Object();
+ Object o2 = new Object();
+ Object o3 = new Object();
+ Object o4 = new Object();
+ Object o5 = new Object();
+ Object o6 = new Object();
+ Object o7 = new Object();
+ Object o8 = new Object();
+ Object o9 = new Object();
+ Object o10 = new Object();
+ Object o11 = new Object();
+ Object o12 = new Object();
+ Object o13 = new Object();
+ Object o14 = new Object();
+ Object o15 = new Object();
+ Object o16 = new Object();
+ Object o17 = new Object();
+ Object o18 = new Object();
+ Object o19 = new Object();
+ Object o20 = new Object();
+ Object o21 = new Object();
+ Object o22 = new Object();
+ Object o23 = new Object();
+ Object o24 = new Object();
+ Object o25 = new Object();
+ Object o26 = new Object();
+ Object o27 = new Object();
+ Object o28 = new Object();
+ Object o29 = new Object();
+ Object o30 = new Object();
+ Object o31 = new Object();
+ Object o32 = new Object();
+ Object o33 = new Object();
+ Object o34 = new Object();
+ Object o35 = new Object();
+ Object o36 = new Object();
+ Object o37 = new Object();
+ Object o38 = new Object();
+ Object o39 = new Object();
+ Object o40 = new Object();
+ Object o41 = new Object();
+ Object o42 = new Object();
+ Object o43 = new Object();
+ Object o44 = new Object();
+ Object o45 = new Object();
+ Object o46 = new Object();
+ Object o47 = new Object();
+ Object o48 = new Object();
+ Object o49 = new Object();
+ Object o50 = new Object();
+ Object o51 = new Object();
+ Object o52 = new Object();
+ Object o53 = new Object();
+ Object o54 = new Object();
+ Object o55 = new Object();
+ Object o56 = new Object();
+ Object o57 = new Object();
+ Object o58 = new Object();
+ Object o59 = new Object();
+ Object o60 = new Object();
+ Object o61 = new Object();
+ Object o62 = new Object();
+ Object o63 = new Object();
+ Object o64 = new Object();
+ Object o65 = new Object();
+ Object o66 = new Object();
+ Object o67 = new Object();
+ Object o68 = new Object();
+ Object o69 = new Object();
+ Object o70 = new Object();
+ Object o71 = new Object();
+ Object o72 = new Object();
+ Object o73 = new Object();
+ Object o74 = new Object();
+ Object o75 = new Object();
+ Object o76 = new Object();
+ Object o77 = new Object();
+ Object o78 = new Object();
+ Object o79 = new Object();
+ Object o80 = new Object();
+ Object o81 = new Object();
+ Object o82 = new Object();
+ Object o83 = new Object();
+ Object o84 = new Object();
+ Object o85 = new Object();
+ Object o86 = new Object();
+ Object o87 = new Object();
+ Object o88 = new Object();
+ Object o89 = new Object();
+ Object o90 = new Object();
+ Object o91 = new Object();
+ Object o92 = new Object();
+ Object o93 = new Object();
+ Object o94 = new Object();
+ Object o95 = new Object();
+ Object o96 = new Object();
+ Object o97 = new Object();
+ Object o98 = new Object();
+ Object o99 = new Object();
+ Object o100 = new Object();
+ Object o101 = new Object();
+ Object o102 = new Object();
+ Object o103 = new Object();
+ Object o104 = new Object();
+ Object o105 = new Object();
+ Object o106 = new Object();
+ Object o107 = new Object();
+ Object o108 = new Object();
+ Object o109 = new Object();
+ Object o110 = new Object();
+ Object o111 = new Object();
+ Object o112 = new Object();
+ Object o113 = new Object();
+ Object o114 = new Object();
+ Object o115 = new Object();
+ Object o116 = new Object();
+ Object o117 = new Object();
+ Object o118 = new Object();
+ Object o119 = new Object();
+ Object o120 = new Object();
+ Object o121 = new Object();
+ Object o122 = new Object();
+ Object o123 = new Object();
+ Object o124 = new Object();
+ Object o125 = new Object();
+ Object o126 = new Object();
+ Object o127 = new Object();
+ Object o128 = new Object();
+ Object o129 = new Object();
+ Object o130 = new Object();
+ Object o131 = new Object();
+ Object o132 = new Object();
+ Object o133 = new Object();
+ Object o134 = new Object();
+ Object o135 = new Object();
+ Object o136 = new Object();
+ Object o137 = new Object();
+ Object o138 = new Object();
+ Object o139 = new Object();
+ Object o140 = new Object();
+ Object o141 = new Object();
+ Object o142 = new Object();
+ Object o143 = new Object();
+ Object o144 = new Object();
+ Object o145 = new Object();
+ Object o146 = new Object();
+ Object o147 = new Object();
+ Object o148 = new Object();
+ Object o149 = new Object();
+ Object o150 = new Object();
+ Object o151 = new Object();
+ Object o152 = new Object();
+ Object o153 = new Object();
+ Object o154 = new Object();
+ Object o155 = new Object();
+ Object o156 = new Object();
+ Object o157 = new Object();
+ Object o158 = new Object();
+ Object o159 = new Object();
+ Object o160 = new Object();
+ Object o161 = new Object();
+ Object o162 = new Object();
+ Object o163 = new Object();
+ Object o164 = new Object();
+ Object o165 = new Object();
+ Object o166 = new Object();
+ Object o167 = new Object();
+ Object o168 = new Object();
+ Object o169 = new Object();
+ Object o170 = new Object();
+ Object o171 = new Object();
+ Object o172 = new Object();
+ Object o173 = new Object();
+ Object o174 = new Object();
+ Object o175 = new Object();
+ Object o176 = new Object();
+ Object o177 = new Object();
+ Object o178 = new Object();
+ Object o179 = new Object();
+ Object o180 = new Object();
+ Object o181 = new Object();
+ Object o182 = new Object();
+ Object o183 = new Object();
+ Object o184 = new Object();
+ Object o185 = new Object();
+ Object o186 = new Object();
+ Object o187 = new Object();
+ Object o188 = new Object();
+ Object o189 = new Object();
+ Object o190 = new Object();
+ Object o191 = new Object();
+ Object o192 = new Object();
+ Object o193 = new Object();
+ Object o194 = new Object();
+ Object o195 = new Object();
+ Object o196 = new Object();
+ Object o197 = new Object();
+ Object o198 = new Object();
+ Object o199 = new Object();
+ Object o200 = new Object();
+ Object o201 = new Object();
+ Object o202 = new Object();
+ Object o203 = new Object();
+ Object o204 = new Object();
+ Object o205 = new Object();
+ Object o206 = new Object();
+ Object o207 = new Object();
+ Object o208 = new Object();
+ Object o209 = new Object();
+ Object o210 = new Object();
+ Object o211 = new Object();
+ Object o212 = new Object();
+ Object o213 = new Object();
+ Object o214 = new Object();
+ Object o215 = new Object();
+ Object o216 = new Object();
+ Object o217 = new Object();
+ Object o218 = new Object();
+ Object o219 = new Object();
+ Object o220 = new Object();
+ Object o221 = new Object();
+ Object o222 = new Object();
+ Object o223 = new Object();
+ Object o224 = new Object();
+ Object o225 = new Object();
+ Object o226 = new Object();
+ Object o227 = new Object();
+ Object o228 = new Object();
+ Object o229 = new Object();
+ Object o230 = new Object();
+ Object o231 = new Object();
+ Object o232 = new Object();
+ Object o233 = new Object();
+ Object o234 = new Object();
+ Object o235 = new Object();
+ Object o236 = new Object();
+ Object o237 = new Object();
+ Object o238 = new Object();
+ Object o239 = new Object();
+ Object o240 = new Object();
+ Object o241 = new Object();
+ Object o242 = new Object();
+ Object o243 = new Object();
+ Object o244 = new Object();
+ Object o245 = new Object();
+ Object o246 = new Object();
+ Object o247 = new Object();
+ Object o248 = new Object();
+ Object o249 = new Object();
+ Object o250 = new Object();
+ Object o251 = new Object();
+ Object o252 = new Object();
+ Object o253 = new Object();
+ Object o254 = new Object();
+ Object o255 = new Object();
+ Object o256 = new Object();
+ Object o257 = new Object();
+ Object o258 = new Object();
+ Object o259 = new Object();
+ Object o260 = new Object();
+ Object o261 = new Object();
+ Object o262 = new Object();
+ Object o263 = new Object();
+ Object o264 = new Object();
+ Object o265 = new Object();
+ Object o266 = new Object();
+ Object o267 = new Object();
+ Object o268 = new Object();
+ Object o269 = new Object();
+ Object o270 = new Object();
+ Object o271 = new Object();
+ Object o272 = new Object();
+ Object o273 = new Object();
+ Object o274 = new Object();
+ Object o275 = new Object();
+ Object o276 = new Object();
+ Object o277 = new Object();
+ Object o278 = new Object();
+ Object o279 = new Object();
+ Object o280 = new Object();
+ Object o281 = new Object();
+ Object o282 = new Object();
+ Object o283 = new Object();
+ Object o284 = new Object();
+ Object o285 = new Object();
+ Object o286 = new Object();
+ Object o287 = new Object();
+ Object o288 = new Object();
+ Object o289 = new Object();
+ Object o290 = new Object();
+ Object o291 = new Object();
+ Object o292 = new Object();
+ Object o293 = new Object();
+ Object o294 = new Object();
+ Object o295 = new Object();
+ Object o296 = new Object();
+ Object o297 = new Object();
+ Object o298 = new Object();
+ Object o299 = new Object();
+ Object o300 = new Object();
+ Object o301 = new Object();
+ Object o302 = new Object();
+ Object o303 = new Object();
+ Object o304 = new Object();
+ Object o305 = new Object();
+ Object o306 = new Object();
+ Object o307 = new Object();
+ Object o308 = new Object();
+ Object o309 = new Object();
+ Object o310 = new Object();
+ Object o311 = new Object();
+ Object o312 = new Object();
+ Object o313 = new Object();
+ Object o314 = new Object();
+ Object o315 = new Object();
+ Object o316 = new Object();
+ Object o317 = new Object();
+ Object o318 = new Object();
+ Object o319 = new Object();
+ Object o320 = new Object();
+ Object o321 = new Object();
+ Object o322 = new Object();
+ Object o323 = new Object();
+ Object o324 = new Object();
+ Object o325 = new Object();
+ Object o326 = new Object();
+ Object o327 = new Object();
+ Object o328 = new Object();
+ Object o329 = new Object();
+ Object o330 = new Object();
+ Object o331 = new Object();
+ Object o332 = new Object();
+ Object o333 = new Object();
+ Object o334 = new Object();
+ Object o335 = new Object();
+ Object o336 = new Object();
+ Object o337 = new Object();
+ Object o338 = new Object();
+ Object o339 = new Object();
+ Object o340 = new Object();
+ Object o341 = new Object();
+ Object o342 = new Object();
+ Object o343 = new Object();
+ Object o344 = new Object();
+ Object o345 = new Object();
+ Object o346 = new Object();
+ Object o347 = new Object();
+ Object o348 = new Object();
+ Object o349 = new Object();
+ Object o350 = new Object();
+ Object o351 = new Object();
+ Object o352 = new Object();
+ Object o353 = new Object();
+ Object o354 = new Object();
+ Object o355 = new Object();
+ Object o356 = new Object();
+ Object o357 = new Object();
+ Object o358 = new Object();
+ Object o359 = new Object();
+ Object o360 = new Object();
+ Object o361 = new Object();
+ Object o362 = new Object();
+ Object o363 = new Object();
+ Object o364 = new Object();
+ Object o365 = new Object();
+ Object o366 = new Object();
+ Object o367 = new Object();
+ Object o368 = new Object();
+ Object o369 = new Object();
+ Object o370 = new Object();
+ Object o371 = new Object();
+ Object o372 = new Object();
+ Object o373 = new Object();
+ Object o374 = new Object();
+ Object o375 = new Object();
+ Object o376 = new Object();
+ Object o377 = new Object();
+ Object o378 = new Object();
+ Object o379 = new Object();
+ Object o380 = new Object();
+ Object o381 = new Object();
+ Object o382 = new Object();
+ Object o383 = new Object();
+ Object o384 = new Object();
+ Object o385 = new Object();
+ Object o386 = new Object();
+ Object o387 = new Object();
+ Object o388 = new Object();
+ Object o389 = new Object();
+ Object o390 = new Object();
+ Object o391 = new Object();
+ Object o392 = new Object();
+ Object o393 = new Object();
+ Object o394 = new Object();
+ Object o395 = new Object();
+ Object o396 = new Object();
+ Object o397 = new Object();
+ Object o398 = new Object();
+ Object o399 = new Object();
+ Object o400 = new Object();
+ Object o401 = new Object();
+ Object o402 = new Object();
+ Object o403 = new Object();
+ Object o404 = new Object();
+ Object o405 = new Object();
+ Object o406 = new Object();
+ Object o407 = new Object();
+ Object o408 = new Object();
+ Object o409 = new Object();
+ Object o410 = new Object();
+ Object o411 = new Object();
+ Object o412 = new Object();
+ Object o413 = new Object();
+ Object o414 = new Object();
+ Object o415 = new Object();
+ Object o416 = new Object();
+ Object o417 = new Object();
+ Object o418 = new Object();
+ Object o419 = new Object();
+ Object o420 = new Object();
+ Object o421 = new Object();
+ Object o422 = new Object();
+ Object o423 = new Object();
+ Object o424 = new Object();
+ Object o425 = new Object();
+ Object o426 = new Object();
+ Object o427 = new Object();
+ Object o428 = new Object();
+ Object o429 = new Object();
+ Object o430 = new Object();
+ Object o431 = new Object();
+ Object o432 = new Object();
+ Object o433 = new Object();
+ Object o434 = new Object();
+ Object o435 = new Object();
+ Object o436 = new Object();
+ Object o437 = new Object();
+ Object o438 = new Object();
+ Object o439 = new Object();
+ Object o440 = new Object();
+ Object o441 = new Object();
+ Object o442 = new Object();
+ Object o460 = new Object();
+ Object o461 = new Object();
+ Object o462 = new Object();
+ Object o463 = new Object();
+ Object o464 = new Object();
+ Object o465 = new Object();
+ Object o466 = new Object();
+ Object o467 = new Object();
+ Object o468 = new Object();
+ Object o469 = new Object();
+ Object o470 = new Object();
+ Object o471 = new Object();
+ Object o472 = new Object();
+ Object o473 = new Object();
+ Object o474 = new Object();
+ Object o475 = new Object();
+ Object o476 = new Object();
+ Object o477 = new Object();
+ Object o478 = new Object();
+ Object o479 = new Object();
+ Object o480 = new Object();
+ Object o481 = new Object();
+ Object o482 = new Object();
+ Object o483 = new Object();
+ Object o484 = new Object();
+ Object o485 = new Object();
+ Object o486 = new Object();
+ Object o487 = new Object();
+ Object o488 = new Object();
+ Object o489 = new Object();
+ Object o490 = new Object();
+ Object o491 = new Object();
+ Object o492 = new Object();
+ Object o493 = new Object();
+ Object o494 = new Object();
+ Object o495 = new Object();
+ Object o496 = new Object();
+ Object o497 = new Object();
+ Object o498 = new Object();
+ Object o499 = new Object();
+ Object o500 = new Object();
+ Object o501 = new Object();
+ Object o502 = new Object();
+ Object o503 = new Object();
+ Object o504 = new Object();
+ Object o505 = new Object();
+ Object o506 = new Object();
+ Object o507 = new Object();
+ Object o508 = new Object();
+ Object o509 = new Object();
+ Object o510 = new Object();
+ Object o511 = new Object();
+ Object o512 = new Object();
+ Object o513 = new Object();
+ Object o514 = new Object();
+ Object o515 = new Object();
+ Object o516 = new Object();
+ Object o517 = new Object();
+ Object o518 = new Object();
+ Object o519 = new Object();
+ Object o520 = new Object();
+ Object o521 = new Object();
+ Object o522 = new Object();
+ Object o523 = new Object();
+ Object o556 = new Object();
+ Object o557 = new Object();
+ Object o558 = new Object();
+ Object o559 = new Object();
+ Object o560 = new Object();
+ Object o561 = new Object();
+ Object o562 = new Object();
+ Object o563 = new Object();
+ Object o564 = new Object();
+ Object o565 = new Object();
+ Object o566 = new Object();
+ Object o567 = new Object();
+ Object o568 = new Object();
+ Object o569 = new Object();
+ Object o570 = new Object();
+ Object o571 = new Object();
+ Object o572 = new Object();
+ Object o573 = new Object();
+ Object o574 = new Object();
+ Object o575 = new Object();
+ Object o576 = new Object();
+ Object o577 = new Object();
+ Object o578 = new Object();
+ Object o579 = new Object();
+ Object o580 = new Object();
+ Object o581 = new Object();
+ Object o582 = new Object();
+ Object o583 = new Object();
+ Object o584 = new Object();
+ Object o585 = new Object();
+ Object o586 = new Object();
+ Object o587 = new Object();
+ Object o588 = new Object();
+ Object o589 = new Object();
+ Object o590 = new Object();
+ Object o591 = new Object();
+ Object o592 = new Object();
+ Object o593 = new Object();
+ Object o594 = new Object();
+ Object o595 = new Object();
+ Object o596 = new Object();
+ Object o597 = new Object();
+ Object o598 = new Object();
+ Object o599 = new Object();
+ Object o600 = new Object();
+ Object o601 = new Object();
+ Object o602 = new Object();
+ Object o603 = new Object();
+ Object o604 = new Object();
+ Object o605 = new Object();
+ Object o606 = new Object();
+ Object o607 = new Object();
+ Object o608 = new Object();
+ Object o609 = new Object();
+ Object o610 = new Object();
+ Object o611 = new Object();
+ Object o612 = new Object();
+ Object o613 = new Object();
+ Object o614 = new Object();
+ Object o615 = new Object();
+ Object o616 = new Object();
+ Object o617 = new Object();
+ Object o618 = new Object();
+ Object o619 = new Object();
+ Object o620 = new Object();
+ Object o621 = new Object();
+ Object o622 = new Object();
+ Object o623 = new Object();
+ Object o624 = new Object();
+ Object o625 = new Object();
+ Object o626 = new Object();
+ Object o627 = new Object();
+ Object o628 = new Object();
+ Object o629 = new Object();
+ Object o630 = new Object();
+ Object o631 = new Object();
+ Object o632 = new Object();
+ Object o633 = new Object();
+ Object o634 = new Object();
+ Object o635 = new Object();
+ Object o636 = new Object();
+ Object o637 = new Object();
+ Object o638 = new Object();
+ Object o639 = new Object();
+ Object o640 = new Object();
+ Object o641 = new Object();
+ Object o642 = new Object();
+ Object o643 = new Object();
+ Object o644 = new Object();
+ Object o645 = new Object();
+ Object o646 = new Object();
+ Object o647 = new Object();
+ Object o648 = new Object();
+ Object o649 = new Object();
+ Object o650 = new Object();
+ Object o651 = new Object();
+ Object o652 = new Object();
+ Object o653 = new Object();
+ Object o654 = new Object();
+ Object o655 = new Object();
+ Object o656 = new Object();
+ Object o657 = new Object();
+ Object o658 = new Object();
+ Object o659 = new Object();
+ Object o660 = new Object();
+ Object o661 = new Object();
+ Object o662 = new Object();
+ Object o663 = new Object();
+ Object o664 = new Object();
+ Object o665 = new Object();
+ Object o666 = new Object();
+ Object o667 = new Object();
+ Object o668 = new Object();
+ Object o669 = new Object();
+ Object o670 = new Object();
+ Object o671 = new Object();
+ Object o672 = new Object();
+ Object o673 = new Object();
+ Object o674 = new Object();
+ Object o675 = new Object();
+ Object o676 = new Object();
+ Object o677 = new Object();
+ Object o678 = new Object();
+ Object o679 = new Object();
+ Object o680 = new Object();
+ Object o681 = new Object();
+ Object o682 = new Object();
+ Object o683 = new Object();
+ Object o684 = new Object();
+ Object o685 = new Object();
+ Object o686 = new Object();
+ Object o687 = new Object();
+ Object o688 = new Object();
+ Object o734 = new Object();
+ Object o735 = new Object();
+ Object o736 = new Object();
+ Object o737 = new Object();
+ Object o738 = new Object();
+ Object o739 = new Object();
+ Object o740 = new Object();
+ Object o741 = new Object();
+ Object o742 = new Object();
+ Object o743 = new Object();
+ Object o744 = new Object();
+ Object o745 = new Object();
+ Object o746 = new Object();
+ Object o747 = new Object();
+ Object o748 = new Object();
+ Object o749 = new Object();
+ Object o750 = new Object();
+ Object o751 = new Object();
+ Object o752 = new Object();
+ Object o753 = new Object();
+ Object o754 = new Object();
+ Object o755 = new Object();
+ Object o756 = new Object();
+ Object o757 = new Object();
+ Object o758 = new Object();
+ Object o759 = new Object();
+ Object o760 = new Object();
+ Object o761 = new Object();
+ Object o762 = new Object();
+ Object o763 = new Object();
+ Object o764 = new Object();
+ Object o765 = new Object();
+ Object o766 = new Object();
+ Object o767 = new Object();
+ Object o768 = new Object();
+ Object o769 = new Object();
+ Object o770 = new Object();
+ Object o771 = new Object();
+ Object o772 = new Object();
+ Object o773 = new Object();
+ Object o774 = new Object();
+ Object o775 = new Object();
+ Object o776 = new Object();
+ Object o777 = new Object();
+ Object o778 = new Object();
+ Object o779 = new Object();
+ Object o780 = new Object();
+ Object o781 = new Object();
+ Object o782 = new Object();
+ Object o783 = new Object();
+ Object o784 = new Object();
+ Object o785 = new Object();
+ Object o786 = new Object();
+ Object o787 = new Object();
+ Object o788 = new Object();
+ Object o789 = new Object();
+ Object o790 = new Object();
+ Object o791 = new Object();
+ Object o792 = new Object();
+ Object o793 = new Object();
+ Object o794 = new Object();
+ Object o795 = new Object();
+ Object o796 = new Object();
+ Object o797 = new Object();
+ Object o798 = new Object();
+ Object o799 = new Object();
+ Object o800 = new Object();
+ Object o801 = new Object();
+ Object o802 = new Object();
+ Object o803 = new Object();
+ Object o804 = new Object();
+ Object o805 = new Object();
+ Object o806 = new Object();
+ Object o807 = new Object();
+ Object o808 = new Object();
+ Object o809 = new Object();
+ Object o810 = new Object();
+ Object o811 = new Object();
+ Object o812 = new Object();
+ Object o813 = new Object();
+ Object o848 = new Object();
+ Object o849 = new Object();
+ Object o850 = new Object();
+ Object o851 = new Object();
+ Object o852 = new Object();
+ Object o853 = new Object();
+ Object o854 = new Object();
+ Object o855 = new Object();
+ Object o856 = new Object();
+ Object o857 = new Object();
+ Object o858 = new Object();
+ Object o859 = new Object();
+ Object o860 = new Object();
+ Object o861 = new Object();
+ Object o862 = new Object();
+ Object o863 = new Object();
+ Object o864 = new Object();
+ Object o865 = new Object();
+ Object o866 = new Object();
+ Object o867 = new Object();
+ Object o868 = new Object();
+ Object o869 = new Object();
+ Object o870 = new Object();
+ Object o871 = new Object();
+ Object o872 = new Object();
+ Object o873 = new Object();
+ Object o874 = new Object();
+ Object o875 = new Object();
+ Object o876 = new Object();
+ Object o877 = new Object();
+ Object o878 = new Object();
+ Object o879 = new Object();
+ Object o880 = new Object();
+ Object o881 = new Object();
+ Object o882 = new Object();
+ Object o883 = new Object();
+ Object o884 = new Object();
+ Object o885 = new Object();
+ Object o886 = new Object();
+ Object o887 = new Object();
+ Object o888 = new Object();
+ Object o889 = new Object();
+ Object o890 = new Object();
+ Object o891 = new Object();
+ Object o892 = new Object();
+ Object o893 = new Object();
+ Object o894 = new Object();
+ Object o895 = new Object();
+ Object o896 = new Object();
+ Object o897 = new Object();
+ Object o898 = new Object();
+ Object o899 = new Object();
+ Object o900 = new Object();
+ Object o901 = new Object();
+ Object o902 = new Object();
+ Object o903 = new Object();
+ Object o904 = new Object();
+ Object o905 = new Object();
+ Object o906 = new Object();
+ Object o907 = new Object();
+ Object o908 = new Object();
+ Object o909 = new Object();
+ Object o910 = new Object();
+ Object o911 = new Object();
+ Object o912 = new Object();
+ Object o913 = new Object();
+ Object o914 = new Object();
+ Object o915 = new Object();
+ Object o916 = new Object();
+ Object o917 = new Object();
+ Object o918 = new Object();
+ Object o919 = new Object();
+ Object o920 = new Object();
+ Object o921 = new Object();
+ Object o922 = new Object();
+ Object o923 = new Object();
+ Object o924 = new Object();
+ Object o925 = new Object();
+ Object o926 = new Object();
+ Object o927 = new Object();
+ Object o928 = new Object();
+ Object o929 = new Object();
+ Object o930 = new Object();
+ Object o931 = new Object();
+ Object o932 = new Object();
+ Object o933 = new Object();
+ Object o934 = new Object();
+ Object o935 = new Object();
+ Object o936 = new Object();
+ Object o937 = new Object();
+ Object o938 = new Object();
+ Object o939 = new Object();
+ Object o940 = new Object();
+ Object o941 = new Object();
+ Object o942 = new Object();
+ Object o943 = new Object();
+ Object o944 = new Object();
+ Object o945 = new Object();
+ Object o946 = new Object();
+ Object o947 = new Object();
+ Object o948 = new Object();
+ Object o949 = new Object();
+ Object o950 = new Object();
+ Object o951 = new Object();
+ Object o952 = new Object();
+ Object o953 = new Object();
+ Object o954 = new Object();
+ Object o955 = new Object();
+ Object o956 = new Object();
+ Object o957 = new Object();
+ Object o958 = new Object();
+ Object o959 = new Object();
+ Object o960 = new Object();
+ Object o961 = new Object();
+ Object o962 = new Object();
+ Object o963 = new Object();
+ Object o964 = new Object();
+ Object o965 = new Object();
+ Object o966 = new Object();
+ Object o967 = new Object();
+ Object o968 = new Object();
+ Object o969 = new Object();
+ Object o970 = new Object();
+ Object o971 = new Object();
+ Object o972 = new Object();
+ Object o973 = new Object();
+ Object o974 = new Object();
+ Object o975 = new Object();
+ Object o976 = new Object();
+ Object o977 = new Object();
+ Object o978 = new Object();
+ Object o979 = new Object();
+ Object o980 = new Object();
+ Object o981 = new Object();
+ Object o982 = new Object();
+ Object o983 = new Object();
+ Object o984 = new Object();
+ Object o985 = new Object();
+ Object o986 = new Object();
+ Object o987 = new Object();
+ Object o988 = new Object();
+ Object o989 = new Object();
+ Object o990 = new Object();
+ Object o991 = new Object();
+ Object o992 = new Object();
+ Object o993 = new Object();
+ Object o994 = new Object();
+ Object o995 = new Object();
+ Object o996 = new Object();
+ Object o997 = new Object();
+ Object o998 = new Object();
+ Object o999 = new Object();
+ }
+
+ static class Deep0 {}
+ static class Deep1 extends Deep0 {}
+ static class Deep2 extends Deep1 {}
+ static class Deep3 extends Deep2 {}
+ static class Deep4 extends Deep3 {}
+ static class Deep5 extends Deep4 {}
+ static class Deep6 extends Deep5 {}
+ static class Deep7 extends Deep6 {}
+ static class Deep8 extends Deep7 {}
+ static class Deep9 extends Deep8 {}
+ static class Deep10 extends Deep9 {}
+ static class Deep11 extends Deep10 {}
+ static class Deep12 extends Deep11 {}
+ static class Deep13 extends Deep12 {}
+ static class Deep14 extends Deep13 {}
+ static class Deep15 extends Deep14 {}
+ static class Deep16 extends Deep15 {}
+ static class Deep17 extends Deep16 {}
+ static class Deep18 extends Deep17 {}
+ static class Deep19 extends Deep18 {}
+ static class Deep20 extends Deep19 {}
+ static class Deep21 extends Deep20 {}
+ static class Deep22 extends Deep21 {}
+ static class Deep23 extends Deep22 {}
+ static class Deep24 extends Deep23 {}
+ static class Deep25 extends Deep24 {}
+ static class Deep26 extends Deep25 {}
+ static class Deep27 extends Deep26 {}
+ static class Deep28 extends Deep27 {}
+ static class Deep29 extends Deep28 {}
+ static class Deep30 extends Deep29 {}
+ static class Deep31 extends Deep30 {}
+ static class Deep32 extends Deep31 {}
+ static class Deep33 extends Deep32 {}
+ static class Deep34 extends Deep33 {}
+ static class Deep35 extends Deep34 {}
+ static class Deep36 extends Deep35 {}
+ static class Deep37 extends Deep36 {}
+ static class Deep38 extends Deep37 {}
+ static class Deep39 extends Deep38 {}
+ static class Deep40 extends Deep39 {}
+ static class Deep41 extends Deep40 {}
+ static class Deep42 extends Deep41 {}
+ static class Deep43 extends Deep42 {}
+ static class Deep44 extends Deep43 {}
+ static class Deep45 extends Deep44 {}
+ static class Deep46 extends Deep45 {}
+ static class Deep47 extends Deep46 {}
+ static class Deep48 extends Deep47 {}
+ static class Deep49 extends Deep48 {}
+ static class Deep50 extends Deep49 {}
+ static class Deep51 extends Deep50 {}
+ static class Deep52 extends Deep51 {}
+ static class Deep53 extends Deep52 {}
+ static class Deep54 extends Deep53 {}
+ static class Deep55 extends Deep54 {}
+ static class Deep56 extends Deep55 {}
+ static class Deep57 extends Deep56 {}
+ static class Deep58 extends Deep57 {}
+ static class Deep59 extends Deep58 {}
+ static class Deep60 extends Deep59 {}
+ static class Deep61 extends Deep60 {}
+ static class Deep62 extends Deep61 {}
+ static class Deep63 extends Deep62 {}
+ static class Deep64 extends Deep63 {}
+ static class Deep65 extends Deep64 {}
+ static class Deep66 extends Deep65 {}
+ static class Deep67 extends Deep66 {}
+ static class Deep68 extends Deep67 {}
+ static class Deep69 extends Deep68 {}
+ static class Deep70 extends Deep69 {}
+ static class Deep71 extends Deep70 {}
+ static class Deep72 extends Deep71 {}
+ static class Deep73 extends Deep72 {}
+ static class Deep74 extends Deep73 {}
+ static class Deep75 extends Deep74 {}
+ static class Deep76 extends Deep75 {}
+ static class Deep77 extends Deep76 {}
+ static class Deep78 extends Deep77 {}
+ static class Deep79 extends Deep78 {}
+ static class Deep80 extends Deep79 {}
+ static class Deep81 extends Deep80 {}
+ static class Deep82 extends Deep81 {}
+ static class Deep83 extends Deep82 {}
+ static class Deep84 extends Deep83 {}
+ static class Deep85 extends Deep84 {}
+ static class Deep86 extends Deep85 {}
+ static class Deep87 extends Deep86 {}
+ static class Deep88 extends Deep87 {}
+ static class Deep89 extends Deep88 {}
+ static class Deep90 extends Deep89 {}
+ static class Deep91 extends Deep90 {}
+ static class Deep92 extends Deep91 {}
+ static class Deep93 extends Deep92 {}
+ static class Deep94 extends Deep93 {}
+ static class Deep95 extends Deep94 {}
+ static class Deep96 extends Deep95 {}
+ static class Deep97 extends Deep96 {}
+ static class Deep98 extends Deep97 {}
+ static class Deep99 extends Deep98 {}
+ static class Deep100 extends Deep99 {}
+
+ static class DeepCloneable extends Deep100 implements Cloneable {
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+ }
+
+ public void time_Object_clone(int reps) {
+ try {
+ CloneableObject o = new CloneableObject();
+ for (int rep = 0; rep < reps; ++rep) {
+ o.clone();
+ }
+ } catch (Exception e) {
+ throw new AssertionError(e.getMessage());
+ }
+ }
+
+ public void time_Object_manyFieldClone(int reps) {
+ try {
+ CloneableManyFieldObject o = new CloneableManyFieldObject();
+ for (int rep = 0; rep < reps; ++rep) {
+ o.clone();
+ }
+ } catch (Exception e) {
+ throw new AssertionError(e.getMessage());
+ }
+ }
+
+ public void time_Object_deepClone(int reps) {
+ try {
+ DeepCloneable o = new DeepCloneable();
+ for (int rep = 0; rep < reps; ++rep) {
+ o.clone();
+ }
+ } catch (Exception e) {
+ throw new AssertionError(e.getMessage());
+ }
+ }
+
+ public void time_Array_clone(int reps) {
+ int[] o = new int[32];
+ for (int rep = 0; rep < reps; ++rep) {
+ o.clone();
+ }
+ }
+
+ public void time_ObjectArray_smallClone(int reps) {
+ Object[] o = new Object[32];
+ for (int i = 0; i < o.length / 2; ++i) {
+ o[i] = new Object();
+ }
+ for (int rep = 0; rep < reps; ++rep) {
+ o.clone();
+ }
+ }
+
+ public void time_ObjectArray_largeClone(int reps) {
+ Object[] o = new Object[2048];
+ for (int i = 0; i < o.length / 2; ++i) {
+ o[i] = new Object();
+ }
+ for (int rep = 0; rep < reps; ++rep) {
+ o.clone();
+ }
+ }
+}
diff --git a/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java b/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java
new file mode 100644
index 0000000..bd5bf1a
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 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.BeforeExperiment;
+
+import java.text.DateFormat;
+import java.util.Locale;
+
+public final class DateFormatBenchmark {
+
+ private Locale locale1;
+ private Locale locale2;
+ private Locale locale3;
+ private Locale locale4;
+
+ @BeforeExperiment
+ protected void setUp() throws Exception {
+ locale1 = Locale.TAIWAN;
+ locale2 = Locale.GERMANY;
+ locale3 = Locale.FRANCE;
+ locale4 = Locale.ITALY;
+ }
+
+ public void timeGetDateTimeInstance(int reps) throws Exception {
+ for (int i = 0; i < reps; ++i) {
+ DateFormat.getDateTimeInstance();
+ }
+ }
+
+ public void timeGetDateTimeInstance_multiple(int reps) throws Exception {
+ for (int i = 0; i < reps; ++i) {
+ DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale1);
+ DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale2);
+ DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale3);
+ DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale4);
+ }
+ }
+}
diff --git a/dalvik/src/main/java/dalvik/system/CloseGuard.java b/dalvik/src/main/java/dalvik/system/CloseGuard.java
index a45ffa1..e718ee7 100644
--- a/dalvik/src/main/java/dalvik/system/CloseGuard.java
+++ b/dalvik/src/main/java/dalvik/system/CloseGuard.java
@@ -118,6 +118,16 @@
private static volatile Reporter REPORTER = new DefaultReporter();
/**
+ * The default {@link Tracker}.
+ */
+ private static final DefaultTracker DEFAULT_TRACKER = new DefaultTracker();
+
+ /**
+ * Hook for customizing how CloseGuard issues are tracked.
+ */
+ private static volatile Tracker currentTracker = DEFAULT_TRACKER;
+
+ /**
* Returns a CloseGuard instance. If CloseGuard is enabled, {@code
* #open(String)} can be used to set up the instance to warn on
* failure to close. If CloseGuard is disabled, a non-null no-op
@@ -139,6 +149,13 @@
}
/**
+ * True if CloseGuard mechanism is enabled.
+ */
+ public static boolean isEnabled() {
+ return ENABLED;
+ }
+
+ /**
* Used to replace default Reporter used to warn of CloseGuard
* violations. Must be non-null.
*/
@@ -156,6 +173,32 @@
return REPORTER;
}
+ /**
+ * Sets the {@link Tracker} that is notified when resources are allocated and released.
+ *
+ * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
+ * MUST NOT be used for any other purposes.
+ *
+ * @throws NullPointerException if tracker is null
+ */
+ public static void setTracker(Tracker tracker) {
+ if (tracker == null) {
+ throw new NullPointerException("tracker == null");
+ }
+ currentTracker = tracker;
+ }
+
+ /**
+ * Returns {@link #setTracker(Tracker) last Tracker that was set}, or otherwise a default
+ * Tracker that does nothing.
+ *
+ * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
+ * MUST NOT be used for any other purposes.
+ */
+ public static Tracker getTracker() {
+ return currentTracker;
+ }
+
private CloseGuard() {}
/**
@@ -178,6 +221,7 @@
}
String message = "Explicit termination method '" + closer + "' not called";
allocationSite = new Throwable(message);
+ currentTracker.open(allocationSite);
}
private Throwable allocationSite;
@@ -187,6 +231,7 @@
* finalization.
*/
public void close() {
+ currentTracker.close(allocationSite);
allocationSite = null;
}
@@ -209,10 +254,35 @@
}
/**
+ * Interface to allow customization of tracking behaviour.
+ *
+ * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
+ * MUST NOT be used for any other purposes.
+ */
+ public interface Tracker {
+ void open(Throwable allocationSite);
+ void close(Throwable allocationSite);
+ }
+
+ /**
+ * Default tracker which does nothing special and simply leaves it up to the GC to detect a
+ * leak.
+ */
+ private static final class DefaultTracker implements Tracker {
+ @Override
+ public void open(Throwable allocationSite) {
+ }
+
+ @Override
+ public void close(Throwable allocationSite) {
+ }
+ }
+
+ /**
* Interface to allow customization of reporting behavior.
*/
- public static interface Reporter {
- public void report (String message, Throwable allocationSite);
+ public interface Reporter {
+ void report (String message, Throwable allocationSite);
}
/**
diff --git a/dalvik/src/test/java/dalvik/system/CloseGuardMonitor.java b/dalvik/src/test/java/dalvik/system/CloseGuardMonitor.java
deleted file mode 100644
index b5bf380..0000000
--- a/dalvik/src/test/java/dalvik/system/CloseGuardMonitor.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2014 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 dalvik.system;
-
-import dalvik.system.CloseGuard.Reporter;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.ref.WeakReference;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * Provides support for detecting issues found by {@link CloseGuard} from within tests.
- *
- * <p>This is a best effort as it relies on both {@link CloseGuard} being enabled and being able to
- * force a GC and finalization, none of which are directly controllable by this.
- *
- * <p>This is loaded using reflection by the AbstractResourceLeakageDetectorTestCase class as that
- * class needs to run on the reference implementation which does not have this class. It implements
- * {@link Runnable} because that is simpler than trying to manage a specialized interface.
- *
- * @hide
- */
-public class CloseGuardMonitor implements Runnable {
- /**
- * The {@link Reporter} instance used to receive warnings from {@link CloseGuard}.
- */
- private final Reporter closeGuardReporter;
-
- /**
- * The list of allocation sites that {@link CloseGuard} has reported as not being released.
- *
- * <p>Is thread safe as this will be called during finalization and so there are no guarantees
- * as to whether it will be called concurrently or not.
- */
- private final List<Throwable> closeGuardAllocationSites = new CopyOnWriteArrayList<>();
-
- /**
- * Default constructor required for reflection.
- */
- public CloseGuardMonitor() {
- System.logI("Creating CloseGuard monitor");
-
- // Save current reporter.
- closeGuardReporter = CloseGuard.getReporter();
-
- // Override the reporter with our own which collates the allocation sites.
- CloseGuard.setReporter(new Reporter() {
- @Override
- public void report(String message, Throwable allocationSite) {
- // Ignore message as it's always the same.
- closeGuardAllocationSites.add(allocationSite);
- }
- });
- }
-
- /**
- * Check to see whether any resources monitored by {@link CloseGuard} were not released before
- * they were garbage collected.
- */
- @Override
- public void run() {
- // Create a weak reference to an object so that we can detect when it is garbage collected.
- WeakReference<Object> reference = new WeakReference<>(new Object());
-
- try {
- // 'Force' a GC and finalize to cause CloseGuards to report warnings. Doesn't loop
- // forever as there are no guarantees that the following code does anything at all so
- // don't want a potential infinite loop.
- Runtime runtime = Runtime.getRuntime();
- for (int i = 0; i < 20; ++i) {
- runtime.gc();
- System.runFinalization();
- try {
- Thread.sleep(1);
- } catch (InterruptedException e) {
- throw new AssertionError(e);
- }
-
- // Check to see if the weak reference has been garbage collected.
- if (reference.get() == null) {
- System.logI("Sentry object has been freed so assuming CloseGuards have reported"
- + " any resource leakages");
- break;
- }
- }
- } finally {
- // Restore the reporter.
- CloseGuard.setReporter(closeGuardReporter);
- }
-
- if (!closeGuardAllocationSites.isEmpty()) {
- StringWriter writer = new StringWriter();
- PrintWriter printWriter = new PrintWriter(writer);
- int i = 0;
- for (Throwable allocationSite : closeGuardAllocationSites) {
- printWriter.print(++i);
- printWriter.print(") ");
- allocationSite.printStackTrace(printWriter);
- printWriter.println(" --------------------------------");
- }
- throw new AssertionError("Potential resource leakage detected:\n" + writer);
- }
- }
-}
diff --git a/dalvik/src/test/java/dalvik/system/CloseGuardTest.java b/dalvik/src/test/java/dalvik/system/CloseGuardTest.java
new file mode 100644
index 0000000..a1d1f42
--- /dev/null
+++ b/dalvik/src/test/java/dalvik/system/CloseGuardTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2016 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 dalvik.system;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Tests {@link CloseGuard}.
+ */
+public class CloseGuardTest {
+
+ /**
+ * Resets the {@link CloseGuard#ENABLED} state back to the value it had when the test started.
+ */
+ @Rule
+ public TestRule rule = this::preserveEnabledState;
+
+ private Statement preserveEnabledState(final Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ boolean oldEnabledState = CloseGuard.isEnabled();
+ try {
+ base.evaluate();
+ } finally {
+ CloseGuard.setEnabled(oldEnabledState);
+ }
+ }
+ };
+ }
+
+ @Test
+ public void testEnabled_NotOpen() throws Throwable {
+ CloseGuard.setEnabled(true);
+ ResourceOwner owner = new ResourceOwner();
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testEnabled_OpenNotClosed() throws Throwable {
+ CloseGuard.setEnabled(true);
+ ResourceOwner owner = new ResourceOwner();
+ owner.open();
+ assertUnreleasedResources(owner, 1);
+ }
+
+ @Test
+ public void testEnabled_OpenThenClosed() throws Throwable {
+ CloseGuard.setEnabled(true);
+ ResourceOwner owner = new ResourceOwner();
+ owner.open();
+ owner.close();
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testEnabledWhenCreated_DisabledWhenOpen() throws Throwable {
+ CloseGuard.setEnabled(true);
+ ResourceOwner owner = new ResourceOwner();
+ CloseGuard.setEnabled(false);
+ owner.open();
+
+ // Although the resource was not released it should not report it because CloseGuard was
+ // not enabled when the CloseGuard was opened.
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testEnabledWhenOpened_DisabledWhenFinalized() throws Throwable {
+ CloseGuard.setEnabled(true);
+ ResourceOwner owner = new ResourceOwner();
+ owner.open();
+ CloseGuard.setEnabled(false);
+
+ // Although the resource was not released it should not report it because CloseGuard was
+ // not enabled when the CloseGuard was finalized.
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testDisabled_NotOpen() throws Throwable {
+ CloseGuard.setEnabled(false);
+ ResourceOwner owner = new ResourceOwner();
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testDisabled_OpenNotClosed() throws Throwable {
+ CloseGuard.setEnabled(false);
+ ResourceOwner owner = new ResourceOwner();
+ owner.open();
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testDisabled_OpenThenClosed() throws Throwable {
+ CloseGuard.setEnabled(false);
+ ResourceOwner owner = new ResourceOwner();
+ owner.open();
+ owner.close();
+ assertUnreleasedResources(owner, 0);
+ }
+
+ @Test
+ public void testDisabledWhenCreated_EnabledWhenOpen() throws Throwable {
+ CloseGuard.setEnabled(false);
+ ResourceOwner owner = new ResourceOwner();
+ CloseGuard.setEnabled(true);
+ owner.open();
+
+ // Although the resource was not released it should not report it because CloseGuard was
+ // not enabled when the CloseGuard was created.
+ assertUnreleasedResources(owner, 0);
+ }
+
+ private void assertUnreleasedResources(ResourceOwner owner, int expectedCount)
+ throws Throwable {
+ try {
+ CloseGuardSupport.getFinalizerChecker().accept(owner, expectedCount);
+ } finally {
+ // Close the resource so that CloseGuard does not generate a warning for real when it
+ // is actually finalized.
+ owner.close();
+ }
+ }
+
+ /**
+ * A test user of {@link CloseGuard}.
+ */
+ private static class ResourceOwner {
+
+ private final CloseGuard closeGuard;
+
+ ResourceOwner() {
+ closeGuard = CloseGuard.get();
+ }
+
+ public void open() {
+ closeGuard.open("close");
+ }
+
+ public void close() {
+ closeGuard.close();
+ }
+
+ /**
+ * Make finalize public so that it can be tested directly without relying on garbage
+ * collection to trigger it.
+ */
+ @Override
+ public void finalize() throws Throwable {
+ closeGuard.warnIfOpen();
+ super.finalize();
+ }
+ }
+}
diff --git a/dalvik/test-rules/src/main/java/dalvik/system/CloseGuardSupport.java b/dalvik/test-rules/src/main/java/dalvik/system/CloseGuardSupport.java
new file mode 100644
index 0000000..7871795
--- /dev/null
+++ b/dalvik/test-rules/src/main/java/dalvik/system/CloseGuardSupport.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2016 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 dalvik.system;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiConsumer;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Provides support for testing classes that use {@link CloseGuard} in order to detect resource
+ * leakages.
+ *
+ * <p>This class should not be used directly by tests as that will prevent them from being
+ * compilable and testable on OpenJDK platform. Instead they should use
+ * {@code libcore.junit.util.ResourceLeakageDetector} which accesses the capabilities of this using
+ * reflection and if it cannot find it (because it is running on OpenJDK) then it will just skip
+ * leakage detection.
+ *
+ * <p>This provides two entry points that are accessed reflectively:
+ * <ul>
+ * <li>
+ * <p>The {@link #getRule()} method. This returns a {@link TestRule} that will fail a test if it
+ * detects any resources that were allocated during the test but were not released.
+ *
+ * <p>This only tracks resources that were allocated on the test thread, although it does not care
+ * what thread they were released on. This avoids flaky false positives where a background thread
+ * allocates a resource during a test but releases it after the test.
+ *
+ * <p>It is still possible to have a false positive in the case where the test causes a caching
+ * mechanism to open a resource and hold it open past the end of the test. In that case if there is
+ * no way to clear the cached data then it should be relatively simple to move the code that invokes
+ * the caching mechanism to outside the scope of this rule. i.e.
+ *
+ * <pre>{@code
+ * @Rule
+ * public final TestRule ruleChain = org.junit.rules.RuleChain
+ * .outerRule(new ...invoke caching mechanism...)
+ * .around(CloseGuardSupport.getRule());
+ * }</pre>
+ * </li>
+ * <li>
+ * <p>The {@link #getFinalizerChecker()} method. This returns a {@link BiConsumer} that takes an
+ * object that owns resources and an expected number of unreleased resources. It will call the
+ * {@link Object#finalize()} method on the object using reflection and throw an
+ * {@link AssertionError} if the number of reported unreleased resources does not match the
+ * expected number.
+ * </li>
+ * </ul>
+ */
+public class CloseGuardSupport {
+
+ private static final TestRule CLOSE_GUARD_RULE = new FailTestWhenResourcesNotClosedRule();
+
+ /**
+ * Get a {@link TestRule} that will detect when resources that use the {@link CloseGuard}
+ * mechanism are not cleaned up properly by a test.
+ *
+ * <p>If the {@link CloseGuard} mechanism is not supported, e.g. on OpenJDK, then the returned
+ * rule does nothing.
+ */
+ public static TestRule getRule() {
+ return CLOSE_GUARD_RULE;
+ }
+
+ private CloseGuardSupport() {
+ }
+
+ /**
+ * Fails a test when resources are not cleaned up properly.
+ */
+ private static class FailTestWhenResourcesNotClosedRule implements TestRule {
+ /**
+ * Returns a {@link Statement} that will fail the test if it ends with unreleased resources.
+ * @param base the test to be run.
+ */
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ // Get the previous tracker so that it can be restored afterwards.
+ CloseGuard.Tracker previousTracker = CloseGuard.getTracker();
+ // Get the previous enabled state so that it can be restored afterwards.
+ boolean previousEnabled = CloseGuard.isEnabled();
+ TestCloseGuardTracker tracker = new TestCloseGuardTracker();
+ Throwable thrown = null;
+ try {
+ // Set the test tracker and enable close guard detection.
+ CloseGuard.setTracker(tracker);
+ CloseGuard.setEnabled(true);
+ base.evaluate();
+ } catch (Throwable throwable) {
+ // Catch and remember the throwable so that it can be rethrown in the
+ // finally block.
+ thrown = throwable;
+ } finally {
+ // Restore the previous tracker and enabled state.
+ CloseGuard.setEnabled(previousEnabled);
+ CloseGuard.setTracker(previousTracker);
+
+ Collection<Throwable> allocationSites =
+ tracker.getAllocationSitesForUnreleasedResources();
+ if (!allocationSites.isEmpty()) {
+ if (thrown == null) {
+ thrown = new IllegalStateException(
+ "Unreleased resources found in test");
+ }
+ for (Throwable allocationSite : allocationSites) {
+ thrown.addSuppressed(allocationSite);
+ }
+ }
+ if (thrown != null) {
+ throw thrown;
+ }
+ }
+ }
+ };
+ }
+ }
+
+ /**
+ * A tracker that keeps a record of the allocation sites for all resources allocated but not
+ * yet released.
+ *
+ * <p>It only tracks resources allocated for the test thread.
+ */
+ private static class TestCloseGuardTracker implements CloseGuard.Tracker {
+
+ /**
+ * A set would be preferable but this is the closest that matches the concurrency
+ * requirements for the use case which prioritise speed of addition and removal over
+ * iteration and access.
+ */
+ private final Set<Throwable> allocationSites =
+ Collections.newSetFromMap(new ConcurrentHashMap<>());
+
+ private final Thread testThread = Thread.currentThread();
+
+ @Override
+ public void open(Throwable allocationSite) {
+ if (Thread.currentThread() == testThread) {
+ allocationSites.add(allocationSite);
+ }
+ }
+
+ @Override
+ public void close(Throwable allocationSite) {
+ // Closing the resource twice could pass null into here.
+ if (allocationSite != null) {
+ allocationSites.remove(allocationSite);
+ }
+ }
+
+ /**
+ * Get the collection of allocation sites for any unreleased resources.
+ */
+ Collection<Throwable> getAllocationSitesForUnreleasedResources() {
+ return new ArrayList<>(allocationSites);
+ }
+ }
+
+ private static final BiConsumer<Object, Integer> FINALIZER_CHECKER
+ = new BiConsumer<Object, Integer>() {
+ @Override
+ public void accept(Object resourceOwner, Integer expectedCount) {
+ finalizerChecker(resourceOwner, expectedCount);
+ }
+ };
+
+ /**
+ * Get access to a {@link BiConsumer} that will determine how many unreleased resources the
+ * first parameter owns and throw a {@link AssertionError} if that does not match the
+ * expected number of resources specified by the second parameter.
+ *
+ * <p>This uses a {@link BiConsumer} as it is a standard interface that is available in all
+ * environments. That helps avoid the caller from having compile time dependencies on this
+ * class which will not be available on OpenJDK.
+ */
+ public static BiConsumer<Object, Integer> getFinalizerChecker() {
+ return FINALIZER_CHECKER;
+ }
+
+ /**
+ * Checks that the supplied {@code resourceOwner} has overridden the {@link Object#finalize()}
+ * method and uses {@link CloseGuard#warnIfOpen()} correctly to detect when the resource is
+ * not released.
+ *
+ * @param resourceOwner the owner of the resource protected by {@link CloseGuard}.
+ * @param expectedCount the expected number of unreleased resources to be held by the owner.
+ *
+ */
+ private static void finalizerChecker(Object resourceOwner, int expectedCount) {
+ Class<?> clazz = resourceOwner.getClass();
+ Method finalizer = null;
+ while (clazz != null && clazz != Object.class) {
+ try {
+ finalizer = clazz.getDeclaredMethod("finalize");
+ break;
+ } catch (NoSuchMethodException e) {
+ // Carry on up the class hierarchy.
+ clazz = clazz.getSuperclass();
+ }
+ }
+
+ if (finalizer == null) {
+ // No finalizer method could be found.
+ throw new AssertionError("Class " + resourceOwner.getClass().getName()
+ + " does not have a finalize() method");
+ }
+
+ // Make the method accessible.
+ finalizer.setAccessible(true);
+
+ CloseGuard.Reporter oldReporter = CloseGuard.getReporter();
+ try {
+ CollectingReporter reporter = new CollectingReporter();
+ CloseGuard.setReporter(reporter);
+
+ // Invoke the finalizer to cause it to get CloseGuard to report a problem if it has
+ // not yet been closed.
+ try {
+ finalizer.invoke(resourceOwner);
+ } catch (ReflectiveOperationException e) {
+ throw new AssertionError(
+ "Could not invoke the finalizer() method on " + resourceOwner, e);
+ }
+
+ reporter.assertUnreleasedResources(expectedCount);
+ } finally {
+ CloseGuard.setReporter(oldReporter);
+ }
+ }
+
+ /**
+ * A {@link CloseGuard.Reporter} that collects any reports about unreleased resources.
+ */
+ private static class CollectingReporter implements CloseGuard.Reporter {
+
+ private final Thread callingThread = Thread.currentThread();
+
+ private final List<Throwable> unreleasedResourceAllocationSites = new ArrayList<>();
+
+ @Override
+ public void report(String message, Throwable allocationSite) {
+ // Only care about resources that are not reported on this thread.
+ if (callingThread == Thread.currentThread()) {
+ unreleasedResourceAllocationSites.add(allocationSite);
+ }
+ }
+
+ void assertUnreleasedResources(int expectedCount) {
+ int unreleasedResourceCount = unreleasedResourceAllocationSites.size();
+ if (unreleasedResourceCount == expectedCount) {
+ return;
+ }
+
+ AssertionError error = new AssertionError(
+ "Expected " + expectedCount + " unreleased resources, found "
+ + unreleasedResourceCount + "; see suppressed exceptions for details");
+ for (Throwable unreleasedResourceAllocationSite : unreleasedResourceAllocationSites) {
+ error.addSuppressed(unreleasedResourceAllocationSite);
+ }
+ throw error;
+ }
+ }
+}
diff --git a/dalvik/test-rules/src/test/java/dalvik/system/CloseGuardSupportTest.java b/dalvik/test-rules/src/test/java/dalvik/system/CloseGuardSupportTest.java
new file mode 100644
index 0000000..fe05710
--- /dev/null
+++ b/dalvik/test-rules/src/test/java/dalvik/system/CloseGuardSupportTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2016 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 dalvik.system;
+
+import java.util.Collections;
+import java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.RunWith;
+import org.junit.runner.notification.Failure;
+import org.junit.runners.JUnit4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+@RunWith(JUnit4.class)
+public class CloseGuardSupportTest {
+
+ @Test
+ public void testDoesReleaseResource() {
+ List<Failure> failures = JUnitCore.runClasses(DoesReleaseResource.class).getFailures();
+ assertEquals(Collections.emptyList(), failures);
+ }
+
+ public static class DoesReleaseResource {
+ @Rule public TestRule rule = CloseGuardSupport.getRule();
+ @Test public void test() {
+ CloseGuard closeGuard = CloseGuard.get();
+ closeGuard.open("test resource");
+ closeGuard.close();
+ }
+ }
+
+ @Test
+ public void testDoesReleaseResourceTwice() {
+ List<Failure> failures = JUnitCore.runClasses(DoesReleaseResourceTwice.class).getFailures();
+ assertEquals(Collections.emptyList(), failures);
+ }
+
+ public static class DoesReleaseResourceTwice {
+ @Rule public TestRule rule = CloseGuardSupport.getRule();
+ @Test public void test() {
+ CloseGuard closeGuard = CloseGuard.get();
+ closeGuard.open("test resource");
+ closeGuard.close();
+ closeGuard.close();
+ }
+ }
+
+ @Test
+ public void testDoesNotReleaseResource() {
+ List<Failure> failures = JUnitCore.runClasses(DoesNotReleaseResource.class).getFailures();
+ assertEquals("Failure count", 1, failures.size());
+ Failure failure = failures.get(0);
+ checkResourceNotReleased(failure, "Unreleased resources found in test");
+ }
+
+ public static class DoesNotReleaseResource {
+ @Rule public TestRule rule = CloseGuardSupport.getRule();
+ @Test public void test() {
+ CloseGuard closeGuard = CloseGuard.get();
+ closeGuard.open("test resource");
+ }
+ }
+
+ @Test
+ public void testDoesNotReleaseResourceDueToFailure() {
+ List<Failure> failures = JUnitCore
+ .runClasses(DoesNotReleaseResourceDueToFailure.class)
+ .getFailures();
+ assertEquals("Failure count", 1, failures.size());
+ Failure failure = failures.get(0);
+ checkResourceNotReleased(failure, "failure");
+ }
+
+ public static class DoesNotReleaseResourceDueToFailure {
+ @Rule public TestRule rule = CloseGuardSupport.getRule();
+ @Test public void test() {
+ CloseGuard closeGuard = CloseGuard.get();
+ closeGuard.open("test resource");
+ fail("failure");
+ }
+ }
+
+ @Test
+ public void testResourceOwnerDoesNotOverrideFinalize() {
+ List<Failure> failures = JUnitCore
+ .runClasses(ResourceOwnerDoesNotOverrideFinalize.class)
+ .getFailures();
+ assertEquals("Failure count", 1, failures.size());
+ Failure failure = failures.get(0);
+ assertEquals("Class java.lang.String does not have a finalize() method",
+ failure.getMessage());
+ }
+
+ public static class ResourceOwnerDoesNotOverrideFinalize {
+ @Rule public TestRule rule = CloseGuardSupport.getRule();
+ @Test
+ public void test() {
+ CloseGuardSupport.getFinalizerChecker().accept("not resource owner", 0);
+ }
+ }
+
+ @Test
+ public void testResourceOwnerOverridesFinalizeButDoesNotReportLeak() {
+ List<Failure> failures = JUnitCore
+ .runClasses(ResourceOwnerOverridesFinalizeButDoesNotReportLeak.class)
+ .getFailures();
+ assertEquals("Failure count", 1, failures.size());
+ Failure failure = failures.get(0);
+ assertEquals("Expected 1 unreleased resources, found 0;"
+ + " see suppressed exceptions for details",
+ failure.getMessage());
+ }
+
+ public static class ResourceOwnerOverridesFinalizeButDoesNotReportLeak {
+ @Rule public TestRule rule = CloseGuardSupport.getRule();
+ @Test
+ public void test() {
+ CloseGuardSupport.getFinalizerChecker().accept(new Object() {
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ }
+ }, 1);
+ }
+ }
+
+ @Test
+ public void testResourceOwnerOverridesFinalizeAndReportsLeak() {
+ List<Failure> failures = JUnitCore
+ .runClasses(ResourceOwnerOverridesFinalizeAndReportsLeak.class)
+ .getFailures();
+ assertEquals("Failure count", 1, failures.size());
+ Failure failure = failures.get(0);
+ checkResourceNotReleased(failure, "Unreleased resources found in test");
+ }
+
+ public static class ResourceOwnerOverridesFinalizeAndReportsLeak {
+ @Rule public TestRule rule = CloseGuardSupport.getRule();
+ @Test
+ public void test() {
+ CloseGuardSupport.getFinalizerChecker().accept(new Object() {
+ private CloseGuard guard = CloseGuard.get();
+ {
+ guard.open("test resource");
+ }
+ @Override
+ protected void finalize() throws Throwable {
+ guard.warnIfOpen();
+ super.finalize();
+ }
+ }, 1);
+ }
+ }
+
+ private void checkResourceNotReleased(Failure failure, String expectedMessage) {
+ @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+ Throwable exception = failure.getException();
+ assertEquals(expectedMessage, exception.getMessage());
+ Throwable[] suppressed = exception.getSuppressed();
+ assertEquals("Suppressed count", 1, suppressed.length);
+ exception = suppressed[0];
+ assertEquals("Explicit termination method 'test resource' not called",
+ exception.getMessage());
+ }
+}
diff --git a/libart/src/main/java/java/lang/DexCache.java b/libart/src/main/java/java/lang/DexCache.java
index 37c1a1d..8465a24 100644
--- a/libart/src/main/java/java/lang/DexCache.java
+++ b/libart/src/main/java/java/lang/DexCache.java
@@ -72,6 +72,12 @@
private long strings;
/**
+ * References to MethodType (C array pointer) as they become resolved following
+ * interpreter semantics.
+ */
+ private long resolvedMethodTypes;
+
+ /**
* The number of elements in the native resolvedFields array.
*/
private int numResolvedFields;
@@ -91,6 +97,11 @@
*/
private int numStrings;
+ /**
+ * The number of elements in the native method types array.
+ */
+ private int numResolvedMethodTypes;
+
// Only created by the VM.
private DexCache() {}
diff --git a/luni/src/main/java/libcore/io/IoBridge.java b/luni/src/main/java/libcore/io/IoBridge.java
index acf9b39..dee5129 100644
--- a/luni/src/main/java/libcore/io/IoBridge.java
+++ b/luni/src/main/java/libcore/io/IoBridge.java
@@ -245,6 +245,7 @@
public static final int JAVA_MCAST_BLOCK_SOURCE = 23;
public static final int JAVA_MCAST_UNBLOCK_SOURCE = 24;
public static final int JAVA_IP_MULTICAST_TTL = 17;
+ public static final int JAVA_IP_TTL = 25;
/**
* java.net has its own socket options similar to the underlying Unix ones. We paper over the
@@ -274,6 +275,10 @@
// Since setting this from java.net always sets IPv4 and IPv6 to the same value,
// it doesn't matter which we return.
return Libcore.os.getsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS);
+ case IoBridge.JAVA_IP_TTL:
+ // Since setting this from java.net always sets IPv4 and IPv6 to the same value,
+ // it doesn't matter which we return.
+ return Libcore.os.getsockoptInt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS);
case SocketOptions.IP_TOS:
// Since setting this from java.net always sets IPv4 and IPv6 to the same value,
// it doesn't matter which we return.
@@ -345,6 +350,10 @@
Libcore.os.setsockoptByte(fd, IPPROTO_IP, IP_MULTICAST_TTL, (Integer) value);
Libcore.os.setsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (Integer) value);
return;
+ case IoBridge.JAVA_IP_TTL:
+ Libcore.os.setsockoptInt(fd, IPPROTO_IP, IP_TTL, (Integer) value);
+ Libcore.os.setsockoptInt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (Integer) value);
+ return;
case SocketOptions.IP_TOS:
Libcore.os.setsockoptInt(fd, IPPROTO_IP, IP_TOS, (Integer) value);
Libcore.os.setsockoptInt(fd, IPPROTO_IPV6, IPV6_TCLASS, (Integer) value);
@@ -606,17 +615,6 @@
try {
fd = Libcore.os.socket(AF_INET6, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
- // The RFC (http://www.ietf.org/rfc/rfc3493.txt) says that IPV6_MULTICAST_HOPS defaults
- // to 1. The Linux kernel (at least up to 2.6.38) accidentally defaults to 64 (which
- // would be correct for the *unicast* hop limit).
- // See http://www.spinics.net/lists/netdev/msg129022.html, though no patch appears to
- // have been applied as a result of that discussion. If that bug is ever fixed, we can
- // remove this code. Until then, we manually set the hop limit on IPv6 datagram sockets.
- // (IPv4 is already correct.)
- if (!stream) {
- Libcore.os.setsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 1);
- }
-
return fd;
} catch (ErrnoException errnoException) {
throw errnoException.rethrowAsSocketException();
diff --git a/luni/src/main/native/ExecStrings.cpp b/luni/src/main/native/ExecStrings.cpp
index a6a62e2..4f90431 100644
--- a/luni/src/main/native/ExecStrings.cpp
+++ b/luni/src/main/native/ExecStrings.cpp
@@ -20,7 +20,8 @@
#include <stdlib.h>
-#include "cutils/log.h"
+#include <android/log.h>
+
#include "ScopedLocalRef.h"
ExecStrings::ExecStrings(JNIEnv* env, jobjectArray java_string_array)
diff --git a/luni/src/main/native/IcuUtilities.cpp b/luni/src/main/native/IcuUtilities.cpp
index 98648a5..6b29e67 100644
--- a/luni/src/main/native/IcuUtilities.cpp
+++ b/luni/src/main/native/IcuUtilities.cpp
@@ -16,16 +16,17 @@
#define LOG_TAG "IcuUtilities"
+#include <android/log.h>
+
#include "IcuUtilities.h"
#include "JniConstants.h"
#include "JniException.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
-#include "cutils/log.h"
#include "unicode/strenum.h"
-#include "unicode/uloc.h"
#include "unicode/ustring.h"
+#include "unicode/uloc.h"
jobjectArray fromStringEnumeration(JNIEnv* env, UErrorCode& status, const char* provider, icu::StringEnumeration* se) {
if (maybeThrowIcuException(env, provider, status)) {
diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp
index 52df40e..ec9d878 100644
--- a/luni/src/main/native/Register.cpp
+++ b/luni/src/main/native/Register.cpp
@@ -16,12 +16,13 @@
#define LOG_TAG "libcore" // We'll be next to "dalvikvm" in the log; make the distinction clear.
-#include "cutils/log.h"
+#include <stdlib.h>
+
+#include "android/log.h"
+
#include "JniConstants.h"
#include "ScopedLocalFrame.h"
-#include <stdlib.h>
-
// DalvikVM calls this on startup, so we can statically register all our native methods.
jint JNI_OnLoad(JavaVM* vm, void*) {
JNIEnv* env;
diff --git a/luni/src/main/native/java_math_NativeBN.cpp b/luni/src/main/native/java_math_NativeBN.cpp
index 45df4c5..559a702 100644
--- a/luni/src/main/native/java_math_NativeBN.cpp
+++ b/luni/src/main/native/java_math_NativeBN.cpp
@@ -139,23 +139,9 @@
uint64_t dw = java_dw;
BIGNUM* a = toBigNum(a0);
- static_assert(sizeof(dw) == sizeof(BN_ULONG) ||
- sizeof(dw) == 2*sizeof(BN_ULONG), "Unknown BN configuration");
-
- if (sizeof(dw) == sizeof(BN_ULONG)) {
- if (!BN_set_word(a, dw)) {
- throwException(env);
- return;
- }
- } else if (sizeof(dw) == 2 * sizeof(BN_ULONG)) {
- if (!bn_wexpand(a, 2)) {
- throwException(env);
- return;
- }
- a->d[0] = dw;
- a->d[1] = dw >> 32;
- a->top = 2;
- bn_correct_top(a);
+ if (!BN_set_u64(a, dw)) {
+ throwException(env);
+ return;
}
BN_set_negative(a, neg);
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index e6f378e..7456028 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -16,6 +16,24 @@
#define LOG_TAG "ICU"
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <memory>
+#include <vector>
+
+#include <android/log.h>
+#include <android-base/unique_fd.h>
+
#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
@@ -24,7 +42,6 @@
#include "ScopedJavaUnicodeString.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
-#include "cutils/log.h"
#include "toStringArray.h"
#include "unicode/brkiter.h"
#include "unicode/calendar.h"
@@ -51,22 +68,6 @@
#include "ureslocs.h"
#include "valueOf.h"
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <string>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-#include <memory>
-#include <vector>
-
-#include <android-base/unique_fd.h>
-
class ScopedResourceBundle {
public:
explicit ScopedResourceBundle(UResourceBundle* bundle) : bundle_(bundle) {
diff --git a/luni/src/main/native/libcore_icu_NativeConverter.cpp b/luni/src/main/native/libcore_icu_NativeConverter.cpp
index bf938d1..f78ca19 100644
--- a/luni/src/main/native/libcore_icu_NativeConverter.cpp
+++ b/luni/src/main/native/libcore_icu_NativeConverter.cpp
@@ -15,6 +15,14 @@
#define LOG_TAG "NativeConverter"
+#include <stdlib.h>
+#include <string.h>
+
+#include <memory>
+#include <vector>
+
+#include <android/log.h>
+
#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
@@ -23,7 +31,6 @@
#include "ScopedPrimitiveArray.h"
#include "ScopedStringChars.h"
#include "ScopedUtfChars.h"
-#include "cutils/log.h"
#include "toStringArray.h"
#include "unicode/ucnv.h"
#include "unicode/ucnv_cb.h"
@@ -31,12 +38,6 @@
#include "unicode/ustring.h"
#include "unicode/utypes.h"
-#include <memory>
-#include <vector>
-
-#include <stdlib.h>
-#include <string.h>
-
#define NativeConverter_REPORT 0
#define NativeConverter_IGNORE 1
#define NativeConverter_REPLACE 2
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index d0b3924..f8fd199 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -16,20 +16,6 @@
#define LOG_TAG "Posix"
-#include "AsynchronousCloseMonitor.h"
-#include "cutils/log.h"
-#include "ExecStrings.h"
-#include "JNIHelp.h"
-#include "JniConstants.h"
-#include "JniException.h"
-#include "NetworkUtilities.h"
-#include "Portability.h"
-#include "ScopedBytes.h"
-#include "ScopedLocalRef.h"
-#include "ScopedPrimitiveArray.h"
-#include "ScopedUtfChars.h"
-#include "toStringArray.h"
-
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
@@ -58,11 +44,26 @@
#include <sys/xattr.h>
#include <termios.h>
#include <unistd.h>
+
#include <memory>
+#include <android/log.h>
#include <android-base/file.h>
#include <android-base/strings.h>
+#include "AsynchronousCloseMonitor.h"
+#include "ExecStrings.h"
+#include "JNIHelp.h"
+#include "JniConstants.h"
+#include "JniException.h"
+#include "NetworkUtilities.h"
+#include "Portability.h"
+#include "ScopedBytes.h"
+#include "ScopedLocalRef.h"
+#include "ScopedPrimitiveArray.h"
+#include "ScopedUtfChars.h"
+#include "toStringArray.h"
+
#ifndef __unused
#define __unused __attribute__((__unused__))
#endif
diff --git a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
index e27af69..aaf3ca1 100644
--- a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
+++ b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
@@ -16,6 +16,14 @@
#define LOG_TAG "ExpatParser"
+#include <expat.h>
+#include <string.h>
+
+#include <memory>
+
+#include <android/log.h>
+#include <android-base/stringprintf.h>
+
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
@@ -24,15 +32,8 @@
#include "ScopedStringChars.h"
#include "ScopedUtfChars.h"
#include "jni.h"
-#include "cutils/log.h"
#include "unicode/unistr.h"
-#include <memory>
-
-#include <string.h>
-#include <expat.h>
-
-#include <android-base/stringprintf.h>
#define BUCKET_COUNT 128
diff --git a/luni/src/test/java/libcore/java/io/OldSequenceInputStreamTest.java b/luni/src/test/java/libcore/java/io/OldSequenceInputStreamTest.java
index f7d9a49..db0fbe6 100644
--- a/luni/src/test/java/libcore/java/io/OldSequenceInputStreamTest.java
+++ b/luni/src/test/java/libcore/java/io/OldSequenceInputStreamTest.java
@@ -17,6 +17,8 @@
package libcore.java.io;
+import java.io.InputStream;
+import java.util.Vector;
import java.io.IOException;
import java.io.SequenceInputStream;
import tests.support.Support_ASimpleInputStream;
@@ -25,8 +27,8 @@
Support_ASimpleInputStream simple1, simple2;
SequenceInputStream si;
- String s1 = "Hello";
- String s2 = "World";
+ final String s1 = "Hello";
+ final String s2 = "World";
public void test_available() throws IOException {
assertEquals("Returned incorrect number of bytes!", s1.length(), si.available());
@@ -152,6 +154,54 @@
}
}
+ public void test_readStackOVerflow() throws Exception {
+ // 2^16 should be enough to overflow
+ Vector<InputStream> inputs = new Vector<>();
+ InputStream emptyInputStream = new Support_ASimpleInputStream(new byte[0]);
+ for (int i=0;i < 32768; i++) {
+ inputs.add(emptyInputStream);
+ }
+
+ SequenceInputStream sequenceInputStream = new SequenceInputStream(inputs.elements());
+ assertEquals(-1, sequenceInputStream.read());
+
+ byte[] buf = new byte[10];
+ sequenceInputStream = new SequenceInputStream(inputs.elements());
+ assertEquals(-1, sequenceInputStream.read(buf, 0, 10));
+ }
+
+ private SequenceInputStream createSequenceInputStreamWithGaps() {
+ Vector<InputStream> inputs = new Vector<>();
+ InputStream emptyInputStream = new Support_ASimpleInputStream(new byte[0]);
+ inputs.add(emptyInputStream);
+ inputs.add(simple1);
+ inputs.add(emptyInputStream);
+ inputs.add(simple2);
+ inputs.add(emptyInputStream);
+ return new SequenceInputStream(inputs.elements());
+ }
+
+ public void test_readArraySkipsEmpty() throws Exception {
+ SequenceInputStream sequenceInputStream1 = createSequenceInputStreamWithGaps();
+ byte[] buf = new byte[10];
+ assertEquals(s1.length(), sequenceInputStream1.read(buf, 0, s1.length()));
+ assertEquals(s1, new String(buf, 0, s1.length()));
+ assertEquals(s2.length(), sequenceInputStream1.read(buf, 0, s2.length()));
+ assertEquals(s2, new String(buf, 0, s2.length()));
+ assertEquals(-1, sequenceInputStream1.read(buf, 0, s1.length()));
+ }
+
+ public void test_readSkipsEmpty() throws Exception {
+ SequenceInputStream sequenceInputStream1 = createSequenceInputStreamWithGaps();
+ for (int i=0;i < s1.length(); i++) {
+ assertEquals(s1.charAt(i), sequenceInputStream1.read());
+ }
+ for (int i=0;i < s2.length(); i++) {
+ assertEquals(s2.charAt(i), sequenceInputStream1.read());
+ }
+ assertEquals(-1, sequenceInputStream1.read());
+ }
+
protected void setUp() {
simple1 = new Support_ASimpleInputStream(s1);
simple2 = new Support_ASimpleInputStream(s2);
diff --git a/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java b/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java
index bc4fe80..9254b8d 100644
--- a/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java
+++ b/luni/src/test/java/libcore/java/lang/ProcessBuilderTest.java
@@ -17,7 +17,6 @@
package libcore.java.lang;
import android.system.Os;
-
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
@@ -38,13 +37,13 @@
import java.util.concurrent.FutureTask;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import junit.framework.TestCase;
import libcore.io.IoUtils;
-import libcore.java.util.AbstractResourceLeakageDetectorTestCase;
import static java.lang.ProcessBuilder.Redirect.INHERIT;
import static java.lang.ProcessBuilder.Redirect.PIPE;
-public class ProcessBuilderTest extends AbstractResourceLeakageDetectorTestCase {
+public class ProcessBuilderTest extends TestCase {
private static final String TAG = ProcessBuilderTest.class.getSimpleName();
private static String shell() {
diff --git a/luni/src/test/java/libcore/java/lang/reflect/ParameterTest.java b/luni/src/test/java/libcore/java/lang/reflect/ParameterTest.java
index 1a45497..18fce55 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/ParameterTest.java
+++ b/luni/src/test/java/libcore/java/lang/reflect/ParameterTest.java
@@ -781,42 +781,6 @@
.checkGetParameterizedType("class " + outerClass.getName() + "");
}
- public void testLambdaClassConstructor() throws Exception {
- Class<?> outerClass = ParameterTest.class;
- Class<?> innerClass = getLambdaClassWith1ParameterConstructor();
- Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
-
- checkLambdaClassConstructor(outerClass, constructor);
- }
-
- private Class<?> getLambdaClassWith1ParameterConstructor() {
- return ((Callable<?>) ParameterTest.this::outerClassMethod).getClass();
- }
-
- public void testLambdaClassConstructor_withMetadata() throws Exception {
- Class<?> outerClass = loadTestOuterClassWithMetadata();
- Object outer = outerClass.newInstance();
- Class<?> innerClass = (Class<?>) outerClass.getDeclaredMethod(
- "getLambdaClassWith1ParameterConstructor").invoke(outer);
- Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
-
- // There should be no parameter metadata for lambda classes.
- checkLambdaClassConstructor(outerClass, constructor);
- }
-
- // This behavior is likely to be quite brittle and may not be specified.
- private void checkLambdaClassConstructor(Class<?> outerClass, Constructor<?> constructor) {
- ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
- helper.checkStandardParametersBehavior()
- .checkParametersToString("[" + outerClass.getName() + " arg0]")
- .checkParametersMetadataNotAvailable()
- .checkParametersNoVarArgs();
-
- helper.getParameterTestHelper(0)
- .checkGetType(outerClass)
- .checkGetParameterizedType("class " + outerClass.getName() + "");
- }
-
private static class NonIdenticalParameters {
@SuppressWarnings("unused")
void method0(String p0) {}
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index 3f750e4..9ba2e07 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -2293,8 +2293,13 @@
testUrlToRequestMapping("$", "$", "$");
testUrlToUriMapping("&", "&", "&", "&", "&");
testUrlToRequestMapping("&", "&", "&");
- testUrlToUriMapping("'", "'", "'", "%27", "'");
- testUrlToRequestMapping("'", "'", "%27");
+
+ // http://b/30405333 - upstream OkHttp encodes single quote (') as %27 in query parameters
+ // but this breaks iTunes remote apps: iTunes currently does not accept %27 so we have a
+ // local patch to retain the historic Android behavior of not encoding single quote.
+ testUrlToUriMapping("'", "'", "'", "'", "'");
+ testUrlToRequestMapping("'", "'", "'");
+
testUrlToUriMapping("(", "(", "(", "(", "(");
testUrlToRequestMapping("(", "(", "(");
testUrlToUriMapping(")", ")", ")", ")", ")");
diff --git a/luni/src/test/java/libcore/java/nio/file/LinuxFileSystemTest.java b/luni/src/test/java/libcore/java/nio/file/LinuxFileSystemTest.java
new file mode 100644
index 0000000..4d2f4cb
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/file/LinuxFileSystemTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2016 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.java.nio.file;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.IOException;
+import java.nio.file.FileStore;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import sun.nio.fs.LinuxFileSystemProvider;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertTrue;
+import static junit.framework.TestCase.fail;
+import static libcore.java.nio.file.LinuxFileSystemTestData.getPathExceptionTestData;
+import static libcore.java.nio.file.LinuxFileSystemTestData.getPathInputOutputTestData;
+
+@RunWith(JUnit4.class)
+public class LinuxFileSystemTest {
+
+ FileSystem fileSystem = FileSystems.getDefault();
+
+ @Test
+ public void test_provider() {
+ assertTrue(fileSystem.provider() instanceof LinuxFileSystemProvider);
+ }
+
+ @Test
+ public void test_isOpen() throws IOException {
+ assertTrue(fileSystem.isOpen());
+ }
+
+ @Test
+ public void test_close() throws IOException {
+ // Close is not supported.
+ try {
+ fileSystem.close();
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+ }
+
+ @Test
+ public void test_isReadOnly() {
+ assertFalse(fileSystem.isReadOnly());
+ }
+
+ @Test
+ public void test_getSeparator() {
+ assertEquals("/", fileSystem.getSeparator());
+ }
+
+ @Test
+ public void test_getRootDirectories() {
+ Iterable<Path> rootDirectories = fileSystem.getRootDirectories();
+ Map<Path, Boolean> pathMap = new HashMap<>();
+ rootDirectories.forEach(path -> pathMap.put(path, true));
+ assertEquals(1, pathMap.size());
+ assertTrue(pathMap.get(Paths.get("/")));
+ }
+
+ @Test
+ public void test_getFileStores() {
+ Iterable<FileStore> fileStores = fileSystem.getFileStores();
+ // Asserting if the the list has non zero number stores.
+ assertTrue(fileStores.iterator().hasNext());
+ }
+
+ @Test
+ public void test_supportedFileAttributeViews() {
+ Set<String> supportedFileAttributeViewsList = fileSystem.supportedFileAttributeViews();
+ assertEquals(6, supportedFileAttributeViewsList.size());
+ assertTrue(supportedFileAttributeViewsList.contains("posix"));
+ assertTrue(supportedFileAttributeViewsList.contains("user"));
+ assertTrue(supportedFileAttributeViewsList.contains("owner"));
+ assertTrue(supportedFileAttributeViewsList.contains("unix"));
+ assertTrue(supportedFileAttributeViewsList.contains("basic"));
+ assertTrue(supportedFileAttributeViewsList.contains("dos"));
+ }
+
+ @Test
+ public void test_get() {
+ List<LinuxFileSystemTestData.TestData> inputOutputTestCases = getPathInputOutputTestData();
+ for (LinuxFileSystemTestData.TestData inputOutputTestCase : inputOutputTestCases) {
+ Assert.assertEquals(inputOutputTestCase.output, fileSystem.getPath(
+ inputOutputTestCase.input, inputOutputTestCase.inputArray).toString());
+ }
+
+ List<LinuxFileSystemTestData.TestData> exceptionTestCases = getPathExceptionTestData();
+ for (LinuxFileSystemTestData.TestData exceptionTestCase : exceptionTestCases) {
+ try {
+ fileSystem.getPath(exceptionTestCase.input, exceptionTestCase.inputArray);
+ Assert.fail();
+ } catch (Exception expected) {
+ Assert.assertEquals(exceptionTestCase.exceptionClass, expected.getClass());
+ }
+ }
+ }
+
+ @Test
+ public void test_getPathMatcher_glob() {
+ PathMatcher pathMatcher = fileSystem.getPathMatcher("glob:" + "*.java");
+ assertTrue(pathMatcher.matches(Paths.get("f.java")));
+ assertFalse(pathMatcher.matches(Paths.get("f")));
+
+ pathMatcher = fileSystem.getPathMatcher("glob:" + "*.*");
+ assertTrue(pathMatcher.matches(Paths.get("f.t")));
+ assertFalse(pathMatcher.matches(Paths.get("f")));
+
+ pathMatcher = fileSystem.getPathMatcher("glob:" + "*.{java,class}");
+ assertTrue(pathMatcher.matches(Paths.get("f.java")));
+ assertTrue(pathMatcher.matches(Paths.get("f.class")));
+ assertFalse(pathMatcher.matches(Paths.get("f.clas")));
+ assertFalse(pathMatcher.matches(Paths.get("f.t")));
+
+ pathMatcher = fileSystem.getPathMatcher("glob:" + "f.?");
+ assertTrue(pathMatcher.matches(Paths.get("f.t")));
+ assertFalse(pathMatcher.matches(Paths.get("f.tl")));
+ assertFalse(pathMatcher.matches(Paths.get("f.")));
+
+ pathMatcher = fileSystem.getPathMatcher("glob:" + "/home/*/*");
+ assertTrue(pathMatcher.matches(Paths.get("/home/f/d")));
+ assertTrue(pathMatcher.matches(Paths.get("/home/f/*")));
+ assertTrue(pathMatcher.matches(Paths.get("/home/*/*")));
+ assertFalse(pathMatcher.matches(Paths.get("/home/f")));
+ assertFalse(pathMatcher.matches(Paths.get("/home/f/d/d")));
+
+ pathMatcher = fileSystem.getPathMatcher("glob:" + "/home/**");
+ assertTrue(pathMatcher.matches(Paths.get("/home/f/d")));
+ assertTrue(pathMatcher.matches(Paths.get("/home/f/*")));
+ assertTrue(pathMatcher.matches(Paths.get("/home/*/*")));
+ assertTrue(pathMatcher.matches(Paths.get("/home/f")));
+ assertTrue(pathMatcher.matches(Paths.get("/home/f/d/d")));
+ assertTrue(pathMatcher.matches(Paths.get("/home/f/d/d/d")));
+ }
+
+ @Test
+ public void test_getPathMatcher_regex() {
+ PathMatcher pathMatcher = fileSystem.getPathMatcher("regex:" + "(hello|hi)*[^a|b]?k.*");
+ assertTrue(pathMatcher.matches(Paths.get("k")));
+ assertTrue(pathMatcher.matches(Paths.get("ck")));
+ assertFalse(pathMatcher.matches(Paths.get("ak")));
+ assertTrue(pathMatcher.matches(Paths.get("kanything")));
+ assertTrue(pathMatcher.matches(Paths.get("hellohik")));
+ assertTrue(pathMatcher.matches(Paths.get("hellok")));
+ assertTrue(pathMatcher.matches(Paths.get("hellohellohellok")));
+ assertFalse(pathMatcher.matches(Paths.get("hellohellohellobk")));
+ assertFalse(pathMatcher.matches(Paths.get("hello")));
+ }
+
+ @Test
+ public void test_getPathMatcher_unsupported() {
+ try {
+ fileSystem.getPathMatcher("unsupported:test");
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+ }
+
+ @Test
+ public void test_getUserPrincipalLookupService() {
+ assertNotNull(fileSystem.getUserPrincipalLookupService());
+ }
+
+ @Test
+ public void test_newWatchService() throws IOException {
+ assertNotNull(fileSystem.newWatchService());
+ }
+}
\ No newline at end of file
diff --git a/luni/src/test/java/libcore/java/nio/file/LinuxFileSystemTestData.java b/luni/src/test/java/libcore/java/nio/file/LinuxFileSystemTestData.java
new file mode 100644
index 0000000..0780727
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/file/LinuxFileSystemTestData.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 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.java.nio.file;
+
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.InvalidPathException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The class provides test cases to libcore.java.nio.file.PathsTest#test_get_URI,
+ * libcore.java.nio.file.PathsTest#test_get_String,
+ * libcore.java.nio.file.LinuxFileSystemTest#test_getPath
+ */
+class LinuxFileSystemTestData {
+ static List<TestData> getPathInputOutputTestData() {
+ List<TestData> inputOutputTestCases = new ArrayList<>();
+ inputOutputTestCases.add(new TestData("d1", "d1"));
+ inputOutputTestCases.add(new TestData("", ""));
+ inputOutputTestCases.add(new TestData("/", "//"));
+ inputOutputTestCases.add(new TestData("d1/d2/d3", "d1//d2/d3"));
+ inputOutputTestCases.add(new TestData("d1/d2", "d1", "", "d2"));
+ inputOutputTestCases.add(new TestData("foo", "", "foo"));
+
+ // If the name separator is "/" and getPath("/foo","bar","gus") is invoked, then the path
+ // string "/foo/bar/gus" is converted to a Path.
+ inputOutputTestCases.add(new TestData("/foo/bar/gus", "/foo", "bar", "gus"));
+ return inputOutputTestCases;
+ }
+
+ static List<TestData> getPathExceptionTestData() {
+ List<TestData> exceptionTestCases = new ArrayList<>();
+ exceptionTestCases.add(new TestData(InvalidPathException.class, "'\u0000'"));
+ exceptionTestCases.add(new TestData(NullPointerException.class, null));
+ return exceptionTestCases;
+ }
+
+ static List<TestData> getPath_URI_InputOutputTestData() {
+ // As of today, there is only one installed provider - LinuxFileSystemProvider and
+ // only scheme supported by it is "file".
+ List<TestData> inputOutputTestCases = new ArrayList<>();
+ inputOutputTestCases.add(new TestData("/d1", "file:///d1"));
+ inputOutputTestCases.add(new TestData("/", "file:///"));
+ inputOutputTestCases.add(new TestData("/d1//d2/d3", "file:///d1//d2/d3"));
+ return inputOutputTestCases;
+ }
+
+ static List<TestData> getPath_URI_ExceptionTestData() {
+ List<TestData> exceptionTestCases = new ArrayList<>();
+ exceptionTestCases.add(new TestData(IllegalArgumentException.class, "d1"));
+ exceptionTestCases.add(new TestData(FileSystemNotFoundException.class, "scheme://d"));
+ exceptionTestCases.add(new TestData(NullPointerException.class, null));
+ exceptionTestCases.add(new TestData(IllegalArgumentException.class, "file:///d#row=4"));
+ exceptionTestCases.add(new TestData(IllegalArgumentException.class, "file:///d?q=5"));
+ exceptionTestCases.add(new TestData(IllegalArgumentException.class, "file://d:5000"));
+ return exceptionTestCases;
+ }
+
+ static class TestData {
+ public String output;
+ public String input;
+ public String[] inputArray;
+ public Class exceptionClass;
+
+ TestData(String output, String input, String... inputArray) {
+ this.output = output;
+ this.input = input;
+ this.inputArray = inputArray;
+ }
+
+ TestData(Class exceptionClass, String input, String... inputArray) {
+ this.exceptionClass = exceptionClass;
+ this.input = input;
+ this.inputArray = inputArray;
+ }
+ }
+}
\ No newline at end of file
diff --git a/luni/src/test/java/libcore/java/nio/file/PathsTest.java b/luni/src/test/java/libcore/java/nio/file/PathsTest.java
new file mode 100644
index 0000000..881d595
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/file/PathsTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 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.java.nio.file;
+
+
+import org.junit.Test;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Paths;
+import java.util.List;
+
+import static libcore.java.nio.file.LinuxFileSystemTestData.*;
+import static libcore.java.nio.file.LinuxFileSystemTestData.getPathInputOutputTestData;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+
+public class PathsTest {
+
+ @Test
+ public void test_get_String() {
+ List<TestData> inputOutputTestCases = getPathInputOutputTestData();
+ for (TestData inputOutputTestCase : inputOutputTestCases) {
+ assertEquals(inputOutputTestCase.output, Paths.get(inputOutputTestCase.input,
+ inputOutputTestCase.inputArray).toString());
+ }
+
+ List<TestData> exceptionTestCases = getPathExceptionTestData();
+ for (TestData exceptionTestCase : exceptionTestCases) {
+ try {
+ Paths.get(exceptionTestCase.input, exceptionTestCase.inputArray);
+ fail();
+ } catch (Exception expected) {
+ assertEquals(exceptionTestCase.exceptionClass, expected.getClass());
+ }
+ }
+ }
+
+ @Test
+ public void test_get_URI() throws URISyntaxException {
+ List<TestData> inputOutputTestCases = getPath_URI_InputOutputTestData();
+ for (TestData inputOutputTestCase : inputOutputTestCases) {
+ assertEquals(inputOutputTestCase.output, Paths.get(new URI(inputOutputTestCase.input)).
+ toString());
+ }
+
+ List<TestData> exceptionTestCases = getPath_URI_ExceptionTestData();
+ for (TestData exceptionTestCase : exceptionTestCases) {
+ try {
+ System.out.println(exceptionTestCase.input);
+ Paths.get(new URI(exceptionTestCase.input));
+ fail();
+ } catch (Exception expected) {
+ assertEquals(exceptionTestCase.exceptionClass, expected.getClass());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/luni/src/test/java/libcore/java/security/AccessControllerTest.java b/luni/src/test/java/libcore/java/security/AccessControllerTest.java
index 1f7da91..5746abd 100644
--- a/luni/src/test/java/libcore/java/security/AccessControllerTest.java
+++ b/luni/src/test/java/libcore/java/security/AccessControllerTest.java
@@ -36,6 +36,7 @@
public void testDoPrivilegedWithCombiner() {
final Permission permission = new RuntimePermission("do stuff");
final DomainCombiner union = new DomainCombiner() {
+ @Override
public ProtectionDomain[] combine(ProtectionDomain[] a, ProtectionDomain[] b) {
throw new AssertionFailedError("Expected combiner to be unused");
}
@@ -48,12 +49,14 @@
final AtomicInteger actionCount = new AtomicInteger();
AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ @Override
public Void run() {
assertEquals(null, AccessController.getContext().getDomainCombiner());
AccessController.getContext().checkPermission(permission);
// Calling doPrivileged again would have exercised the combiner
AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ @Override
public Void run() {
actionCount.incrementAndGet();
assertEquals(null, AccessController.getContext().getDomainCombiner());
diff --git a/luni/src/test/java/libcore/java/security/SignatureTest.java b/luni/src/test/java/libcore/java/security/SignatureTest.java
index 8d1af37..055b8fe 100644
--- a/luni/src/test/java/libcore/java/security/SignatureTest.java
+++ b/luni/src/test/java/libcore/java/security/SignatureTest.java
@@ -16,6 +16,7 @@
package libcore.java.security;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -78,6 +79,7 @@
public void testSignature_getInstance_SuppliedProviderNotRegistered_Success() throws Exception {
Provider mockProvider = new MockProvider("MockProvider") {
+ @Override
public void setup() {
put("Signature.FOO", MockSignatureSpi.AllKeyTypes.class.getName());
}
@@ -92,6 +94,7 @@
public void testSignature_getInstance_DoesNotSupportKeyClass_Success() throws Exception {
Provider mockProvider = new MockProvider("MockProvider") {
+ @Override
public void setup() {
put("Signature.FOO", MockSignatureSpi.AllKeyTypes.class.getName());
put("Signature.FOO SupportedKeyClasses", "None");
@@ -116,6 +119,7 @@
public void testSignature_init_DoesNotSupportKeyClass_throwsInvalidKeyException()
throws Exception {
Provider mockProvider = new MockProvider("MockProvider") {
+ @Override
public void setup() {
put("Signature.FOO", MockSignatureSpi.AllKeyTypes.class.getName());
put("Signature.FOO SupportedKeyClasses", "None");
@@ -136,6 +140,7 @@
public void testSignature_getInstance_OnlyUsesSpecifiedProvider_SameNameAndClass_Success()
throws Exception {
Provider mockProvider = new MockProvider("MockProvider") {
+ @Override
public void setup() {
put("Signature.FOO", MockSignatureSpi.AllKeyTypes.class.getName());
}
@@ -145,6 +150,7 @@
try {
{
Provider mockProvider2 = new MockProvider("MockProvider") {
+ @Override
public void setup() {
put("Signature.FOO", MockSignatureSpi.AllKeyTypes.class.getName());
}
@@ -159,18 +165,21 @@
public void testSignature_getInstance_DelayedInitialization_KeyType() throws Exception {
Provider mockProviderSpecific = new MockProvider("MockProviderSpecific") {
+ @Override
public void setup() {
put("Signature.FOO", MockSignatureSpi.SpecificKeyTypes.class.getName());
put("Signature.FOO SupportedKeyClasses", MockPrivateKey.class.getName());
}
};
Provider mockProviderSpecific2 = new MockProvider("MockProviderSpecific2") {
+ @Override
public void setup() {
put("Signature.FOO", MockSignatureSpi.SpecificKeyTypes2.class.getName());
put("Signature.FOO SupportedKeyClasses", MockPrivateKey2.class.getName());
}
};
Provider mockProviderAll = new MockProvider("MockProviderAll") {
+ @Override
public void setup() {
put("Signature.FOO", MockSignatureSpi.AllKeyTypes.class.getName());
}
@@ -422,6 +431,7 @@
public void testSignature_getProvider_Subclass() throws Exception {
Provider mockProviderNonSpi = new MockProvider("MockProviderNonSpi") {
+ @Override
public void setup() {
put("Signature.FOO", MySignature.class.getName());
}
@@ -2874,7 +2884,8 @@
Signature sig = Signature.getInstance("NONEwithRSA");
sig.initVerify(pubKey);
sig.update(Vector1Data);
- assertFalse("Invalid signature must not verify", sig.verify("Invalid".getBytes()));
+ assertFalse("Invalid signature must not verify",
+ sig.verify("Invalid".getBytes(UTF_8)));
}
public void testSign_NONEwithRSA_Key_DataTooLarge_Failure() throws Exception {
@@ -2973,7 +2984,8 @@
sig.initVerify(pubKey);
sig.update(Vector1Data);
- assertFalse("Invalid signature should not verify", sig.verify("Invalid sig".getBytes()));
+ assertFalse("Invalid signature should not verify",
+ sig.verify("Invalid sig".getBytes(UTF_8)));
}
public void testVerify_NONEwithRSA_Key_SignatureTooLarge_Failure() throws Exception {
@@ -3299,13 +3311,13 @@
Signature ecdsaVerify = Signature.getInstance("SHA1withECDSA");
ecdsaVerify.initVerify(pub);
- ecdsaVerify.update("Satoshi Nakamoto".getBytes("UTF-8"));
+ ecdsaVerify.update("Satoshi Nakamoto".getBytes(UTF_8));
boolean result = ecdsaVerify.verify(SIGNATURE);
assertEquals(true, result);
ecdsaVerify = Signature.getInstance("SHA1withECDSA");
ecdsaVerify.initVerify(pub);
- ecdsaVerify.update("Not Satoshi Nakamoto".getBytes("UTF-8"));
+ ecdsaVerify.update("Not Satoshi Nakamoto".getBytes(UTF_8));
result = ecdsaVerify.verify(SIGNATURE);
assertEquals(false, result);
}
diff --git a/luni/src/test/java/libcore/java/security/cert/CertificateFactoryTest.java b/luni/src/test/java/libcore/java/security/cert/CertificateFactoryTest.java
index a3a721a..7b82cc6 100644
--- a/luni/src/test/java/libcore/java/security/cert/CertificateFactoryTest.java
+++ b/luni/src/test/java/libcore/java/security/cert/CertificateFactoryTest.java
@@ -16,6 +16,8 @@
package libcore.java.security.cert;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
import com.android.org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
import com.android.org.bouncycastle.asn1.x509.BasicConstraints;
import com.android.org.bouncycastle.asn1.x509.Extension;
@@ -50,6 +52,7 @@
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
+import java.util.Locale;
import java.util.List;
import java.util.TimeZone;
@@ -103,7 +106,7 @@
+ "-----END CERTIFICATE-----\r\n";
private static final byte[] VALID_CERTIFICATE_PEM_HEADER = "-----BEGIN CERTIFICATE-----\n"
- .getBytes();
+ .getBytes(UTF_8);
private static final byte[] VALID_CERTIFICATE_PEM_DATA =
("MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBM"
@@ -122,10 +125,10 @@
+ "ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF"
+ "AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5"
+ "u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6"
- + "z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==").getBytes();
+ + "z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==").getBytes(UTF_8);
private static final byte[] VALID_CERTIFICATE_PEM_FOOTER = "\n-----END CERTIFICATE-----\n"
- .getBytes();
+ .getBytes(UTF_8);
private static final String INVALID_CERTIFICATE_PEM =
"-----BEGIN CERTIFICATE-----\n"
@@ -183,19 +186,19 @@
private void test_generateCertificate(CertificateFactory cf) throws Exception {
{
- byte[] valid = VALID_CERTIFICATE_PEM.getBytes();
+ byte[] valid = VALID_CERTIFICATE_PEM.getBytes(UTF_8);
Certificate c = cf.generateCertificate(new ByteArrayInputStream(valid));
assertNotNull(c);
}
{
- byte[] valid = VALID_CERTIFICATE_PEM_CRLF.getBytes();
+ byte[] valid = VALID_CERTIFICATE_PEM_CRLF.getBytes(UTF_8);
Certificate c = cf.generateCertificate(new ByteArrayInputStream(valid));
assertNotNull(c);
}
try {
- byte[] invalid = INVALID_CERTIFICATE_PEM.getBytes();
+ byte[] invalid = INVALID_CERTIFICATE_PEM.getBytes(UTF_8);
cf.generateCertificate(new ByteArrayInputStream(invalid));
fail();
} catch (CertificateException expected) {
@@ -263,7 +266,7 @@
throws Exception {
try {
Certificate c = cf.generateCertificate(new ByteArrayInputStream(
- "-----BEGIN CERTIFICATE-----".getBytes()));
+ "-----BEGIN CERTIFICATE-----".getBytes(UTF_8)));
if (!"BC".equals(cf.getProvider().getName())) {
fail("should throw CertificateException: " + cf.getProvider().getName());
}
@@ -277,7 +280,7 @@
private void test_generateCertificate_InputStream_Offset_Correct(CertificateFactory cf)
throws Exception {
- byte[] valid = VALID_CERTIFICATE_PEM.getBytes();
+ byte[] valid = VALID_CERTIFICATE_PEM.getBytes(UTF_8);
byte[] doubleCertificateData = new byte[valid.length * 2];
System.arraycopy(valid, 0, doubleCertificateData, 0, valid.length);
diff --git a/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java b/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java
index 817ad28..7178a59 100644
--- a/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java
+++ b/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java
@@ -16,6 +16,8 @@
package libcore.java.security.cert;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
import sun.security.provider.X509Factory;
import sun.security.x509.X509CRLImpl;
import tests.support.resource.Support_Resources;
@@ -30,7 +32,6 @@
import java.security.InvalidKeyException;
import java.security.Provider;
import java.security.Security;
-import java.security.SignatureException;
import java.security.cert.CRL;
import java.security.cert.CRLReason;
import java.security.cert.CertificateFactory;
@@ -129,7 +130,7 @@
final InputStream ris = Support_Resources.getStream(name);
try {
- final BufferedReader buf = new BufferedReader(new InputStreamReader(ris));
+ final BufferedReader buf = new BufferedReader(new InputStreamReader(ris, UTF_8));
String line;
while ((line = buf.readLine()) != null) {
diff --git a/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java b/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java
index f1cd4ff..0b01541 100644
--- a/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java
+++ b/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java
@@ -16,7 +16,7 @@
package libcore.java.security.cert;
-import tests.support.resource.Support_Resources;
+import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
@@ -56,11 +56,10 @@
import java.util.List;
import java.util.Locale;
import java.util.Set;
-
import javax.security.auth.x500.X500Principal;
-
import junit.framework.TestCase;
import libcore.java.security.StandardNames;
+import tests.support.resource.Support_Resources;
public class X509CertificateTest extends TestCase {
private Provider[] mX509Providers;
@@ -173,7 +172,7 @@
final SimpleDateFormat sdf =
new SimpleDateFormat("MMM dd HH:mm:ss yyyy zzz", Locale.US);
- final BufferedReader buf = new BufferedReader(new InputStreamReader(ris));
+ final BufferedReader buf = new BufferedReader(new InputStreamReader(ris, UTF_8));
String line = buf.readLine();
int index = line.indexOf('=');
assertEquals("notBefore", line.substring(0, index));
@@ -199,7 +198,7 @@
private BigInteger getRsaCertificateSerial() throws Exception {
final InputStream ris = Support_Resources.getStream("x509/cert-rsa-serial.txt");
try {
- final BufferedReader buf = new BufferedReader(new InputStreamReader(ris));
+ final BufferedReader buf = new BufferedReader(new InputStreamReader(ris, UTF_8));
String line = buf.readLine();
int index = line.indexOf('=');
diff --git a/luni/src/test/java/libcore/java/text/DateFormatTest.java b/luni/src/test/java/libcore/java/text/DateFormatTest.java
new file mode 100644
index 0000000..8e215ab
--- /dev/null
+++ b/luni/src/test/java/libcore/java/text/DateFormatTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 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.java.text;
+
+import junit.framework.TestCase;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+public class DateFormatTest extends TestCase {
+
+ // Regression test for http://b/31762542. If this test fails it implies that changes to
+ // DateFormat.is24Hour will not be effective.
+ public void testIs24Hour_notCached() throws Exception {
+ Boolean originalIs24Hour = DateFormat.is24Hour;
+ try {
+ // These tests hardcode expectations for Locale.US.
+ DateFormat.is24Hour = null; // null == locale default (12 hour for US)
+ checkTimePattern(DateFormat.SHORT, "h:mm a");
+ checkTimePattern(DateFormat.MEDIUM, "h:mm:ss a");
+
+ DateFormat.is24Hour = true; // Explicit 24 hour.
+ checkTimePattern(DateFormat.SHORT, "HH:mm");
+ checkTimePattern(DateFormat.MEDIUM, "HH:mm:ss");
+
+ DateFormat.is24Hour = false; // Explicit 12 hour.
+ checkTimePattern(DateFormat.SHORT, "h:mm a");
+ checkTimePattern(DateFormat.MEDIUM, "h:mm:ss a");
+ } finally {
+ DateFormat.is24Hour = originalIs24Hour;
+ }
+ }
+
+ private static void checkTimePattern(int style, String expectedPattern) {
+ final Locale locale = Locale.US;
+ final Date current = new Date(1468250177000L); // 20160711 15:16:17 GMT
+ DateFormat format = DateFormat.getTimeInstance(style, locale);
+ String actualDateString = format.format(current);
+ SimpleDateFormat sdf = new SimpleDateFormat(expectedPattern, locale);
+ String expectedDateString = sdf.format(current);
+ assertEquals(expectedDateString, actualDateString);
+ }
+}
diff --git a/luni/src/test/java/libcore/java/util/AbstractResourceLeakageDetectorTestCase.java b/luni/src/test/java/libcore/java/util/AbstractResourceLeakageDetectorTestCase.java
deleted file mode 100644
index 5ea67d3..0000000
--- a/luni/src/test/java/libcore/java/util/AbstractResourceLeakageDetectorTestCase.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2014 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.java.util;
-
-import junit.framework.TestCase;
-
-/**
- * Ensures that resources used within a test are cleaned up; will detect problems with tests and
- * also with runtime.
- */
-public abstract class AbstractResourceLeakageDetectorTestCase extends TestCase {
- /**
- * The leakage detector.
- */
- private ResourceLeakageDetector detector;
-
- @Override
- protected void setUp() throws Exception {
- detector = ResourceLeakageDetector.newDetector();
- }
-
- @Override
- protected void tearDown() throws Exception {
- // If available check for resource leakage. At this point it is impossible to determine
- // whether the test has thrown an exception. If it has then the exception thrown by this
- // could hide that test failure; it largely depends on the test runner.
- if (detector != null) {
- detector.checkForLeaks();
- }
- }
-}
diff --git a/luni/src/test/java/libcore/java/util/CurrencyTest.java b/luni/src/test/java/libcore/java/util/CurrencyTest.java
index 91584de..552ad9e 100644
--- a/luni/src/test/java/libcore/java/util/CurrencyTest.java
+++ b/luni/src/test/java/libcore/java/util/CurrencyTest.java
@@ -18,14 +18,10 @@
import java.util.Currency;
import java.util.Locale;
-import java.util.Objects;
import java.util.Set;
import libcore.util.SerializationTester;
-import static java.util.Locale.Category.DISPLAY;
-import static java.util.Locale.Category.FORMAT;
-
public class CurrencyTest extends junit.framework.TestCase {
// Regression test to ensure that Currency.getSymbol(Locale) returns the
// currency code if ICU doesn't have a localization of the symbol. The
@@ -53,13 +49,12 @@
*/
public void test_getSymbol_noLocaleArgument() {
Currency currency = Currency.getInstance("DEM");
- Locales locales = getDefaultLocales();
+ Locales locales = Locales.getAndSetDefaultForTest(Locale.US, Locale.GERMANY, Locale.FRANCE);
try {
- // Locales(locale, displayLocale, formatLocale)
- setDefaultLocales(new Locales(Locale.US, Locale.GERMANY, Locale.FRANCE));
+ // getAndSetDefaultForTest(uncategorizedLocale, displayLocale, formatLocale)
assertEquals("DM", currency.getSymbol());
} finally {
- setDefaultLocales(locales);
+ locales.setAsDefault();
}
}
@@ -115,13 +110,12 @@
*/
public void test_getDisplayName_noLocaleArgument() {
Currency currency = Currency.getInstance("DEM");
- Locales locales = getDefaultLocales();
+ // getAndSetDefaultForTest(uncategorizedLocale, displayLocale, formatLocale)
+ Locales locales = Locales.getAndSetDefaultForTest(Locale.US, Locale.GERMANY, Locale.FRANCE);
try {
- // Locales(uncategorizedLocale, displayLocale, formatLocale)
- setDefaultLocales(new Locales(Locale.US, Locale.GERMANY, Locale.FRANCE));
assertEquals("Deutsche Mark", currency.getDisplayName());
} finally {
- setDefaultLocales(locales);
+ locales.setAsDefault();
}
}
@@ -171,53 +165,4 @@
assertEquals(0, Currency.getInstance("XFU").getNumericCode());
}
- static Locales getDefaultLocales() {
- return new Locales(
- Locale.getDefault(), Locale.getDefault(DISPLAY), Locale.getDefault(FORMAT));
- }
-
- static void setDefaultLocales(Locales locales) {
- // The lines below must set the Locales in this order because setDefault(Locale)
- // overwrites the other ones.
- Locale.setDefault(locales.uncategorizedLocale);
- Locale.setDefault(DISPLAY, locales.displayLocale);
- Locale.setDefault(FORMAT, locales.formatLocale);
-
- assertEquals(locales, getDefaultLocales()); // sanity check
- }
-
- static class Locales {
- final Locale uncategorizedLocale;
- final Locale displayLocale;
- final Locale formatLocale;
-
- public Locales(Locale uncategorizedLocale, Locale displayLocale, Locale formatLocale) {
- this.uncategorizedLocale = uncategorizedLocale;
- this.displayLocale = displayLocale;
- this.formatLocale = formatLocale;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof Locales)) {
- return false;
- }
- Locales that = (Locales) obj;
- return uncategorizedLocale.equals(that.uncategorizedLocale)
- && displayLocale.equals(that.displayLocale)
- && formatLocale.equals(that.formatLocale);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(uncategorizedLocale, displayLocale, formatLocale);
- }
-
- @Override
- public String toString() {
- return "Locales[displayLocale=" + displayLocale + ", locale=" + uncategorizedLocale +
- ", formatLocale=" + formatLocale + ']';
- }
- }
-
}
diff --git a/luni/src/test/java/libcore/java/util/LocaleTest.java b/luni/src/test/java/libcore/java/util/LocaleTest.java
index f9146b3..91af1b7 100644
--- a/luni/src/test/java/libcore/java/util/LocaleTest.java
+++ b/luni/src/test/java/libcore/java/util/LocaleTest.java
@@ -29,6 +29,31 @@
import java.util.MissingResourceException;
public class LocaleTest extends junit.framework.TestCase {
+
+ public void test_extension_absent() throws Exception {
+ Locale locale = Locale.forLanguageTag("en-US");
+ assertFalse(locale.hasExtensions());
+ assertEquals(locale, locale.stripExtensions());
+ }
+
+ public void test_extension_builder() throws Exception {
+ Locale.Builder b = new Locale.Builder();
+ Locale localeWithoutExtension = b.build();
+ b.setExtension('g', "FO_ba-BR_bg");
+ Locale locale = b.build();
+ assertTrue(locale.hasExtensions());
+ assertFalse(locale.stripExtensions().hasExtensions());
+ assertEquals(localeWithoutExtension, locale.stripExtensions());
+ }
+
+ public void test_extension_languageTag() throws Exception {
+ Locale lA = Locale.forLanguageTag("en-Latn-US-x-foo");
+ Locale lB = Locale.forLanguageTag("en-Latn-US");
+ assertTrue(lA.hasExtensions());
+ assertFalse(lB.hasExtensions());
+ assertEquals(lB, lA.stripExtensions());
+ }
+
// http://b/2611311; if there's no display language/country/variant, use the raw codes.
public void test_getDisplayName_invalid() throws Exception {
Locale invalid = new Locale("AaBbCc", "DdEeFf", "GgHhIi");
@@ -774,22 +799,27 @@
Locale l = b.build();
- // getDisplayScript() test relies on the default locale. We set it here to avoid test
- // failures if the test device is set to a non-English locale.
- Locale.setDefault(Locale.US);
- assertEquals("Latin", l.getDisplayScript());
+ // getAndSetDefaultForTest(uncategorizedLocale, displayLocale, formatLocale)
+ Locales locales = Locales.getAndSetDefaultForTest(Locale.US, Locale.GERMANY, Locale.FRANCE);
+ try {
+ // Check that getDisplayScript() uses the default DISPLAY Locale.
+ assertEquals("Lateinisch", l.getDisplayScript()); // the German word for "Latin"
- assertEquals("Lateinisch", l.getDisplayScript(Locale.GERMAN));
- // Fallback for navajo, a language for which we don't have data.
- assertEquals("Latin", l.getDisplayScript(new Locale("nv", "US")));
+ assertEquals("latino", l.getDisplayScript(Locale.ITALY));
- b= new Locale.Builder();
- b.setLanguage("en").setRegion("US").setScript("Fooo");
+ // Fallback for navajo, a language for which we don't have data.
+ assertEquals("Latin", l.getDisplayScript(new Locale("nv", "US")));
- // Will be equivalent to getScriptCode for scripts that aren't
- // registered with ISO-15429 (but are otherwise well formed).
- l = b.build();
- assertEquals("Fooo", l.getDisplayScript());
+ b = new Locale.Builder();
+ b.setLanguage("en").setRegion("US").setScript("Fooo");
+
+ // Will be equivalent to getScriptCode for scripts that aren't
+ // registered with ISO-15429 (but are otherwise well formed).
+ l = b.build();
+ assertEquals("Fooo", l.getDisplayScript());
+ } finally {
+ locales.setAsDefault();
+ }
}
public void test_setLanguageTag_malformedTags() {
@@ -1254,6 +1284,7 @@
public void test_setDefault_withCategory() {
final Locale defaultLocale = Locale.getDefault();
try {
+ // Establish a baseline for the checks further down
Locale.setDefault(Locale.US);
assertEquals(Locale.US, Locale.getDefault(Locale.Category.FORMAT));
assertEquals(Locale.US, Locale.getDefault(Locale.Category.DISPLAY));
@@ -1273,6 +1304,12 @@
assertEquals(Locale.FRANCE, Locale.getDefault(Locale.Category.FORMAT));
assertEquals(Locale.FRANCE, Locale.getDefault(Locale.Category.DISPLAY));
assertEquals(Locale.FRANCE, Locale.getDefault());
+
+ // Check that setDefault(Locale) sets all three defaults
+ Locale.setDefault(Locale.US);
+ assertEquals(Locale.US, Locale.getDefault(Locale.Category.FORMAT));
+ assertEquals(Locale.US, Locale.getDefault(Locale.Category.DISPLAY));
+ assertEquals(Locale.US, Locale.getDefault());
} finally {
Locale.setDefault(defaultLocale);
}
diff --git a/luni/src/test/java/libcore/java/util/Locales.java b/luni/src/test/java/libcore/java/util/Locales.java
new file mode 100644
index 0000000..102188b
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/Locales.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 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.java.util;
+
+import java.util.Locale;
+import java.util.Objects;
+
+import static java.util.Locale.Category.DISPLAY;
+import static java.util.Locale.Category.FORMAT;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Helper class for tests that need to temporarily change the default Locales.
+ */
+class Locales {
+ private final Locale uncategorizedLocale;
+ private final Locale displayLocale;
+ private final Locale formatLocale;
+
+ private Locales(Locale uncategorizedLocale, Locale displayLocale, Locale formatLocale) {
+ this.uncategorizedLocale = uncategorizedLocale;
+ this.displayLocale = displayLocale;
+ this.formatLocale = formatLocale;
+ }
+
+ /**
+ * Sets the specified default Locale, default DISPLAY Locale and default FORMAT Locale.
+ * Every call to this method should be paired with exactly one corresponding call to
+ * reset the previous values:
+ * <pre>
+ * Locales locales = Locales.getAndSetDefaultForTest(Locale.US, Locale.CHINA, Locale.UK);
+ * try {
+ * ...
+ * } finally {
+ * locales.setAsDefault();
+ * }
+ * </pre>
+ */
+ public static Locales getAndSetDefaultForTest(Locale uncategorizedLocale, Locale displayLocale,
+ Locale formatLocale) {
+ Locales oldLocales = getDefault();
+ Locales newLocales = new Locales(uncategorizedLocale, displayLocale, formatLocale);
+ newLocales.setAsDefault();
+ assertEquals(newLocales, getDefault()); // sanity check
+ return oldLocales;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Locales)) {
+ return false;
+ }
+ Locales that = (Locales) obj;
+ return uncategorizedLocale.equals(that.uncategorizedLocale)
+ && displayLocale.equals(that.displayLocale)
+ && formatLocale.equals(that.formatLocale);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(uncategorizedLocale, displayLocale, formatLocale);
+ }
+
+ @Override
+ public String toString() {
+ return "Locales[displayLocale=" + displayLocale + ", locale=" + uncategorizedLocale +
+ ", formatLocale=" + formatLocale + ']';
+ }
+
+ /**
+ * Reset the system's default Locale values to what they were when this
+ * Locales was obtained.
+ */
+ public void setAsDefault() {
+ // The lines below must set the Locales in this order because setDefault(Locale)
+ // overwrites the other ones.
+ Locale.setDefault(uncategorizedLocale);
+ Locale.setDefault(DISPLAY, displayLocale);
+ Locale.setDefault(FORMAT, formatLocale);
+ }
+
+ public static Locales getDefault() {
+ return new Locales(
+ Locale.getDefault(), Locale.getDefault(DISPLAY), Locale.getDefault(FORMAT));
+ }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/ResourceLeakageDetector.java b/luni/src/test/java/libcore/java/util/ResourceLeakageDetector.java
deleted file mode 100644
index 954665a..0000000
--- a/luni/src/test/java/libcore/java/util/ResourceLeakageDetector.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2014 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.java.util;
-
-/**
- * Detects resource leakages for resources that are protected by <code>CloseGuard</code> mechanism.
- *
- * <p>If multiple instances of this are active at the same time, i.e. have been created but not yet
- * had their {@link #checkForLeaks()} method called then while they will report all the leakages
- * detected they may report the leakages caused by the code being tested by another detector.
- *
- * <p>The underlying CloseGuardMonitor is loaded using reflection to ensure that this will run,
- * albeit doing nothing, on the reference implementation.
- */
-public class ResourceLeakageDetector {
- /** The class for the CloseGuardMonitor, null if not supported. */
- private static final Class<?> CLOSE_GUARD_MONITOR_CLASS;
-
- static {
- ClassLoader classLoader = ResourceLeakageDetector.class.getClassLoader();
- Class<?> clazz;
- try {
- // Make sure that the CloseGuard class exists; this ensures that this is not running
- // on a RI JVM.
- classLoader.loadClass("dalvik.system.CloseGuard");
-
- // Load the monitor class for later instantiation.
- clazz = classLoader.loadClass("dalvik.system.CloseGuardMonitor");
-
- } catch (ClassNotFoundException e) {
- System.err.println("Resource leakage will not be detected; "
- + "this is expected in the reference implementation");
- e.printStackTrace(System.err);
-
- // Ignore, probably running in reference implementation.
- clazz = null;
- }
-
- CLOSE_GUARD_MONITOR_CLASS = clazz;
- }
-
- /**
- * The underlying CloseGuardMonitor that will perform the post test checks for resource
- * leakage.
- */
- private Runnable postTestChecker;
-
- /**
- * Create a new detector.
- *
- * @return The new {@link ResourceLeakageDetector}, its {@link #checkForLeaks()} method must be
- * called otherwise it will not clean up properly after itself.
- */
- public static ResourceLeakageDetector newDetector()
- throws Exception {
- return new ResourceLeakageDetector();
- }
-
- private ResourceLeakageDetector()
- throws Exception {
- if (CLOSE_GUARD_MONITOR_CLASS != null) {
- postTestChecker = (Runnable) CLOSE_GUARD_MONITOR_CLASS.newInstance();
- }
- }
-
- /**
- * Detect any leaks that have arisen since this was created.
- *
- * @throws Exception If any leaks were detected.
- */
- public void checkForLeaks() throws Exception {
- // If available check for resource leakage.
- if (postTestChecker != null) {
- postTestChecker.run();
- }
- }
-}
diff --git a/luni/src/test/java/libcore/java/util/ResourceLeakageDetectorTest.java b/luni/src/test/java/libcore/java/util/ResourceLeakageDetectorTest.java
deleted file mode 100644
index 5509f73..0000000
--- a/luni/src/test/java/libcore/java/util/ResourceLeakageDetectorTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2014 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.java.util;
-
-import dalvik.system.CloseGuard;
-import junit.framework.TestCase;
-
-/**
- * Test for {@link ResourceLeakageDetector}
- */
-public class ResourceLeakageDetectorTest extends TestCase {
- /**
- * This test will not work on RI as it does not support the <code>CloseGuard</code> or similar
- * mechanism.
- */
- // TODO(paulduffin): b/31542223 - Work out why this is failing in CTS, fix and reenable.
- public void notestDetectsUnclosedCloseGuard() throws Exception {
- ResourceLeakageDetector detector = ResourceLeakageDetector.newDetector();
- try {
- CloseGuard closeGuard = createCloseGuard();
- closeGuard.open("open");
- } finally {
- boolean leaksDetected = true;
- try {
- System.logI("Checking for leaks");
- detector.checkForLeaks();
- leaksDetected = false;
- } catch (AssertionError expected) {
- // The leak detector should throw this error.
- }
-
- if (!leaksDetected) {
- fail("Did not detect any leaks");
- }
- }
- }
-
- public void testIgnoresClosedCloseGuard() throws Exception {
- ResourceLeakageDetector detector = ResourceLeakageDetector.newDetector();
- try {
- CloseGuard closeGuard = createCloseGuard();
- closeGuard.open("open");
- closeGuard.close();
- } finally {
- detector.checkForLeaks();
- }
- }
-
- /**
- * Private method to ensure that the CloseGuard object is garbage collected.
- */
- private CloseGuard createCloseGuard() {
- final CloseGuard closeGuard = CloseGuard.get();
- new Object() {
- @Override
- protected void finalize() throws Throwable {
- try {
- closeGuard.warnIfOpen();
- } finally {
- super.finalize();
- }
- }
- };
-
- return closeGuard;
- }
-}
diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
index c5260328..ed5fdfb 100644
--- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
@@ -406,6 +406,21 @@
setExpectedBlockSize("RSA", Cipher.DECRYPT_MODE, 256);
setExpectedBlockSize("RSA/ECB/NoPadding", Cipher.DECRYPT_MODE, 256);
setExpectedBlockSize("RSA/ECB/PKCS1Padding", Cipher.DECRYPT_MODE, 256);
+
+ // OAEP padding modes change the output and block size. SHA-1 is the default.
+ setExpectedBlockSize("RSA/ECB/OAEPPadding", Cipher.ENCRYPT_MODE, 214);
+ setExpectedBlockSize("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", Cipher.ENCRYPT_MODE, 214);
+ setExpectedBlockSize("RSA/ECB/OAEPWithSHA-224AndMGF1Padding", Cipher.ENCRYPT_MODE, 198);
+ setExpectedBlockSize("RSA/ECB/OAEPWithSHA-256AndMGF1Padding", Cipher.ENCRYPT_MODE, 190);
+ setExpectedBlockSize("RSA/ECB/OAEPWithSHA-384AndMGF1Padding", Cipher.ENCRYPT_MODE, 158);
+ setExpectedBlockSize("RSA/ECB/OAEPWithSHA-512AndMGF1Padding", Cipher.ENCRYPT_MODE, 126);
+
+ setExpectedBlockSize("RSA/ECB/OAEPPadding", Cipher.DECRYPT_MODE, 256);
+ setExpectedBlockSize("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", Cipher.DECRYPT_MODE, 256);
+ setExpectedBlockSize("RSA/ECB/OAEPWithSHA-224AndMGF1Padding", Cipher.DECRYPT_MODE, 256);
+ setExpectedBlockSize("RSA/ECB/OAEPWithSHA-256AndMGF1Padding", Cipher.DECRYPT_MODE, 256);
+ setExpectedBlockSize("RSA/ECB/OAEPWithSHA-384AndMGF1Padding", Cipher.DECRYPT_MODE, 256);
+ setExpectedBlockSize("RSA/ECB/OAEPWithSHA-512AndMGF1Padding", Cipher.DECRYPT_MODE, 256);
}
}
@@ -614,6 +629,7 @@
setExpectedOutputSize("RSA", Cipher.DECRYPT_MODE, 256);
setExpectedOutputSize("RSA/ECB/NoPadding", Cipher.DECRYPT_MODE, 256);
setExpectedOutputSize("RSA/ECB/PKCS1Padding", Cipher.DECRYPT_MODE, 245);
+ setExpectedOutputSize("RSA/ECB/OAEPPadding", Cipher.DECRYPT_MODE, 256);
// SunJCE returns the full for size even when PKCS1Padding is specified
setExpectedOutputSize("RSA/ECB/PKCS1Padding", Cipher.DECRYPT_MODE, "SunJCE", 256);
@@ -621,6 +637,21 @@
// BC strips the leading 0 for us even when NoPadding is specified
setExpectedOutputSize("RSA", Cipher.DECRYPT_MODE, "BC", 255);
setExpectedOutputSize("RSA/ECB/NoPadding", Cipher.DECRYPT_MODE, "BC", 255);
+
+ // OAEP padding modes change the output and block size. SHA-1 is the default.
+ setExpectedOutputSize("RSA/ECB/OAEPPadding", Cipher.DECRYPT_MODE, 214);
+ setExpectedOutputSize("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", Cipher.DECRYPT_MODE, 214);
+ setExpectedOutputSize("RSA/ECB/OAEPWithSHA-224AndMGF1Padding", Cipher.DECRYPT_MODE, 198);
+ setExpectedOutputSize("RSA/ECB/OAEPWithSHA-256AndMGF1Padding", Cipher.DECRYPT_MODE, 190);
+ setExpectedOutputSize("RSA/ECB/OAEPWithSHA-384AndMGF1Padding", Cipher.DECRYPT_MODE, 158);
+ setExpectedOutputSize("RSA/ECB/OAEPWithSHA-512AndMGF1Padding", Cipher.DECRYPT_MODE, 126);
+
+ setExpectedOutputSize("RSA/ECB/OAEPPadding", Cipher.ENCRYPT_MODE, 256);
+ setExpectedOutputSize("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", Cipher.ENCRYPT_MODE, 256);
+ setExpectedOutputSize("RSA/ECB/OAEPWithSHA-224AndMGF1Padding", Cipher.ENCRYPT_MODE, 256);
+ setExpectedOutputSize("RSA/ECB/OAEPWithSHA-256AndMGF1Padding", Cipher.ENCRYPT_MODE, 256);
+ setExpectedOutputSize("RSA/ECB/OAEPWithSHA-384AndMGF1Padding", Cipher.ENCRYPT_MODE, 256);
+ setExpectedOutputSize("RSA/ECB/OAEPWithSHA-512AndMGF1Padding", Cipher.ENCRYPT_MODE, 256);
}
private static void setExpectedOutputSize(String algorithm, int value) {
@@ -2315,6 +2346,55 @@
};
/*
+ * echo -n 'This is a test of OAEP' | openssl pkeyutl -encrypt -inkey /tmp/rsakey.txt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha1 -pkeyopt rsa_oaep_label:010203FFA00A | xxd -p -i | sed 's/0x/(byte) 0x/g'
+ */
+ public static final byte[] RSA_Vector2_OAEP_SHA256_MGF1_SHA1_LABEL = new byte[] {
+ (byte) 0x80, (byte) 0xb1, (byte) 0xf2, (byte) 0xc2, (byte) 0x03, (byte) 0xc5,
+ (byte) 0xdf, (byte) 0xbd, (byte) 0xed, (byte) 0xfe, (byte) 0xe6, (byte) 0xff,
+ (byte) 0xd3, (byte) 0x38, (byte) 0x1e, (byte) 0x6d, (byte) 0xae, (byte) 0x47,
+ (byte) 0xfe, (byte) 0x19, (byte) 0xf9, (byte) 0x8c, (byte) 0xf1, (byte) 0x4d,
+ (byte) 0x18, (byte) 0x2b, (byte) 0x7e, (byte) 0x8e, (byte) 0x47, (byte) 0x39,
+ (byte) 0xa8, (byte) 0x04, (byte) 0xc4, (byte) 0x7d, (byte) 0x56, (byte) 0x03,
+ (byte) 0x15, (byte) 0x92, (byte) 0x18, (byte) 0xde, (byte) 0x56, (byte) 0xb3,
+ (byte) 0x01, (byte) 0x93, (byte) 0x16, (byte) 0xe3, (byte) 0xfa, (byte) 0xaa,
+ (byte) 0xf3, (byte) 0x73, (byte) 0x39, (byte) 0x26, (byte) 0xfb, (byte) 0xb0,
+ (byte) 0x18, (byte) 0x20, (byte) 0xdb, (byte) 0xa1, (byte) 0xbf, (byte) 0x31,
+ (byte) 0x22, (byte) 0xc8, (byte) 0x1d, (byte) 0xdb, (byte) 0xa0, (byte) 0x5a,
+ (byte) 0x22, (byte) 0xcd, (byte) 0x09, (byte) 0xb3, (byte) 0xcb, (byte) 0xa2,
+ (byte) 0x46, (byte) 0x14, (byte) 0x35, (byte) 0x66, (byte) 0xe8, (byte) 0xb8,
+ (byte) 0x07, (byte) 0x23, (byte) 0xc5, (byte) 0xae, (byte) 0xe6, (byte) 0xf1,
+ (byte) 0x7a, (byte) 0x8f, (byte) 0x5c, (byte) 0x44, (byte) 0x34, (byte) 0xbf,
+ (byte) 0xd6, (byte) 0xf8, (byte) 0x0c, (byte) 0xc7, (byte) 0x8d, (byte) 0xcd,
+ (byte) 0x23, (byte) 0x84, (byte) 0xbe, (byte) 0x9b, (byte) 0xbf, (byte) 0x9a,
+ (byte) 0x70, (byte) 0x0f, (byte) 0x18, (byte) 0xc0, (byte) 0x6f, (byte) 0x23,
+ (byte) 0x67, (byte) 0xf8, (byte) 0xbb, (byte) 0xce, (byte) 0xc2, (byte) 0x47,
+ (byte) 0x82, (byte) 0xa0, (byte) 0xa5, (byte) 0x60, (byte) 0xcd, (byte) 0x25,
+ (byte) 0xa5, (byte) 0x4b, (byte) 0xe4, (byte) 0x06, (byte) 0x7f, (byte) 0x46,
+ (byte) 0x62, (byte) 0x86, (byte) 0x94, (byte) 0xbc, (byte) 0x7f, (byte) 0xb0,
+ (byte) 0x2e, (byte) 0xc1, (byte) 0x8c, (byte) 0x6c, (byte) 0x58, (byte) 0x05,
+ (byte) 0x6f, (byte) 0x35, (byte) 0x76, (byte) 0xd3, (byte) 0xdf, (byte) 0xc0,
+ (byte) 0xdd, (byte) 0x66, (byte) 0xbe, (byte) 0xa1, (byte) 0x7e, (byte) 0x52,
+ (byte) 0xed, (byte) 0x81, (byte) 0x0e, (byte) 0x2d, (byte) 0x5b, (byte) 0x2b,
+ (byte) 0xe3, (byte) 0x52, (byte) 0x0e, (byte) 0x56, (byte) 0x9b, (byte) 0x05,
+ (byte) 0x72, (byte) 0xa8, (byte) 0xc8, (byte) 0x57, (byte) 0x22, (byte) 0x67,
+ (byte) 0x0e, (byte) 0x5f, (byte) 0x01, (byte) 0xf2, (byte) 0x69, (byte) 0x66,
+ (byte) 0x6a, (byte) 0x47, (byte) 0x4f, (byte) 0x78, (byte) 0xb3, (byte) 0x1e,
+ (byte) 0x7d, (byte) 0xce, (byte) 0xb3, (byte) 0x35, (byte) 0xdf, (byte) 0x23,
+ (byte) 0xac, (byte) 0xf8, (byte) 0x88, (byte) 0xa1, (byte) 0xde, (byte) 0x38,
+ (byte) 0x96, (byte) 0xfd, (byte) 0xa2, (byte) 0x5d, (byte) 0x09, (byte) 0x52,
+ (byte) 0x11, (byte) 0x2b, (byte) 0x21, (byte) 0xf0, (byte) 0x0d, (byte) 0x4c,
+ (byte) 0x15, (byte) 0xc3, (byte) 0x88, (byte) 0x2b, (byte) 0xf6, (byte) 0x2b,
+ (byte) 0xe3, (byte) 0xfd, (byte) 0x52, (byte) 0xf0, (byte) 0x09, (byte) 0x5c,
+ (byte) 0x4f, (byte) 0x5b, (byte) 0x8b, (byte) 0x84, (byte) 0x71, (byte) 0x72,
+ (byte) 0x8d, (byte) 0xaa, (byte) 0x6c, (byte) 0x55, (byte) 0xba, (byte) 0xe7,
+ (byte) 0x9c, (byte) 0xba, (byte) 0xbf, (byte) 0xf4, (byte) 0x09, (byte) 0x0a,
+ (byte) 0x60, (byte) 0xec, (byte) 0x53, (byte) 0xa4, (byte) 0x01, (byte) 0xa5,
+ (byte) 0xf2, (byte) 0x58, (byte) 0xab, (byte) 0x95, (byte) 0x68, (byte) 0x79,
+ (byte) 0x0b, (byte) 0xc3, (byte) 0xc4, (byte) 0x00, (byte) 0x68, (byte) 0x19,
+ (byte) 0xca, (byte) 0x07, (byte) 0x0d, (byte) 0x32
+ };
+
+ /*
* echo -n 'This is a test of OAEP' | openssl pkeyutl -encrypt -inkey rsakey.pem \
* -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha224 -pkeyopt rsa_mgf1_md:sha224 \
* | xxd -p -i | sed 's/0x/(byte) 0x/g'
@@ -2518,6 +2598,55 @@
(byte) 0x9e, (byte) 0x77, (byte) 0xe0, (byte) 0xaa
};
+ /*
+ * echo -n 'This is a test of OAEP' | openssl pkeyutl -encrypt -inkey /tmp/rsakey.txt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha512 -pkeyopt rsa_mgf1_md:sha512 -pkeyopt rsa_oaep_label:010203FFA00A | xxd -p -i | sed 's/0x/(byte) 0x/g'
+ */
+ public static final byte[] RSA_Vector2_OAEP_SHA512_MGF1_SHA512_LABEL = new byte[] {
+ (byte) 0x31, (byte) 0x3b, (byte) 0x23, (byte) 0xcf, (byte) 0x40, (byte) 0xfe,
+ (byte) 0x15, (byte) 0x94, (byte) 0xd6, (byte) 0x81, (byte) 0x21, (byte) 0x69,
+ (byte) 0x8e, (byte) 0x58, (byte) 0xd5, (byte) 0x0f, (byte) 0xa8, (byte) 0x72,
+ (byte) 0x94, (byte) 0x13, (byte) 0xfe, (byte) 0xf9, (byte) 0xa1, (byte) 0x47,
+ (byte) 0x49, (byte) 0x91, (byte) 0xcb, (byte) 0x66, (byte) 0xe6, (byte) 0x5d,
+ (byte) 0x02, (byte) 0xad, (byte) 0xd4, (byte) 0x2f, (byte) 0x4f, (byte) 0xab,
+ (byte) 0xb7, (byte) 0x9e, (byte) 0xc0, (byte) 0xf0, (byte) 0x3d, (byte) 0x66,
+ (byte) 0x0e, (byte) 0x20, (byte) 0x82, (byte) 0x7f, (byte) 0x22, (byte) 0x8f,
+ (byte) 0x81, (byte) 0xba, (byte) 0x47, (byte) 0xc7, (byte) 0xaf, (byte) 0xb6,
+ (byte) 0x0e, (byte) 0x78, (byte) 0xe3, (byte) 0x30, (byte) 0xd7, (byte) 0x6c,
+ (byte) 0x81, (byte) 0xc2, (byte) 0x05, (byte) 0x7e, (byte) 0xe9, (byte) 0xac,
+ (byte) 0x8d, (byte) 0x45, (byte) 0x25, (byte) 0xe8, (byte) 0x26, (byte) 0x39,
+ (byte) 0x88, (byte) 0x64, (byte) 0x2e, (byte) 0xc6, (byte) 0xed, (byte) 0xd4,
+ (byte) 0xad, (byte) 0x94, (byte) 0xc8, (byte) 0x4e, (byte) 0x4a, (byte) 0x71,
+ (byte) 0x1e, (byte) 0x11, (byte) 0x14, (byte) 0x03, (byte) 0x56, (byte) 0x02,
+ (byte) 0x28, (byte) 0x32, (byte) 0x8f, (byte) 0xe2, (byte) 0x16, (byte) 0x4a,
+ (byte) 0x62, (byte) 0xa6, (byte) 0x9a, (byte) 0x8d, (byte) 0xf8, (byte) 0x33,
+ (byte) 0x35, (byte) 0xa2, (byte) 0xc7, (byte) 0x70, (byte) 0xcc, (byte) 0x26,
+ (byte) 0x1e, (byte) 0x4d, (byte) 0x9c, (byte) 0x4e, (byte) 0x2b, (byte) 0xe8,
+ (byte) 0xfd, (byte) 0x07, (byte) 0x33, (byte) 0x15, (byte) 0x53, (byte) 0x11,
+ (byte) 0x5c, (byte) 0x6f, (byte) 0x5d, (byte) 0x23, (byte) 0x7b, (byte) 0x3f,
+ (byte) 0x73, (byte) 0xff, (byte) 0xf4, (byte) 0xbe, (byte) 0x1f, (byte) 0xe6,
+ (byte) 0x5a, (byte) 0xb8, (byte) 0x2b, (byte) 0xd2, (byte) 0xbe, (byte) 0xa0,
+ (byte) 0x91, (byte) 0x5d, (byte) 0xca, (byte) 0x89, (byte) 0xb3, (byte) 0xce,
+ (byte) 0x0a, (byte) 0x2b, (byte) 0xce, (byte) 0xb9, (byte) 0xbe, (byte) 0x5d,
+ (byte) 0xb2, (byte) 0xc2, (byte) 0xd6, (byte) 0xa9, (byte) 0xbc, (byte) 0x37,
+ (byte) 0xed, (byte) 0x9a, (byte) 0xba, (byte) 0x35, (byte) 0xf8, (byte) 0x6e,
+ (byte) 0x63, (byte) 0x76, (byte) 0xd1, (byte) 0x12, (byte) 0xf5, (byte) 0x89,
+ (byte) 0xf0, (byte) 0x13, (byte) 0x86, (byte) 0xe7, (byte) 0x1b, (byte) 0x94,
+ (byte) 0xcb, (byte) 0xc8, (byte) 0x5c, (byte) 0x4c, (byte) 0x1b, (byte) 0x8a,
+ (byte) 0x2d, (byte) 0x6b, (byte) 0x24, (byte) 0x1a, (byte) 0x38, (byte) 0x14,
+ (byte) 0x77, (byte) 0x49, (byte) 0xe5, (byte) 0x08, (byte) 0x25, (byte) 0xe4,
+ (byte) 0xa6, (byte) 0xcf, (byte) 0x62, (byte) 0xfd, (byte) 0x66, (byte) 0x28,
+ (byte) 0xf0, (byte) 0x3a, (byte) 0x9c, (byte) 0x31, (byte) 0xef, (byte) 0x48,
+ (byte) 0x2a, (byte) 0xd3, (byte) 0x3e, (byte) 0x29, (byte) 0xfa, (byte) 0x18,
+ (byte) 0x8f, (byte) 0xd6, (byte) 0xaa, (byte) 0x1d, (byte) 0x10, (byte) 0xcd,
+ (byte) 0x35, (byte) 0x25, (byte) 0x92, (byte) 0x48, (byte) 0xa0, (byte) 0x2c,
+ (byte) 0xc1, (byte) 0x31, (byte) 0xeb, (byte) 0x47, (byte) 0x5b, (byte) 0x22,
+ (byte) 0x52, (byte) 0x7c, (byte) 0xf5, (byte) 0xec, (byte) 0x76, (byte) 0x90,
+ (byte) 0x94, (byte) 0x58, (byte) 0xd9, (byte) 0xd6, (byte) 0xe0, (byte) 0x0a,
+ (byte) 0x3f, (byte) 0x09, (byte) 0x98, (byte) 0x03, (byte) 0xc5, (byte) 0x07,
+ (byte) 0x8f, (byte) 0x89, (byte) 0x1e, (byte) 0x62, (byte) 0x2c, (byte) 0xea,
+ (byte) 0x17, (byte) 0x0a, (byte) 0x2e, (byte) 0x68
+ };
+
public void testRSA_ECB_NoPadding_Private_OnlyDoFinal_Success() throws Exception {
for (String provider : RSA_PROVIDERS) {
testRSA_ECB_NoPadding_Private_OnlyDoFinal_Success(provider);
@@ -3552,21 +3681,38 @@
addRsaOaepTest("SHA-256", MGF1ParameterSpec.SHA256, RSA_Vector2_OAEP_SHA256_MGF1_SHA256);
addRsaOaepTest("SHA-384", MGF1ParameterSpec.SHA384, RSA_Vector2_OAEP_SHA384_MGF1_SHA384);
addRsaOaepTest("SHA-512", MGF1ParameterSpec.SHA512, RSA_Vector2_OAEP_SHA512_MGF1_SHA512);
+ addRsaOaepTest("SHA-256", MGF1ParameterSpec.SHA1, RSA_Vector2_OAEP_SHA256_MGF1_SHA1_LABEL,
+ new byte[] { 0x01, 0x02, 0x03, (byte) 0xFF, (byte) 0xA0, 0x0A });
+ addRsaOaepTest("SHA-512", MGF1ParameterSpec.SHA512, RSA_Vector2_OAEP_SHA512_MGF1_SHA512_LABEL,
+ new byte[] { 0x01, 0x02, 0x03, (byte) 0xFF, (byte) 0xA0, 0x0A });
}
private static void addRsaOaepTest(String digest, MGF1ParameterSpec mgf1Spec, byte[] vector) {
+ addRsaOaepTest(digest, mgf1Spec, vector, null);
+ }
+
+ private static void addRsaOaepTest(String digest, MGF1ParameterSpec mgf1Spec, byte[] vector, byte[] label) {
+ final PSource pSource;
+ if (label == null) {
+ pSource = PSource.PSpecified.DEFAULT;
+ } else {
+ pSource = new PSource.PSpecified(label);
+ }
+
if (mgf1Spec.getDigestAlgorithm().equals(digest)) {
- RSA_OAEP_CIPHER_TEST_PARAMS.add(new OAEPCipherTestParam(
- "RSA/ECB/OAEPWith" + digest + "AndMGF1Padding",
- null,
- (PublicKey) getEncryptKey("RSA"),
- (PrivateKey) getDecryptKey("RSA"),
- RSA_Vector2_Plaintext,
- vector));
+ if (label == null) {
+ RSA_OAEP_CIPHER_TEST_PARAMS.add(new OAEPCipherTestParam(
+ "RSA/ECB/OAEPWith" + digest + "AndMGF1Padding",
+ null,
+ (PublicKey) getEncryptKey("RSA"),
+ (PrivateKey) getDecryptKey("RSA"),
+ RSA_Vector2_Plaintext,
+ vector));
+ }
RSA_OAEP_CIPHER_TEST_PARAMS.add(new OAEPCipherTestParam(
"RSA/ECB/OAEPWith" + digest + "AndMGF1Padding",
- new OAEPParameterSpec(digest, "MGF1", mgf1Spec, PSource.PSpecified.DEFAULT),
+ new OAEPParameterSpec(digest, "MGF1", mgf1Spec, pSource),
(PublicKey) getEncryptKey("RSA"),
(PrivateKey) getDecryptKey("RSA"),
RSA_Vector2_Plaintext,
@@ -3575,7 +3721,7 @@
RSA_OAEP_CIPHER_TEST_PARAMS.add(new OAEPCipherTestParam(
"RSA/ECB/OAEPPadding",
- new OAEPParameterSpec(digest, "MGF1", mgf1Spec, PSource.PSpecified.DEFAULT),
+ new OAEPParameterSpec(digest, "MGF1", mgf1Spec, pSource),
(PublicKey) getEncryptKey("RSA"),
(PrivateKey) getDecryptKey("RSA"),
RSA_Vector2_Plaintext,
@@ -3679,6 +3825,14 @@
MGF1ParameterSpec mgf1Spec = (MGF1ParameterSpec) oaepSpec.getMGFParameters();
logStream.append(", mgf1Hash=" + mgf1Spec.getDigestAlgorithm());
}
+ logStream.append(", pSource=");
+ PSource pSource = oaepSpec.getPSource();
+ logStream.append(pSource.getAlgorithm());
+ if (pSource.getAlgorithm().equals("PSpecified")) {
+ logStream.append(":{");
+ logStream.append(Arrays.toString(((PSource.PSpecified) pSource).getValue()));
+ logStream.append('}');
+ }
logStream.append('}');
}
@@ -3691,6 +3845,17 @@
c.init(Cipher.ENCRYPT_MODE, p.encryptKey, p.spec);
+ // This doesn't quite work on OAEPPadding unless it's the default case,
+ // because its size depends on the message digest algorithms used.
+ if (!p.transformation.endsWith("OAEPPADDING")) {
+ assertEquals(p.transformation + " getBlockSize() ENCRYPT_MODE",
+ getExpectedBlockSize(p.transformation, Cipher.ENCRYPT_MODE, provider),
+ c.getBlockSize());
+ }
+ assertTrue(p.transformation + " getOutputSize(0) ENCRYPT_MODE",
+ getExpectedOutputSize(p.transformation, Cipher.ENCRYPT_MODE, provider) <= c
+ .getOutputSize(0));
+
if (p.aad != null) {
c.updateAAD(p.aad);
}
@@ -3707,6 +3872,18 @@
c.init(Cipher.DECRYPT_MODE, p.decryptKey, p.spec);
+ assertEquals(p.transformation + " getBlockSize() DECRYPT_MODE",
+ getExpectedBlockSize(p.transformation, Cipher.DECRYPT_MODE, provider),
+ c.getBlockSize());
+
+ // This doesn't quite work on OAEPPadding unless it's the default case,
+ // because its size depends on the message digest algorithms used.
+ if (!p.transformation.endsWith("OAEPPADDING")) {
+ assertTrue(p.transformation + " getOutputSize(0) DECRYPT_MODE",
+ getExpectedOutputSize(p.transformation, Cipher.DECRYPT_MODE, provider) <= c
+ .getOutputSize(0));
+ }
+
if (!isAEAD(p.transformation)) {
try {
c.updateAAD(new byte[8]);
@@ -3723,14 +3900,14 @@
throw maybe;
}
} catch (BadPaddingException maybe) {
- // BC's OAEP has a bug where it doesn't support empty decrypt
+ // BC's OAEP has a bug where it doesn't support decrypt of a zero-length plaintext
if (!("BC".equals(provider) && p.transformation.contains("OAEP"))) {
throw maybe;
}
}
- // empty decrypt
- {
+ // decrypt an empty ciphertext; not valid for RSA
+ if (!p.transformation.contains("OAEP")) {
if ((!isAEAD(p.transformation)
&& (StandardNames.IS_RI || provider.equals("AndroidOpenSSL") ||
(provider.equals("BC") && p.transformation.contains("/CTR/"))))
@@ -3753,11 +3930,6 @@
if (!isAEAD(p.transformation)) {
throw maybe;
}
- } catch (BadPaddingException maybe) {
- // BC's OAEP has a bug where it doesn't support empty decrypt
- if (!("BC".equals(provider) && p.transformation.contains("OAEP"))) {
- throw maybe;
- }
}
try {
c.update(new byte[0]);
@@ -3771,11 +3943,6 @@
if (!isAEAD(p.transformation)) {
throw maybe;
}
- } catch (BadPaddingException maybe) {
- // BC's OAEP has a bug where it doesn't support empty decrypt
- if (!("BC".equals(provider) && p.transformation.contains("OAEP"))) {
- throw maybe;
- }
}
} else {
throw new AssertionError("Define your behavior here for " + provider);
diff --git a/luni/src/test/java/libcore/javax/crypto/KeyAgreementTest.java b/luni/src/test/java/libcore/javax/crypto/KeyAgreementTest.java
index 9281b43..809c290 100644
--- a/luni/src/test/java/libcore/javax/crypto/KeyAgreementTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/KeyAgreementTest.java
@@ -37,6 +37,7 @@
public void testKeyAgreement_getInstance_SuppliedProviderNotRegistered_Success()
throws Exception {
Provider mockProvider = new MockProvider("MockProvider") {
+ @Override
public void setup() {
put("KeyAgreement.FOO", MockKeyAgreementSpi.AllKeyTypes.class.getName());
}
@@ -52,6 +53,7 @@
public void testKeyAgreement_getInstance_DoesNotSupportKeyClass_Success()
throws Exception {
Provider mockProvider = new MockProvider("MockProvider") {
+ @Override
public void setup() {
put("KeyAgreement.FOO", MockKeyAgreementSpi.AllKeyTypes.class.getName());
put("KeyAgreement.FOO SupportedKeyClasses", "none");
@@ -76,6 +78,7 @@
public void testKeyAgreement_init_DoesNotSupportKeyClass_throwsInvalidKeyException()
throws Exception {
Provider mockProvider = new MockProvider("MockProvider") {
+ @Override
public void setup() {
put("KeyAgreement.FOO", MockKeyAgreementSpi.AllKeyTypes.class.getName());
put("KeyAgreement.FOO SupportedKeyClasses", "none");
diff --git a/luni/src/test/java/libcore/javax/crypto/MacTest.java b/luni/src/test/java/libcore/javax/crypto/MacTest.java
index b308f02..61da2bb 100644
--- a/luni/src/test/java/libcore/javax/crypto/MacTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/MacTest.java
@@ -16,13 +16,17 @@
package libcore.javax.crypto;
-import junit.framework.TestCase;
+import static java.nio.charset.StandardCharsets.UTF_8;
import java.security.InvalidKeyException;
import java.security.Provider;
import java.security.Security;
-
+import java.util.Arrays;
import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import junit.framework.TestCase;
public class MacTest extends TestCase {
private static abstract class MockProvider extends Provider {
@@ -42,6 +46,7 @@
public void testMac_init_DoesNotSupportKeyClass_throwsInvalidKeyException()
throws Exception {
Provider mockProvider = new MockProvider("MockProvider") {
+ @Override
public void setup() {
put("Mac.FOO", MockMacSpi.AllKeyTypes.class.getName());
put("Mac.FOO SupportedKeyClasses", "none");
@@ -69,4 +74,61 @@
assertEquals("HmacSHA224", androidOpenSSLProvider.get("Alg.Alias.Mac.1.2.840.113549.2.8"));
assertEquals("HmacSHA256", androidOpenSSLProvider.get("Alg.Alias.Mac.1.2.840.113549.2.9"));
}
+
+ // Known answers from the SunJCE provider using the code below. Run with
+ // vogar --classpath sunjce_provider.jar
+ //
+ // secretKeyFactory = SecretKeyFactory.getInstance("PBEWithHmacSHA" + shaVariant + "AndAES_128",
+ // new com.sun.crypto.provider.SunJCE());
+ // pbeKeySpec = new PBEKeySpec(password);
+ //
+ // secretKey = secretKeyFactory.generateSecret(pbeKeySpec);
+ // mac = Mac.getInstance("PBEWITHHMACSHA" + shaVariant, new com.sun.crypto.provider.SunJCE());
+ // mac.init(secretKey, new PBEParameterSpec(salt, iterationCount));
+ // byte[] sunResult = mac.doFinal(plaintext);
+ private final byte[][] SUN_JCA_KNOWN_ANSWERS_FOR_SHA_VARIANTS = {
+ { 44, -78, -97, -109, -125, 49, 68, 58, -9, -99, -27, -122, 58, 27, 7, 45, 87, -92,
+ -74, 64 },
+ { 59, -13, 28, 53, 79, -79, -127, 117, 3, -23, -75, -127, -44, -47, -43, 28, 76, -114,
+ -110, 26, 59, 70, -91, 19, -52, 36, -64, -54 },
+ { 88, 54, -105, -122, 14, 73, -40, -43, 52, -21, -33, -103, 32, 81, 115, 53, 111, 78,
+ 32, -108, 71, -74, -84, 125, 80, 13, -35, -36, 27, 56, 32, 104 },
+ { -83, 60, -92, 44, -58, 86, -121, 104, 114, -67, 14, 80, 84, -48, -14, 38, 14, -62,
+ -96, 118, 53, -59, -33, -90, 85, -110, 105, -119, -81, 57, 43, -66, 99, 106, 35,
+ -16, -115, 29, -56, -52, -39, 102, -1, -90, 110, -52, 48, -32},
+ { -22, -69, -77, 11, -14, -128, -121, 5, 48, 18, 107, -22, 64, -45, 18, 60, 24, -42,
+ -67, 111, 110, -99, -19, 14, -21, -43, 26, 68, -40, 82, 123, 39, 115, 34, 6,
+ -67, 27, -73, -63, -56, -39, 65, -75, -14, -5, -94, -8, 126, -44, -97, 95, 31,
+ 61, 123, -17, 14, 117, 71, -45, 53, -76, -91, 91, -121}
+ };
+
+ /**
+ * Test that BC has the same results as the SunJCA provider for
+ */
+ public void test_PBEWITHHMACSHA_Variants() throws Exception {
+ byte[] plaintext = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34 };
+ byte[] salt = "saltsalt".getBytes(UTF_8);
+ char[] password = "password".toCharArray();
+ int iterationCount = 100;
+ int[] shaVariants = { 1, 224, 256, 384, 512 };
+
+ for (int shaVariantIndex = 0; shaVariantIndex < shaVariants.length; shaVariantIndex++) {
+ int shaVariant = shaVariants[shaVariantIndex];
+ SecretKeyFactory secretKeyFactory =
+ SecretKeyFactory.getInstance("PBKDF2WITHHMACSHA" + shaVariant, "BC");
+ PBEKeySpec pbeKeySpec = new PBEKeySpec(password,
+ salt,
+ iterationCount,
+ // Key depending on block size!
+ (shaVariant < 384) ? 64 : 128);
+ SecretKey secretKey = secretKeyFactory.generateSecret(pbeKeySpec);
+ Mac mac = Mac.getInstance("PBEWITHHMACSHA" + shaVariant, "BC");
+ mac.init(secretKey);
+ byte[] bcResult = mac.doFinal(plaintext);
+ assertEquals(
+ Arrays.toString(SUN_JCA_KNOWN_ANSWERS_FOR_SHA_VARIANTS[shaVariantIndex]),
+ Arrays.toString(bcResult));
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/javax/crypto/MockMacSpi.java b/luni/src/test/java/libcore/javax/crypto/MockMacSpi.java
index 0edeba7..d3ff9d5 100644
--- a/luni/src/test/java/libcore/javax/crypto/MockMacSpi.java
+++ b/luni/src/test/java/libcore/javax/crypto/MockMacSpi.java
@@ -26,7 +26,6 @@
import javax.crypto.BadPaddingException;
import javax.crypto.MacSpi;
-import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
diff --git a/luni/src/test/java/libcore/javax/crypto/SecretKeyFactoryTest.java b/luni/src/test/java/libcore/javax/crypto/SecretKeyFactoryTest.java
index ef5adc9..0878bac 100644
--- a/luni/src/test/java/libcore/javax/crypto/SecretKeyFactoryTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/SecretKeyFactoryTest.java
@@ -16,6 +16,8 @@
package libcore.javax.crypto;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;
@@ -171,7 +173,7 @@
public void test_PBKDF2_b8312059() throws Exception {
char[] password = "\u0141\u0142".toCharArray();
- byte[] salt = "salt".getBytes();
+ byte[] salt = "salt".getBytes(UTF_8);
int iterations = 4096;
int keyLength = 160;
byte[] expected_utf8 = new byte[] {
diff --git a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParameterGeneratorTestDH.java b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParameterGeneratorTestDH.java
index 77d81db..aed6ce8 100644
--- a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParameterGeneratorTestDH.java
+++ b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParameterGeneratorTestDH.java
@@ -25,6 +25,7 @@
super("DH", new AlgorithmParameterKeyAgreementHelper("DH"));
}
+ @Override
public void testAlgorithmParameterGenerator() throws Exception {
super.testAlgorithmParameterGenerator();
}
diff --git a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDH.java b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDH.java
index f8a5b5d..6e62c03 100644
--- a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDH.java
+++ b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDH.java
@@ -61,6 +61,7 @@
}
// Broken Test: Suffers from DH slowness, disabling for now
+ @Override
public void testAlgorithmParameters() throws Exception {
super.testAlgorithmParameters();
}
diff --git a/luni/src/test/java/libcore/javax/crypto/spec/KeyPairGeneratorTestDH.java b/luni/src/test/java/libcore/javax/crypto/spec/KeyPairGeneratorTestDH.java
index 1ef4c8c..5a74d68 100644
--- a/luni/src/test/java/libcore/javax/crypto/spec/KeyPairGeneratorTestDH.java
+++ b/luni/src/test/java/libcore/javax/crypto/spec/KeyPairGeneratorTestDH.java
@@ -26,6 +26,7 @@
}
// Broken Test: Takes ages due to DH computations. Disabling for now.
+ @Override
public void testKeyPairGenerator() throws Exception {
super.testKeyPairGenerator();
}
diff --git a/luni/src/test/java/libcore/javax/net/ServerSocketFactoryTest.java b/luni/src/test/java/libcore/javax/net/ServerSocketFactoryTest.java
index 77996dd..edb184c 100644
--- a/luni/src/test/java/libcore/javax/net/ServerSocketFactoryTest.java
+++ b/luni/src/test/java/libcore/javax/net/ServerSocketFactoryTest.java
@@ -102,14 +102,14 @@
}
fail("Failed to exhaust backlog after " + max + " connections!");
} catch (IOException expected) {
+ } finally {
+ for (Socket socket : backlog) {
+ socket.close();
+ }
}
System.out.println("backlog peaked at " + peak);
- for (Socket socket : backlog) {
- socket.close();
- }
-
/*
* In 4.5 of UNIX Network Programming, Stevens says:
* "Berkeley-derived implementations add a fudge factor to the
diff --git a/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java b/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java
index b99a3f1..cd693c9 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java
@@ -26,7 +26,6 @@
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Arrays;
-import java.util.Locale;
import java.util.Set;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
@@ -42,6 +41,7 @@
private TestKeyStore testKeyStore;
+ @Override
protected void setUp() throws Exception {
// note the rare usage of DSA keys here in addition to RSA
testKeyStore = new TestKeyStore.Builder()
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
index 1628260..d9a7b4f 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
@@ -16,6 +16,8 @@
package libcore.javax.net.ssl;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
@@ -124,7 +126,7 @@
new PSKKeyManagerProxy() {
@Override
protected SecretKey getKey(String identityHint, String identity, SSLEngine engine) {
- return new SecretKeySpec("Just an arbitrary key".getBytes(), "RAW");
+ return new SecretKeySpec("Just an arbitrary key".getBytes(UTF_8), "RAW");
}
});
TestSSLContext c = TestSSLContext.createWithAdditionalKeyManagers(
@@ -223,9 +225,9 @@
"TLS".equalsIgnoreCase(c.clientContext.getProtocol())
&& cipherSuite.contains("_CBC_");
- assertSendsCorrectly("This is the client. Hello!".getBytes(),
+ assertSendsCorrectly("This is the client. Hello!".getBytes(UTF_8),
pair.client, pair.server, needsRecordSplit);
- assertSendsCorrectly("This is the server. Hi!".getBytes(),
+ assertSendsCorrectly("This is the server. Hi!".getBytes(UTF_8),
pair.server, pair.client, needsRecordSplit);
} finally {
if (pair != null) {
@@ -818,11 +820,12 @@
final CountDownLatch startUpSync = new CountDownLatch(2);
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Void> client = executor.submit(new Callable<Void>() {
+ @Override
public Void call() throws Exception {
startUpSync.countDown();
for (int i = 0; i < NUM_STRESS_ITERATIONS; i++) {
- assertSendsCorrectly("This is the client. Hello!".getBytes(),
+ assertSendsCorrectly("This is the client. Hello!".getBytes(UTF_8),
pair.client, pair.server, false);
}
@@ -830,11 +833,12 @@
}
});
Future<Void> server = executor.submit(new Callable<Void>() {
+ @Override
public Void call() throws Exception {
startUpSync.countDown();
for (int i = 0; i < NUM_STRESS_ITERATIONS; i++) {
- assertSendsCorrectly("This is the server. Hi!".getBytes(),
+ assertSendsCorrectly("This is the server. Hi!".getBytes(UTF_8),
pair.server, pair.client, false);
}
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
index d2ad9fd..4f12841b 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
@@ -16,6 +16,8 @@
package libcore.javax.net.ssl;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.EOFException;
@@ -125,14 +127,14 @@
String clientToServerString = "this is sent from the client to the server...";
String serverToClientString = "... and this from the server to the client";
- byte[] clientToServer = clientToServerString.getBytes();
- byte[] serverToClient = serverToClientString.getBytes();
+ byte[] clientToServer = clientToServerString.getBytes(UTF_8);
+ byte[] serverToClient = serverToClientString.getBytes(UTF_8);
KeyManager pskKeyManager = PSKKeyManagerProxy.getConscryptPSKKeyManager(
new PSKKeyManagerProxy() {
@Override
protected SecretKey getKey(String identityHint, String identity, Socket socket) {
- return new SecretKeySpec("Just an arbitrary key".getBytes(), "RAW");
+ return new SecretKeySpec("Just an arbitrary key".getBytes(UTF_8), "RAW");
}
});
TestSSLContext c = TestSSLContext.createWithAdditionalKeyManagers(
@@ -533,6 +535,7 @@
executor.shutdown();
final boolean[] handshakeCompletedListenerCalled = new boolean[1];
client.addHandshakeCompletedListener(new HandshakeCompletedListener() {
+ @Override
public void handshakeCompleted(HandshakeCompletedEvent event) {
try {
SSLSession session = event.getSession();
@@ -655,6 +658,7 @@
});
executor.shutdown();
client.addHandshakeCompletedListener(new HandshakeCompletedListener() {
+ @Override
public void handshakeCompleted(HandshakeCompletedEvent event) {
throw expectedException;
}
@@ -1108,6 +1112,7 @@
// ...so are a lot of other operations...
HandshakeCompletedListener l = new HandshakeCompletedListener () {
+ @Override
public void handshakeCompleted(HandshakeCompletedEvent e) {}
};
client.addHandshakeCompletedListener(l);
@@ -1385,10 +1390,10 @@
// Reflection is used so this can compile on the RI
String expectedClassName = "com.android.org.conscrypt.OpenSSLSocketImpl";
- Class actualClass = client.getClass();
+ Class<?> actualClass = client.getClass();
assertEquals(expectedClassName, actualClass.getName());
Method setSoWriteTimeout = actualClass.getMethod("setSoWriteTimeout",
- new Class[] { Integer.TYPE });
+ new Class<?>[] { Integer.TYPE });
setSoWriteTimeout.invoke(client, 1);
@@ -1953,6 +1958,7 @@
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Void> s = executor.submit(new Callable<Void>() {
+ @Override
public Void call() throws Exception {
server.setEnabledProtocols(new String[] { "TLSv1.2" });
server.setEnabledCipherSuites(serverCipherSuites);
@@ -1961,6 +1967,7 @@
}
});
Future<Void> c = executor.submit(new Callable<Void>() {
+ @Override
public Void call() throws Exception {
client.setEnabledProtocols(new String[] { "TLSv1.2" });
client.setEnabledCipherSuites(clientCipherSuites);
@@ -1991,6 +1998,7 @@
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Void> s = executor.submit(new Callable<Void>() {
+ @Override
public Void call() throws Exception {
server.setEnabledProtocols(new String[] { "TLSv1.2", "TLSv1.1" });
server.startHandshake();
@@ -1998,6 +2006,7 @@
}
});
Future<Void> c = executor.submit(new Callable<Void>() {
+ @Override
public Void call() throws Exception {
client.setEnabledProtocols(new String[] { "TLSv1.1" });
client.startHandshake();
@@ -2034,6 +2043,7 @@
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Void> s = executor.submit(new Callable<Void>() {
+ @Override
public Void call() throws Exception {
server.setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1" });
server.setEnabledCipherSuites(serverCipherSuites);
@@ -2049,6 +2059,7 @@
}
});
Future<Void> c = executor.submit(new Callable<Void>() {
+ @Override
public Void call() throws Exception {
client.setEnabledProtocols(new String[] { "TLSv1" });
client.setEnabledCipherSuites(clientCipherSuites);
@@ -2083,6 +2094,7 @@
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Void> c = executor.submit(new Callable<Void>() {
+ @Override
public Void call() throws Exception {
try {
client.startHandshake();
@@ -2095,6 +2107,7 @@
}
});
Future<Void> s = executor.submit(new Callable<Void>() {
+ @Override
public Void call() throws Exception {
// Wait until the client sends something.
byte[] scratch = new byte[8192];
@@ -2134,6 +2147,7 @@
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Void> s = executor.submit(new Callable<Void>() {
+ @Override
public Void call() throws Exception {
try {
server.startHandshake();
@@ -2146,6 +2160,7 @@
}
});
Future<Void> c = executor.submit(new Callable<Void>() {
+ @Override
public Void call() throws Exception {
// Send bogus ClientHello:
// TLSv1.2 Record Layer: Handshake Protocol: Client Hello
@@ -2225,11 +2240,9 @@
final SSLSocket client = (SSLSocket)
context.clientContext.getSocketFactory().createSocket();
- try {
- client.setEnabledProtocols(new String[] {"SSLv3"});
- fail("SSLSocket should not support SSLv3 protocol");
- } catch (IllegalArgumentException expected) {
- }
+ // For app compatibility, SSLv3 is stripped out when setting only.
+ client.setEnabledProtocols(new String[] {"SSLv3"});
+ assertEquals(0, client.getEnabledProtocols().length);
try {
client.setEnabledProtocols(new String[] {"SSL"});
diff --git a/luni/src/test/java/libcore/net/NetworkSecurityPolicyTest.java b/luni/src/test/java/libcore/net/NetworkSecurityPolicyTest.java
index fc312fc..da85c7d 100644
--- a/luni/src/test/java/libcore/net/NetworkSecurityPolicyTest.java
+++ b/luni/src/test/java/libcore/net/NetworkSecurityPolicyTest.java
@@ -28,8 +28,9 @@
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.concurrent.Future;
-import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.ErrorManager;
@@ -214,6 +215,7 @@
logger.publish(record);
assertNull(mockErrorManager.getMostRecentException());
server.assertDataTransmittedByClient();
+ logger.close();
}
// Assert that client does not transmit any data when cleartext traffic is not permitted.
@@ -235,8 +237,8 @@
private static class CapturingServerSocket implements Closeable {
private final ServerSocket mSocket;
private final int mPort;
- private final Thread mListeningThread;
- private final FutureTask<byte[]> mFirstChunkReceivedFuture;
+ private final ExecutorService executor;
+ private final Future<byte[]> mFirstChunkReceivedFuture;
/**
* Constructs a new socket listening on a local port.
@@ -252,32 +254,29 @@
public CapturingServerSocket(final byte[] replyOnConnect) throws IOException {
mSocket = new ServerSocket(0);
mPort = mSocket.getLocalPort();
- mFirstChunkReceivedFuture = new FutureTask<byte[]>(new Callable<byte[]>() {
- @Override
- public byte[] call() throws Exception {
- try (Socket client = mSocket.accept()) {
- // Reply (if requested)
- if (replyOnConnect != null) {
- client.getOutputStream().write(replyOnConnect);
- client.getOutputStream().flush();
- }
-
- // Read request
- byte[] buf = new byte[64 * 1024];
- int chunkSize = client.getInputStream().read(buf);
- if (chunkSize == -1) {
- // Connection closed without any data received
- return new byte[0];
- }
- // Received some data
- return Arrays.copyOf(buf, chunkSize);
- } finally {
- IoUtils.closeQuietly(mSocket);
+ Callable<byte[]> callable = () -> {
+ try (Socket client = mSocket.accept()) {
+ // Reply (if requested)
+ if (replyOnConnect != null) {
+ client.getOutputStream().write(replyOnConnect);
+ client.getOutputStream().flush();
}
+
+ // Read request
+ byte[] buf = new byte[64 * 1024];
+ int chunkSize = client.getInputStream().read(buf);
+ if (chunkSize == -1) {
+ // Connection closed without any data received
+ return new byte[0];
+ }
+ // Received some data
+ return Arrays.copyOf(buf, chunkSize);
+ } finally {
+ IoUtils.closeQuietly(mSocket);
}
- });
- mListeningThread = new Thread(mFirstChunkReceivedFuture);
- mListeningThread.start();
+ };
+ executor = Executors.newSingleThreadExecutor();
+ mFirstChunkReceivedFuture = executor.submit(callable);
}
public int getPort() {
@@ -291,12 +290,12 @@
@Override
public void close() {
IoUtils.closeQuietly(mSocket);
- mListeningThread.interrupt();
+ executor.shutdown();
}
private void assertDataTransmittedByClient()
throws Exception {
- byte[] firstChunkFromClient = getFirstReceivedChunkFuture().get(2, TimeUnit.SECONDS);
+ byte[] firstChunkFromClient = getFirstReceivedChunkFuture().get(4, TimeUnit.SECONDS);
if ((firstChunkFromClient == null) || (firstChunkFromClient.length == 0)) {
fail("Client did not transmit any data to server");
}
@@ -306,7 +305,7 @@
throws Exception {
byte[] firstChunkFromClient;
try {
- firstChunkFromClient = getFirstReceivedChunkFuture().get(2, TimeUnit.SECONDS);
+ firstChunkFromClient = getFirstReceivedChunkFuture().get(4, TimeUnit.SECONDS);
} catch (TimeoutException expected) {
return;
}
diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherSpiTest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherSpiTest.java
index e240f6f..1a2ac23 100644
--- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherSpiTest.java
+++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/CipherSpiTest.java
@@ -22,6 +22,7 @@
package org.apache.harmony.crypto.tests.javax.crypto;
+import java.nio.DirectByteBuffer;
import java.security.spec.AlgorithmParameterSpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@@ -35,6 +36,7 @@
import javax.crypto.ShortBufferException;
import javax.crypto.CipherSpi;
import java.nio.ByteBuffer;
+import java.util.concurrent.atomic.AtomicInteger;
import junit.framework.TestCase;
@@ -298,6 +300,137 @@
bb2.position(0);
assertTrue("Incorrect result", cSpi.engineDoFinal(bb1, bb2) > 0);
}
+
+ public void testCrypt_doNotCallPositionInNonArrayBackedInputBuffer() throws Exception {
+ ByteBuffer nonArrayBackedInputBuffer = new MockNonArrayBackedByteBuffer(10, false);
+ ByteBuffer nonArrayBackedOutputBuffer = new MockNonArrayBackedByteBuffer(10, false);
+ Mock_CipherSpi cipherSpi = new Mock_CipherSpi() {
+ public int engineGetOutputSize(int inputLength) {
+ return inputLength;
+ }
+ };
+ cipherSpi.engineUpdate(nonArrayBackedInputBuffer, nonArrayBackedOutputBuffer);
+ assertEquals(0, nonArrayBackedInputBuffer.position());
+ }
+
+ public void testCrypt_doNotCallPutForZeroLengthOutput() throws Exception {
+ ByteBuffer nonArrayBackedInputBuffer = new MockNonArrayBackedByteBuffer(10, false);
+ ByteBuffer nonArrayBackedOutputBuffer = new MockNonArrayBackedByteBuffer(10, false) {
+ @Override
+ public ByteBuffer put(byte[] dst, int offset, int length) {
+ if (length == 0) {
+ throw new IllegalStateException("put shouldn't be called with length 0");
+ }
+ return this;
+ }
+ };
+
+ Mock_CipherSpi cipherSpi = new Mock_CipherSpi() {
+ public int engineUpdate(
+ byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) {
+ return 0;
+ }
+ };
+
+ // The put method is not called in the output buffer and so the test passes.
+ cipherSpi.engineUpdate(nonArrayBackedInputBuffer, nonArrayBackedOutputBuffer);
+ }
+
+ // In case a call to engineGetOutputSize returns 0 for the whole input size, but a positive
+ // value for the chunk size to be written, check that the positive output size is used in the
+ // second attempt to read from the the buffer.
+ public void testCrypt_outputSizeUpdatedAfterShortBufferException()
+ throws Exception {
+
+ // 4096 is the value hardcoded for a maximum array allocation in CipherSpi#getTempArraySize
+ final int maxInternalArrayAllocation = 4096;
+ // The length of the input is greater than the max chunk allowed, so the size of the chunk
+ // and the size of the input will differ.
+ final int testInputLength = maxInternalArrayAllocation + 1;
+ // Length to be returned the second time engineGetOutputSize is called (that is, when it's
+ // called with maxInternalArrayAllocation). First length returned (that is, when it's
+ // called with testInputLength) is 0.
+ final int testSecondOutputLength = 1000;
+
+ final AtomicInteger firstGetLength = new AtomicInteger(0);
+ final AtomicInteger secondGetLength = new AtomicInteger(0);
+
+ ByteBuffer inputBuffer = new MockNonArrayBackedByteBuffer(testInputLength, false) {
+ private boolean getWasCalled = false;
+
+ @Override
+ public ByteBuffer get(byte[] dst, int offset, int length) {
+ if (!getWasCalled) {
+ getWasCalled = true;
+ firstGetLength.set(length);
+ } else {
+ if (secondGetLength.get() == 0) {
+ secondGetLength.set(length);
+ }
+ }
+ return this;
+ }
+ };
+
+ ByteBuffer outputBuffer = new MockNonArrayBackedByteBuffer(10, false);
+
+ Mock_CipherSpi cipherSpi = new Mock_CipherSpi() {
+ @Override
+ public int engineGetOutputSize(int inputLength) {
+ if (inputLength == testInputLength) {
+ return 0;
+ } else if (inputLength == maxInternalArrayAllocation) {
+ return testSecondOutputLength;
+ } else {
+ throw new IllegalStateException("Unexpected value " + inputLength);
+ }
+ }
+
+ @Override
+ public int engineUpdate(
+ byte[] inArray, int inOfs, int inLen, byte[] outArray, int outputOffset)
+ throws ShortBufferException {
+ if (inLen == maxInternalArrayAllocation) {
+ throw new ShortBufferException("to be caught in order to retry with a new"
+ + "output size");
+ }
+ return 0;
+ }
+ };
+
+ cipherSpi.engineUpdate(inputBuffer, outputBuffer);
+
+ assertEquals(
+ "first call to get must use the input length, as the output length "
+ + "from engineGetOutputSize is 0",
+ maxInternalArrayAllocation,
+ firstGetLength.get());
+
+ assertEquals(
+ "second call to get must use the new output length",
+ testSecondOutputLength,
+ secondGetLength.get());
+ }
+
+ // The tests using ByteBuffer depend on final methods (like hasArray) that cannot be mocked in
+ // Mockito, so the mock is done manually. ByteBuffer has abstract methods that are
+ // package-private, so extending DirectByteBuffer. It happens to be not backed by an array, so
+ // we use it when we need a byte buffer not array-backed.
+ private class MockNonArrayBackedByteBuffer extends DirectByteBuffer {
+ public MockNonArrayBackedByteBuffer(int capacity, boolean isReadOnly) {
+ super(capacity, 0 /* addr */, null /* fd */, null /* unmapper */, isReadOnly);
+ }
+
+ @Override
+ public ByteBuffer get(byte[] dst, int offset, int length) {
+ return this;
+ }
+
+ @Override
+ public ByteBuffer put(byte[] dst, int offset, int length) {
+ return this;
+ }
+ }
}
/**
*
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
index 61c6d03..9c562ee 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
@@ -531,7 +531,7 @@
try {
uc2.getInputStream();
fail();
- } catch (Throwable expected) {
+ } catch (IOException expected) {
}
}
diff --git a/ojluni/src/main/java/java/io/InputStream.java b/ojluni/src/main/java/java/io/InputStream.java
index 63d31d5..6c46a40 100644
--- a/ojluni/src/main/java/java/io/InputStream.java
+++ b/ojluni/src/main/java/java/io/InputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -193,8 +193,10 @@
* up skipping over some smaller number of bytes, possibly <code>0</code>.
* This may result from any of a number of conditions; reaching end of file
* before <code>n</code> bytes have been skipped is only one possibility.
- * The actual number of bytes skipped is returned. If <code>n</code> is
- * negative, no bytes are skipped.
+ * The actual number of bytes skipped is returned. If {@code n} is
+ * negative, the {@code skip} method for class {@code InputStream} always
+ * returns 0, and no bytes are skipped. Subclasses may handle the negative
+ * value differently.
*
* <p> The <code>skip</code> method of this class creates a
* byte array and then repeatedly reads into it until <code>n</code> bytes
@@ -304,8 +306,7 @@
*
* <p> The general contract of <code>reset</code> is:
*
- * <p><ul>
- *
+ * <ul>
* <li> If the method <code>markSupported</code> returns
* <code>true</code>, then:
*
diff --git a/ojluni/src/main/java/java/io/InputStreamReader.java b/ojluni/src/main/java/java/io/InputStreamReader.java
index 2cda0ce..e131dca 100644
--- a/ojluni/src/main/java/java/io/InputStreamReader.java
+++ b/ojluni/src/main/java/java/io/InputStreamReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@
/**
* An InputStreamReader is a bridge from byte streams to character streams: It
* reads bytes and decodes them into characters using a specified {@link
- * java.nio.charset.Charset <code>charset</code>}. The charset that it uses
+ * java.nio.charset.Charset charset}. The charset that it uses
* may be specified by name or may be given explicitly, or the platform's
* default charset may be accepted.
*
@@ -86,7 +86,7 @@
*
* @param charsetName
* The name of a supported
- * {@link java.nio.charset.Charset </code>charset<code>}
+ * {@link java.nio.charset.Charset charset}
*
* @exception UnsupportedEncodingException
* If the named charset is not supported
@@ -101,7 +101,7 @@
}
/**
- * Creates an InputStreamReader that uses the given charset. </p>
+ * Creates an InputStreamReader that uses the given charset.
*
* @param in An InputStream
* @param cs A charset
@@ -117,7 +117,7 @@
}
/**
- * Creates an InputStreamReader that uses the given charset decoder. </p>
+ * Creates an InputStreamReader that uses the given charset decoder.
*
* @param in An InputStream
* @param dec A charset decoder
diff --git a/ojluni/src/main/java/java/io/LineNumberInputStream.java b/ojluni/src/main/java/java/io/LineNumberInputStream.java
index d3b5d9b..1f37a98 100644
--- a/ojluni/src/main/java/java/io/LineNumberInputStream.java
+++ b/ojluni/src/main/java/java/io/LineNumberInputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,13 +30,13 @@
* functionality of keeping track of the current line number.
* <p>
* A line is a sequence of bytes ending with a carriage return
- * character (<code>'\r'</code>), a newline character
- * (<code>'\n'</code>), or a carriage return character followed
+ * character ({@code '\u005Cr'}), a newline character
+ * ({@code '\u005Cn'}), or a carriage return character followed
* immediately by a linefeed character. In all three cases, the line
* terminating character(s) are returned as a single newline character.
* <p>
- * The line number begins at <code>0</code>, and is incremented by
- * <code>1</code> when a <code>read</code> returns a newline character.
+ * The line number begins at {@code 0}, and is incremented by
+ * {@code 1} when a {@code read} returns a newline character.
*
* @author Arthur van Hoff
* @see java.io.LineNumberReader
@@ -66,27 +66,28 @@
/**
* Reads the next byte of data from this input stream. The value
- * byte is returned as an <code>int</code> in the range
- * <code>0</code> to <code>255</code>. If no byte is available
+ * byte is returned as an {@code int} in the range
+ * {@code 0} to {@code 255}. If no byte is available
* because the end of the stream has been reached, the value
- * <code>-1</code> is returned. This method blocks until input data
+ * {@code -1} is returned. This method blocks until input data
* is available, the end of the stream is detected, or an exception
* is thrown.
* <p>
- * The <code>read</code> method of
- * <code>LineNumberInputStream</code> calls the <code>read</code>
+ * The {@code read} method of
+ * {@code LineNumberInputStream} calls the {@code read}
* method of the underlying input stream. It checks for carriage
* returns and newline characters in the input, and modifies the
* current line number as appropriate. A carriage-return character or
* a carriage return followed by a newline character are both
* converted into a single newline character.
*
- * @return the next byte of data, or <code>-1</code> if the end of this
+ * @return the next byte of data, or {@code -1} if the end of this
* stream is reached.
* @exception IOException if an I/O error occurs.
* @see java.io.FilterInputStream#in
* @see java.io.LineNumberInputStream#getLineNumber()
*/
+ @SuppressWarnings("fallthrough")
public int read() throws IOException {
int c = pushBack;
@@ -110,18 +111,18 @@
}
/**
- * Reads up to <code>len</code> bytes of data from this input stream
+ * Reads up to {@code len} bytes of data from this input stream
* into an array of bytes. This method blocks until some input is available.
* <p>
- * The <code>read</code> method of
- * <code>LineNumberInputStream</code> repeatedly calls the
- * <code>read</code> method of zero arguments to fill in the byte array.
+ * The {@code read} method of
+ * {@code LineNumberInputStream} repeatedly calls the
+ * {@code read} method of zero arguments to fill in the byte array.
*
* @param b the buffer into which the data is read.
* @param off the start offset of the data.
* @param len the maximum number of bytes read.
* @return the total number of bytes read into the buffer, or
- * <code>-1</code> if there is no more data because the end of
+ * {@code -1} if there is no more data because the end of
* this stream has been reached.
* @exception IOException if an I/O error occurs.
* @see java.io.LineNumberInputStream#read()
@@ -159,15 +160,15 @@
}
/**
- * Skips over and discards <code>n</code> bytes of data from this
- * input stream. The <code>skip</code> method may, for a variety of
+ * Skips over and discards {@code n} bytes of data from this
+ * input stream. The {@code skip} method may, for a variety of
* reasons, end up skipping over some smaller number of bytes,
- * possibly <code>0</code>. The actual number of bytes skipped is
- * returned. If <code>n</code> is negative, no bytes are skipped.
+ * possibly {@code 0}. The actual number of bytes skipped is
+ * returned. If {@code n} is negative, no bytes are skipped.
* <p>
- * The <code>skip</code> method of <code>LineNumberInputStream</code> creates
+ * The {@code skip} method of {@code LineNumberInputStream} creates
* a byte array and then repeatedly reads into it until
- * <code>n</code> bytes have been read or the end of the stream has
+ * {@code n} bytes have been read or the end of the stream has
* been reached.
*
* @param n the number of bytes to be skipped.
@@ -224,12 +225,12 @@
* <p>
* Note that if the underlying input stream is able to supply
* <i>k</i> input characters without blocking, the
- * <code>LineNumberInputStream</code> can guarantee only to provide
+ * {@code LineNumberInputStream} can guarantee only to provide
* <i>k</i>/2 characters without blocking, because the
* <i>k</i> characters from the underlying input stream might
- * consist of <i>k</i>/2 pairs of <code>'\r'</code> and
- * <code>'\n'</code>, which are converted to just
- * <i>k</i>/2 <code>'\n'</code> characters.
+ * consist of <i>k</i>/2 pairs of {@code '\u005Cr'} and
+ * {@code '\u005Cn'}, which are converted to just
+ * <i>k</i>/2 {@code '\u005Cn'} characters.
*
* @return the number of bytes that can be read from this input stream
* without blocking.
@@ -242,12 +243,12 @@
/**
* Marks the current position in this input stream. A subsequent
- * call to the <code>reset</code> method repositions this stream at
+ * call to the {@code reset} method repositions this stream at
* the last marked position so that subsequent reads re-read the same bytes.
* <p>
- * The <code>mark</code> method of
- * <code>LineNumberInputStream</code> remembers the current line
- * number in a private variable, and then calls the <code>mark</code>
+ * The {@code mark} method of
+ * {@code LineNumberInputStream} remembers the current line
+ * number in a private variable, and then calls the {@code mark}
* method of the underlying input stream.
*
* @param readlimit the maximum limit of bytes that can be read before
@@ -263,12 +264,12 @@
/**
* Repositions this stream to the position at the time the
- * <code>mark</code> method was last called on this input stream.
+ * {@code mark} method was last called on this input stream.
* <p>
- * The <code>reset</code> method of
- * <code>LineNumberInputStream</code> resets the line number to be
- * the line number at the time the <code>mark</code> method was
- * called, and then calls the <code>reset</code> method of the
+ * The {@code reset} method of
+ * {@code LineNumberInputStream} resets the line number to be
+ * the line number at the time the {@code mark} method was
+ * called, and then calls the {@code reset} method of the
* underlying input stream.
* <p>
* Stream marks are intended to be used in
diff --git a/ojluni/src/main/java/java/io/LineNumberReader.java b/ojluni/src/main/java/java/io/LineNumberReader.java
index 31f1e87..29884fd 100644
--- a/ojluni/src/main/java/java/io/LineNumberReader.java
+++ b/ojluni/src/main/java/java/io/LineNumberReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -120,6 +120,7 @@
* @throws IOException
* If an I/O error occurs
*/
+ @SuppressWarnings("fallthrough")
public int read() throws IOException {
synchronized (lock) {
int c = super.read();
@@ -159,6 +160,7 @@
* @throws IOException
* If an I/O error occurs
*/
+ @SuppressWarnings("fallthrough")
public int read(char cbuf[], int off, int len) throws IOException {
synchronized (lock) {
int n = super.read(cbuf, off, len);
diff --git a/ojluni/src/main/java/java/io/ObjectInputStream.java b/ojluni/src/main/java/java/io/ObjectInputStream.java
index 419d095..f562fe4 100644
--- a/ojluni/src/main/java/java/io/ObjectInputStream.java
+++ b/ojluni/src/main/java/java/io/ObjectInputStream.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -111,7 +111,7 @@
*
* <p>Serializable classes that require special handling during the
* serialization and deserialization process should implement the following
- * methods:<p>
+ * methods:
*
* <pre>
* private void writeObject(java.io.ObjectOutputStream stream)
@@ -316,6 +316,7 @@
* @throws SecurityException if a security manager exists and its
* <code>checkPermission</code> method denies enabling
* subclassing.
+ * @throws IOException if an I/O error occurs while creating this stream
* @see SecurityManager#checkPermission
* @see java.io.SerializablePermission
*/
@@ -493,11 +494,12 @@
public void defaultReadObject()
throws IOException, ClassNotFoundException
{
- if (curContext == null) {
+ SerialCallbackContext ctx = curContext;
+ if (ctx == null) {
throw new NotActiveException("not in call to readObject");
}
- Object curObj = curContext.getObj();
- ObjectStreamClass curDesc = curContext.getDesc();
+ Object curObj = ctx.getObj();
+ ObjectStreamClass curDesc = ctx.getDesc();
bin.setBlockDataMode(false);
defaultReadFields(curObj, curDesc);
bin.setBlockDataMode(true);
@@ -531,11 +533,12 @@
public ObjectInputStream.GetField readFields()
throws IOException, ClassNotFoundException
{
- if (curContext == null) {
+ SerialCallbackContext ctx = curContext;
+ if (ctx == null) {
throw new NotActiveException("not in call to readObject");
}
- Object curObj = curContext.getObj();
- ObjectStreamClass curDesc = curContext.getDesc();
+ Object curObj = ctx.getObj();
+ ObjectStreamClass curDesc = ctx.getDesc();
bin.setBlockDataMode(false);
GetFieldImpl getField = new GetFieldImpl(curDesc);
getField.readFields();
@@ -693,9 +696,9 @@
boolean hasNonPublicInterface = false;
// define proxy in class loader of non-public interface(s), if any
- Class[] classObjs = new Class[interfaces.length];
+ Class<?>[] classObjs = new Class<?>[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
- Class cl = Class.forName(interfaces[i], false, latestLoader);
+ Class<?> cl = Class.forName(interfaces[i], false, latestLoader);
if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
if (hasNonPublicInterface) {
if (nonPublicLoader != cl.getClassLoader()) {
@@ -1233,7 +1236,7 @@
* "enableSubclassImplementation" SerializablePermission is checked.
*/
private void verifySubclass() {
- Class cl = getClass();
+ Class<?> cl = getClass();
if (cl == ObjectInputStream.class) {
return;
}
@@ -1477,12 +1480,12 @@
* ClassNotFoundException will be associated with the class' handle in the
* handle table).
*/
- private Class readClass(boolean unshared) throws IOException {
+ private Class<?> readClass(boolean unshared) throws IOException {
if (bin.readByte() != TC_CLASS) {
throw new InternalError();
}
ObjectStreamClass desc = readClassDesc(false);
- Class cl = desc.forClass();
+ Class<?> cl = desc.forClass();
passHandle = handles.assign(unshared ? unsharedMarker : cl);
ClassNotFoundException resolveEx = desc.getResolveException();
@@ -1552,7 +1555,7 @@
ifaces[i] = bin.readUTF();
}
- Class cl = null;
+ Class<?> cl = null;
ClassNotFoundException resolveEx = null;
bin.setBlockDataMode(true);
try {
@@ -1605,7 +1608,7 @@
"failed to read class descriptor").initCause(ex);
}
- Class cl = null;
+ Class<?> cl = null;
ClassNotFoundException resolveEx = null;
bin.setBlockDataMode(true);
final boolean checksRequired = isCustomSubclass();
@@ -1665,7 +1668,7 @@
int len = bin.readInt();
Object array = null;
- Class cl, ccl = null;
+ Class<?> cl, ccl = null;
if ((cl = desc.forClass()) != null) {
ccl = cl.getComponentType();
array = Array.newInstance(ccl, len);
@@ -1718,7 +1721,7 @@
* Reads in and returns enum constant, or null if enum type is
* unresolvable. Sets passHandle to enum constant's assigned handle.
*/
- private Enum readEnum(boolean unshared) throws IOException {
+ private Enum<?> readEnum(boolean unshared) throws IOException {
if (bin.readByte() != TC_ENUM) {
throw new InternalError();
}
@@ -1735,24 +1738,26 @@
}
String name = readString(false);
- Enum en = null;
- Class cl = desc.forClass();
+ Enum<?> result = null;
+ Class<?> cl = desc.forClass();
if (cl != null) {
try {
- en = Enum.valueOf(cl, name);
+ @SuppressWarnings("unchecked")
+ Enum<?> en = Enum.valueOf((Class)cl, name);
+ result = en;
} catch (IllegalArgumentException ex) {
throw (IOException) new InvalidObjectException(
"enum constant " + name + " does not exist in " +
cl).initCause(ex);
}
if (!unshared) {
- handles.setObject(enumHandle, en);
+ handles.setObject(enumHandle, result);
}
}
handles.finish(enumHandle);
passHandle = enumHandle;
- return en;
+ return result;
}
/**
@@ -1827,6 +1832,8 @@
throws IOException
{
SerialCallbackContext oldContext = curContext;
+ if (oldContext != null)
+ oldContext.check();
curContext = null;
try {
boolean blocked = desc.hasBlockExternalData();
@@ -1851,6 +1858,8 @@
skipCustomData();
}
} finally {
+ if (oldContext != null)
+ oldContext.check();
curContext = oldContext;
}
/*
@@ -1881,12 +1890,12 @@
ObjectStreamClass slotDesc = slots[i].desc;
if (slots[i].hasData) {
- if (obj != null &&
- slotDesc.hasReadObjectMethod() &&
- handles.lookupException(passHandle) == null)
- {
+ if (obj == null || handles.lookupException(passHandle) != null) {
+ defaultReadFields(null, slotDesc); // skip field values
+ } else if (slotDesc.hasReadObjectMethod()) {
SerialCallbackContext oldContext = curContext;
-
+ if (oldContext != null)
+ oldContext.check();
try {
curContext = new SerialCallbackContext(obj, slotDesc);
@@ -1903,6 +1912,8 @@
handles.markException(passHandle, ex);
} finally {
curContext.setUsed();
+ if (oldContext!= null)
+ oldContext.check();
curContext = oldContext;
}
@@ -1915,6 +1926,7 @@
} else {
defaultReadFields(obj, slotDesc);
}
+
if (slotDesc.hasWriteObjectData()) {
skipCustomData();
} else {
@@ -1968,8 +1980,7 @@
private void defaultReadFields(Object obj, ObjectStreamClass desc)
throws IOException
{
- // REMIND: is isInstance check necessary?
- Class cl = desc.forClass();
+ Class<?> cl = desc.forClass();
if (cl != null && obj != null && !cl.isInstance(obj)) {
throw new ClassCastException();
}
@@ -2172,7 +2183,7 @@
* class descriptor, returns -1. Throws IllegalArgumentException if
* neither incoming nor local class descriptor contains a match.
*/
- private int getFieldOffset(String name, Class type) {
+ private int getFieldOffset(String name, Class<?> type) {
ObjectStreamField field = desc.getField(name, type);
if (field != null) {
return field.getOffset();
@@ -2870,6 +2881,7 @@
return readUTFBody(readUnsignedShort());
}
+ @SuppressWarnings("deprecation")
public String readLine() throws IOException {
return din.readLine(); // deprecated, not worth optimizing
}
diff --git a/ojluni/src/main/java/java/io/ObjectOutputStream.java b/ojluni/src/main/java/java/io/ObjectOutputStream.java
index f2abe23..1503112 100644
--- a/ojluni/src/main/java/java/io/ObjectOutputStream.java
+++ b/ojluni/src/main/java/java/io/ObjectOutputStream.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -264,6 +264,7 @@
* @throws SecurityException if a security manager exists and its
* <code>checkPermission</code> method denies enabling
* subclassing.
+ * @throws IOException if an I/O error occurs while creating this stream
* @see SecurityManager#checkPermission
* @see java.io.SerializablePermission
*/
@@ -445,11 +446,12 @@
* <code>OutputStream</code>
*/
public void defaultWriteObject() throws IOException {
- if ( curContext == null ) {
+ SerialCallbackContext ctx = curContext;
+ if (ctx == null) {
throw new NotActiveException("not in call to writeObject");
}
- Object curObj = curContext.getObj();
- ObjectStreamClass curDesc = curContext.getDesc();
+ Object curObj = ctx.getObj();
+ ObjectStreamClass curDesc = ctx.getDesc();
bout.setBlockDataMode(false);
defaultWriteFields(curObj, curDesc);
bout.setBlockDataMode(true);
@@ -467,11 +469,12 @@
*/
public ObjectOutputStream.PutField putFields() throws IOException {
if (curPut == null) {
- if (curContext == null) {
+ SerialCallbackContext ctx = curContext;
+ if (ctx == null) {
throw new NotActiveException("not in call to writeObject");
}
- Object curObj = curContext.getObj();
- ObjectStreamClass curDesc = curContext.getDesc();
+ Object curObj = ctx.getObj();
+ ObjectStreamClass curDesc = ctx.getDesc();
curPut = new PutFieldImpl(curDesc);
}
return curPut;
@@ -500,7 +503,7 @@
* stream. The state is reset to be the same as a new ObjectOutputStream.
* The current point in the stream is marked as reset so the corresponding
* ObjectInputStream will be reset at the same point. Objects previously
- * written to the stream will not be refered to as already being in the
+ * written to the stream will not be referred to as already being in the
* stream. They will be written to the stream again.
*
* @throws IOException if reset() is invoked while serializing an object.
@@ -1051,7 +1054,7 @@
* "enableSubclassImplementation" SerializablePermission is checked.
*/
private void verifySubclass() {
- Class cl = getClass();
+ Class<?> cl = getClass();
if (cl == ObjectOutputStream.class) {
return;
}
@@ -1077,22 +1080,22 @@
* override security-sensitive non-final methods. Returns true if subclass
* is "safe", false otherwise.
*/
- private static boolean auditSubclass(final Class subcl) {
+ private static boolean auditSubclass(final Class<?> subcl) {
Boolean result = AccessController.doPrivileged(
new PrivilegedAction<Boolean>() {
public Boolean run() {
- for (Class cl = subcl;
+ for (Class<?> cl = subcl;
cl != ObjectOutputStream.class;
cl = cl.getSuperclass())
{
try {
cl.getDeclaredMethod(
- "writeUnshared", new Class[] { Object.class });
+ "writeUnshared", new Class<?>[] { Object.class });
return Boolean.FALSE;
} catch (NoSuchMethodException ex) {
}
try {
- cl.getDeclaredMethod("putFields", (Class[]) null);
+ cl.getDeclaredMethod("putFields", (Class<?>[]) null);
return Boolean.FALSE;
} catch (NoSuchMethodException ex) {
}
@@ -1141,13 +1144,13 @@
// check for replacement object
Object orig = obj;
- Class cl = obj.getClass();
+ Class<?> cl = obj.getClass();
ObjectStreamClass desc;
/* ----- BEGIN android -----
for (;;) {
// REMIND: skip this check for strings/arrays?
- Class repCl;
+ Class<?> repCl;
desc = ObjectStreamClass.lookup(cl, true);
if (!desc.hasWriteReplaceMethod() ||
(obj = desc.invokeWriteReplace(obj)) == null ||
@@ -1213,7 +1216,7 @@
} else if (cl.isArray()) {
writeArray(obj, desc, unshared);
} else if (obj instanceof Enum) {
- writeEnum((Enum) obj, desc, unshared);
+ writeEnum((Enum<?>) obj, desc, unshared);
} else if (obj instanceof Serializable) {
writeOrdinaryObject(obj, desc, unshared);
} else {
@@ -1248,7 +1251,7 @@
/**
* Writes representation of given class to stream.
*/
- private void writeClass(Class cl, boolean unshared) throws IOException {
+ private void writeClass(Class<?> cl, boolean unshared) throws IOException {
bout.writeByte(TC_CLASS);
writeClassDesc(ObjectStreamClass.lookup(cl, true), false);
handles.assign(unshared ? null : cl);
@@ -1287,15 +1290,15 @@
bout.writeByte(TC_PROXYCLASSDESC);
handles.assign(unshared ? null : desc);
- Class cl = desc.forClass();
- Class[] ifaces = cl.getInterfaces();
+ Class<?> cl = desc.forClass();
+ Class<?>[] ifaces = cl.getInterfaces();
bout.writeInt(ifaces.length);
for (int i = 0; i < ifaces.length; i++) {
bout.writeUTF(ifaces[i].getName());
}
bout.setBlockDataMode(true);
- if (isCustomSubclass()) {
+ if (cl != null && isCustomSubclass()) {
ReflectUtil.checkPackageAccess(cl);
}
annotateProxyClass(cl);
@@ -1322,9 +1325,9 @@
writeClassDescriptor(desc);
}
- Class cl = desc.forClass();
+ Class<?> cl = desc.forClass();
bout.setBlockDataMode(true);
- if (isCustomSubclass()) {
+ if (cl != null && isCustomSubclass()) {
ReflectUtil.checkPackageAccess(cl);
}
annotateClass(cl);
@@ -1362,7 +1365,7 @@
writeClassDesc(desc, false);
handles.assign(unshared ? null : array);
- Class ccl = desc.forClass().getComponentType();
+ Class<?> ccl = desc.forClass().getComponentType();
if (ccl.isPrimitive()) {
if (ccl == Integer.TYPE) {
int[] ia = (int[]) array;
@@ -1433,7 +1436,7 @@
/**
* Writes given enum constant to stream.
*/
- private void writeEnum(Enum en,
+ private void writeEnum(Enum<?> en,
ObjectStreamClass desc,
boolean unshared)
throws IOException
@@ -1559,7 +1562,11 @@
private void defaultWriteFields(Object obj, ObjectStreamClass desc)
throws IOException
{
- // REMIND: perform conservative isInstance check here?
+ Class<?> cl = desc.forClass();
+ if (cl != null && obj != null && !cl.isInstance(obj)) {
+ throw new ClassCastException();
+ }
+
desc.checkDefaultSerialize();
int primDataSize = desc.getPrimDataSize();
@@ -1756,7 +1763,7 @@
* types, and any other non-null type matches assignable types only.
* Throws IllegalArgumentException if no matching field found.
*/
- private int getFieldOffset(String name, Class type) {
+ private int getFieldOffset(String name, Class<?> type) {
ObjectStreamField field = desc.getField(name, type);
if (field == null) {
throw new IllegalArgumentException("no such field " + name +
diff --git a/ojluni/src/main/java/java/io/ObjectStreamClass.java b/ojluni/src/main/java/java/io/ObjectStreamClass.java
index 08096c4..ff1cf82 100644
--- a/ojluni/src/main/java/java/io/ObjectStreamClass.java
+++ b/ojluni/src/main/java/java/io/ObjectStreamClass.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -169,7 +169,7 @@
private volatile ClassDataSlot[] dataLayout;
/** serialization-appropriate constructor, or null if none */
- private Constructor cons;
+ private Constructor<?> cons;
/** class-defined writeObject method, or null if none */
private Method writeObjectMethod;
/** class-defined readObject method, or null if none */
@@ -506,7 +506,7 @@
fieldRefl = getReflector(fields, this);
} catch (InvalidClassException ex) {
// field mismatches impossible when matching local fields vs. self
- throw new InternalError();
+ throw new InternalError(ex);
}
if (deserializeEx == null) {
@@ -956,7 +956,7 @@
return cons.newInstance();
} catch (IllegalAccessException ex) {
// should not occur, as access checks have been suppressed
- throw new InternalError();
+ throw new InternalError(ex);
}
} else {
throw new UnsupportedOperationException();
@@ -984,7 +984,7 @@
}
} catch (IllegalAccessException ex) {
// should not occur, as access checks have been suppressed
- throw new InternalError();
+ throw new InternalError(ex);
}
} else {
throw new UnsupportedOperationException();
@@ -1015,7 +1015,7 @@
}
} catch (IllegalAccessException ex) {
// should not occur, as access checks have been suppressed
- throw new InternalError();
+ throw new InternalError(ex);
}
} else {
throw new UnsupportedOperationException();
@@ -1043,7 +1043,7 @@
}
} catch (IllegalAccessException ex) {
// should not occur, as access checks have been suppressed
- throw new InternalError();
+ throw new InternalError(ex);
}
} else {
throw new UnsupportedOperationException();
@@ -1068,11 +1068,11 @@
throw (ObjectStreamException) th;
} else {
throwMiscException(th);
- throw new InternalError(); // never reached
+ throw new InternalError(th); // never reached
}
} catch (IllegalAccessException ex) {
// should not occur, as access checks have been suppressed
- throw new InternalError();
+ throw new InternalError(ex);
}
} else {
throw new UnsupportedOperationException();
@@ -1097,11 +1097,11 @@
throw (ObjectStreamException) th;
} else {
throwMiscException(th);
- throw new InternalError(); // never reached
+ throw new InternalError(th); // never reached
}
} catch (IllegalAccessException ex) {
// should not occur, as access checks have been suppressed
- throw new InternalError();
+ throw new InternalError(ex);
}
} else {
throw new UnsupportedOperationException();
@@ -1330,9 +1330,9 @@
* Access checks are disabled on the returned constructor (if any), since
* the defining class may still be non-public.
*/
- private static Constructor getExternalizableConstructor(Class<?> cl) {
+ private static Constructor<?> getExternalizableConstructor(Class<?> cl) {
try {
- Constructor cons = cl.getDeclaredConstructor((Class<?>[]) null);
+ Constructor<?> cons = cl.getDeclaredConstructor((Class<?>[]) null);
cons.setAccessible(true);
return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ?
cons : null;
@@ -1346,7 +1346,7 @@
* superclass, or null if none found. Access checks are disabled on the
* returned constructor (if any).
*/
- private static Constructor getSerializableConstructor(Class<?> cl) {
+ private static Constructor<?> getSerializableConstructor(Class<?> cl) {
Class<?> initCl = cl;
while (Serializable.class.isAssignableFrom(initCl)) {
if ((initCl = initCl.getSuperclass()) == null) {
@@ -1354,7 +1354,7 @@
}
}
try {
- Constructor cons = initCl.getDeclaredConstructor((Class<?>[]) null);
+ Constructor<?> cons = initCl.getDeclaredConstructor((Class<?>[]) null);
int mods = cons.getModifiers();
if ((mods & Modifier.PRIVATE) != 0 ||
((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
@@ -1739,7 +1739,7 @@
dout.writeUTF("()V");
}
- Constructor[] cons = cl.getDeclaredConstructors();
+ Constructor<?>[] cons = cl.getDeclaredConstructors();
MemberSignature[] consSigs = new MemberSignature[cons.length];
for (int i = 0; i < cons.length; i++) {
consSigs[i] = new MemberSignature(cons[i]);
@@ -1800,7 +1800,7 @@
}
return hash;
} catch (IOException ex) {
- throw new InternalError();
+ throw new InternalError(ex);
} catch (NoSuchAlgorithmException ex) {
throw new SecurityException(ex.getMessage());
}
@@ -1834,7 +1834,7 @@
signature = getClassSignature(field.getType());
}
- public MemberSignature(Constructor cons) {
+ public MemberSignature(Constructor<?> cons) {
member = cons;
name = cons.getName();
signature = getMethodSignature(
diff --git a/ojluni/src/main/java/java/io/ObjectStreamConstants.java b/ojluni/src/main/java/java/io/ObjectStreamConstants.java
index ddbada9..23f72b4 100644
--- a/ojluni/src/main/java/java/io/ObjectStreamConstants.java
+++ b/ojluni/src/main/java/java/io/ObjectStreamConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -219,7 +219,7 @@
* This protocol is written by JVM 1.2.
*
* Externalizable data is written in block data mode and is
- * terminated with TC_ENDBLOCKDATA. Externalizable classdescriptor
+ * terminated with TC_ENDBLOCKDATA. Externalizable class descriptor
* flags has SC_BLOCK_DATA enabled. JVM 1.1.6 and greater can
* read this format change.
*
diff --git a/ojluni/src/main/java/java/io/ObjectStreamField.java b/ojluni/src/main/java/java/io/ObjectStreamField.java
index 0eee71f..c49bcac 100644
--- a/ojluni/src/main/java/java/io/ObjectStreamField.java
+++ b/ojluni/src/main/java/java/io/ObjectStreamField.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -235,6 +235,8 @@
* Returns boolean value indicating whether or not the serializable field
* represented by this ObjectStreamField instance is unshared.
*
+ * @return {@code true} if this field is unshared
+ *
* @since 1.4
*/
public boolean isUnshared() {
diff --git a/ojluni/src/main/java/java/io/OutputStreamWriter.java b/ojluni/src/main/java/java/io/OutputStreamWriter.java
index b4e4b9e..5f7b9e3 100644
--- a/ojluni/src/main/java/java/io/OutputStreamWriter.java
+++ b/ojluni/src/main/java/java/io/OutputStreamWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@
/**
* An OutputStreamWriter is a bridge from character streams to byte streams:
* Characters written to it are encoded into bytes using a specified {@link
- * java.nio.charset.Charset <code>charset</code>}. The charset that it uses
+ * java.nio.charset.Charset charset}. The charset that it uses
* may be specified by name or may be given explicitly, or the platform's
* default charset may be accepted.
*
@@ -86,7 +86,7 @@
*
* @param charsetName
* The name of a supported
- * {@link java.nio.charset.Charset </code>charset<code>}
+ * {@link java.nio.charset.Charset charset}
*
* @exception UnsupportedEncodingException
* If the named encoding is not supported
@@ -115,7 +115,7 @@
}
/**
- * Creates an OutputStreamWriter that uses the given charset. </p>
+ * Creates an OutputStreamWriter that uses the given charset.
*
* @param out
* An OutputStream
@@ -134,7 +134,7 @@
}
/**
- * Creates an OutputStreamWriter that uses the given charset encoder. </p>
+ * Creates an OutputStreamWriter that uses the given charset encoder.
*
* @param out
* An OutputStream
diff --git a/ojluni/src/main/java/java/io/PipedInputStream.java b/ojluni/src/main/java/java/io/PipedInputStream.java
index 66cf19d..d7fb790 100644
--- a/ojluni/src/main/java/java/io/PipedInputStream.java
+++ b/ojluni/src/main/java/java/io/PipedInputStream.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,7 +45,7 @@
* The piped input stream contains a buffer,
* decoupling read operations from write operations,
* within limits.
- * A pipe is said to be <a name=BROKEN> <i>broken</i> </a> if a
+ * A pipe is said to be <a name="BROKEN"> <i>broken</i> </a> if a
* thread that was providing data bytes to the connected
* piped output stream is no longer alive.
*
@@ -123,7 +123,7 @@
* @param src the stream to connect to.
* @param pipeSize the size of the pipe's buffer.
* @exception IOException if an I/O error occurs.
- * @exception IllegalArgumentException if <code>pipeSize <= 0</code>.
+ * @exception IllegalArgumentException if {@code pipeSize <= 0}.
* @since 1.6
*/
public PipedInputStream(PipedOutputStream src, int pipeSize)
@@ -153,7 +153,7 @@
* connected} to a <code>PipedOutputStream</code> before being used.
*
* @param pipeSize the size of the pipe's buffer.
- * @exception IllegalArgumentException if <code>pipeSize <= 0</code>.
+ * @exception IllegalArgumentException if {@code pipeSize <= 0}.
* @since 1.6
*/
public PipedInputStream(int pipeSize) {
@@ -178,15 +178,14 @@
* unconnected piped output stream and <code>snk</code>
* is an unconnected piped input stream, they
* may be connected by either the call:
- * <p>
+ *
* <pre><code>snk.connect(src)</code> </pre>
* <p>
* or the call:
- * <p>
+ *
* <pre><code>src.connect(snk)</code> </pre>
* <p>
- * The two
- * calls have the same effect.
+ * The two calls have the same effect.
*
* @param src The piped output stream to connect to.
* @exception IOException if an I/O error occurs.
@@ -199,7 +198,7 @@
* Receives a byte of data. This method will block if no input is
* available.
* @param b the byte being received
- * @exception IOException If the pipe is <a href=#BROKEN> <code>broken</code></a>,
+ * @exception IOException If the pipe is <a href="#BROKEN"> <code>broken</code></a>,
* {@link #connect(java.io.PipedOutputStream) unconnected},
* closed, or if an I/O error occurs.
* @since JDK1.1
@@ -225,7 +224,7 @@
* @param b the buffer into which the data is received
* @param off the start offset of the data
* @param len the maximum number of bytes received
- * @exception IOException If the pipe is <a href=#BROKEN> broken</a>,
+ * @exception IOException If the pipe is <a href="#BROKEN"> broken</a>,
* {@link #connect(java.io.PipedOutputStream) unconnected},
* closed,or if an I/O error occurs.
*/
@@ -309,7 +308,7 @@
* stream is reached.
* @exception IOException if the pipe is
* {@link #connect(java.io.PipedOutputStream) unconnected},
- * <a href=#BROKEN> <code>broken</code></a>, closed,
+ * <a href="#BROKEN"> <code>broken</code></a>, closed,
* or if an I/O error occurs.
*/
public synchronized int read() throws IOException {
@@ -377,7 +376,7 @@
* @exception IndexOutOfBoundsException If <code>off</code> is negative,
* <code>len</code> is negative, or <code>len</code> is greater than
* <code>b.length - off</code>
- * @exception IOException if the pipe is <a href=#BROKEN> <code>broken</code></a>,
+ * @exception IOException if the pipe is <a href="#BROKEN"> <code>broken</code></a>,
* {@link #connect(java.io.PipedOutputStream) unconnected},
* closed, or if an I/O error occurs.
*/
@@ -435,7 +434,7 @@
* without blocking, or {@code 0} if this input stream has been
* closed by invoking its {@link #close()} method, or if the pipe
* is {@link #connect(java.io.PipedOutputStream) unconnected}, or
- * <a href=#BROKEN> <code>broken</code></a>.
+ * <a href="#BROKEN"> <code>broken</code></a>.
*
* @exception IOException if an I/O error occurs.
* @since JDK1.0.2
diff --git a/ojluni/src/main/java/java/io/PipedReader.java b/ojluni/src/main/java/java/io/PipedReader.java
index 93b7205..e4ec566 100644
--- a/ojluni/src/main/java/java/io/PipedReader.java
+++ b/ojluni/src/main/java/java/io/PipedReader.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -96,7 +96,7 @@
* @param src the stream to connect to.
* @param pipeSize the size of the pipe's buffer.
* @exception IOException if an I/O error occurs.
- * @exception IllegalArgumentException if <code>pipeSize <= 0</code>.
+ * @exception IllegalArgumentException if {@code pipeSize <= 0}.
* @since 1.6
*/
public PipedReader(PipedWriter src, int pipeSize) throws IOException {
@@ -125,7 +125,7 @@
* before being used.
*
* @param pipeSize the size of the pipe's buffer.
- * @exception IllegalArgumentException if <code>pipeSize <= 0</code>.
+ * @exception IllegalArgumentException if {@code pipeSize <= 0}.
* @since 1.6
*/
public PipedReader(int pipeSize) {
@@ -150,15 +150,14 @@
* unconnected piped writer and <code>snk</code>
* is an unconnected piped reader, they
* may be connected by either the call:
- * <p>
+ *
* <pre><code>snk.connect(src)</code> </pre>
* <p>
* or the call:
- * <p>
+ *
* <pre><code>src.connect(snk)</code> </pre>
* <p>
- * The two
- * calls have the same effect.
+ * The two calls have the same effect.
*
* @param src The piped writer to connect to.
* @exception IOException if an I/O error occurs.
diff --git a/ojluni/src/main/java/java/io/PrintStream.java b/ojluni/src/main/java/java/io/PrintStream.java
index 6968527..08bb3a3 100644
--- a/ojluni/src/main/java/java/io/PrintStream.java
+++ b/ojluni/src/main/java/java/io/PrintStream.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -302,7 +302,7 @@
* creating the file
*
* @throws SecurityException
- * If a security manager is presentand {@link
+ * If a security manager is present and {@link
* SecurityManager#checkWrite checkWrite(file.getPath())}
* denies write access to the file
*
@@ -869,7 +869,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -919,7 +919,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -962,7 +962,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -1019,7 +1019,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
diff --git a/ojluni/src/main/java/java/io/PrintWriter.java b/ojluni/src/main/java/java/io/PrintWriter.java
index 102c3a2..9287a19 100644
--- a/ojluni/src/main/java/java/io/PrintWriter.java
+++ b/ojluni/src/main/java/java/io/PrintWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -784,7 +784,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -835,7 +835,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -879,7 +879,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -939,7 +939,7 @@
* <tt>null</tt> argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
diff --git a/ojluni/src/main/java/java/io/PushbackInputStream.java b/ojluni/src/main/java/java/io/PushbackInputStream.java
index af0b525..b44848d 100644
--- a/ojluni/src/main/java/java/io/PushbackInputStream.java
+++ b/ojluni/src/main/java/java/io/PushbackInputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -85,7 +85,7 @@
*
* @param in the input stream from which bytes will be read.
* @param size the size of the pushback buffer.
- * @exception IllegalArgumentException if size is <= 0
+ * @exception IllegalArgumentException if {@code size <= 0}
* @since JDK1.1
*/
public PushbackInputStream(InputStream in, int size) {
diff --git a/ojluni/src/main/java/java/io/PushbackReader.java b/ojluni/src/main/java/java/io/PushbackReader.java
index 2f5b18c..f918621 100644
--- a/ojluni/src/main/java/java/io/PushbackReader.java
+++ b/ojluni/src/main/java/java/io/PushbackReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,7 @@
*
* @param in The reader from which characters will be read
* @param size The size of the pushback buffer
- * @exception IllegalArgumentException if size is <= 0
+ * @exception IllegalArgumentException if {@code size <= 0}
*/
public PushbackReader(Reader in, int size) {
super(in);
diff --git a/ojluni/src/main/java/java/io/Reader.java b/ojluni/src/main/java/java/io/Reader.java
index e2248c4..1c9cca6 100644
--- a/ojluni/src/main/java/java/io/Reader.java
+++ b/ojluni/src/main/java/java/io/Reader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -91,7 +91,7 @@
* -1 if this source of characters is at its end
* @throws IOException if an I/O error occurs
* @throws NullPointerException if target is null
- * @throws ReadOnlyBufferException if target is a read only buffer
+ * @throws java.nio.ReadOnlyBufferException if target is a read only buffer
* @since 1.5
*/
public int read(java.nio.CharBuffer target) throws IOException {
diff --git a/ojluni/src/main/java/java/io/SequenceInputStream.java b/ojluni/src/main/java/java/io/SequenceInputStream.java
index f64ec38..01da7f6 100644
--- a/ojluni/src/main/java/java/io/SequenceInputStream.java
+++ b/ojluni/src/main/java/java/io/SequenceInputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
*/
public
class SequenceInputStream extends InputStream {
- Enumeration e;
+ Enumeration<? extends InputStream> e;
InputStream in;
/**
@@ -85,7 +85,7 @@
* @param s2 the second input stream to read.
*/
public SequenceInputStream(InputStream s1, InputStream s2) {
- Vector v = new Vector(2);
+ Vector<InputStream> v = new Vector<>(2);
v.addElement(s1);
v.addElement(s2);
@@ -135,7 +135,7 @@
* @since JDK1.1
*/
public int available() throws IOException {
- if(in == null) {
+ if (in == null) {
return 0; // no way to signal EOF from available()
}
return in.available();
@@ -160,15 +160,14 @@
* @exception IOException if an I/O error occurs.
*/
public int read() throws IOException {
- if (in == null) {
- return -1;
- }
- int c = in.read();
- if (c == -1) {
+ while (in != null) {
+ int c = in.read();
+ if (c != -1) {
+ return c;
+ }
nextStream();
- return read();
}
- return c;
+ return -1;
}
/**
@@ -204,13 +203,14 @@
} else if (len == 0) {
return 0;
}
-
- int n = in.read(b, off, len);
- if (n <= 0) {
+ do {
+ int n = in.read(b, off, len);
+ if (n > 0) {
+ return n;
+ }
nextStream();
- return read(b, off, len);
- }
- return n;
+ } while (in != null);
+ return -1;
}
/**
diff --git a/ojluni/src/main/java/java/io/SerialCallbackContext.java b/ojluni/src/main/java/java/io/SerialCallbackContext.java
index 748d38e..4009087 100644
--- a/ojluni/src/main/java/java/io/SerialCallbackContext.java
+++ b/ojluni/src/main/java/java/io/SerialCallbackContext.java
@@ -60,6 +60,13 @@
return desc;
}
+ public void check() throws NotActiveException {
+ if (thread != null && thread != Thread.currentThread()) {
+ throw new NotActiveException(
+ "expected thread: " + thread + ", but got: " + Thread.currentThread());
+ }
+ }
+
private void checkAndSetUsed() throws NotActiveException {
if (thread != Thread.currentThread()) {
throw new NotActiveException(
diff --git a/ojluni/src/main/java/java/io/Serializable.java b/ojluni/src/main/java/java/io/Serializable.java
index 83bfe03..96ea33c 100644
--- a/ojluni/src/main/java/java/io/Serializable.java
+++ b/ojluni/src/main/java/java/io/Serializable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -55,7 +55,7 @@
*
* Classes that require special handling during the serialization and
* deserialization process must implement special methods with these exact
- * signatures: <p>
+ * signatures:
*
* <PRE>
* private void writeObject(java.io.ObjectOutputStream out)
@@ -101,7 +101,7 @@
*
* <p>Serializable classes that need to designate an alternative object to be
* used when writing an object to the stream should implement this
- * special method with the exact signature: <p>
+ * special method with the exact signature:
*
* <PRE>
* ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
@@ -115,7 +115,7 @@
*
* Classes that need to designate a replacement when an instance of it
* is read from the stream should implement this special method with the
- * exact signature.<p>
+ * exact signature.
*
* <PRE>
* ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
@@ -133,7 +133,7 @@
* deserialization will result in an {@link InvalidClassException}. A
* serializable class can declare its own serialVersionUID explicitly by
* declaring a field named <code>"serialVersionUID"</code> that must be static,
- * final, and of type <code>long</code>:<p>
+ * final, and of type <code>long</code>:
*
* <PRE>
* ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
diff --git a/ojluni/src/main/java/java/io/SerializablePermission.java b/ojluni/src/main/java/java/io/SerializablePermission.java
index ab1ccf4..e11f3ee 100644
--- a/ojluni/src/main/java/java/io/SerializablePermission.java
+++ b/ojluni/src/main/java/java/io/SerializablePermission.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/io/StreamTokenizer.java b/ojluni/src/main/java/java/io/StreamTokenizer.java
index 81ec5d5..3c7c7cc 100644
--- a/ojluni/src/main/java/java/io/StreamTokenizer.java
+++ b/ojluni/src/main/java/java/io/StreamTokenizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
import java.util.Arrays;
/**
- * The <code>StreamTokenizer</code> class takes an input stream and
+ * The {@code StreamTokenizer} class takes an input stream and
* parses it into "tokens", allowing the tokens to be
* read one at a time. The parsing process is controlled by a table
* and a number of flags that can be set to various states. The
@@ -36,7 +36,7 @@
* strings, and various comment styles.
* <p>
* Each byte read from the input stream is regarded as a character
- * in the range <code>'\u0000'</code> through <code>'\u00FF'</code>.
+ * in the range {@code '\u005Cu0000'} through {@code '\u005Cu00FF'}.
* The character value is used to look up five possible attributes of
* the character: <i>white space</i>, <i>alphabetic</i>,
* <i>numeric</i>, <i>string quote</i>, and <i>comment character</i>.
@@ -53,8 +53,8 @@
* <p>
* A typical application first constructs an instance of this class,
* sets up the syntax tables, and then repeatedly loops calling the
- * <code>nextToken</code> method in each iteration of the loop until
- * it returns the value <code>TT_EOF</code>.
+ * {@code nextToken} method in each iteration of the loop until
+ * it returns the value {@code TT_EOF}.
*
* @author James Gosling
* @see java.io.StreamTokenizer#nextToken()
@@ -99,19 +99,19 @@
private static final byte CT_COMMENT = 16;
/**
- * After a call to the <code>nextToken</code> method, this field
+ * After a call to the {@code nextToken} method, this field
* contains the type of the token just read. For a single character
* token, its value is the single character, converted to an integer.
* For a quoted string token, its value is the quote character.
* Otherwise, its value is one of the following:
* <ul>
- * <li><code>TT_WORD</code> indicates that the token is a word.
- * <li><code>TT_NUMBER</code> indicates that the token is a number.
- * <li><code>TT_EOL</code> indicates that the end of line has been read.
+ * <li>{@code TT_WORD} indicates that the token is a word.
+ * <li>{@code TT_NUMBER} indicates that the token is a number.
+ * <li>{@code TT_EOL} indicates that the end of line has been read.
* The field can only have this value if the
- * <code>eolIsSignificant</code> method has been called with the
- * argument <code>true</code>.
- * <li><code>TT_EOF</code> indicates that the end of the input stream
+ * {@code eolIsSignificant} method has been called with the
+ * argument {@code true}.
+ * <li>{@code TT_EOF} indicates that the end of the input stream
* has been reached.
* </ul>
* <p>
@@ -160,8 +160,8 @@
* the string.
* <p>
* The current token is a word when the value of the
- * <code>ttype</code> field is <code>TT_WORD</code>. The current token is
- * a quoted string token when the value of the <code>ttype</code> field is
+ * {@code ttype} field is {@code TT_WORD}. The current token is
+ * a quoted string token when the value of the {@code ttype} field is
* a quote character.
* <p>
* The initial value of this field is null.
@@ -175,7 +175,7 @@
/**
* If the current token is a number, this field contains the value
* of that number. The current token is a number when the value of
- * the <code>ttype</code> field is <code>TT_NUMBER</code>.
+ * the {@code ttype} field is {@code TT_NUMBER}.
* <p>
* The initial value of this field is 0.0.
*
@@ -201,14 +201,14 @@
* stream. The stream tokenizer is initialized to the following
* default state:
* <ul>
- * <li>All byte values <code>'A'</code> through <code>'Z'</code>,
- * <code>'a'</code> through <code>'z'</code>, and
- * <code>'\u00A0'</code> through <code>'\u00FF'</code> are
+ * <li>All byte values {@code 'A'} through {@code 'Z'},
+ * {@code 'a'} through {@code 'z'}, and
+ * {@code '\u005Cu00A0'} through {@code '\u005Cu00FF'} are
* considered to be alphabetic.
- * <li>All byte values <code>'\u0000'</code> through
- * <code>'\u0020'</code> are considered to be white space.
- * <li><code>'/'</code> is a comment character.
- * <li>Single quote <code>'\''</code> and double quote <code>'"'</code>
+ * <li>All byte values {@code '\u005Cu0000'} through
+ * {@code '\u005Cu0020'} are considered to be white space.
+ * <li>{@code '/'} is a comment character.
+ * <li>Single quote {@code '\u005C''} and double quote {@code '"'}
* are string quote characters.
* <li>Numbers are parsed.
* <li>Ends of lines are treated as white space, not as separate tokens.
@@ -252,7 +252,7 @@
/**
* Resets this tokenizer's syntax table so that all characters are
- * "ordinary." See the <code>ordinaryChar</code> method
+ * "ordinary." See the {@code ordinaryChar} method
* for more information on a character being ordinary.
*
* @see java.io.StreamTokenizer#ordinaryChar(int)
@@ -305,7 +305,7 @@
* Specifies that all characters <i>c</i> in the range
* <code>low <= <i>c</i> <= high</code>
* are "ordinary" in this tokenizer. See the
- * <code>ordinaryChar</code> method for more information on a
+ * {@code ordinaryChar} method for more information on a
* character being ordinary.
*
* @param low the low end of the range.
@@ -327,12 +327,12 @@
* character has as a comment character, word component, string
* delimiter, white space, or number character. When such a character
* is encountered by the parser, the parser treats it as a
- * single-character token and sets <code>ttype</code> field to the
+ * single-character token and sets {@code ttype} field to the
* character value.
*
* <p>Making a line terminator character "ordinary" may interfere
- * with the ability of a <code>StreamTokenizer</code> to count
- * lines. The <code>lineno</code> method may no longer reflect
+ * with the ability of a {@code StreamTokenizer} to count
+ * lines. The {@code lineno} method may no longer reflect
* the presence of such terminator characters in its line count.
*
* @param ch the character.
@@ -361,9 +361,9 @@
* Specifies that matching pairs of this character delimit string
* constants in this tokenizer.
* <p>
- * When the <code>nextToken</code> method encounters a string
- * constant, the <code>ttype</code> field is set to the string
- * delimiter and the <code>sval</code> field is set to the body of
+ * When the {@code nextToken} method encounters a string
+ * constant, the {@code ttype} field is set to the string
+ * delimiter and the {@code sval} field is set to the body of
* the string.
* <p>
* If a string quote character is encountered, then a string is
@@ -371,7 +371,7 @@
* the string quote character, up to (but not including) the next
* occurrence of that same string quote character, or a line
* terminator, or end of file. The usual escape sequences such as
- * <code>"\n"</code> and <code>"\t"</code> are recognized and
+ * {@code "\u005Cn"} and {@code "\u005Ct"} are recognized and
* converted to single characters as the string is parsed.
*
* <p>Any other attribute settings for the specified character are cleared.
@@ -398,9 +398,9 @@
* <p>
* When the parser encounters a word token that has the format of a
* double precision floating-point number, it treats the token as a
- * number rather than a word, by setting the <code>ttype</code>
- * field to the value <code>TT_NUMBER</code> and putting the numeric
- * value of the token into the <code>nval</code> field.
+ * number rather than a word, by setting the {@code ttype}
+ * field to the value {@code TT_NUMBER} and putting the numeric
+ * value of the token into the {@code nval} field.
*
* @see java.io.StreamTokenizer#nval
* @see java.io.StreamTokenizer#TT_NUMBER
@@ -416,21 +416,21 @@
/**
* Determines whether or not ends of line are treated as tokens.
* If the flag argument is true, this tokenizer treats end of lines
- * as tokens; the <code>nextToken</code> method returns
- * <code>TT_EOL</code> and also sets the <code>ttype</code> field to
+ * as tokens; the {@code nextToken} method returns
+ * {@code TT_EOL} and also sets the {@code ttype} field to
* this value when an end of line is read.
* <p>
* A line is a sequence of characters ending with either a
- * carriage-return character (<code>'\r'</code>) or a newline
- * character (<code>'\n'</code>). In addition, a carriage-return
+ * carriage-return character ({@code '\u005Cr'}) or a newline
+ * character ({@code '\u005Cn'}). In addition, a carriage-return
* character followed immediately by a newline character is treated
* as a single end-of-line token.
* <p>
- * If the <code>flag</code> is false, end-of-line characters are
+ * If the {@code flag} is false, end-of-line characters are
* treated as white space and serve only to separate tokens.
*
- * @param flag <code>true</code> indicates that end-of-line characters
- * are separate tokens; <code>false</code> indicates that
+ * @param flag {@code true} indicates that end-of-line characters
+ * are separate tokens; {@code false} indicates that
* end-of-line characters are white space.
* @see java.io.StreamTokenizer#nextToken()
* @see java.io.StreamTokenizer#ttype
@@ -442,14 +442,14 @@
/**
* Determines whether or not the tokenizer recognizes C-style comments.
- * If the flag argument is <code>true</code>, this stream tokenizer
+ * If the flag argument is {@code true}, this stream tokenizer
* recognizes C-style comments. All text between successive
- * occurrences of <code>/*</code> and <code>*/</code> are discarded.
+ * occurrences of {@code /*} and <code>*/</code> are discarded.
* <p>
- * If the flag argument is <code>false</code>, then C-style comments
+ * If the flag argument is {@code false}, then C-style comments
* are not treated specially.
*
- * @param flag <code>true</code> indicates to recognize and ignore
+ * @param flag {@code true} indicates to recognize and ignore
* C-style comments.
*/
public void slashStarComments(boolean flag) {
@@ -458,15 +458,15 @@
/**
* Determines whether or not the tokenizer recognizes C++-style comments.
- * If the flag argument is <code>true</code>, this stream tokenizer
+ * If the flag argument is {@code true}, this stream tokenizer
* recognizes C++-style comments. Any occurrence of two consecutive
- * slash characters (<code>'/'</code>) is treated as the beginning of
+ * slash characters ({@code '/'}) is treated as the beginning of
* a comment that extends to the end of the line.
* <p>
- * If the flag argument is <code>false</code>, then C++-style
+ * If the flag argument is {@code false}, then C++-style
* comments are not treated specially.
*
- * @param flag <code>true</code> indicates to recognize and ignore
+ * @param flag {@code true} indicates to recognize and ignore
* C++-style comments.
*/
public void slashSlashComments(boolean flag) {
@@ -475,16 +475,16 @@
/**
* Determines whether or not word token are automatically lowercased.
- * If the flag argument is <code>true</code>, then the value in the
- * <code>sval</code> field is lowercased whenever a word token is
- * returned (the <code>ttype</code> field has the
- * value <code>TT_WORD</code> by the <code>nextToken</code> method
+ * If the flag argument is {@code true}, then the value in the
+ * {@code sval} field is lowercased whenever a word token is
+ * returned (the {@code ttype} field has the
+ * value {@code TT_WORD} by the {@code nextToken} method
* of this tokenizer.
* <p>
- * If the flag argument is <code>false</code>, then the
- * <code>sval</code> field is not modified.
+ * If the flag argument is {@code false}, then the
+ * {@code sval} field is not modified.
*
- * @param fl <code>true</code> indicates that all word tokens should
+ * @param fl {@code true} indicates that all word tokens should
* be lowercased.
* @see java.io.StreamTokenizer#nextToken()
* @see java.io.StreamTokenizer#ttype
@@ -506,9 +506,9 @@
/**
* Parses the next token from the input stream of this tokenizer.
- * The type of the next token is returned in the <code>ttype</code>
+ * The type of the next token is returned in the {@code ttype}
* field. Additional information about the token may be in the
- * <code>nval</code> field or the <code>sval</code> field of this
+ * {@code nval} field or the {@code sval} field of this
* tokenizer.
* <p>
* Typical clients of this
@@ -516,7 +516,7 @@
* calling nextToken to parse successive tokens until TT_EOF
* is returned.
*
- * @return the value of the <code>ttype</code> field.
+ * @return the value of the {@code ttype} field.
* @exception IOException if an I/O error occurs.
* @see java.io.StreamTokenizer#nval
* @see java.io.StreamTokenizer#sval
@@ -752,10 +752,10 @@
}
/**
- * Causes the next call to the <code>nextToken</code> method of this
- * tokenizer to return the current value in the <code>ttype</code>
- * field, and not to modify the value in the <code>nval</code> or
- * <code>sval</code> field.
+ * Causes the next call to the {@code nextToken} method of this
+ * tokenizer to return the current value in the {@code ttype}
+ * field, and not to modify the value in the {@code nval} or
+ * {@code sval} field.
*
* @see java.io.StreamTokenizer#nextToken()
* @see java.io.StreamTokenizer#nval
diff --git a/ojluni/src/main/java/java/io/StringReader.java b/ojluni/src/main/java/java/io/StringReader.java
index 3778408..ce9ff60 100644
--- a/ojluni/src/main/java/java/io/StringReader.java
+++ b/ojluni/src/main/java/java/io/StringReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -163,7 +163,7 @@
* is no actual limit, so this argument must not
* be negative, but is otherwise ignored.
*
- * @exception IllegalArgumentException If readAheadLimit is < 0
+ * @exception IllegalArgumentException If {@code readAheadLimit < 0}
* @exception IOException If an I/O error occurs
*/
public void mark(int readAheadLimit) throws IOException {
diff --git a/ojluni/src/main/java/java/io/UnixFileSystem.java b/ojluni/src/main/java/java/io/UnixFileSystem.java
index 6ce3f6f..1659b17 100644
--- a/ojluni/src/main/java/java/io/UnixFileSystem.java
+++ b/ojluni/src/main/java/java/io/UnixFileSystem.java
@@ -236,6 +236,7 @@
private native int getBooleanAttributes0(String abspath);
+ // Android-changed: Added thread policy check
public int getBooleanAttributes(File f) {
BlockGuard.getThreadPolicy().onReadFromDisk();
@@ -245,43 +246,43 @@
return rv | (hidden ? BA_HIDDEN : 0);
}
+ // Android-changed: Added thread policy check
public boolean checkAccess(File f, int access) {
BlockGuard.getThreadPolicy().onReadFromDisk();
return checkAccess0(f, access);
}
-
private native boolean checkAccess0(File f, int access);
+ // Android-changed: Added thread policy check
public long getLastModifiedTime(File f) {
BlockGuard.getThreadPolicy().onReadFromDisk();
return getLastModifiedTime0(f);
}
-
private native long getLastModifiedTime0(File f);
+ // Android-changed: Added thread policy check
public long getLength(File f) {
BlockGuard.getThreadPolicy().onReadFromDisk();
return getLength0(f);
}
-
private native long getLength0(File f);
+ // Android-changed: Added thread policy check
public boolean setPermission(File f, int access, boolean enable, boolean owneronly) {
BlockGuard.getThreadPolicy().onWriteToDisk();
return setPermission0(f, access, enable, owneronly);
}
-
private native boolean setPermission0(File f, int access, boolean enable, boolean owneronly);
/* -- File operations -- */
-
+ // Android-changed: Added thread policy check
public boolean createFileExclusively(String path) throws IOException {
BlockGuard.getThreadPolicy().onWriteToDisk();
return createFileExclusively0(path);
}
-
private native boolean createFileExclusively0(String path) throws IOException;
+ // Android-changed: Added thread policy check
public boolean delete(File f) {
// Keep canonicalization caches in sync after file deletion
// and renaming operations. Could be more clever than this
@@ -296,20 +297,21 @@
private native boolean delete0(File f);
+ // Android-changed: Added thread policy check
public String[] list(File f) {
BlockGuard.getThreadPolicy().onReadFromDisk();
return list0(f);
}
-
private native String[] list0(File f);
+ // Android-changed: Added thread policy check
public boolean createDirectory(File f) {
BlockGuard.getThreadPolicy().onWriteToDisk();
return createDirectory0(f);
}
-
private native boolean createDirectory0(File f);
+ // Android-changed: Added thread policy check
public boolean rename(File f1, File f2) {
// Keep canonicalization caches in sync after file deletion
// and renaming operations. Could be more clever than this
@@ -324,18 +326,18 @@
private native boolean rename0(File f1, File f2);
+ // Android-changed: Added thread policy check
public boolean setLastModifiedTime(File f, long time) {
BlockGuard.getThreadPolicy().onWriteToDisk();
return setLastModifiedTime0(f, time);
}
-
private native boolean setLastModifiedTime0(File f, long time);
+ // Android-changed: Added thread policy check
public boolean setReadOnly(File f) {
BlockGuard.getThreadPolicy().onWriteToDisk();
return setReadOnly0(f);
}
-
private native boolean setReadOnly0(File f);
@@ -354,12 +356,12 @@
}
/* -- Disk usage -- */
+ // Android-changed: Added thread policy check
public long getSpace(File f, int t) {
BlockGuard.getThreadPolicy().onReadFromDisk();
return getSpace0(f, t);
}
-
private native long getSpace0(File f, int t);
/* -- Basic infrastructure -- */
diff --git a/ojluni/src/main/java/java/io/Writer.java b/ojluni/src/main/java/java/io/Writer.java
index f0c6db4..8747a13 100644
--- a/ojluni/src/main/java/java/io/Writer.java
+++ b/ojluni/src/main/java/java/io/Writer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,7 +57,7 @@
/**
* Size of writeBuffer, must be >= 1
*/
- private final int writeBufferSize = 1024;
+ private static final int WRITE_BUFFER_SIZE = 1024;
/**
* The object used to synchronize operations on this stream. For
@@ -107,7 +107,7 @@
public void write(int c) throws IOException {
synchronized (lock) {
if (writeBuffer == null){
- writeBuffer = new char[writeBufferSize];
+ writeBuffer = new char[WRITE_BUFFER_SIZE];
}
writeBuffer[0] = (char) c;
write(writeBuffer, 0, 1);
@@ -180,9 +180,9 @@
public void write(String str, int off, int len) throws IOException {
synchronized (lock) {
char cbuf[];
- if (len <= writeBufferSize) {
+ if (len <= WRITE_BUFFER_SIZE) {
if (writeBuffer == null) {
- writeBuffer = new char[writeBufferSize];
+ writeBuffer = new char[WRITE_BUFFER_SIZE];
}
cbuf = writeBuffer;
} else { // Don't permanently allocate very large buffers.
diff --git a/ojluni/src/main/java/java/lang/Enum.java b/ojluni/src/main/java/java/lang/Enum.java
index 56666f2..8ada57f 100644
--- a/ojluni/src/main/java/java/lang/Enum.java
+++ b/ojluni/src/main/java/java/lang/Enum.java
@@ -234,26 +234,28 @@
*/
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name) {
- if (enumType == null)
+ // Android-changed: Use a static BasicLruCache mapping Enum class -> Enum instance array.
+ if (enumType == null) {
throw new NullPointerException("enumType == null");
- if (name == null)
- throw new NullPointerException("Name is null");
+ }
+ if (name == null) {
+ throw new NullPointerException("name == null");
+ }
T[] values = getSharedConstants(enumType);
- T result = null;
- if (values != null) {
- for (T value : values) {
- if (name.equals(value.name())) {
- result = value;
- }
- }
- } else {
+ if (values == null) {
throw new IllegalArgumentException(enumType.toString() + " is not an enum type.");
}
- if (result != null)
- return result;
+ // Iterate backwards through the array to retain historic Android behavior in the
+ // unexpected / likely invalid case where there are multiple values with the same name.
+ for (int i = values.length - 1; i >= 0; --i) {
+ T value = values[i];
+ if (name.equals(value.name())) {
+ return value;
+ }
+ }
throw new IllegalArgumentException(
- "No enum constant " + enumType.getCanonicalName() + "." + name);
+ "No enum constant " + enumType.getCanonicalName() + "." + name);
}
private static final BasicLruCache<Class<? extends Enum>, Object[]> sharedConstantsCache
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandle.java b/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
index ef4f7fe..0c27b99 100644
--- a/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
+++ b/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
@@ -455,16 +455,16 @@
* field_id in the equivalent instruction.
*/
- /** @hide */ public static final int INVOKE_VIRTUAL = 0x6e;
- /** @hide */ public static final int INVOKE_SUPER = 0x6f;
- /** @hide */ public static final int INVOKE_DIRECT = 0x70;
- /** @hide */ public static final int INVOKE_STATIC = 0x71;
- /** @hide */ public static final int INVOKE_INTERFACE = 0x72;
+ /** @hide */ public static final int INVOKE_VIRTUAL = 0;
+ /** @hide */ public static final int INVOKE_SUPER = 1;
+ /** @hide */ public static final int INVOKE_DIRECT = 2;
+ /** @hide */ public static final int INVOKE_STATIC = 3;
+ /** @hide */ public static final int INVOKE_INTERFACE = 4;
- /** @hide */ public static final int SGET = 0x60;
- /** @hide */ public static final int SPUT = 0x67;
- /** @hide */ public static final int IGET = 0x52;
- /** @hide */ public static final int IPUT = 0x59;
+ /** @hide */ public static final int SGET = 5;
+ /** @hide */ public static final int SPUT = 6;
+ /** @hide */ public static final int IGET = 7;
+ /** @hide */ public static final int IPUT = 8;
// The kind of this method handle (used by the runtime). This is one of the INVOKE_*
// constants or SGET/SPUT, IGET/IPUT.
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandles.java b/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
index bd2f60d..a321410 100644
--- a/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
+++ b/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
@@ -1018,8 +1018,63 @@
*/
public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
- // TODO(narayan): Implement this method.
- throw new UnsupportedOperationException("MethodHandles.Lookup.findSpecial is not implemented");
+ if (specialCaller == null) {
+ throw new NullPointerException("specialCaller == null");
+ }
+
+ if (type == null) {
+ throw new NullPointerException("type == null");
+ }
+
+ if (name == null) {
+ throw new NullPointerException("name == null");
+ }
+
+ if (refc == null) {
+ throw new NullPointerException("ref == null");
+ }
+
+ // Make sure that the special caller is identical to the lookup class or that we have
+ // private access.
+ checkSpecialCaller(specialCaller);
+
+ // Even though constructors are invoked using a "special" invoke, handles to them can't
+ // be created using findSpecial. Callers must use findConstructor instead.
+ if ("<init>".equals(name)) {
+ throw new NoSuchMethodException("<init> is constructor.");
+ }
+
+ Method method = refc.getDeclaredMethod(name, type.ptypes());
+ if (Modifier.isPrivate(method.getModifiers())) {
+ // Since this is a private method, we'll need to also make sure that the
+ // lookup class is the same as the refering class. We've already checked that
+ // the specialCaller is the same as the special lookup class, both of these must
+ // be the same as the declaring class(*) in order to access the private method.
+ //
+ // (*) Well, this isn't true for nested classes but OpenJDK doesn't support those
+ // either.
+ if (refc != lookupClass()) {
+ throw new IllegalAccessException("no private access for invokespecial : "
+ + refc + ", from" + this);
+ }
+
+ // This is a private method, so there's nothing special to do.
+ MethodType handleType = type.insertParameterTypes(0, refc);
+ return new MethodHandleImpl(method.getArtMethod(), MethodHandle.INVOKE_DIRECT,
+ handleType);
+ }
+
+ // This is a public, protected or package-private method, which means we're expecting
+ // invoke-super semantics. We'll have to restrict the receiver type appropriately on the
+ // handle once we check that there really is a "super" relationship between them.
+ if (!method.getDeclaringClass().isAssignableFrom(specialCaller)) {
+ throw new IllegalAccessException(refc + "is not assignable from " + specialCaller);
+ }
+
+ // Note that we restrict the receiver to "specialCaller" instances.
+ MethodType handleType = type.insertParameterTypes(0, specialCaller);
+ return new MethodHandleImpl(method.getArtMethod(), MethodHandle.INVOKE_SUPER,
+ handleType);
}
/**
@@ -1404,17 +1459,21 @@
return "member is private to package";
}
- private static final boolean ALLOW_NESTMATE_ACCESS = false;
+ // Android-changed: checkSpecialCaller assumes that ALLOW_NESTMATE_ACCESS = false,
+ // as in upstream OpenJDK.
+ //
+ // private static final boolean ALLOW_NESTMATE_ACCESS = false;
private void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException {
- int allowedModes = this.allowedModes;
- // Android-changed: No support for TRUSTED lookups.
+ // Android-changed: No support for TRUSTED lookups. Also construct the
+ // IllegalAccessException by hand because the upstream code implicitly assumes
+ // that the lookupClass == specialCaller.
+ //
// if (allowedModes == TRUSTED) return;
- if (!hasPrivateAccess()
- || (specialCaller != lookupClass()
- && !(ALLOW_NESTMATE_ACCESS &&
- VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
- throwMakeAccessException("no private access for invokespecial", this);
+ if (!hasPrivateAccess() || (specialCaller != lookupClass())) {
+ throw new IllegalAccessException("no private access for invokespecial : "
+ + specialCaller + ", from" + this);
+ }
}
public void throwMakeAccessException(String message, Object from) throws
diff --git a/ojluni/src/main/java/java/net/Inet6AddressImpl.java b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
index 203ccb8..98417a9 100644
--- a/ojluni/src/main/java/java/net/Inet6AddressImpl.java
+++ b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
@@ -28,13 +28,18 @@
import android.system.GaiException;
import android.system.StructAddrinfo;
import dalvik.system.BlockGuard;
+
+import libcore.io.IoBridge;
import libcore.io.Libcore;
+import java.io.FileDescriptor;
import java.io.IOException;
import static android.system.OsConstants.AF_UNSPEC;
import static android.system.OsConstants.AI_ADDRCONFIG;
import static android.system.OsConstants.EACCES;
+import static android.system.OsConstants.ECONNREFUSED;
+import static android.system.OsConstants.NI_NAMEREQD;
import static android.system.OsConstants.SOCK_STREAM;
/*
@@ -140,9 +145,12 @@
@Override
public boolean isReachable(InetAddress addr, int timeout, NetworkInterface netif, int ttl) throws IOException {
- byte[] ifaddr = null;
- int scope = -1;
- int netif_scope = -1;
+ // Android-changed: rewritten on the top of IoBridge and Libcore.os
+ // TODO (b/31926888): try ICMP first (http://code.google.com/p/android/issues/detail?id=20106)
+
+ // No good, let's fall back to TCP
+ FileDescriptor fd = IoBridge.socket(true);
+ InetAddress sourceAddr = null;
if (netif != null) {
/*
* Let's make sure we bind to an address of the proper family.
@@ -155,31 +163,32 @@
while (it.hasMoreElements()) {
inetaddr = it.nextElement();
if (inetaddr.getClass().isInstance(addr)) {
- ifaddr = inetaddr.getAddress();
- if (inetaddr instanceof Inet6Address) {
- netif_scope = ((Inet6Address) inetaddr).getScopeId();
- }
+ sourceAddr = inetaddr;
break;
}
}
- if (ifaddr == null) {
+
+ if (sourceAddr == null) {
// Interface doesn't support the address family of
// the destination
return false;
}
}
- if (addr instanceof Inet6Address)
- scope = ((Inet6Address) addr).getScopeId();
- BlockGuard.getThreadPolicy().onNetwork();
-
- // Never throw an IOException from isReachable. If something terrible happens either
- // with the network interface in question (or with the destination), then just return
- // false (i.e, state that the address is unreachable.
try {
- return isReachable0(addr.getAddress(), scope, timeout, ifaddr, ttl, netif_scope);
- } catch (IOException ioe) {
- return false;
+ if (sourceAddr != null) {
+ IoBridge.bind(fd, sourceAddr, 0);
+ }
+ IoBridge.connect(fd, addr, 7 /* Echo-protocol port */, timeout);
+ return true;
+ } catch (IOException e) {
+ // Connection refused by remote (ECONNREFUSED) implies reachable. Otherwise silently
+ // ignore the exception and return false.
+ Throwable cause = e.getCause();
+ return cause instanceof ErrnoException
+ && ((ErrnoException) cause).errno == ECONNREFUSED;
+ } finally {
+ IoBridge.closeAndSignalBlockedThreads(fd);
}
}
@@ -215,6 +224,15 @@
}
}
- private native String getHostByAddr0(byte[] addr) throws UnknownHostException;
- private native boolean isReachable0(byte[] addr, int scope, int timeout, byte[] inf, int ttl, int if_scope) throws IOException;
+ private String getHostByAddr0(byte[] addr) throws UnknownHostException {
+ // Android-changed: Rewritten on the top of Libcore.os
+ InetAddress hostaddr = InetAddress.getByAddress(addr);
+ try {
+ return Libcore.os.getnameinfo(hostaddr, NI_NAMEREQD);
+ } catch (GaiException e) {
+ UnknownHostException uhe = new UnknownHostException(hostaddr.toString());
+ uhe.initCause(e);
+ throw uhe;
+ }
+ }
}
diff --git a/ojluni/src/main/java/java/nio/file/FileSystem.java b/ojluni/src/main/java/java/nio/file/FileSystem.java
index 03ace89..bb6f136 100644
--- a/ojluni/src/main/java/java/nio/file/FileSystem.java
+++ b/ojluni/src/main/java/java/nio/file/FileSystem.java
@@ -335,18 +335,12 @@
* </tr>
* <tr>
* <td><tt>/home/*/*</tt>
- * <td>Matches <tt>/home/gus/data</tt> on UNIX platforms</td>
+ * <td>Matches <tt>/home/gus/data</tt></td>
* </tr>
* <tr>
* <td><tt>/home/**</tt>
* <td>Matches <tt>/home/gus</tt> and
- * <tt>/home/gus/data</tt> on UNIX platforms</td>
- * </tr>
- * <tr>
- * <td><tt>C:\\*</tt>
- * <td>Matches <tt>C:\foo</tt> and <tt>C:\bar</tt> on the Windows
- * platform (note that the backslash is escaped; as a string literal in the
- * Java Language the pattern would be <tt>"C:\\\\*"</tt>) </td>
+ * <tt>/home/gus/data</tt></td>
* </tr>
*
* </table>
diff --git a/ojluni/src/main/java/java/text/BreakIterator.java b/ojluni/src/main/java/java/text/BreakIterator.java
index be75a9e..6e7e053 100644
--- a/ojluni/src/main/java/java/text/BreakIterator.java
+++ b/ojluni/src/main/java/java/text/BreakIterator.java
@@ -445,6 +445,7 @@
*/
public static BreakIterator getWordInstance(Locale locale)
{
+ // Android-changed: Switched to ICU.
return new IcuIteratorWrapper(
android.icu.text.BreakIterator.getWordInstance(locale));
}
@@ -470,6 +471,7 @@
*/
public static BreakIterator getLineInstance(Locale locale)
{
+ // Android-changed: Switched to ICU.
return new IcuIteratorWrapper(
android.icu.text.BreakIterator.getLineInstance(locale));
}
@@ -495,6 +497,7 @@
*/
public static BreakIterator getCharacterInstance(Locale locale)
{
+ // Android-changed: Switched to ICU.
return new IcuIteratorWrapper(
android.icu.text.BreakIterator.getCharacterInstance(locale));
}
@@ -520,25 +523,23 @@
*/
public static BreakIterator getSentenceInstance(Locale locale)
{
+ // Android-changed: Switched to ICU.
return new IcuIteratorWrapper(
android.icu.text.BreakIterator.getSentenceInstance(locale));
}
+ // Android-changed: Removed references to BreakIteratorProvider.
/**
* Returns an array of all locales for which the
* <code>get*Instance</code> methods of this class can return
* localized instances.
- * The returned array represents the union of locales supported by the Java
- * runtime and by installed
- * {@link java.text.spi.BreakIteratorProvider BreakIteratorProvider} implementations.
- * It must contain at least a <code>Locale</code>
- * instance equal to {@link java.util.Locale#US Locale.US}.
*
* @return An array of locales for which localized
* <code>BreakIterator</code> instances are available.
*/
public static synchronized Locale[] getAvailableLocales()
{
+ // Android-changed: Switched to ICU.
return android.icu.text.BreakIterator.getAvailableLocales();
}
}
diff --git a/ojluni/src/main/java/java/text/Collator.java b/ojluni/src/main/java/java/text/Collator.java
index 478074c..01e7dc9 100644
--- a/ojluni/src/main/java/java/text/Collator.java
+++ b/ojluni/src/main/java/java/text/Collator.java
@@ -229,6 +229,7 @@
public static synchronized
Collator getInstance(Locale desiredLocale)
{
+ // Android-changed: Switched to ICU.
if (desiredLocale == null) {
throw new NullPointerException("locale == null");
}
@@ -317,6 +318,7 @@
*/
public synchronized int getStrength()
{
+ // Android-changed: Switched to ICU.
// The value for IDENTICAL in ICU differs from that used in this class.
int value = icuColl.getStrength();
return (value == android.icu.text.Collator.IDENTICAL) ? IDENTICAL : value;
@@ -336,6 +338,7 @@
* PRIMARY, SECONDARY, TERTIARY or IDENTICAL.
*/
public synchronized void setStrength(int newStrength) {
+ // Android-changed: Switched to ICU.
// The ICU value for IDENTICAL differs from that defined in this class.
if (newStrength == IDENTICAL) {
newStrength = android.icu.text.Collator.IDENTICAL;
@@ -364,6 +367,7 @@
*/
public synchronized int getDecomposition()
{
+ // Android-changed: Switched to ICU.
return decompositionMode_ICU_Java(icuColl.getDecomposition());
}
/**
@@ -378,23 +382,21 @@
* mode.
*/
public synchronized void setDecomposition(int decompositionMode) {
+ // Android-changed: Switched to ICU.
icuColl.setDecomposition(decompositionMode_Java_ICU(decompositionMode));
}
+ // Android-changed: Removed references to CollatorProvider.
/**
* Returns an array of all locales for which the
* <code>getInstance</code> methods of this class can return
* localized instances.
- * The returned array represents the union of locales supported
- * by the Java runtime and by installed
- * {@link java.text.spi.CollatorProvider CollatorProvider} implementations.
- * It must contain at least a Locale instance equal to
- * {@link java.util.Locale#US Locale.US}.
*
* @return An array of locales for which localized
* <code>Collator</code> instances are available.
*/
public static synchronized Locale[] getAvailableLocales() {
+ // Android-changed: Removed reference to CollatorProvider. Switched to ICU.
return ICU.getAvailableCollatorLocales();
}
@@ -432,6 +434,7 @@
public Object clone()
{
try {
+ // Android-changed: Switched to ICU.
Collator clone = (Collator) super.clone();
clone.icuColl = (android.icu.text.Collator) icuColl.clone();
return clone;
@@ -459,6 +462,7 @@
return false;
}
Collator other = (Collator) that;
+ // Android-changed: Switched to ICU.
return icuColl == null ? other.icuColl == null : icuColl.equals(other.icuColl);
}
@@ -476,6 +480,7 @@
*/
protected Collator()
{
+ // Android-changed: Switched to ICU.
icuColl = android.icu.text.RuleBasedCollator.getInstance(Locale.getDefault());
}
diff --git a/ojluni/src/main/java/java/text/DateFormat.java b/ojluni/src/main/java/java/text/DateFormat.java
index 6d7c956..799694e 100644
--- a/ojluni/src/main/java/java/text/DateFormat.java
+++ b/ojluni/src/main/java/java/text/DateFormat.java
@@ -40,18 +40,14 @@
package java.text;
import java.io.InvalidObjectException;
-import java.text.spi.DateFormatProvider;
import java.util.Calendar;
import java.util.Date;
-import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
-import java.util.ResourceBundle;
import java.util.TimeZone;
-import java.util.spi.LocaleServiceProvider;
-import sun.util.LocaleServiceProviderPool;
+import libcore.icu.ICU;
/**
* {@code DateFormat} is an abstract class for date/time formatting subclasses which
@@ -596,7 +592,12 @@
return getDateTimeInstance(SHORT, SHORT);
}
- /** @hide */
+ // Android-changed: Added support for overriding locale default 12 / 24 hour preference.
+ /**
+ * {@code null}: use Locale default. {@code true}: force 24-hour format.
+ * {@code false} force 12-hour format.
+ * @hide
+ */
public static Boolean is24Hour;
/**
@@ -606,24 +607,19 @@
DateFormat.is24Hour = is24Hour;
}
+ // Android-changed: Remove reference to DateFormatProvider.
/**
* Returns an array of all locales for which the
* <code>get*Instance</code> methods of this class can return
* localized instances.
- * The returned array represents the union of locales supported by the Java
- * runtime and by installed
- * {@link java.text.spi.DateFormatProvider DateFormatProvider} implementations.
- * It must contain at least a <code>Locale</code> instance equal to
- * {@link java.util.Locale#US Locale.US}.
*
* @return An array of locales for which localized
* <code>DateFormat</code> instances are available.
*/
public static Locale[] getAvailableLocales()
{
- LocaleServiceProviderPool pool =
- LocaleServiceProviderPool.getPool(DateFormatProvider.class);
- return pool.getAvailableLocales();
+ // Android-changed: Removed used of DateFormatProvider. Switched to use ICU.
+ return ICU.getAvailableLocales();
}
/**
@@ -803,23 +799,8 @@
} else {
dateStyle = -1;
}
+ // Android-changed: Removed used of DateFormatProvider.
try {
- // Check whether a provider can provide an implementation that's closer
- // to the requested locale than what the Java runtime itself can provide.
- LocaleServiceProviderPool pool =
- LocaleServiceProviderPool.getPool(DateFormatProvider.class);
- if (pool.hasProviders()) {
- DateFormat providersInstance = pool.getLocalizedObject(
- DateFormatGetter.INSTANCE,
- loc,
- timeStyle,
- dateStyle,
- flags);
- if (providersInstance != null) {
- return providersInstance;
- }
- }
-
return new SimpleDateFormat(timeStyle, dateStyle, loc);
} catch (MissingResourceException e) {
return new SimpleDateFormat("M/d/yy h:mm a");
@@ -1046,37 +1027,4 @@
*/
public final static Field TIME_ZONE = new Field("time zone", -1);
}
-
- /**
- * Obtains a DateFormat instance from a DateFormatProvider
- * implementation.
- */
- private static class DateFormatGetter
- implements LocaleServiceProviderPool.LocalizedObjectGetter<DateFormatProvider, DateFormat> {
- private static final DateFormatGetter INSTANCE = new DateFormatGetter();
-
- public DateFormat getObject(DateFormatProvider dateFormatProvider,
- Locale locale,
- String key,
- Object... params) {
- assert params.length == 3;
-
- int timeStyle = (Integer)params[0];
- int dateStyle = (Integer)params[1];
- int flags = (Integer)params[2];
-
- switch (flags) {
- case 1:
- return dateFormatProvider.getTimeInstance(timeStyle, locale);
- case 2:
- return dateFormatProvider.getDateInstance(dateStyle, locale);
- case 3:
- return dateFormatProvider.getDateTimeInstance(dateStyle, timeStyle, locale);
- default:
- assert false : "should not happen";
- }
-
- return null;
- }
- }
}
diff --git a/ojluni/src/main/java/java/text/DateFormatSymbols.java b/ojluni/src/main/java/java/text/DateFormatSymbols.java
index c617a18..47f0973 100644
--- a/ojluni/src/main/java/java/text/DateFormatSymbols.java
+++ b/ojluni/src/main/java/java/text/DateFormatSymbols.java
@@ -44,7 +44,6 @@
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.ref.SoftReference;
-import java.text.spi.DateFormatSymbolsProvider;
import java.util.Arrays;
import java.util.Locale;
import java.util.Objects;
@@ -52,9 +51,9 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import libcore.icu.ICU;
import libcore.icu.LocaleData;
import libcore.icu.TimeZoneNames;
-import sun.util.LocaleServiceProviderPool;
/**
* <code>DateFormatSymbols</code> is a public class for encapsulating
@@ -103,15 +102,13 @@
*/
public class DateFormatSymbols implements Serializable, Cloneable {
+ // Android-changed: Removed reference to DateFormatSymbolsProvider but suggested getInstance()
+ // be used instead in case Android supports it in future.
/**
* Construct a DateFormatSymbols object by loading format data from
* resources for the default {@link java.util.Locale.Category#FORMAT FORMAT}
- * locale. This constructor can only
- * construct instances for the locales supported by the Java
- * runtime environment, not for those supported by installed
- * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
- * implementations. For full locale coverage, use the
- * {@link #getInstance(Locale) getInstance} method.
+ * locale. It is recommended that the {@link #getInstance(Locale) getInstance} method is used
+ * instead.
* <p>This is equivalent to calling
* {@link #DateFormatSymbols(Locale)
* DateFormatSymbols(Locale.getDefault(Locale.Category.FORMAT))}.
@@ -127,14 +124,12 @@
initializeData(Locale.getDefault(Locale.Category.FORMAT));
}
+ // Android-changed: Removed reference to DateFormatSymbolsProvider but suggested getInstance()
+ // be used instead in case Android supports it in future.
/**
* Construct a DateFormatSymbols object by loading format data from
- * resources for the given locale. This constructor can only
- * construct instances for the locales supported by the Java
- * runtime environment, not for those supported by installed
- * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
- * implementations. For full locale coverage, use the
- * {@link #getInstance(Locale) getInstance} method.
+ * resources for the given locale. It is recommended that the
+ * {@link #getInstance(Locale) getInstance} method is used instead.
*
* @param locale the desired locale
* @see #getInstance(Locale)
@@ -361,33 +356,25 @@
*/
private String[] tinyStandAloneWeekdays;
+ // Android-changed: Removed reference to DateFormatSymbolsProvider.
/**
* Returns an array of all locales for which the
* <code>getInstance</code> methods of this class can return
* localized instances.
- * The returned array represents the union of locales supported by the
- * Java runtime and by installed
- * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
- * implementations. It must contain at least a <code>Locale</code>
- * instance equal to {@link java.util.Locale#US Locale.US}.
*
* @return An array of locales for which localized
* <code>DateFormatSymbols</code> instances are available.
* @since 1.6
*/
public static Locale[] getAvailableLocales() {
- LocaleServiceProviderPool pool=
- LocaleServiceProviderPool.getPool(DateFormatSymbolsProvider.class);
- return pool.getAvailableLocales();
+ // Android-changed: No support for DateFormatSymbolsProvider.
+ return ICU.getAvailableLocales();
}
+ // Android-changed: Removed reference to DateFormatSymbolsProvider.
/**
* Gets the <code>DateFormatSymbols</code> instance for the default
- * locale. This method provides access to <code>DateFormatSymbols</code>
- * instances for locales supported by the Java runtime itself as well
- * as for those supported by installed
- * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
- * implementations.
+ * locale.
* <p>This is equivalent to calling {@link #getInstance(Locale)
* getInstance(Locale.getDefault(Locale.Category.FORMAT))}.
* @see java.util.Locale#getDefault(java.util.Locale.Category)
@@ -399,23 +386,17 @@
return getInstance(Locale.getDefault(Locale.Category.FORMAT));
}
+ // Android-changed: Removed reference to DateFormatSymbolsProvider.
/**
* Gets the <code>DateFormatSymbols</code> instance for the specified
- * locale. This method provides access to <code>DateFormatSymbols</code>
- * instances for locales supported by the Java runtime itself as well
- * as for those supported by installed
- * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
- * implementations.
+ * locale.
* @param locale the given locale.
* @return a <code>DateFormatSymbols</code> instance.
* @exception NullPointerException if <code>locale</code> is null
* @since 1.6
*/
public static final DateFormatSymbols getInstance(Locale locale) {
- DateFormatSymbols dfs = getProviderInstance(locale);
- if (dfs != null) {
- return dfs;
- }
+ // Android-changed: Removed used of DateFormatSymbolsProvider.
return (DateFormatSymbols) getCachedInstance(locale).clone();
}
@@ -426,27 +407,10 @@
* an application.
*/
static final DateFormatSymbols getInstanceRef(Locale locale) {
- DateFormatSymbols dfs = getProviderInstance(locale);
- if (dfs != null) {
- return dfs;
- }
+ // Android-changed: Removed used of DateFormatSymbolsProvider.
return getCachedInstance(locale);
}
- private static DateFormatSymbols getProviderInstance(Locale locale) {
- DateFormatSymbols providersInstance = null;
-
- // Check whether a provider can provide an implementation that's closer
- // to the requested locale than what the Java runtime itself can provide.
- LocaleServiceProviderPool pool =
- LocaleServiceProviderPool.getPool(DateFormatSymbolsProvider.class);
- if (pool.hasProviders()) {
- providersInstance = pool.getLocalizedObject(
- DateFormatSymbolsGetter.INSTANCE, locale);
- }
- return providersInstance;
- }
-
/**
* Returns a cached DateFormatSymbols if it's found in the
* cache. Otherwise, this method returns a newly cached instance
@@ -580,6 +544,7 @@
cachedHashCode = 0;
}
+ // Android-changed: Removed reference to TimeZoneNameProvider.
/**
* Gets time zone strings. Use of this method is discouraged; use
* {@link java.util.TimeZone#getDisplayName() TimeZone.getDisplayName()}
@@ -611,9 +576,7 @@
* If {@link #setZoneStrings(String[][]) setZoneStrings} has been called
* on this <code>DateFormatSymbols</code> instance, then the strings
* provided by that call are returned. Otherwise, the returned array
- * contains names provided by the Java runtime and by installed
- * {@link java.util.spi.TimeZoneNameProvider TimeZoneNameProvider}
- * implementations.
+ * contains names provided by the runtime.
*
* @return the time zone strings.
* @see #setZoneStrings(String[][])
@@ -1004,23 +967,4 @@
internalZoneStrings();
stream.defaultWriteObject();
}
-
- /**
- * Obtains a DateFormatSymbols instance from a DateFormatSymbolsProvider
- * implementation.
- */
- private static class DateFormatSymbolsGetter
- implements LocaleServiceProviderPool.LocalizedObjectGetter<DateFormatSymbolsProvider,
- DateFormatSymbols> {
- private static final DateFormatSymbolsGetter INSTANCE =
- new DateFormatSymbolsGetter();
-
- public DateFormatSymbols getObject(DateFormatSymbolsProvider dateFormatSymbolsProvider,
- Locale locale,
- String key,
- Object... params) {
- assert params.length == 0;
- return dateFormatSymbolsProvider.getInstance(locale);
- }
- }
}
diff --git a/ojluni/src/main/java/java/text/DecimalFormatSymbols.java b/ojluni/src/main/java/java/text/DecimalFormatSymbols.java
index a2bb05b..3937065 100644
--- a/ojluni/src/main/java/java/text/DecimalFormatSymbols.java
+++ b/ojluni/src/main/java/java/text/DecimalFormatSymbols.java
@@ -44,14 +44,12 @@
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;
-import java.text.spi.DecimalFormatSymbolsProvider;
import java.util.Currency;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
+import libcore.icu.ICU;
import libcore.icu.LocaleData;
-import sun.util.LocaleServiceProviderPool;
-
/**
* This class represents the set of symbols (such as the decimal separator,
* the grouping separator, and so on) needed by <code>DecimalFormat</code>
@@ -68,15 +66,13 @@
public class DecimalFormatSymbols implements Cloneable, Serializable {
+ // Android-changed: Removed reference to DecimalFormatSymbolsProvider but suggested
+ // getInstance() be used instead in case Android supports it in future.
/**
* Create a DecimalFormatSymbols object for the default
* {@link java.util.Locale.Category#FORMAT FORMAT} locale.
- * This constructor can only construct instances for the locales
- * supported by the Java runtime environment, not for those
- * supported by installed
- * {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider}
- * implementations. For full locale coverage, use the
- * {@link #getInstance(Locale) getInstance} method.
+ * It is recommended that the {@link #getInstance(Locale) getInstance} method is used
+ * instead.
* <p>This is equivalent to calling
* {@link #DecimalFormatSymbols(Locale)
* DecimalFormatSymbols(Locale.getDefault(Locale.Category.FORMAT))}.
@@ -87,14 +83,12 @@
initialize( Locale.getDefault(Locale.Category.FORMAT) );
}
+ // Android-changed: Removed reference to DecimalFormatSymbolsProvider but suggested
+ // getInstance() be used instead in case Android supports it in future.
/**
* Create a DecimalFormatSymbols object for the given locale.
- * This constructor can only construct instances for the locales
- * supported by the Java runtime environment, not for those
- * supported by installed
- * {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider}
- * implementations. For full locale coverage, use the
- * {@link #getInstance(Locale) getInstance} method.
+ * It is recommended that the {@link #getInstance(Locale) getInstance} method is used
+ * instead.
* If the specified locale contains the {@link java.util.Locale#UNICODE_LOCALE_EXTENSION}
* for the numbering system, the instance is initialized with the specified numbering
* system if the JRE implementation supports it. For example,
@@ -111,33 +105,25 @@
initialize( locale );
}
+ // Android-changed: Removed reference to DecimalFormatSymbolsProvider.
/**
* Returns an array of all locales for which the
* <code>getInstance</code> methods of this class can return
* localized instances.
- * The returned array represents the union of locales supported by the Java
- * runtime and by installed
- * {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider}
- * implementations. It must contain at least a <code>Locale</code>
- * instance equal to {@link java.util.Locale#US Locale.US}.
*
* @return an array of locales for which localized
* <code>DecimalFormatSymbols</code> instances are available.
* @since 1.6
*/
public static Locale[] getAvailableLocales() {
- LocaleServiceProviderPool pool =
- LocaleServiceProviderPool.getPool(DecimalFormatSymbolsProvider.class);
- return pool.getAvailableLocales();
+ // Android-changed: Removed used of DecimalFormatSymbolsProvider. Switched to use ICU.
+ return ICU.getAvailableLocales();
}
+ // Android-changed: Removed reference to DecimalFormatSymbolsProvider.
/**
* Gets the <code>DecimalFormatSymbols</code> instance for the default
- * locale. This method provides access to <code>DecimalFormatSymbols</code>
- * instances for locales supported by the Java runtime itself as well
- * as for those supported by installed
- * {@link java.text.spi.DecimalFormatSymbolsProvider
- * DecimalFormatSymbolsProvider} implementations.
+ * locale.
* <p>This is equivalent to calling
* {@link #getInstance(Locale)
* getInstance(Locale.getDefault(Locale.Category.FORMAT))}.
@@ -150,13 +136,10 @@
return getInstance(Locale.getDefault(Locale.Category.FORMAT));
}
+ // Android-changed: Removed reference to DecimalFormatSymbolsProvider.
/**
* Gets the <code>DecimalFormatSymbols</code> instance for the specified
- * locale. This method provides access to <code>DecimalFormatSymbols</code>
- * instances for locales supported by the Java runtime itself as well
- * as for those supported by installed
- * {@link java.text.spi.DecimalFormatSymbolsProvider
- * DecimalFormatSymbolsProvider} implementations.
+ * locale.
* If the specified locale contains the {@link java.util.Locale#UNICODE_LOCALE_EXTENSION}
* for the numbering system, the instance is initialized with the specified numbering
* system if the JRE implementation supports it. For example,
@@ -172,19 +155,7 @@
* @since 1.6
*/
public static final DecimalFormatSymbols getInstance(Locale locale) {
-
- // Check whether a provider can provide an implementation that's closer
- // to the requested locale than what the Java runtime itself can provide.
- LocaleServiceProviderPool pool =
- LocaleServiceProviderPool.getPool(DecimalFormatSymbolsProvider.class);
- if (pool.hasProviders()) {
- DecimalFormatSymbols providersInstance = pool.getLocalizedObject(
- DecimalFormatSymbolsGetter.INSTANCE, locale);
- if (providersInstance != null) {
- return providersInstance;
- }
- }
-
+ // Android-changed: Removed used of DecimalFormatSymbolsProvider.
return new DecimalFormatSymbols(locale);
}
@@ -659,6 +630,7 @@
private void initialize( Locale locale ) {
this.locale = locale;
+ // Android-changed: Removed use of DecimalFormatSymbolsProvider. Switched to ICU.
// get resource bundle data - try the cache first
boolean needCacheUpdate = false;
Object[] data = cachedLocaleData.get(locale);
@@ -1128,24 +1100,4 @@
private static final ConcurrentHashMap<Locale, Object[]> cachedLocaleData = new ConcurrentHashMap<Locale, Object[]>(3);
private transient android.icu.text.DecimalFormatSymbols cachedIcuDFS = null;
-
- /**
- * Obtains a DecimalFormatSymbols instance from a DecimalFormatSymbolsProvider
- * implementation.
- */
- private static class DecimalFormatSymbolsGetter
- implements LocaleServiceProviderPool.LocalizedObjectGetter<DecimalFormatSymbolsProvider,
- DecimalFormatSymbols> {
- private static final DecimalFormatSymbolsGetter INSTANCE =
- new DecimalFormatSymbolsGetter();
-
- public DecimalFormatSymbols getObject(
- DecimalFormatSymbolsProvider decimalFormatSymbolsProvider,
- Locale locale,
- String key,
- Object... params) {
- assert params.length == 0;
- return decimalFormatSymbolsProvider.getInstance(locale);
- }
- }
}
diff --git a/ojluni/src/main/java/java/text/NumberFormat.java b/ojluni/src/main/java/java/text/NumberFormat.java
index 476983f..218a668 100644
--- a/ojluni/src/main/java/java/text/NumberFormat.java
+++ b/ojluni/src/main/java/java/text/NumberFormat.java
@@ -45,18 +45,15 @@
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.math.RoundingMode;
-import java.text.spi.NumberFormatProvider;
import java.util.Currency;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;
-import java.util.ResourceBundle;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
-import java.util.spi.LocaleServiceProvider;
+import libcore.icu.ICU;
import libcore.icu.LocaleData;
-import sun.util.LocaleServiceProviderPool;
/**
* <code>NumberFormat</code> is the abstract base class for all number
@@ -548,23 +545,18 @@
return getInstance(inLocale, PERCENTSTYLE);
}
+ // Android-changed: Removed reference to NumberFormatProvider.
/**
* Returns an array of all locales for which the
* <code>get*Instance</code> methods of this class can return
* localized instances.
- * The returned array represents the union of locales supported by the Java
- * runtime and by installed
- * {@link java.text.spi.NumberFormatProvider NumberFormatProvider} implementations.
- * It must contain at least a <code>Locale</code> instance equal to
- * {@link java.util.Locale#US Locale.US}.
*
* @return An array of locales for which localized
* <code>NumberFormat</code> instances are available.
*/
public static Locale[] getAvailableLocales() {
- LocaleServiceProviderPool pool =
- LocaleServiceProviderPool.getPool(NumberFormatProvider.class);
- return pool.getAvailableLocales();
+ // Android-changed: Removed used of NumberFormatProvider. Switched to use ICU.
+ return ICU.getAvailableLocales();
}
/**
@@ -829,20 +821,7 @@
private static NumberFormat getInstance(Locale desiredLocale,
int choice) {
- // Check whether a provider can provide an implementation that's closer
- // to the requested locale than what the Java runtime itself can provide.
- LocaleServiceProviderPool pool =
- LocaleServiceProviderPool.getPool(NumberFormatProvider.class);
- if (pool.hasProviders()) {
- NumberFormat providersInstance = pool.getLocalizedObject(
- NumberFormatGetter.INSTANCE,
- desiredLocale,
- choice);
- if (providersInstance != null) {
- return providersInstance;
- }
- }
-
+ // Android-changed: Removed use of NumberFormatProvider. Switched to use ICU.
/* try the cache first */
String[] numberPatterns = (String[])cachedLocaleData.get(desiredLocale);
if (numberPatterns == null) { /* cache miss */
@@ -1219,36 +1198,4 @@
*/
public static final Field EXPONENT_SIGN = new Field("exponent sign");
}
-
- /**
- * Obtains a NumberFormat instance from a NumberFormatProvider implementation.
- */
- private static class NumberFormatGetter
- implements LocaleServiceProviderPool.LocalizedObjectGetter<NumberFormatProvider,
- NumberFormat> {
- private static final NumberFormatGetter INSTANCE = new NumberFormatGetter();
-
- public NumberFormat getObject(NumberFormatProvider numberFormatProvider,
- Locale locale,
- String key,
- Object... params) {
- assert params.length == 1;
- int choice = (Integer)params[0];
-
- switch (choice) {
- case NUMBERSTYLE:
- return numberFormatProvider.getNumberInstance(locale);
- case PERCENTSTYLE:
- return numberFormatProvider.getPercentInstance(locale);
- case CURRENCYSTYLE:
- return numberFormatProvider.getCurrencyInstance(locale);
- case INTEGERSTYLE:
- return numberFormatProvider.getIntegerInstance(locale);
- default:
- assert false : choice;
- }
-
- return null;
- }
- }
}
diff --git a/ojluni/src/main/java/java/text/SimpleDateFormat.java b/ojluni/src/main/java/java/text/SimpleDateFormat.java
index b17245f..de2a93e 100644
--- a/ojluni/src/main/java/java/text/SimpleDateFormat.java
+++ b/ojluni/src/main/java/java/text/SimpleDateFormat.java
@@ -534,12 +534,6 @@
private static final String GMT = "GMT";
/**
- * Cache to hold the DateTimePatterns of a Locale.
- */
- private static final ConcurrentMap<Locale, String[]> cachedLocaleData
- = new ConcurrentHashMap<Locale, String[]>(3);
-
- /**
* Cache NumberFormat instances with Locale key.
*/
private static final ConcurrentMap<Locale, NumberFormat> cachedNumberFormatData
@@ -662,33 +656,20 @@
// initialize calendar and related fields
initializeCalendar(loc);
- /* try the cache first */
- String[] dateTimePatterns = cachedLocaleData.get(loc);
- if (dateTimePatterns == null) { /* cache miss */
- LocaleData localeData = LocaleData.get(loc);
- dateTimePatterns = new String[9];
- dateTimePatterns[DateFormat.SHORT + 4] = localeData.getDateFormat(DateFormat.SHORT);
- dateTimePatterns[DateFormat.MEDIUM + 4] = localeData.getDateFormat(DateFormat.MEDIUM);
- dateTimePatterns[DateFormat.LONG + 4] = localeData.getDateFormat(DateFormat.LONG);
- dateTimePatterns[DateFormat.FULL + 4] = localeData.getDateFormat(DateFormat.FULL);
- dateTimePatterns[DateFormat.SHORT] = localeData.getTimeFormat(DateFormat.SHORT);
- dateTimePatterns[DateFormat.MEDIUM] = localeData.getTimeFormat(DateFormat.MEDIUM);
- dateTimePatterns[DateFormat.LONG] = localeData.getTimeFormat(DateFormat.LONG);
- dateTimePatterns[DateFormat.FULL] = localeData.getTimeFormat(DateFormat.FULL);
- dateTimePatterns[8] = "{0} {1}";
- /* update cache */
- cachedLocaleData.putIfAbsent(loc, dateTimePatterns);
- }
formatData = DateFormatSymbols.getInstanceRef(loc);
+ LocaleData localeData = LocaleData.get(loc);
if ((timeStyle >= 0) && (dateStyle >= 0)) {
- Object[] dateTimeArgs = {dateTimePatterns[dateStyle + 4], dateTimePatterns[timeStyle]};
- pattern = MessageFormat.format(dateTimePatterns[8], dateTimeArgs);
+ Object[] dateTimeArgs = {
+ localeData.getDateFormat(dateStyle),
+ localeData.getTimeFormat(timeStyle),
+ };
+ pattern = MessageFormat.format("{0} {1}", dateTimeArgs);
}
else if (timeStyle >= 0) {
- pattern = dateTimePatterns[timeStyle];
+ pattern = localeData.getTimeFormat(timeStyle);
}
else if (dateStyle >= 0) {
- pattern = dateTimePatterns[dateStyle + 4];
+ pattern = localeData.getDateFormat(dateStyle);
}
else {
throw new IllegalArgumentException("No date or time style specified");
diff --git a/ojluni/src/main/java/java/text/spi/BreakIteratorProvider.java b/ojluni/src/main/java/java/text/spi/BreakIteratorProvider.java
deleted file mode 100644
index dd4a1a2..0000000
--- a/ojluni/src/main/java/java/text/spi/BreakIteratorProvider.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.text.spi;
-
-import java.text.BreakIterator;
-import java.util.Locale;
-import java.util.spi.LocaleServiceProvider;
-
-/**
- * An abstract class for service providers that
- * provide concrete implementations of the
- * {@link java.text.BreakIterator BreakIterator} class.
- *
- * @since 1.6
- */
-public abstract class BreakIteratorProvider extends LocaleServiceProvider {
-
- /**
- * Sole constructor. (For invocation by subclass constructors, typically
- * implicit.)
- */
- protected BreakIteratorProvider() {
- }
-
- /**
- * Returns a new <code>BreakIterator</code> instance
- * for <a href="../BreakIterator.html#word">word breaks</a>
- * for the given locale.
- * @param locale the desired locale
- * @return A break iterator for word breaks
- * @exception NullPointerException if <code>locale</code> is null
- * @exception IllegalArgumentException if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @see java.text.BreakIterator#getWordInstance(java.util.Locale)
- */
- public abstract BreakIterator getWordInstance(Locale locale);
-
- /**
- * Returns a new <code>BreakIterator</code> instance
- * for <a href="../BreakIterator.html#line">line breaks</a>
- * for the given locale.
- * @param locale the desired locale
- * @return A break iterator for line breaks
- * @exception NullPointerException if <code>locale</code> is null
- * @exception IllegalArgumentException if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @see java.text.BreakIterator#getLineInstance(java.util.Locale)
- */
- public abstract BreakIterator getLineInstance(Locale locale);
-
- /**
- * Returns a new <code>BreakIterator</code> instance
- * for <a href="../BreakIterator.html#character">character breaks</a>
- * for the given locale.
- * @param locale the desired locale
- * @return A break iterator for character breaks
- * @exception NullPointerException if <code>locale</code> is null
- * @exception IllegalArgumentException if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @see java.text.BreakIterator#getCharacterInstance(java.util.Locale)
- */
- public abstract BreakIterator getCharacterInstance(Locale locale);
-
- /**
- * Returns a new <code>BreakIterator</code> instance
- * for <a href="../BreakIterator.html#sentence">sentence breaks</a>
- * for the given locale.
- * @param locale the desired locale
- * @return A break iterator for sentence breaks
- * @exception NullPointerException if <code>locale</code> is null
- * @exception IllegalArgumentException if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @see java.text.BreakIterator#getSentenceInstance(java.util.Locale)
- */
- public abstract BreakIterator getSentenceInstance(Locale locale);
-}
diff --git a/ojluni/src/main/java/java/text/spi/CollatorProvider.java b/ojluni/src/main/java/java/text/spi/CollatorProvider.java
deleted file mode 100644
index 1480908..0000000
--- a/ojluni/src/main/java/java/text/spi/CollatorProvider.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.text.spi;
-
-import java.text.Collator;
-import java.util.Locale;
-import java.util.spi.LocaleServiceProvider;
-
-/**
- * An abstract class for service providers that
- * provide concrete implementations of the
- * {@link java.text.Collator Collator} class.
- *
- * @since 1.6
- */
-public abstract class CollatorProvider extends LocaleServiceProvider {
-
- /**
- * Sole constructor. (For invocation by subclass constructors, typically
- * implicit.)
- */
- protected CollatorProvider() {
- }
-
- /**
- * Returns a new <code>Collator</code> instance for the specified locale.
- * @param locale the desired locale.
- * @return the <code>Collator</code> for the desired locale.
- * @exception NullPointerException if
- * <code>locale</code> is null
- * @exception IllegalArgumentException if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @see java.text.Collator#getInstance(java.util.Locale)
- */
- public abstract Collator getInstance(Locale locale);
-}
diff --git a/ojluni/src/main/java/java/text/spi/DateFormatProvider.java b/ojluni/src/main/java/java/text/spi/DateFormatProvider.java
deleted file mode 100644
index e12effd..0000000
--- a/ojluni/src/main/java/java/text/spi/DateFormatProvider.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.text.spi;
-
-import java.text.DateFormat;
-import java.util.Locale;
-import java.util.spi.LocaleServiceProvider;
-
-/**
- * An abstract class for service providers that
- * provide concrete implementations of the
- * {@link java.text.DateFormat DateFormat} class.
- *
- * @since 1.6
- */
-public abstract class DateFormatProvider extends LocaleServiceProvider {
-
- /**
- * Sole constructor. (For invocation by subclass constructors, typically
- * implicit.)
- */
- protected DateFormatProvider() {
- }
-
- /**
- * Returns a new <code>DateFormat</code> instance which formats time
- * with the given formatting style for the specified locale.
- * @param style the given formatting style. Either one of
- * {@link java.text.DateFormat#SHORT DateFormat.SHORT},
- * {@link java.text.DateFormat#MEDIUM DateFormat.MEDIUM},
- * {@link java.text.DateFormat#LONG DateFormat.LONG}, or
- * {@link java.text.DateFormat#FULL DateFormat.FULL}.
- * @param locale the desired locale.
- * @exception IllegalArgumentException if <code>style</code> is invalid,
- * or if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @exception NullPointerException if <code>locale</code> is null
- * @return a time formatter.
- * @see java.text.DateFormat#getTimeInstance(int, java.util.Locale)
- */
- public abstract DateFormat getTimeInstance(int style, Locale locale);
-
- /**
- * Returns a new <code>DateFormat</code> instance which formats date
- * with the given formatting style for the specified locale.
- * @param style the given formatting style. Either one of
- * {@link java.text.DateFormat#SHORT DateFormat.SHORT},
- * {@link java.text.DateFormat#MEDIUM DateFormat.MEDIUM},
- * {@link java.text.DateFormat#LONG DateFormat.LONG}, or
- * {@link java.text.DateFormat#FULL DateFormat.FULL}.
- * @param locale the desired locale.
- * @exception IllegalArgumentException if <code>style</code> is invalid,
- * or if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @exception NullPointerException if <code>locale</code> is null
- * @return a date formatter.
- * @see java.text.DateFormat#getDateInstance(int, java.util.Locale)
- */
- public abstract DateFormat getDateInstance(int style, Locale locale);
-
- /**
- * Returns a new <code>DateFormat</code> instance which formats date and time
- * with the given formatting style for the specified locale.
- * @param dateStyle the given date formatting style. Either one of
- * {@link java.text.DateFormat#SHORT DateFormat.SHORT},
- * {@link java.text.DateFormat#MEDIUM DateFormat.MEDIUM},
- * {@link java.text.DateFormat#LONG DateFormat.LONG}, or
- * {@link java.text.DateFormat#FULL DateFormat.FULL}.
- * @param timeStyle the given time formatting style. Either one of
- * {@link java.text.DateFormat#SHORT DateFormat.SHORT},
- * {@link java.text.DateFormat#MEDIUM DateFormat.MEDIUM},
- * {@link java.text.DateFormat#LONG DateFormat.LONG}, or
- * {@link java.text.DateFormat#FULL DateFormat.FULL}.
- * @param locale the desired locale.
- * @exception IllegalArgumentException if <code>dateStyle</code> or
- * <code>timeStyle</code> is invalid,
- * or if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @exception NullPointerException if <code>locale</code> is null
- * @return a date/time formatter.
- * @see java.text.DateFormat#getDateTimeInstance(int, int, java.util.Locale)
- */
- public abstract DateFormat
- getDateTimeInstance(int dateStyle, int timeStyle, Locale locale);
-}
diff --git a/ojluni/src/main/java/java/text/spi/DateFormatSymbolsProvider.java b/ojluni/src/main/java/java/text/spi/DateFormatSymbolsProvider.java
deleted file mode 100644
index bc3a8fb..0000000
--- a/ojluni/src/main/java/java/text/spi/DateFormatSymbolsProvider.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.text.spi;
-
-import java.text.DateFormatSymbols;
-import java.util.Locale;
-import java.util.spi.LocaleServiceProvider;
-
-/**
- * An abstract class for service providers that
- * provide instances of the
- * {@link java.text.DateFormatSymbols DateFormatSymbols} class.
- *
- * @since 1.6
- */
-public abstract class DateFormatSymbolsProvider extends LocaleServiceProvider {
-
- /**
- * Sole constructor. (For invocation by subclass constructors, typically
- * implicit.)
- */
- protected DateFormatSymbolsProvider() {
- }
-
- /**
- * Returns a new <code>DateFormatSymbols</code> instance for the
- * specified locale.
- *
- * @param locale the desired locale
- * @exception NullPointerException if <code>locale</code> is null
- * @exception IllegalArgumentException if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @return a <code>DateFormatSymbols</code> instance.
- * @see java.text.DateFormatSymbols#getInstance(java.util.Locale)
- */
- public abstract DateFormatSymbols getInstance(Locale locale);
-}
diff --git a/ojluni/src/main/java/java/text/spi/DecimalFormatSymbolsProvider.java b/ojluni/src/main/java/java/text/spi/DecimalFormatSymbolsProvider.java
deleted file mode 100644
index d1d078c..0000000
--- a/ojluni/src/main/java/java/text/spi/DecimalFormatSymbolsProvider.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.text.spi;
-
-import java.text.DecimalFormatSymbols;
-import java.util.Locale;
-import java.util.spi.LocaleServiceProvider;
-
-/**
- * An abstract class for service providers that
- * provide instances of the
- * {@link java.text.DecimalFormatSymbols DecimalFormatSymbols} class.
- *
- * <p>The requested {@code Locale} may contain an <a
- * href="../../util/Locale.html#def_locale_extension"> extension</a> for
- * specifying the desired numbering system. For example, {@code "ar-u-nu-arab"}
- * (in the BCP 47 language tag form) specifies Arabic with the Arabic-Indic
- * digits and symbols, while {@code "ar-u-nu-latn"} specifies Arabic with the
- * Latin digits and symbols. Refer to the <em>Unicode Locale Data Markup
- * Language (LDML)</em> specification for numbering systems.
- *
- * @since 1.6
- * @see Locale#forLanguageTag(String)
- * @see Locale#getExtension(char)
- */
-public abstract class DecimalFormatSymbolsProvider extends LocaleServiceProvider {
-
- /**
- * Sole constructor. (For invocation by subclass constructors, typically
- * implicit.)
- */
- protected DecimalFormatSymbolsProvider() {
- }
-
- /**
- * Returns a new <code>DecimalFormatSymbols</code> instance for the
- * specified locale.
- *
- * @param locale the desired locale
- * @exception NullPointerException if <code>locale</code> is null
- * @exception IllegalArgumentException if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @return a <code>DecimalFormatSymbols</code> instance.
- * @see java.text.DecimalFormatSymbols#getInstance(java.util.Locale)
- */
- public abstract DecimalFormatSymbols getInstance(Locale locale);
-}
diff --git a/ojluni/src/main/java/java/text/spi/NumberFormatProvider.java b/ojluni/src/main/java/java/text/spi/NumberFormatProvider.java
deleted file mode 100644
index a375b69..0000000
--- a/ojluni/src/main/java/java/text/spi/NumberFormatProvider.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.text.spi;
-
-import java.text.NumberFormat;
-import java.util.Locale;
-import java.util.spi.LocaleServiceProvider;
-
-/**
- * An abstract class for service providers that
- * provide concrete implementations of the
- * {@link java.text.NumberFormat NumberFormat} class.
- *
- * @since 1.6
- */
-public abstract class NumberFormatProvider extends LocaleServiceProvider {
-
- /**
- * Sole constructor. (For invocation by subclass constructors, typically
- * implicit.)
- */
- protected NumberFormatProvider() {
- }
-
- /**
- * Returns a new <code>NumberFormat</code> instance which formats
- * monetary values for the specified locale.
- *
- * @param locale the desired locale.
- * @exception NullPointerException if <code>locale</code> is null
- * @exception IllegalArgumentException if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @return a currency formatter
- * @see java.text.NumberFormat#getCurrencyInstance(java.util.Locale)
- */
- public abstract NumberFormat getCurrencyInstance(Locale locale);
-
- /**
- * Returns a new <code>NumberFormat</code> instance which formats
- * integer values for the specified locale.
- * The returned number format is configured to
- * round floating point numbers to the nearest integer using
- * half-even rounding (see {@link java.math.RoundingMode#HALF_EVEN HALF_EVEN})
- * for formatting, and to parse only the integer part of
- * an input string (see {@link
- * java.text.NumberFormat#isParseIntegerOnly isParseIntegerOnly}).
- *
- * @param locale the desired locale
- * @exception NullPointerException if <code>locale</code> is null
- * @exception IllegalArgumentException if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @return a number format for integer values
- * @see java.text.NumberFormat#getIntegerInstance(java.util.Locale)
- */
- public abstract NumberFormat getIntegerInstance(Locale locale);
-
- /**
- * Returns a new general-purpose <code>NumberFormat</code> instance for
- * the specified locale.
- *
- * @param locale the desired locale
- * @exception NullPointerException if <code>locale</code> is null
- * @exception IllegalArgumentException if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @return a general-purpose number formatter
- * @see java.text.NumberFormat#getNumberInstance(java.util.Locale)
- */
- public abstract NumberFormat getNumberInstance(Locale locale);
-
- /**
- * Returns a new <code>NumberFormat</code> instance which formats
- * percentage values for the specified locale.
- *
- * @param locale the desired locale
- * @exception NullPointerException if <code>locale</code> is null
- * @exception IllegalArgumentException if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @return a percent formatter
- * @see java.text.NumberFormat#getPercentInstance(java.util.Locale)
- */
- public abstract NumberFormat getPercentInstance(Locale locale);
-}
diff --git a/ojluni/src/main/java/java/text/spi/package.html b/ojluni/src/main/java/java/text/spi/package.html
deleted file mode 100644
index fa08ec1..0000000
--- a/ojluni/src/main/java/java/text/spi/package.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head>
-<!--
-Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
-DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
-This code is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 2 only, as
-published by the Free Software Foundation. Oracle designates this
-particular file as subject to the "Classpath" exception as provided
-by Oracle in the LICENSE file that accompanied this code.
-
-This code is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-version 2 for more details (a copy is included in the LICENSE file that
-accompanied this code).
-
-You should have received a copy of the GNU General Public License version
-2 along with this work; if not, write to the Free Software Foundation,
-Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-or visit www.oracle.com if you need additional information or have any
-questions.
--->
-
-</head>
-<body bgcolor="white">
-Service provider classes for the classes in the java.text package.
-<!--
-<h2>Package Specification</h2>
-
-##### FILL IN ANY SPECS NEEDED BY JAVA COMPATIBILITY KIT #####
-<ul>
- <li><a href="">##### REFER TO ANY FRAMEMAKER SPECIFICATION HERE #####</a>
-</ul>
-
-<h2>Related Documentation</h2>
-
-For overviews, tutorials, examples, guides, and tool documentation, please see:
-<ul>
- <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
-</ul>
--->
-
-@since 1.6
-</body>
-</html>
diff --git a/ojluni/src/main/java/java/util/Arrays.java b/ojluni/src/main/java/java/util/Arrays.java
index df3f769..0f175c3 100644
--- a/ojluni/src/main/java/java/util/Arrays.java
+++ b/ojluni/src/main/java/java/util/Arrays.java
@@ -26,7 +26,7 @@
package java.util;
-import java.lang.reflect.*;
+import java.lang.reflect.Array;
import java.util.concurrent.ForkJoinPool;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
@@ -80,6 +80,8 @@
*/
public static final int MIN_ARRAY_SORT_GRAN = 1 << 13;
+ // Suppresses default constructor, ensuring non-instantiability.
+ private Arrays() {}
/**
* A comparator that implements the natural ordering of a group of
@@ -104,11 +106,43 @@
static final NaturalOrder INSTANCE = new NaturalOrder();
}
- // Suppresses default constructor, ensuring non-instantiability.
- private Arrays() {}
+ /**
+ * Checks that {@code fromIndex} and {@code toIndex} are in
+ * the range and throws an appropriate exception, if they aren't.
+ */
+ private static void rangeCheck(int length, int fromIndex, int toIndex) {
+ if (fromIndex > toIndex) {
+ throw new IllegalArgumentException(
+ "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
+ }
+ if (fromIndex < 0) {
+ throw new ArrayIndexOutOfBoundsException(fromIndex);
+ }
+ if (toIndex > length) {
+ throw new ArrayIndexOutOfBoundsException(toIndex);
+ }
+ }
+
+ /**
+ * Checks that the range described by {@code offset} and {@code count} doesn't exceed
+ * {@code arrayLength}.
+ *
+ * Android changed.
+ * @hide
+ */
+ public static void checkOffsetAndCount(int arrayLength, int offset, int count) {
+ if ((offset | count) < 0 || offset > arrayLength || arrayLength - offset < count) {
+ throw new ArrayIndexOutOfBoundsException(arrayLength, offset,
+ count);
+ }
+ }
/*
- * Sorting of primitive type arrays.
+ * Sorting methods. Note that all public "sort" methods take the
+ * same form: Performing argument checks if necessary, and then
+ * expanding arguments into those required for the internal
+ * implementation methods residing in other package-private
+ * classes (except for legacyMergeSort, included in this class).
*/
/**
@@ -1167,50 +1201,6 @@
*/
/**
- * Old merge sort implementation can be selected (for
- * compatibility with broken comparators) using a system property.
- * Cannot be a static boolean in the enclosing class due to
- * circular dependencies. To be removed in a future release.
- */
- static final class LegacyMergeSort {
- // Android-changed: Never use circular merge sort.
- private static final boolean userRequested = false;
- }
-
- /*
- * If this platform has an optimizing VM, check whether ComparableTimSort
- * offers any performance benefit over TimSort in conjunction with a
- * comparator that returns:
- * {@code ((Comparable)first).compareTo(Second)}.
- * If not, you are better off deleting ComparableTimSort to
- * eliminate the code duplication. In other words, the commented
- * out code below is the preferable implementation for sorting
- * arrays of Comparables if it offers sufficient performance.
- */
-
-// /**
-// * A comparator that implements the natural ordering of a group of
-// * mutually comparable elements. Using this comparator saves us
-// * from duplicating most of the code in this file (one version for
-// * Comparables, one for explicit Comparators).
-// */
-// private static final Comparator<Object> NATURAL_ORDER =
-// new Comparator<Object>() {
-// @SuppressWarnings("unchecked")
-// public int compare(Object first, Object second) {
-// return ((Comparable<Object>)first).compareTo(second);
-// }
-// };
-//
-// public static void sort(Object[] a) {
-// sort(a, 0, a.length, NATURAL_ORDER);
-// }
-//
-// public static void sort(Object[] a, int fromIndex, int toIndex) {
-// sort(a, fromIndex, toIndex, NATURAL_ORDER);
-// }
-
- /**
* Sorts the specified array of objects into ascending order, according
* to the {@linkplain Comparable natural ordering} of its elements.
* All elements in the array must implement the {@link Comparable}
@@ -1240,7 +1230,7 @@
*
* <p>The implementation was adapted from Tim Peters's list sort for Python
* (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
- * TimSort</a>). It uses techiques from Peter McIlroy's "Optimistic
+ * TimSort</a>). It uses techniques from Peter McIlroy's "Optimistic
* Sorting and Information Theoretic Complexity", in Proceedings of the
* Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
* January 1993.
@@ -1253,18 +1243,13 @@
* {@link Comparable} contract
*/
public static void sort(Object[] a) {
- if (LegacyMergeSort.userRequested)
- legacyMergeSort(a);
- else
+ // Android-changed: LegacyMergeSort is no longer supported
+ // if (LegacyMergeSort.userRequested)
+ // legacyMergeSort(a);
+ // else
ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
}
- /** To be removed in a future release. */
- private static void legacyMergeSort(Object[] a) {
- Object[] aux = a.clone();
- mergeSort(aux, a, 0, a.length, 0);
- }
-
/**
* Sorts the specified range of the specified array of objects into
* ascending order, according to the
@@ -1299,7 +1284,7 @@
*
* <p>The implementation was adapted from Tim Peters's list sort for Python
* (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
- * TimSort</a>). It uses techiques from Peter McIlroy's "Optimistic
+ * TimSort</a>). It uses techniques from Peter McIlroy's "Optimistic
* Sorting and Information Theoretic Complexity", in Proceedings of the
* Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
* January 1993.
@@ -1319,20 +1304,13 @@
*/
public static void sort(Object[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
- if (LegacyMergeSort.userRequested)
- legacyMergeSort(a, fromIndex, toIndex);
- else
+ // Android-changed: LegacyMergeSort is no longer supported
+ // if (LegacyMergeSort.userRequested)
+ // legacyMergeSort(a, fromIndex, toIndex);
+ // else
ComparableTimSort.sort(a, fromIndex, toIndex, null, 0, 0);
}
- /** To be removed in a future release. */
- private static void legacyMergeSort(Object[] a,
- int fromIndex, int toIndex) {
- rangeCheck(a.length, fromIndex, toIndex);
- Object[] aux = copyOfRange(a, fromIndex, toIndex);
- mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
- }
-
/**
* Tuning parameter: list size at or below which insertion sort will be
* used in preference to mergesort.
@@ -1348,6 +1326,7 @@
* off is the offset to generate corresponding low, high in src
* To be removed in a future release.
*/
+ @SuppressWarnings({"unchecked", "rawtypes"})
private static void mergeSort(Object[] src,
Object[] dest,
int low,
@@ -1426,11 +1405,12 @@
*
* <p>The implementation was adapted from Tim Peters's list sort for Python
* (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
- * TimSort</a>). It uses techiques from Peter McIlroy's "Optimistic
+ * TimSort</a>). It uses techniques from Peter McIlroy's "Optimistic
* Sorting and Information Theoretic Complexity", in Proceedings of the
* Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
* January 1993.
*
+ * @param <T> the class of the objects to be sorted
* @param a the array to be sorted
* @param c the comparator to determine the order of the array. A
* {@code null} value indicates that the elements'
@@ -1444,22 +1424,14 @@
if (c == null) {
sort(a);
} else {
- if (LegacyMergeSort.userRequested)
- legacyMergeSort(a, c);
- else
+ // Android-changed: LegacyMergeSort is no longer supported
+ // if (LegacyMergeSort.userRequested)
+ // legacyMergeSort(a, c);
+ // else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
- /** To be removed in a future release. */
- private static <T> void legacyMergeSort(T[] a, Comparator<? super T> c) {
- T[] aux = a.clone();
- if (c==null)
- mergeSort(aux, a, 0, a.length, 0);
- else
- mergeSort(aux, a, 0, a.length, 0, c);
- }
-
/**
* Sorts the specified range of the specified array of objects according
* to the order induced by the specified comparator. The range to be
@@ -1491,11 +1463,12 @@
*
* <p>The implementation was adapted from Tim Peters's list sort for Python
* (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
- * TimSort</a>). It uses techiques from Peter McIlroy's "Optimistic
+ * TimSort</a>). It uses techniques from Peter McIlroy's "Optimistic
* Sorting and Information Theoretic Complexity", in Proceedings of the
* Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
* January 1993.
*
+ * @param <T> the class of the objects to be sorted
* @param a the array to be sorted
* @param fromIndex the index of the first element (inclusive) to be
* sorted
@@ -1517,89 +1490,14 @@
sort(a, fromIndex, toIndex);
} else {
rangeCheck(a.length, fromIndex, toIndex);
- if (LegacyMergeSort.userRequested)
- legacyMergeSort(a, fromIndex, toIndex, c);
- else
+ // Android-changed: LegacyMergeSort is no longer supported
+ // if (LegacyMergeSort.userRequested)
+ // legacyMergeSort(a, fromIndex, toIndex, c);
+ // else
TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);
}
}
- /** To be removed in a future release. */
- private static <T> void legacyMergeSort(T[] a, int fromIndex, int toIndex,
- Comparator<? super T> c) {
- rangeCheck(a.length, fromIndex, toIndex);
- T[] aux = copyOfRange(a, fromIndex, toIndex);
- if (c==null)
- mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
- else
- mergeSort(aux, a, fromIndex, toIndex, -fromIndex, c);
- }
-
- /**
- * Src is the source array that starts at index 0
- * Dest is the (possibly larger) array destination with a possible offset
- * low is the index in dest to start sorting
- * high is the end index in dest to end sorting
- * off is the offset into src corresponding to low in dest
- * To be removed in a future release.
- */
- private static void mergeSort(Object[] src,
- Object[] dest,
- int low, int high, int off,
- Comparator c) {
- int length = high - low;
-
- // Insertion sort on smallest arrays
- if (length < INSERTIONSORT_THRESHOLD) {
- for (int i=low; i<high; i++)
- for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
- swap(dest, j, j-1);
- return;
- }
-
- // Recursively sort halves of dest into src
- int destLow = low;
- int destHigh = high;
- low += off;
- high += off;
- int mid = (low + high) >>> 1;
- mergeSort(dest, src, low, mid, -off, c);
- mergeSort(dest, src, mid, high, -off, c);
-
- // If list is already sorted, just copy from src to dest. This is an
- // optimization that results in faster sorts for nearly ordered lists.
- if (c.compare(src[mid-1], src[mid]) <= 0) {
- System.arraycopy(src, low, dest, destLow, length);
- return;
- }
-
- // Merge sorted halves (now in src) into dest
- for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
- if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
- dest[i] = src[p++];
- else
- dest[i] = src[q++];
- }
- }
-
- /**
- * Checks that {@code fromIndex} and {@code toIndex} are in
- * the range and throws an appropriate exception, if they aren't.
- */
- private static void rangeCheck(int length, int fromIndex, int toIndex) {
- if (fromIndex > toIndex) {
- throw new IllegalArgumentException(
- "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
- }
- if (fromIndex < 0) {
- throw new ArrayIndexOutOfBoundsException(fromIndex);
- }
- if (toIndex > length) {
- throw new ArrayIndexOutOfBoundsException(toIndex);
- }
- }
-
-
// Parallel prefix
/**
@@ -2462,7 +2360,9 @@
while (low <= high) {
int mid = (low + high) >>> 1;
+ @SuppressWarnings("rawtypes")
Comparable midVal = (Comparable)a[mid];
+ @SuppressWarnings("unchecked")
int cmp = midVal.compareTo(key);
if (cmp < 0)
@@ -2486,6 +2386,7 @@
* elements equal to the specified object, there is no guarantee which one
* will be found.
*
+ * @param <T> the class of the objects in the array
* @param a the array to be searched
* @param key the value to be searched for
* @param c the comparator by which the array is ordered. A
@@ -2521,6 +2422,7 @@
* If the range contains multiple elements equal to the specified object,
* there is no guarantee which one will be found.
*
+ * @param <T> the class of the objects in the array
* @param a the array to be searched
* @param fromIndex the index of the first element (inclusive) to be
* searched
@@ -3192,6 +3094,7 @@
* is greater than that of the original array.
* The resulting array is of exactly the same class as the original array.
*
+ * @param <T> the class of the objects in the array
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @return a copy of the original array, truncated or padded with nulls
@@ -3200,6 +3103,7 @@
* @throws NullPointerException if <tt>original</tt> is null
* @since 1.6
*/
+ @SuppressWarnings("unchecked")
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
@@ -3214,6 +3118,8 @@
* is greater than that of the original array.
* The resulting array is of the class <tt>newType</tt>.
*
+ * @param <U> the class of the objects in the original array
+ * @param <T> the class of the objects in the returned array
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @param newType the class of the copy to be returned
@@ -3227,6 +3133,7 @@
* @since 1.6
*/
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
+ @SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
@@ -3443,6 +3350,7 @@
* <p>
* The resulting array is of exactly the same class as the original array.
*
+ * @param <T> the class of the objects in the array
* @param original the array from which a range is to be copied
* @param from the initial index of the range to be copied, inclusive
* @param to the final index of the range to be copied, exclusive.
@@ -3455,8 +3363,9 @@
* @throws NullPointerException if <tt>original</tt> is null
* @since 1.6
*/
+ @SuppressWarnings("unchecked")
public static <T> T[] copyOfRange(T[] original, int from, int to) {
- return copyOfRange(original, from, to, (Class<T[]>) original.getClass());
+ return copyOfRange(original, from, to, (Class<? extends T[]>) original.getClass());
}
/**
@@ -3474,6 +3383,8 @@
* of the returned array will be <tt>to - from</tt>.
* The resulting array is of the class <tt>newType</tt>.
*
+ * @param <U> the class of the objects in the original array
+ * @param <T> the class of the objects in the returned array
* @param original the array from which a range is to be copied
* @param from the initial index of the range to be copied, inclusive
* @param to the final index of the range to be copied, exclusive.
@@ -3494,6 +3405,7 @@
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
+ @SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
@@ -3805,10 +3717,12 @@
* List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
* </pre>
*
+ * @param <T> the class of the objects in the array
* @param a the array by which the list will be backed
* @return a list view of the specified array
*/
@SafeVarargs
+ @SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
@@ -3863,12 +3777,13 @@
@Override
public int indexOf(Object o) {
- if (o==null) {
- for (int i=0; i<a.length; i++)
- if (a[i]==null)
+ E[] a = this.a;
+ if (o == null) {
+ for (int i = 0; i < a.length; i++)
+ if (a[i] == null)
return i;
} else {
- for (int i=0; i<a.length; i++)
+ for (int i = 0; i < a.length; i++)
if (o.equals(a[i]))
return i;
}
@@ -3881,6 +3796,11 @@
}
@Override
+ public Spliterator<E> spliterator() {
+ return Spliterators.spliterator(a, Spliterator.ORDERED);
+ }
+
+ @Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
for (E e : a) {
@@ -3898,8 +3818,8 @@
}
@Override
- public Spliterator<E> spliterator() {
- return Spliterators.spliterator(a, Spliterator.ORDERED);
+ public void sort(Comparator<? super E> c) {
+ Arrays.sort(a, c);
}
}
@@ -4192,6 +4112,7 @@
for (Object element : a) {
int elementHash = 0;
+ // Android-changed: getComponentType() is faster than instanceof()
if (element != null) {
Class<?> cl = element.getClass().getComponentType();
if (cl == null)
@@ -4273,6 +4194,7 @@
if (e1 == e2)
continue;
+ // Android-changed: Return early if e2 == null
if (e1 == null || e2 == null)
return false;
@@ -4286,6 +4208,7 @@
}
static boolean deepEquals0(Object e1, Object e2) {
+ // Android-changed: getComponentType() is faster than instanceof()
Class<?> cl1 = e1.getClass().getComponentType();
Class<?> cl2 = e2.getClass().getComponentType();
@@ -4654,7 +4577,7 @@
if (element == null) {
buf.append("null");
} else {
- Class eClass = element.getClass();
+ Class<?> eClass = element.getClass();
if (eClass.isArray()) {
if (eClass == byte[].class)
@@ -4691,6 +4614,7 @@
dejaVu.remove(a);
}
+
/**
* Set all elements of the specified array, using the provided
* generator function to compute each element.
@@ -4846,21 +4770,6 @@
}
/**
- * Checks that the range described by {@code offset} and {@code count} doesn't exceed
- * {@code arrayLength}.
- *
- * Android changed.
- * @hide
- */
- public static void checkOffsetAndCount(int arrayLength, int offset, int count) {
- if ((offset | count) < 0 || offset > arrayLength || arrayLength - offset < count) {
- throw new ArrayIndexOutOfBoundsException(arrayLength, offset,
- count);
- }
- }
-
-
- /**
* Returns a {@link Spliterator} covering all of the specified array.
*
* <p>The spliterator reports {@link Spliterator#SIZED},
@@ -5019,7 +4928,6 @@
Spliterator.ORDERED | Spliterator.IMMUTABLE);
}
-
/**
* Returns a sequential {@link Stream} with the specified array as its
* source.
diff --git a/ojluni/src/main/java/java/util/Collections.java b/ojluni/src/main/java/java/util/Collections.java
index 5a4de2a..65b9b55 100644
--- a/ojluni/src/main/java/java/util/Collections.java
+++ b/ojluni/src/main/java/java/util/Collections.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,8 @@
*/
package java.util;
-
+import java.io.Serializable;
+import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
@@ -35,11 +36,10 @@
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
-import java.util.function.UnaryOperator;
-
/**
* This class consists exclusively of static methods that operate on or return
@@ -162,9 +162,16 @@
* @throws IllegalArgumentException (optional) if the implementation
* detects that the natural ordering of the list elements is
* found to violate the {@link Comparable} contract
+ * @see List#sort(Comparator)
*/
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> void sort(List<T> list) {
+ // Android-changed BEGIN: List.sort() is implemented on top of
+ // Collections.sort() rather than the other way around. For backwards
+ // compatibility, Collections.sort() never changes a List's modCount,
+ // but List.sort() implementations may.
+ // was: list.sort(null);
+
if (list.getClass() == ArrayList.class) {
Arrays.sort(((ArrayList) list).elementData, 0, list.size());
return;
@@ -177,6 +184,7 @@
i.next();
i.set((T)a[j]);
}
+ // Android-changed END
}
/**
@@ -231,9 +239,16 @@
* list-iterator does not support the {@code set} operation.
* @throws IllegalArgumentException (optional) if the comparator is
* found to violate the {@link Comparator} contract
+ * @see List#sort(Comparator)
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static <T> void sort(List<T> list, Comparator<? super T> c) {
+ // Android-changed BEGIN: List.sort() is implemented on top of
+ // Collections.sort() rather than the other way around. For backwards
+ // compatibility, Collections.sort() never changes a List's modCount,
+ // but List.sort() implementations may.
+ // was: list.sort(c);
+
if (list.getClass() == ArrayList.class) {
Arrays.sort(((ArrayList) list).elementData, 0, list.size(), (Comparator) c);
return;
@@ -246,6 +261,7 @@
i.next();
i.set((T)a[j]);
}
+ // Android-changed END
}
@@ -1152,12 +1168,10 @@
public void forEach(Consumer<? super E> action) {
c.forEach(action);
}
-
@Override
public boolean removeIf(Predicate<? super E> filter) {
throw new UnsupportedOperationException();
}
-
@SuppressWarnings("unchecked")
@Override
public Spliterator<E> spliterator() {
@@ -1254,6 +1268,96 @@
}
/**
+ * Returns an unmodifiable view of the specified navigable set. This method
+ * allows modules to provide users with "read-only" access to internal
+ * navigable sets. Query operations on the returned navigable set "read
+ * through" to the specified navigable set. Attempts to modify the returned
+ * navigable set, whether direct, via its iterator, or via its
+ * {@code subSet}, {@code headSet}, or {@code tailSet} views, result in
+ * an {@code UnsupportedOperationException}.<p>
+ *
+ * The returned navigable set will be serializable if the specified
+ * navigable set is serializable.
+ *
+ * @param <T> the class of the objects in the set
+ * @param s the navigable set for which an unmodifiable view is to be
+ * returned
+ * @return an unmodifiable view of the specified navigable set
+ * @since 1.8
+ * @hide
+ */
+ public static <T> NavigableSet<T> unmodifiableNavigableSet(NavigableSet<T> s) {
+ return new UnmodifiableNavigableSet<>(s);
+ }
+
+ /**
+ * Wraps a navigable set and disables all of the mutative operations.
+ *
+ * @param <E> type of elements
+ * @serial include
+ */
+ static class UnmodifiableNavigableSet<E>
+ extends UnmodifiableSortedSet<E>
+ implements NavigableSet<E>, Serializable {
+
+ private static final long serialVersionUID = -6027448201786391929L;
+
+ /**
+ * A singleton empty unmodifiable navigable set used for
+ * {@link #emptyNavigableSet()}.
+ *
+ * @param <E> type of elements, if there were any, and bounds
+ */
+ private static class EmptyNavigableSet<E> extends UnmodifiableNavigableSet<E>
+ implements Serializable {
+ private static final long serialVersionUID = -6291252904449939134L;
+
+ public EmptyNavigableSet() {
+ super(new TreeSet<E>());
+ }
+
+ private Object readResolve() { return EMPTY_NAVIGABLE_SET; }
+ }
+
+ @SuppressWarnings("rawtypes")
+ private static final NavigableSet<?> EMPTY_NAVIGABLE_SET =
+ new EmptyNavigableSet<>();
+
+ /**
+ * The instance we are protecting.
+ */
+ private final NavigableSet<E> ns;
+
+ UnmodifiableNavigableSet(NavigableSet<E> s) {super(s); ns = s;}
+
+ public E lower(E e) { return ns.lower(e); }
+ public E floor(E e) { return ns.floor(e); }
+ public E ceiling(E e) { return ns.ceiling(e); }
+ public E higher(E e) { return ns.higher(e); }
+ public E pollFirst() { throw new UnsupportedOperationException(); }
+ public E pollLast() { throw new UnsupportedOperationException(); }
+ public NavigableSet<E> descendingSet()
+ { return new UnmodifiableNavigableSet<>(ns.descendingSet()); }
+ public Iterator<E> descendingIterator()
+ { return descendingSet().iterator(); }
+
+ public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
+ return new UnmodifiableNavigableSet<>(
+ ns.subSet(fromElement, fromInclusive, toElement, toInclusive));
+ }
+
+ public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+ return new UnmodifiableNavigableSet<>(
+ ns.headSet(toElement, inclusive));
+ }
+
+ public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+ return new UnmodifiableNavigableSet<>(
+ ns.tailSet(fromElement, inclusive));
+ }
+ }
+
+ /**
* Returns an unmodifiable view of the specified list. This method allows
* modules to provide users with "read-only" access to internal
* lists. Query operations on the returned list "read through" to the
@@ -1307,6 +1411,7 @@
public boolean addAll(int index, Collection<? extends E> c) {
throw new UnsupportedOperationException();
}
+
@Override
public void replaceAll(UnaryOperator<E> operator) {
throw new UnsupportedOperationException();
@@ -1315,6 +1420,7 @@
public void sort(Comparator<? super E> c) {
throw new UnsupportedOperationException();
}
+
public ListIterator<E> listIterator() {return listIterator(0);}
public ListIterator<E> listIterator(final int index) {
@@ -1450,9 +1556,9 @@
throw new UnsupportedOperationException();
}
- private transient Set<K> keySet = null;
- private transient Set<Map.Entry<K,V>> entrySet = null;
- private transient Collection<V> values = null;
+ private transient Set<K> keySet;
+ private transient Set<Map.Entry<K,V>> entrySet;
+ private transient Collection<V> values;
public Set<K> keySet() {
if (keySet==null)
@@ -1521,19 +1627,19 @@
@Override
public V computeIfPresent(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V compute(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V merge(K key, V value,
- BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@@ -1559,7 +1665,6 @@
return e -> action.accept(new UnmodifiableEntry<>(e));
}
- // Override default methods in Collection
public void forEach(Consumer<? super Entry<K, V>> action) {
Objects.requireNonNull(action);
c.forEach(entryConsumer(action));
@@ -1794,6 +1899,149 @@
public K lastKey() { return sm.lastKey(); }
}
+ /**
+ * Returns an unmodifiable view of the specified navigable map. This method
+ * allows modules to provide users with "read-only" access to internal
+ * navigable maps. Query operations on the returned navigable map "read
+ * through" to the specified navigable map. Attempts to modify the returned
+ * navigable map, whether direct, via its collection views, or via its
+ * {@code subMap}, {@code headMap}, or {@code tailMap} views, result in
+ * an {@code UnsupportedOperationException}.<p>
+ *
+ * The returned navigable map will be serializable if the specified
+ * navigable map is serializable.
+ *
+ * @param <K> the class of the map keys
+ * @param <V> the class of the map values
+ * @param m the navigable map for which an unmodifiable view is to be
+ * returned
+ * @return an unmodifiable view of the specified navigable map
+ * @since 1.8
+ * @hide
+ */
+ public static <K,V> NavigableMap<K,V> unmodifiableNavigableMap(NavigableMap<K, ? extends V> m) {
+ return new UnmodifiableNavigableMap<>(m);
+ }
+
+ /**
+ * @serial include
+ */
+ static class UnmodifiableNavigableMap<K,V>
+ extends UnmodifiableSortedMap<K,V>
+ implements NavigableMap<K,V>, Serializable {
+ private static final long serialVersionUID = -4858195264774772197L;
+
+ /**
+ * A class for the {@link EMPTY_NAVIGABLE_MAP} which needs readResolve
+ * to preserve singleton property.
+ *
+ * @param <K> type of keys, if there were any, and of bounds
+ * @param <V> type of values, if there were any
+ */
+ private static class EmptyNavigableMap<K,V> extends UnmodifiableNavigableMap<K,V>
+ implements Serializable {
+
+ private static final long serialVersionUID = -2239321462712562324L;
+
+ EmptyNavigableMap() { super(new TreeMap<K,V>()); }
+
+ @Override
+ public NavigableSet<K> navigableKeySet()
+ { return emptyNavigableSet(); }
+
+ private Object readResolve() { return EMPTY_NAVIGABLE_MAP; }
+ }
+
+ /**
+ * Singleton for {@link emptyNavigableMap()} which is also immutable.
+ */
+ private static final EmptyNavigableMap<?,?> EMPTY_NAVIGABLE_MAP =
+ new EmptyNavigableMap<>();
+
+ /**
+ * The instance we wrap and protect.
+ */
+ private final NavigableMap<K, ? extends V> nm;
+
+ UnmodifiableNavigableMap(NavigableMap<K, ? extends V> m)
+ {super(m); nm = m;}
+
+ public K lowerKey(K key) { return nm.lowerKey(key); }
+ public K floorKey(K key) { return nm.floorKey(key); }
+ public K ceilingKey(K key) { return nm.ceilingKey(key); }
+ public K higherKey(K key) { return nm.higherKey(key); }
+
+ @SuppressWarnings("unchecked")
+ public Entry<K, V> lowerEntry(K key) {
+ Entry<K,V> lower = (Entry<K, V>) nm.lowerEntry(key);
+ return (null != lower)
+ ? new UnmodifiableEntrySet.UnmodifiableEntry<>(lower)
+ : null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Entry<K, V> floorEntry(K key) {
+ Entry<K,V> floor = (Entry<K, V>) nm.floorEntry(key);
+ return (null != floor)
+ ? new UnmodifiableEntrySet.UnmodifiableEntry<>(floor)
+ : null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Entry<K, V> ceilingEntry(K key) {
+ Entry<K,V> ceiling = (Entry<K, V>) nm.ceilingEntry(key);
+ return (null != ceiling)
+ ? new UnmodifiableEntrySet.UnmodifiableEntry<>(ceiling)
+ : null;
+ }
+
+
+ @SuppressWarnings("unchecked")
+ public Entry<K, V> higherEntry(K key) {
+ Entry<K,V> higher = (Entry<K, V>) nm.higherEntry(key);
+ return (null != higher)
+ ? new UnmodifiableEntrySet.UnmodifiableEntry<>(higher)
+ : null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Entry<K, V> firstEntry() {
+ Entry<K,V> first = (Entry<K, V>) nm.firstEntry();
+ return (null != first)
+ ? new UnmodifiableEntrySet.UnmodifiableEntry<>(first)
+ : null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Entry<K, V> lastEntry() {
+ Entry<K,V> last = (Entry<K, V>) nm.lastEntry();
+ return (null != last)
+ ? new UnmodifiableEntrySet.UnmodifiableEntry<>(last)
+ : null;
+ }
+
+ public Entry<K, V> pollFirstEntry()
+ { throw new UnsupportedOperationException(); }
+ public Entry<K, V> pollLastEntry()
+ { throw new UnsupportedOperationException(); }
+ public NavigableMap<K, V> descendingMap()
+ { return unmodifiableNavigableMap(nm.descendingMap()); }
+ public NavigableSet<K> navigableKeySet()
+ { return unmodifiableNavigableSet(nm.navigableKeySet()); }
+ public NavigableSet<K> descendingKeySet()
+ { return unmodifiableNavigableSet(nm.descendingKeySet()); }
+
+ public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
+ return unmodifiableNavigableMap(
+ nm.subMap(fromKey, fromInclusive, toKey, toInclusive));
+ }
+
+ public NavigableMap<K, V> headMap(K toKey, boolean inclusive)
+ { return unmodifiableNavigableMap(nm.headMap(toKey, inclusive)); }
+ public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive)
+ { return unmodifiableNavigableMap(nm.tailMap(fromKey, inclusive)); }
+ }
+
// Synch Wrappers
/**
@@ -2078,6 +2326,122 @@
}
/**
+ * Returns a synchronized (thread-safe) navigable set backed by the
+ * specified navigable set. In order to guarantee serial access, it is
+ * critical that <strong>all</strong> access to the backing navigable set is
+ * accomplished through the returned navigable set (or its views).<p>
+ *
+ * It is imperative that the user manually synchronize on the returned
+ * navigable set when iterating over it or any of its {@code subSet},
+ * {@code headSet}, or {@code tailSet} views.
+ * <pre>
+ * NavigableSet s = Collections.synchronizedNavigableSet(new TreeSet());
+ * ...
+ * synchronized (s) {
+ * Iterator i = s.iterator(); // Must be in the synchronized block
+ * while (i.hasNext())
+ * foo(i.next());
+ * }
+ * </pre>
+ * or:
+ * <pre>
+ * NavigableSet s = Collections.synchronizedNavigableSet(new TreeSet());
+ * NavigableSet s2 = s.headSet(foo, true);
+ * ...
+ * synchronized (s) { // Note: s, not s2!!!
+ * Iterator i = s2.iterator(); // Must be in the synchronized block
+ * while (i.hasNext())
+ * foo(i.next());
+ * }
+ * </pre>
+ * Failure to follow this advice may result in non-deterministic behavior.
+ *
+ * <p>The returned navigable set will be serializable if the specified
+ * navigable set is serializable.
+ *
+ * @param <T> the class of the objects in the set
+ * @param s the navigable set to be "wrapped" in a synchronized navigable
+ * set
+ * @return a synchronized view of the specified navigable set
+ * @since 1.8
+ * @hide
+ */
+ public static <T> NavigableSet<T> synchronizedNavigableSet(NavigableSet<T> s) {
+ return new SynchronizedNavigableSet<>(s);
+ }
+
+ /**
+ * @serial include
+ */
+ static class SynchronizedNavigableSet<E>
+ extends SynchronizedSortedSet<E>
+ implements NavigableSet<E>
+ {
+ private static final long serialVersionUID = -5505529816273629798L;
+
+ private final NavigableSet<E> ns;
+
+ SynchronizedNavigableSet(NavigableSet<E> s) {
+ super(s);
+ ns = s;
+ }
+
+ SynchronizedNavigableSet(NavigableSet<E> s, Object mutex) {
+ super(s, mutex);
+ ns = s;
+ }
+ public E lower(E e) { synchronized (mutex) {return ns.lower(e);} }
+ public E floor(E e) { synchronized (mutex) {return ns.floor(e);} }
+ public E ceiling(E e) { synchronized (mutex) {return ns.ceiling(e);} }
+ public E higher(E e) { synchronized (mutex) {return ns.higher(e);} }
+ public E pollFirst() { synchronized (mutex) {return ns.pollFirst();} }
+ public E pollLast() { synchronized (mutex) {return ns.pollLast();} }
+
+ public NavigableSet<E> descendingSet() {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(ns.descendingSet(), mutex);
+ }
+ }
+
+ public Iterator<E> descendingIterator()
+ { synchronized (mutex) { return descendingSet().iterator(); } }
+
+ public NavigableSet<E> subSet(E fromElement, E toElement) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(ns.subSet(fromElement, true, toElement, false), mutex);
+ }
+ }
+ public NavigableSet<E> headSet(E toElement) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(ns.headSet(toElement, false), mutex);
+ }
+ }
+ public NavigableSet<E> tailSet(E fromElement) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, true), mutex);
+ }
+ }
+
+ public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(ns.subSet(fromElement, fromInclusive, toElement, toInclusive), mutex);
+ }
+ }
+
+ public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(ns.headSet(toElement, inclusive), mutex);
+ }
+ }
+
+ public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(ns.tailSet(fromElement, inclusive), mutex);
+ }
+ }
+ }
+
+ /**
* Returns a synchronized (thread-safe) list backed by the specified
* list. In order to guarantee serial access, it is critical that
* <strong>all</strong> access to the backing list is accomplished
@@ -2327,9 +2691,9 @@
synchronized (mutex) {m.clear();}
}
- private transient Set<K> keySet = null;
- private transient Set<Map.Entry<K,V>> entrySet = null;
- private transient Collection<V> values = null;
+ private transient Set<K> keySet;
+ private transient Set<Map.Entry<K,V>> entrySet;
+ private transient Collection<V> values;
public Set<K> keySet() {
synchronized (mutex) {
@@ -2398,22 +2762,22 @@
}
@Override
public V computeIfAbsent(K key,
- Function<? super K, ? extends V> mappingFunction) {
+ Function<? super K, ? extends V> mappingFunction) {
synchronized (mutex) {return m.computeIfAbsent(key, mappingFunction);}
}
@Override
public V computeIfPresent(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
synchronized (mutex) {return m.computeIfPresent(key, remappingFunction);}
}
@Override
public V compute(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
synchronized (mutex) {return m.compute(key, remappingFunction);}
}
@Override
public V merge(K key, V value,
- BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
synchronized (mutex) {return m.merge(key, value, remappingFunction);}
}
@@ -2519,6 +2883,167 @@
}
}
+ /**
+ * Returns a synchronized (thread-safe) navigable map backed by the
+ * specified navigable map. In order to guarantee serial access, it is
+ * critical that <strong>all</strong> access to the backing navigable map is
+ * accomplished through the returned navigable map (or its views).<p>
+ *
+ * It is imperative that the user manually synchronize on the returned
+ * navigable map when iterating over any of its collection views, or the
+ * collections views of any of its {@code subMap}, {@code headMap} or
+ * {@code tailMap} views.
+ * <pre>
+ * NavigableMap m = Collections.synchronizedNavigableMap(new TreeMap());
+ * ...
+ * Set s = m.keySet(); // Needn't be in synchronized block
+ * ...
+ * synchronized (m) { // Synchronizing on m, not s!
+ * Iterator i = s.iterator(); // Must be in synchronized block
+ * while (i.hasNext())
+ * foo(i.next());
+ * }
+ * </pre>
+ * or:
+ * <pre>
+ * NavigableMap m = Collections.synchronizedNavigableMap(new TreeMap());
+ * NavigableMap m2 = m.subMap(foo, true, bar, false);
+ * ...
+ * Set s2 = m2.keySet(); // Needn't be in synchronized block
+ * ...
+ * synchronized (m) { // Synchronizing on m, not m2 or s2!
+ * Iterator i = s.iterator(); // Must be in synchronized block
+ * while (i.hasNext())
+ * foo(i.next());
+ * }
+ * </pre>
+ * Failure to follow this advice may result in non-deterministic behavior.
+ *
+ * <p>The returned navigable map will be serializable if the specified
+ * navigable map is serializable.
+ *
+ * @param <K> the class of the map keys
+ * @param <V> the class of the map values
+ * @param m the navigable map to be "wrapped" in a synchronized navigable
+ * map
+ * @return a synchronized view of the specified navigable map.
+ * @since 1.8
+ * @hide
+ */
+ public static <K,V> NavigableMap<K,V> synchronizedNavigableMap(NavigableMap<K,V> m) {
+ return new SynchronizedNavigableMap<>(m);
+ }
+
+ /**
+ * A synchronized NavigableMap.
+ *
+ * @serial include
+ */
+ static class SynchronizedNavigableMap<K,V>
+ extends SynchronizedSortedMap<K,V>
+ implements NavigableMap<K,V>
+ {
+ private static final long serialVersionUID = 699392247599746807L;
+
+ private final NavigableMap<K,V> nm;
+
+ SynchronizedNavigableMap(NavigableMap<K,V> m) {
+ super(m);
+ nm = m;
+ }
+ SynchronizedNavigableMap(NavigableMap<K,V> m, Object mutex) {
+ super(m, mutex);
+ nm = m;
+ }
+
+ public Entry<K, V> lowerEntry(K key)
+ { synchronized (mutex) { return nm.lowerEntry(key); } }
+ public K lowerKey(K key)
+ { synchronized (mutex) { return nm.lowerKey(key); } }
+ public Entry<K, V> floorEntry(K key)
+ { synchronized (mutex) { return nm.floorEntry(key); } }
+ public K floorKey(K key)
+ { synchronized (mutex) { return nm.floorKey(key); } }
+ public Entry<K, V> ceilingEntry(K key)
+ { synchronized (mutex) { return nm.ceilingEntry(key); } }
+ public K ceilingKey(K key)
+ { synchronized (mutex) { return nm.ceilingKey(key); } }
+ public Entry<K, V> higherEntry(K key)
+ { synchronized (mutex) { return nm.higherEntry(key); } }
+ public K higherKey(K key)
+ { synchronized (mutex) { return nm.higherKey(key); } }
+ public Entry<K, V> firstEntry()
+ { synchronized (mutex) { return nm.firstEntry(); } }
+ public Entry<K, V> lastEntry()
+ { synchronized (mutex) { return nm.lastEntry(); } }
+ public Entry<K, V> pollFirstEntry()
+ { synchronized (mutex) { return nm.pollFirstEntry(); } }
+ public Entry<K, V> pollLastEntry()
+ { synchronized (mutex) { return nm.pollLastEntry(); } }
+
+ public NavigableMap<K, V> descendingMap() {
+ synchronized (mutex) {
+ return
+ new SynchronizedNavigableMap<>(nm.descendingMap(), mutex);
+ }
+ }
+
+ public NavigableSet<K> keySet() {
+ return navigableKeySet();
+ }
+
+ public NavigableSet<K> navigableKeySet() {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(nm.navigableKeySet(), mutex);
+ }
+ }
+
+ public NavigableSet<K> descendingKeySet() {
+ synchronized (mutex) {
+ return new SynchronizedNavigableSet<>(nm.descendingKeySet(), mutex);
+ }
+ }
+
+
+ public SortedMap<K,V> subMap(K fromKey, K toKey) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableMap<>(
+ nm.subMap(fromKey, true, toKey, false), mutex);
+ }
+ }
+ public SortedMap<K,V> headMap(K toKey) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableMap<>(nm.headMap(toKey, false), mutex);
+ }
+ }
+ public SortedMap<K,V> tailMap(K fromKey) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableMap<>(nm.tailMap(fromKey, true),mutex);
+ }
+ }
+
+ public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableMap<>(
+ nm.subMap(fromKey, fromInclusive, toKey, toInclusive), mutex);
+ }
+ }
+
+ public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableMap<>(
+ nm.headMap(toKey, inclusive), mutex);
+ }
+ }
+
+ public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
+ synchronized (mutex) {
+ return new SynchronizedNavigableMap<>(
+ nm.tailMap(fromKey, inclusive), mutex);
+ }
+ }
+ }
+
// Dynamically typesafe collection wrappers
/**
@@ -2601,9 +3126,11 @@
final Collection<E> c;
final Class<E> type;
- void typeCheck(Object o) {
+ @SuppressWarnings("unchecked")
+ E typeCheck(Object o) {
if (o != null && !type.isInstance(o))
throw new ClassCastException(badElementMsg(o));
+ return (E) o;
}
private String badElementMsg(Object o) {
@@ -2612,10 +3139,8 @@
}
CheckedCollection(Collection<E> c, Class<E> type) {
- if (c==null || type == null)
- throw new NullPointerException();
- this.c = c;
- this.type = type;
+ this.c = Objects.requireNonNull(c, "c");
+ this.type = Objects.requireNonNull(type, "type");
}
public int size() { return c.size(); }
@@ -2648,12 +3173,9 @@
// Android-note: Should we delegate to it for forEachRemaining ?
}
- public boolean add(E e) {
- typeCheck(e);
- return c.add(e);
- }
+ public boolean add(E e) { return c.add(typeCheck(e)); }
- private E[] zeroLengthElementArray = null; // Lazily initialized
+ private E[] zeroLengthElementArray; // Lazily initialized
private E[] zeroLengthElementArray() {
return zeroLengthElementArray != null ? zeroLengthElementArray :
@@ -2662,7 +3184,7 @@
@SuppressWarnings("unchecked")
Collection<E> checkedCopyOf(Collection<? extends E> coll) {
- Object[] a = null;
+ Object[] a;
try {
E[] z = zeroLengthElementArray();
a = coll.toArray(z);
@@ -2704,7 +3226,62 @@
public Stream<E> stream() {return c.stream();}
@Override
public Stream<E> parallelStream() {return c.parallelStream();}
+ }
+ /**
+ * Returns a dynamically typesafe view of the specified queue.
+ * Any attempt to insert an element of the wrong type will result in
+ * an immediate {@link ClassCastException}. Assuming a queue contains
+ * no incorrectly typed elements prior to the time a dynamically typesafe
+ * view is generated, and that all subsequent access to the queue
+ * takes place through the view, it is <i>guaranteed</i> that the
+ * queue cannot contain an incorrectly typed element.
+ *
+ * <p>A discussion of the use of dynamically typesafe views may be
+ * found in the documentation for the {@link #checkedCollection
+ * checkedCollection} method.
+ *
+ * <p>The returned queue will be serializable if the specified queue
+ * is serializable.
+ *
+ * <p>Since {@code null} is considered to be a value of any reference
+ * type, the returned queue permits insertion of {@code null} elements
+ * whenever the backing queue does.
+ *
+ * @param <E> the class of the objects in the queue
+ * @param queue the queue for which a dynamically typesafe view is to be
+ * returned
+ * @param type the type of element that {@code queue} is permitted to hold
+ * @return a dynamically typesafe view of the specified queue
+ * @since 1.8
+ * @hide
+ */
+ public static <E> Queue<E> checkedQueue(Queue<E> queue, Class<E> type) {
+ return new CheckedQueue<>(queue, type);
+ }
+
+ /**
+ * @serial include
+ */
+ static class CheckedQueue<E>
+ extends CheckedCollection<E>
+ implements Queue<E>, Serializable
+ {
+ private static final long serialVersionUID = 1433151992604707767L;
+ final Queue<E> queue;
+
+ CheckedQueue(Queue<E> queue, Class<E> elementType) {
+ super(queue, elementType);
+ this.queue = queue;
+ }
+
+ public E element() {return queue.element();}
+ public boolean equals(Object o) {return o == this || c.equals(o);}
+ public int hashCode() {return c.hashCode();}
+ public E peek() {return queue.peek();}
+ public E poll() {return queue.poll();}
+ public E remove() {return queue.remove();}
+ public boolean offer(E e) {return queue.offer(typeCheck(e));}
}
/**
@@ -2815,6 +3392,89 @@
}
}
+/**
+ * Returns a dynamically typesafe view of the specified navigable set.
+ * Any attempt to insert an element of the wrong type will result in an
+ * immediate {@link ClassCastException}. Assuming a navigable set
+ * contains no incorrectly typed elements prior to the time a
+ * dynamically typesafe view is generated, and that all subsequent
+ * access to the navigable set takes place through the view, it is
+ * <em>guaranteed</em> that the navigable set cannot contain an incorrectly
+ * typed element.
+ *
+ * <p>A discussion of the use of dynamically typesafe views may be
+ * found in the documentation for the {@link #checkedCollection
+ * checkedCollection} method.
+ *
+ * <p>The returned navigable set will be serializable if the specified
+ * navigable set is serializable.
+ *
+ * <p>Since {@code null} is considered to be a value of any reference
+ * type, the returned navigable set permits insertion of null elements
+ * whenever the backing sorted set does.
+ *
+ * @param <E> the class of the objects in the set
+ * @param s the navigable set for which a dynamically typesafe view is to be
+ * returned
+ * @param type the type of element that {@code s} is permitted to hold
+ * @return a dynamically typesafe view of the specified navigable set
+ * @since 1.8
+ * @hide
+ */
+ public static <E> NavigableSet<E> checkedNavigableSet(NavigableSet<E> s,
+ Class<E> type) {
+ return new CheckedNavigableSet<>(s, type);
+ }
+
+ /**
+ * @serial include
+ */
+ static class CheckedNavigableSet<E> extends CheckedSortedSet<E>
+ implements NavigableSet<E>, Serializable
+ {
+ private static final long serialVersionUID = -5429120189805438922L;
+
+ private final NavigableSet<E> ns;
+
+ CheckedNavigableSet(NavigableSet<E> s, Class<E> type) {
+ super(s, type);
+ ns = s;
+ }
+
+ public E lower(E e) { return ns.lower(e); }
+ public E floor(E e) { return ns.floor(e); }
+ public E ceiling(E e) { return ns.ceiling(e); }
+ public E higher(E e) { return ns.higher(e); }
+ public E pollFirst() { return ns.pollFirst(); }
+ public E pollLast() {return ns.pollLast(); }
+ public NavigableSet<E> descendingSet()
+ { return checkedNavigableSet(ns.descendingSet(), type); }
+ public Iterator<E> descendingIterator()
+ {return checkedNavigableSet(ns.descendingSet(), type).iterator(); }
+
+ public NavigableSet<E> subSet(E fromElement, E toElement) {
+ return checkedNavigableSet(ns.subSet(fromElement, true, toElement, false), type);
+ }
+ public NavigableSet<E> headSet(E toElement) {
+ return checkedNavigableSet(ns.headSet(toElement, false), type);
+ }
+ public NavigableSet<E> tailSet(E fromElement) {
+ return checkedNavigableSet(ns.tailSet(fromElement, true), type);
+ }
+
+ public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
+ return checkedNavigableSet(ns.subSet(fromElement, fromInclusive, toElement, toInclusive), type);
+ }
+
+ public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+ return checkedNavigableSet(ns.headSet(toElement, inclusive), type);
+ }
+
+ public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+ return checkedNavigableSet(ns.tailSet(fromElement, inclusive), type);
+ }
+ }
+
/**
* Returns a dynamically typesafe view of the specified list.
* Any attempt to insert an element of the wrong type will result in
@@ -2871,13 +3531,11 @@
public int lastIndexOf(Object o) { return list.lastIndexOf(o); }
public E set(int index, E element) {
- typeCheck(element);
- return list.set(index, element);
+ return list.set(index, typeCheck(element));
}
public void add(int index, E element) {
- typeCheck(element);
- list.add(index, element);
+ list.add(index, typeCheck(element));
}
public boolean addAll(int index, Collection<? extends E> c) {
@@ -2898,13 +3556,11 @@
public void remove() { i.remove(); }
public void set(E e) {
- typeCheck(e);
- i.set(e);
+ i.set(typeCheck(e));
}
public void add(E e) {
- typeCheck(e);
- i.add(e);
+ i.add(typeCheck(e));
}
@Override
@@ -2929,14 +3585,7 @@
@Override
public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
-
- // Android-changed: Modified from OpenJDK 8 code because typeCheck returns void in
- // OpenJDK 7.
- list.replaceAll(e -> {
- E newValue = operator.apply(e);
- typeCheck(newValue);
- return newValue;
- });
+ list.replaceAll(e -> typeCheck(operator.apply(e)));
}
@Override
@@ -3038,12 +3687,12 @@
private String badKeyMsg(Object key) {
return "Attempt to insert " + key.getClass() +
- " key into map with key type " + keyType;
+ " key into map with key type " + keyType;
}
private String badValueMsg(Object value) {
return "Attempt to insert " + value.getClass() +
- " value into map with value type " + valueType;
+ " value into map with value type " + valueType;
}
CheckedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType) {
@@ -3091,7 +3740,7 @@
m.put(e.getKey(), e.getValue());
}
- private transient Set<Map.Entry<K,V>> entrySet = null;
+ private transient Set<Map.Entry<K,V>> entrySet;
public Set<Map.Entry<K,V>> entrySet() {
if (entrySet==null)
@@ -3434,6 +4083,178 @@
}
}
+ /**
+ * Returns a dynamically typesafe view of the specified navigable map.
+ * Any attempt to insert a mapping whose key or value have the wrong
+ * type will result in an immediate {@link ClassCastException}.
+ * Similarly, any attempt to modify the value currently associated with
+ * a key will result in an immediate {@link ClassCastException},
+ * whether the modification is attempted directly through the map
+ * itself, or through a {@link Map.Entry} instance obtained from the
+ * map's {@link Map#entrySet() entry set} view.
+ *
+ * <p>Assuming a map contains no incorrectly typed keys or values
+ * prior to the time a dynamically typesafe view is generated, and
+ * that all subsequent access to the map takes place through the view
+ * (or one of its collection views), it is <em>guaranteed</em> that the
+ * map cannot contain an incorrectly typed key or value.
+ *
+ * <p>A discussion of the use of dynamically typesafe views may be
+ * found in the documentation for the {@link #checkedCollection
+ * checkedCollection} method.
+ *
+ * <p>The returned map will be serializable if the specified map is
+ * serializable.
+ *
+ * <p>Since {@code null} is considered to be a value of any reference
+ * type, the returned map permits insertion of null keys or values
+ * whenever the backing map does.
+ *
+ * @param <K> type of map keys
+ * @param <V> type of map values
+ * @param m the map for which a dynamically typesafe view is to be
+ * returned
+ * @param keyType the type of key that {@code m} is permitted to hold
+ * @param valueType the type of value that {@code m} is permitted to hold
+ * @return a dynamically typesafe view of the specified map
+ * @since 1.8
+ * @hide
+ */
+ public static <K,V> NavigableMap<K,V> checkedNavigableMap(NavigableMap<K, V> m,
+ Class<K> keyType,
+ Class<V> valueType) {
+ return new CheckedNavigableMap<>(m, keyType, valueType);
+ }
+
+ /**
+ * @serial include
+ */
+ static class CheckedNavigableMap<K,V> extends CheckedSortedMap<K,V>
+ implements NavigableMap<K,V>, Serializable
+ {
+ private static final long serialVersionUID = -4852462692372534096L;
+
+ private final NavigableMap<K, V> nm;
+
+ CheckedNavigableMap(NavigableMap<K, V> m,
+ Class<K> keyType, Class<V> valueType) {
+ super(m, keyType, valueType);
+ nm = m;
+ }
+
+ public Comparator<? super K> comparator() { return nm.comparator(); }
+ public K firstKey() { return nm.firstKey(); }
+ public K lastKey() { return nm.lastKey(); }
+
+ public Entry<K, V> lowerEntry(K key) {
+ Entry<K,V> lower = nm.lowerEntry(key);
+ return (null != lower)
+ ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(lower, valueType)
+ : null;
+ }
+
+ public K lowerKey(K key) { return nm.lowerKey(key); }
+
+ public Entry<K, V> floorEntry(K key) {
+ Entry<K,V> floor = nm.floorEntry(key);
+ return (null != floor)
+ ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(floor, valueType)
+ : null;
+ }
+
+ public K floorKey(K key) { return nm.floorKey(key); }
+
+ public Entry<K, V> ceilingEntry(K key) {
+ Entry<K,V> ceiling = nm.ceilingEntry(key);
+ return (null != ceiling)
+ ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(ceiling, valueType)
+ : null;
+ }
+
+ public K ceilingKey(K key) { return nm.ceilingKey(key); }
+
+ public Entry<K, V> higherEntry(K key) {
+ Entry<K,V> higher = nm.higherEntry(key);
+ return (null != higher)
+ ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(higher, valueType)
+ : null;
+ }
+
+ public K higherKey(K key) { return nm.higherKey(key); }
+
+ public Entry<K, V> firstEntry() {
+ Entry<K,V> first = nm.firstEntry();
+ return (null != first)
+ ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(first, valueType)
+ : null;
+ }
+
+ public Entry<K, V> lastEntry() {
+ Entry<K,V> last = nm.lastEntry();
+ return (null != last)
+ ? new CheckedMap.CheckedEntrySet.CheckedEntry<>(last, valueType)
+ : null;
+ }
+
+ public Entry<K, V> pollFirstEntry() {
+ Entry<K,V> entry = nm.pollFirstEntry();
+ return (null == entry)
+ ? null
+ : new CheckedMap.CheckedEntrySet.CheckedEntry<>(entry, valueType);
+ }
+
+ public Entry<K, V> pollLastEntry() {
+ Entry<K,V> entry = nm.pollLastEntry();
+ return (null == entry)
+ ? null
+ : new CheckedMap.CheckedEntrySet.CheckedEntry<>(entry, valueType);
+ }
+
+ public NavigableMap<K, V> descendingMap() {
+ return checkedNavigableMap(nm.descendingMap(), keyType, valueType);
+ }
+
+ public NavigableSet<K> keySet() {
+ return navigableKeySet();
+ }
+
+ public NavigableSet<K> navigableKeySet() {
+ return checkedNavigableSet(nm.navigableKeySet(), keyType);
+ }
+
+ public NavigableSet<K> descendingKeySet() {
+ return checkedNavigableSet(nm.descendingKeySet(), keyType);
+ }
+
+ @Override
+ public NavigableMap<K,V> subMap(K fromKey, K toKey) {
+ return checkedNavigableMap(nm.subMap(fromKey, true, toKey, false),
+ keyType, valueType);
+ }
+
+ @Override
+ public NavigableMap<K,V> headMap(K toKey) {
+ return checkedNavigableMap(nm.headMap(toKey, false), keyType, valueType);
+ }
+
+ @Override
+ public NavigableMap<K,V> tailMap(K fromKey) {
+ return checkedNavigableMap(nm.tailMap(fromKey, true), keyType, valueType);
+ }
+
+ public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
+ return checkedNavigableMap(nm.subMap(fromKey, fromInclusive, toKey, toInclusive), keyType, valueType);
+ }
+
+ public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
+ return checkedNavigableMap(nm.headMap(toKey, inclusive), keyType, valueType);
+ }
+
+ public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
+ return checkedNavigableMap(nm.tailMap(fromKey, inclusive), keyType, valueType);
+ }
+ }
+
// Empty collections
/**
@@ -3623,7 +4444,50 @@
private Object readResolve() {
return EMPTY_SET;
}
+ }
+ /**
+ * Returns an empty sorted set (immutable). This set is serializable.
+ *
+ * <p>This example illustrates the type-safe way to obtain an empty
+ * sorted set:
+ * <pre> {@code
+ * SortedSet<String> s = Collections.emptySortedSet();
+ * }</pre>
+ *
+ * @implNote Implementations of this method need not create a separate
+ * {@code SortedSet} object for each call.
+ *
+ * @param <E> type of elements, if there were any, in the set
+ * @return the empty sorted set
+ * @since 1.8
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ public static <E> SortedSet<E> emptySortedSet() {
+ return (SortedSet<E>) UnmodifiableNavigableSet.EMPTY_NAVIGABLE_SET;
+ }
+
+ /**
+ * Returns an empty navigable set (immutable). This set is serializable.
+ *
+ * <p>This example illustrates the type-safe way to obtain an empty
+ * navigable set:
+ * <pre> {@code
+ * NavigableSet<String> s = Collections.emptyNavigableSet();
+ * }</pre>
+ *
+ * @implNote Implementations of this method need not
+ * create a separate {@code NavigableSet} object for each call.
+ *
+ * @param <E> type of elements, if there were any, in the set
+ * @return the empty navigable set
+ * @since 1.8
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ public static <E> NavigableSet<E> emptyNavigableSet() {
+ return (NavigableSet<E>) UnmodifiableNavigableSet.EMPTY_NAVIGABLE_SET;
}
/**
@@ -3641,10 +4505,12 @@
* <pre>
* List<String> s = Collections.emptyList();
* </pre>
- * Implementation note: Implementations of this method need not
- * create a separate <tt>List</tt> object for each call. Using this
- * method is likely to have comparable cost to using the like-named
- * field. (Unlike this method, the field does not provide type safety.)
+ *
+ * @implNote
+ * Implementations of this method need not create a separate <tt>List</tt>
+ * object for each call. Using this method is likely to have comparable
+ * cost to using the like-named field. (Unlike this method, the field does
+ * not provide type safety.)
*
* @param <T> type of elements, if there were any, in the list
* @return an empty immutable list
@@ -3701,6 +4567,13 @@
Objects.requireNonNull(filter);
return false;
}
+ @Override
+ public void replaceAll(UnaryOperator<E> operator) {
+ Objects.requireNonNull(operator);
+ }
+ @Override
+ public void sort(Comparator<? super E> c) {
+ }
// Override default methods in Collection
@Override
@@ -3711,15 +4584,6 @@
@Override
public Spliterator<E> spliterator() { return Spliterators.emptySpliterator(); }
- @Override
- public void replaceAll(UnaryOperator<E> operator) {
- Objects.requireNonNull(operator);
- }
- @Override
- public void sort(Comparator<? super E> c) {
- }
-
-
// Preserves singleton property
private Object readResolve() {
return EMPTY_LIST;
@@ -3759,6 +4623,50 @@
}
/**
+ * Returns an empty sorted map (immutable). This map is serializable.
+ *
+ * <p>This example illustrates the type-safe way to obtain an empty map:
+ * <pre> {@code
+ * SortedMap<String, Date> s = Collections.emptySortedMap();
+ * }</pre>
+ *
+ * @implNote Implementations of this method need not create a separate
+ * {@code SortedMap} object for each call.
+ *
+ * @param <K> the class of the map keys
+ * @param <V> the class of the map values
+ * @return an empty sorted map
+ * @since 1.8
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ public static final <K,V> SortedMap<K,V> emptySortedMap() {
+ return (SortedMap<K,V>) UnmodifiableNavigableMap.EMPTY_NAVIGABLE_MAP;
+ }
+
+ /**
+ * Returns an empty navigable map (immutable). This map is serializable.
+ *
+ * <p>This example illustrates the type-safe way to obtain an empty map:
+ * <pre> {@code
+ * NavigableMap<String, Date> s = Collections.emptyNavigableMap();
+ * }</pre>
+ *
+ * @implNote Implementations of this method need not create a separate
+ * {@code NavigableMap} object for each call.
+ *
+ * @param <K> the class of the map keys
+ * @param <V> the class of the map values
+ * @return an empty navigable map
+ * @since 1.8
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ public static final <K,V> NavigableMap<K,V> emptyNavigableMap() {
+ return (NavigableMap<K,V>) UnmodifiableNavigableMap.EMPTY_NAVIGABLE_MAP;
+ }
+
+ /**
* @serial include
*/
private static class EmptyMap<K,V>
@@ -3821,25 +4729,25 @@
@Override
public V computeIfAbsent(K key,
- Function<? super K, ? extends V> mappingFunction) {
+ Function<? super K, ? extends V> mappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfPresent(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V compute(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V merge(K key, V value,
- BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@@ -4022,15 +4930,16 @@
throw new UnsupportedOperationException();
}
@Override
- public Spliterator<E> spliterator() {
- return singletonSpliterator(element);
- }
public void replaceAll(UnaryOperator<E> operator) {
throw new UnsupportedOperationException();
}
@Override
public void sort(Comparator<? super E> c) {
}
+ @Override
+ public Spliterator<E> spliterator() {
+ return singletonSpliterator(element);
+ }
}
/**
@@ -4065,19 +4974,15 @@
v = value;
}
- public int size() {return 1;}
+ public int size() {return 1;}
+ public boolean isEmpty() {return false;}
+ public boolean containsKey(Object key) {return eq(key, k);}
+ public boolean containsValue(Object value) {return eq(value, v);}
+ public V get(Object key) {return (eq(key, k) ? v : null);}
- public boolean isEmpty() {return false;}
-
- public boolean containsKey(Object key) {return eq(key, k);}
-
- public boolean containsValue(Object value) {return eq(value, v);}
-
- public V get(Object key) {return (eq(key, k) ? v : null);}
-
- private transient Set<K> keySet = null;
- private transient Set<Map.Entry<K,V>> entrySet = null;
- private transient Collection<V> values = null;
+ private transient Set<K> keySet;
+ private transient Set<Map.Entry<K,V>> entrySet;
+ private transient Collection<V> values;
public Set<K> keySet() {
if (keySet==null)
@@ -4136,25 +5041,25 @@
@Override
public V computeIfAbsent(K key,
- Function<? super K, ? extends V> mappingFunction) {
+ Function<? super K, ? extends V> mappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfPresent(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V compute(K key,
- BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V merge(K key, V value,
- BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
+ BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
}
@@ -4753,7 +5658,6 @@
public boolean removeIf(Predicate<? super E> filter) {
return q.removeIf(filter);
}
-
@Override
public Spliterator<E> spliterator() {return q.spliterator();}
@Override
diff --git a/ojluni/src/main/java/java/util/Locale.java b/ojluni/src/main/java/java/util/Locale.java
index 5d1a775..1bbac52 100644
--- a/ojluni/src/main/java/java/util/Locale.java
+++ b/ojluni/src/main/java/java/util/Locale.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,13 +46,9 @@
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;
-import java.security.AccessController;
import java.text.MessageFormat;
-import java.util.spi.LocaleNameProvider;
import libcore.icu.ICU;
-import sun.security.action.GetPropertyAction;
-import sun.util.LocaleServiceProviderPool;
import sun.util.locale.BaseLocale;
import sun.util.locale.InternalLocaleBuilder;
import sun.util.locale.LanguageTag;
@@ -61,7 +57,6 @@
import sun.util.locale.LocaleSyntaxException;
import sun.util.locale.LocaleUtils;
import sun.util.locale.ParseStatus;
-import sun.util.locale.UnicodeLocaleExtension;
/**
* A <code>Locale</code> object represents a specific geographical, political,
@@ -82,7 +77,7 @@
* described below.
*
* <dl>
- * <dt><a name="def_language"></a><b>language</b></dt>
+ * <dt><a name="def_language"><b>language</b></a></dt>
*
* <dd>ISO 639 alpha-2 or alpha-3 language code, or registered
* language subtags up to 8 alpha letters (for future enhancements).
@@ -90,51 +85,51 @@
* alpha-2 code must be used. You can find a full list of valid
* language codes in the IANA Language Subtag Registry (search for
* "Type: language"). The language field is case insensitive, but
- * <code>Locale</code> always canonicalizes to lower case.</dd><br>
+ * <code>Locale</code> always canonicalizes to lower case.</dd>
*
* <dd>Well-formed language values have the form
* <code>[a-zA-Z]{2,8}</code>. Note that this is not the the full
* BCP47 language production, since it excludes extlang. They are
* not needed since modern three-letter language codes replace
- * them.</dd><br>
+ * them.</dd>
*
- * <dd>Example: "en" (English), "ja" (Japanese), "kok" (Konkani)</dd><br>
+ * <dd>Example: "en" (English), "ja" (Japanese), "kok" (Konkani)</dd>
*
- * <dt><a name="def_script"/></a><b>script</b></dt>
+ * <dt><a name="def_script"><b>script</b></a></dt>
*
* <dd>ISO 15924 alpha-4 script code. You can find a full list of
* valid script codes in the IANA Language Subtag Registry (search
* for "Type: script"). The script field is case insensitive, but
* <code>Locale</code> always canonicalizes to title case (the first
* letter is upper case and the rest of the letters are lower
- * case).</dd><br>
+ * case).</dd>
*
* <dd>Well-formed script values have the form
- * <code>[a-zA-Z]{4}</code></dd><br>
+ * <code>[a-zA-Z]{4}</code></dd>
*
- * <dd>Example: "Latn" (Latin), "Cyrl" (Cyrillic)</dd><br>
+ * <dd>Example: "Latn" (Latin), "Cyrl" (Cyrillic)</dd>
*
- * <dt><a name="def_region"></a><b>country (region)</b></dt>
+ * <dt><a name="def_region"><b>country (region)</b></a></dt>
*
* <dd>ISO 3166 alpha-2 country code or UN M.49 numeric-3 area code.
* You can find a full list of valid country and region codes in the
* IANA Language Subtag Registry (search for "Type: region"). The
* country (region) field is case insensitive, but
- * <code>Locale</code> always canonicalizes to upper case.</dd><br>
+ * <code>Locale</code> always canonicalizes to upper case.</dd>
*
* <dd>Well-formed country/region values have
- * the form <code>[a-zA-Z]{2} | [0-9]{3}</code></dd><br>
+ * the form <code>[a-zA-Z]{2} | [0-9]{3}</code></dd>
*
* <dd>Example: "US" (United States), "FR" (France), "029"
- * (Caribbean)</dd><br>
+ * (Caribbean)</dd>
*
- * <dt><a name="def_variant"></a><b>variant</b></dt>
+ * <dt><a name="def_variant"><b>variant</b></a></dt>
*
* <dd>Any arbitrary value used to indicate a variation of a
* <code>Locale</code>. Where there are two or more variant values
* each indicating its own semantics, these values should be ordered
* by importance, with most important first, separated by
- * underscore('_'). The variant field is case sensitive.</dd><br>
+ * underscore('_'). The variant field is case sensitive.</dd>
*
* <dd>Note: IETF BCP 47 places syntactic restrictions on variant
* subtags. Also BCP 47 subtags are strictly used to indicate
@@ -150,16 +145,16 @@
* cultural behaviors such as calendar type or number script. In
* BCP 47 this kind of information, which does not identify the
* language, is supported by extension subtags or private use
- * subtags.</dd><br>
+ * subtags.</dd>
*
* <dd>Well-formed variant values have the form <code>SUBTAG
* (('_'|'-') SUBTAG)*</code> where <code>SUBTAG =
* [0-9][0-9a-zA-Z]{3} | [0-9a-zA-Z]{5,8}</code>. (Note: BCP 47 only
- * uses hyphen ('-') as a delimiter, this is more lenient).</dd><br>
+ * uses hyphen ('-') as a delimiter, this is more lenient).</dd>
*
- * <dd>Example: "polyton" (Polytonic Greek), "POSIX"</dd><br>
+ * <dd>Example: "polyton" (Polytonic Greek), "POSIX"</dd>
*
- * <dt><a name="def_extensions"></a><b>extensions</b></dt>
+ * <dt><a name="def_extensions"><b>extensions</b></a></dt>
*
* <dd>A map from single character keys to string values, indicating
* extensions apart from language identification. The extensions in
@@ -167,14 +162,14 @@
* extension subtags and private use subtags. The extensions are
* case insensitive, but <code>Locale</code> canonicalizes all
* extension keys and values to lower case. Note that extensions
- * cannot have empty values.</dd><br>
+ * cannot have empty values.</dd>
*
* <dd>Well-formed keys are single characters from the set
* <code>[0-9a-zA-Z]</code>. Well-formed values have the form
* <code>SUBTAG ('-' SUBTAG)*</code> where for the key 'x'
* <code>SUBTAG = [0-9a-zA-Z]{1,8}</code> and for other keys
* <code>SUBTAG = [0-9a-zA-Z]{2,8}</code> (that is, 'x' allows
- * single-character subtags).</dd><br>
+ * single-character subtags).</dd>
*
* <dd>Example: key="u"/value="ca-japanese" (Japanese Calendar),
* key="x"/value="java-1-7"</dd>
@@ -187,7 +182,7 @@
* requirement (is well-formed), but does not validate the value
* itself. See {@link Builder} for details.
*
- * <h4><a name="def_locale_extension"></a>Unicode locale/language extension</h4>
+ * <h3><a name="def_locale_extension">Unicode locale/language extension</a></h3>
*
* <p>UTS#35, "Unicode Locale Data Markup Language" defines optional
* attributes and keywords to override or refine the default behavior
@@ -278,7 +273,8 @@
* you can use <code>getDisplayLanguage</code> to get the name of
* the language suitable for displaying to the user. Interestingly,
* the <code>getDisplayXXX</code> methods are themselves locale-sensitive
- * and have two versions: one that uses the default locale and one
+ * and have two versions: one that uses the default
+ * {@link Locale.Category#DISPLAY DISPLAY} locale and one
* that uses the locale specified as an argument.
*
* <p>The Java Platform provides a number of classes that perform locale-sensitive
@@ -296,7 +292,8 @@
* </pre>
* </blockquote>
* Each of these methods has two variants; one with an explicit locale
- * and one without; the latter uses the default locale:
+ * and one without; the latter uses the default
+ * {@link Locale.Category#FORMAT FORMAT} locale:
* <blockquote>
* <pre>
* NumberFormat.getInstance(myLocale)
@@ -334,7 +331,7 @@
* Clients desiring a string representation of the complete locale can
* then always rely on <code>toLanguageTag</code> for this purpose.
*
- * <h5><a name="special_cases_constructor"></a>Special cases</h5>
+ * <h5><a name="special_cases_constructor">Special cases</a></h5>
*
* <p>For compatibility reasons, two
* non-conforming locales are treated as special cases. These are
@@ -816,10 +813,6 @@
*/
public static Locale getDefault() {
// do not synchronize this method - see 4071298
- // it's OK if more than one default locale happens to be created
- if (defaultLocale == null) {
- defaultLocale = initDefault();
- }
return defaultLocale;
}
@@ -841,16 +834,23 @@
*/
public static Locale getDefault(Locale.Category category) {
// do not synchronize this method - see 4071298
- // it's OK if more than one default locale happens to be created
switch (category) {
case DISPLAY:
if (defaultDisplayLocale == null) {
- defaultDisplayLocale = initDefault(category);
+ synchronized(Locale.class) {
+ if (defaultDisplayLocale == null) {
+ defaultDisplayLocale = initDefault(category);
+ }
+ }
}
return defaultDisplayLocale;
case FORMAT:
if (defaultFormatLocale == null) {
- defaultFormatLocale = initDefault(category);
+ synchronized(Locale.class) {
+ if (defaultFormatLocale == null) {
+ defaultFormatLocale = initDefault(category);
+ }
+ }
}
return defaultFormatLocale;
default:
@@ -859,6 +859,10 @@
return getDefault();
}
+ // Android-changed BEGIN:
+ // 1.) In initDefault(), user.locale gets priority
+ // 2.) In both initDefault methods, use System.getProperty() instead
+ // of legacy AccessController / GetPropertyAction security code.
/**
* @hide visible for testing.
*/
@@ -890,13 +894,11 @@
country = System.getProperty("user.country", "");
variant = System.getProperty("user.variant", "");
}
+
return getInstance(language, script, country, variant, null);
}
private static Locale initDefault(Locale.Category category) {
- // make sure defaultLocale is initialized
- final Locale defaultLocale = getDefault();
-
return getInstance(
System.getProperty(category.languageKey, defaultLocale.getLanguage()),
System.getProperty(category.scriptKey, defaultLocale.getScript()),
@@ -904,6 +906,7 @@
System.getProperty(category.variantKey, defaultLocale.getVariant()),
null);
}
+ // Android-changed END
/**
* Sets the default locale for this instance of the Java Virtual Machine.
@@ -937,6 +940,7 @@
setDefault(Category.DISPLAY, newLocale);
setDefault(Category.FORMAT, newLocale);
defaultLocale = newLocale;
+ // Android-added: Keep ICU state in sync with java.util.
ICU.setDefaultLocale(newLocale.toLanguageTag());
}
@@ -990,18 +994,15 @@
}
}
+ // Android-changed: Removed references to LocaleServiceProvider.
/**
* Returns an array of all installed locales.
- * The returned array represents the union of locales supported
- * by the Java runtime environment and by installed
- * {@link java.util.spi.LocaleServiceProvider LocaleServiceProvider}
- * implementations. It must contain at least a <code>Locale</code>
- * instance equal to {@link java.util.Locale#US Locale.US}.
*
* @return An array of installed locales.
*/
public static Locale[] getAvailableLocales() {
- return LocaleServiceProviderPool.getAllAvailableLocales();
+ // Android-changed: Removed used of LocaleServiceProviderPool. Switched to use ICU.
+ return ICU.getAvailableLocales();
}
/**
@@ -1012,9 +1013,11 @@
* country (region), such as 3-letter numeric UN M.49 area codes.
* Therefore, the list returned by this method does not contain ALL valid
* codes that can be used to create Locales.
+ *
+ * @return An array of ISO 3166 two-letter country codes.
*/
public static String[] getISOCountries() {
- // Android-changed: Use ICU.
+ // Android-changed: Switched to use ICU.
return ICU.getISOCountries();
}
@@ -1031,9 +1034,11 @@
* 8 characters in length. Therefore, the list returned by this method does
* not contain ALL valid codes that can be used to create Locales.
* </ul>
+ *
+ * @return Am array of ISO 639 two-letter language codes.
*/
public static String[] getISOLanguages() {
- // Android-changed: Use ICU.
+ // Android-changed: Switched to use ICU.
return ICU.getISOLanguages();
}
@@ -1097,6 +1102,30 @@
}
/**
+ * Returns {@code true} if this {@code Locale} has any <a href="#def_extensions">
+ * extensions</a>.
+ *
+ * @return {@code true} if this {@code Locale} has any extensions
+ * @since 1.8
+ */
+ public boolean hasExtensions() {
+ return localeExtensions != null;
+ }
+
+ /**
+ * Returns a copy of this {@code Locale} with no <a href="#def_extensions">
+ * extensions</a>. If this {@code Locale} has no extensions, this {@code Locale}
+ * is returned.
+ *
+ * @return a copy of this {@code Locale} with no extensions, or {@code this}
+ * if {@code this} has no extensions
+ * @since 1.8
+ */
+ public Locale stripExtensions() {
+ return hasExtensions() ? Locale.getInstance(baseLocale, null) : this;
+ }
+
+ /**
* Returns the extension (or private use) value associated with
* the specified key, or null if there is no extension
* associated with the key. To be well-formed, the key must be one
@@ -1115,7 +1144,7 @@
if (!LocaleExtensions.isValidKey(key)) {
throw new IllegalArgumentException("Ill-formed extension key: " + key);
}
- return (localeExtensions == null) ? null : localeExtensions.getExtensionValue(key);
+ return hasExtensions() ? localeExtensions.getExtensionValue(key) : null;
}
/**
@@ -1128,7 +1157,7 @@
* @since 1.7
*/
public Set<Character> getExtensionKeys() {
- if (localeExtensions == null) {
+ if (!hasExtensions()) {
return Collections.emptySet();
}
return localeExtensions.getKeys();
@@ -1143,7 +1172,7 @@
* @since 1.7
*/
public Set<String> getUnicodeLocaleAttributes() {
- if (localeExtensions == null) {
+ if (!hasExtensions()) {
return Collections.emptySet();
}
return localeExtensions.getUnicodeLocaleAttributes();
@@ -1164,10 +1193,10 @@
* @since 1.7
*/
public String getUnicodeLocaleType(String key) {
- if (!UnicodeLocaleExtension.isKey(key)) {
+ if (!isUnicodeExtensionKey(key)) {
throw new IllegalArgumentException("Ill-formed Unicode locale key: " + key);
}
- return (localeExtensions == null) ? null : localeExtensions.getUnicodeLocaleType(key);
+ return hasExtensions() ? localeExtensions.getUnicodeLocaleType(key) : null;
}
/**
@@ -1208,7 +1237,7 @@
* Returns a string representation of this <code>Locale</code>
* object, consisting of language, country, variant, script,
* and extensions as below:
- * <p><blockquote>
+ * <blockquote>
* language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions
* </blockquote>
*
@@ -1232,15 +1261,15 @@
* fields only. To represent a Locale as a String for interchange purposes, use
* {@link #toLanguageTag}.
*
- * <p>Examples: <ul><tt>
- * <li>en
- * <li>de_DE
- * <li>_GB
- * <li>en_US_WIN
- * <li>de__POSIX
- * <li>zh_CN_#Hans
- * <li>zh_TW_#Hant-x-java
- * <li>th_TH_TH_#u-nu-thai</tt></ul>
+ * <p>Examples: <ul>
+ * <li><tt>en</tt></li>
+ * <li><tt>de_DE</tt></li>
+ * <li><tt>_GB</tt></li>
+ * <li><tt>en_US_WIN</tt></li>
+ * <li><tt>de__POSIX</tt></li>
+ * <li><tt>zh_CN_#Hans</tt></li>
+ * <li><tt>zh_TW_#Hant-x-java</tt></li>
+ * <li><tt>th_TH_TH_#u-nu-thai</tt></li></ul>
*
* @return A string representation of the Locale, for debugging.
* @see #getDisplayName
@@ -1348,6 +1377,10 @@
* @since 1.7
*/
public String toLanguageTag() {
+ if (languageTag != null) {
+ return languageTag;
+ }
+
LanguageTag tag = LanguageTag.parseLocale(baseLocale, localeExtensions);
StringBuilder buf = new StringBuilder();
@@ -1391,7 +1424,13 @@
buf.append(subtag);
}
- return buf.toString();
+ String langTag = buf.toString();
+ synchronized (this) {
+ if (languageTag == null) {
+ languageTag = langTag;
+ }
+ }
+ return languageTag;
}
/**
@@ -1449,7 +1488,7 @@
* // returns "ja-JP-u-ca-japanese-x-lvariant-JP"
* Locale.forLanguageTag("th-TH-x-lvariant-TH").toLanguageTag();
* // returns "th-TH-u-nu-thai-x-lvariant-TH"
- * <pre></ul>
+ * </pre></ul>
*
* <p>This implements the 'Language-Tag' production of BCP47, and
* so supports grandfathered (regular and irregular) as well as
@@ -1460,7 +1499,7 @@
*
* <p>Grandfathered tags with canonical replacements are as follows:
*
- * <table>
+ * <table summary="Grandfathered tags with canonical replacements">
* <tbody align="center">
* <tr><th>grandfathered tag</th><th> </th><th>modern replacement</th></tr>
* <tr><td>art-lojban</td><td> </td><td>jbo</td></tr>
@@ -1489,7 +1528,7 @@
* <p>Grandfathered tags with no modern replacement will be
* converted as follows:
*
- * <table>
+ * <table summary="Grandfathered tags with no modern replacement">
* <tbody align="center">
* <tr><th>grandfathered tag</th><th> </th><th>converts to</th></tr>
* <tr><td>cel-gaulish</td><td> </td><td>xtg-x-cel-gaulish</td></tr>
@@ -1542,21 +1581,26 @@
* three-letter language abbreviation is not available for this locale.
*/
public String getISO3Language() throws MissingResourceException {
- // Android-changed: Use ICU.getIso3Language. Also return "" for empty languages
- // for the sake of backwards compatibility.
String lang = baseLocale.getLanguage();
if (lang.length() == 3) {
return lang;
- } else if (lang.isEmpty()) {
+ }
+ // Android-added BEGIN
+ // return "" for empty languages for the sake of backwards compatibility.
+ else if (lang.isEmpty()) {
return "";
}
+ // Android-added END
+ // Android-changed BEGIN: Use ICU.
+ // String language3 = getISO3Code(lang, LocaleISOData.isoLanguageTable);
+ // if (language3 == null) {
String language3 = ICU.getISO3Language(lang);
if (!lang.isEmpty() && language3.isEmpty()) {
+ // Android-changed END
throw new MissingResourceException("Couldn't find 3-letter language code for "
+ lang, "FormatData_" + toString(), "ShortLanguage");
}
-
return language3;
}
@@ -1574,7 +1618,7 @@
* three-letter country abbreviation is not available for this locale.
*/
public String getISO3Country() throws MissingResourceException {
- // Android changed: Use.getIso3Country. Also return "" for missing regions.
+ // Android-changed BEGIN: Use ICU. Also return "" for missing regions.
final String region = baseLocale.getRegion();
// Note that this will return an UN.M49 region code
if (region.length() == 3) {
@@ -1589,25 +1633,34 @@
throw new MissingResourceException("Couldn't find 3-letter country code for "
+ baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry");
}
+ // Android-changed END
return country3;
}
/**
* Returns a name for the locale's language that is appropriate for display to the
* user.
- * If possible, the name returned will be localized for the default locale.
- * For example, if the locale is fr_FR and the default locale
+ * If possible, the name returned will be localized for the default
+ * {@link Locale.Category#DISPLAY DISPLAY} locale.
+ * For example, if the locale is fr_FR and the default
+ * {@link Locale.Category#DISPLAY DISPLAY} locale
* is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and
- * the default locale is fr_FR, getDisplayLanguage() will return "anglais".
- * If the name returned cannot be localized for the default locale,
+ * the default {@link Locale.Category#DISPLAY DISPLAY} locale is fr_FR,
+ * getDisplayLanguage() will return "anglais".
+ * If the name returned cannot be localized for the default
+ * {@link Locale.Category#DISPLAY DISPLAY} locale,
* (say, we don't have a Japanese name for Croatian),
* this function falls back on the English name, and uses the ISO code as a last-resort
* value. If the locale doesn't specify a language, this function returns the empty string.
+ *
+ * @return The name of the display language.
*/
public final String getDisplayLanguage() {
return getDisplayLanguage(getDefault(Category.DISPLAY));
}
+ // Android-changed BEGIN: Use ICU; documentation; backwards compatibility hacks;
+ // added private helper methods.
/**
* Returns the name of this locale's language, localized to {@code locale}.
* If the language name is unknown, the language code is returned.
@@ -1672,56 +1725,73 @@
return true;
}
+ // Android-changed END
/**
* Returns a name for the the locale's script that is appropriate for display to
- * the user. If possible, the name will be localized for the default locale. Returns
+ * the user. If possible, the name will be localized for the default
+ * {@link Locale.Category#DISPLAY DISPLAY} locale. Returns
* the empty string if this locale doesn't specify a script code.
*
- * @return the display name of the script code for the current default locale
+ * @return the display name of the script code for the current default
+ * {@link Locale.Category#DISPLAY DISPLAY} locale
* @since 1.7
*/
public String getDisplayScript() {
- return getDisplayScript(getDefault());
+ return getDisplayScript(getDefault(Category.DISPLAY));
}
/**
- * Returns the name of this locale's script code, localized to {@link Locale}. If the
- * script code is unknown, the return value of this method is the same as that of
- * {@link #getScript()}.
+ * Returns a name for the locale's script that is appropriate
+ * for display to the user. If possible, the name will be
+ * localized for the given locale. Returns the empty string if
+ * this locale doesn't specify a script code.
*
+ * @param inLocale The locale for which to retrieve the display script.
+ * @return the display name of the script code for the current default
+ * {@link Locale.Category#DISPLAY DISPLAY} locale
+ * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
* @since 1.7
*/
- public String getDisplayScript(Locale locale) {
+ public String getDisplayScript(Locale inLocale) {
+ // Android-changed BEGIN: Use ICU.
String scriptCode = baseLocale.getScript();
if (scriptCode.isEmpty()) {
return "";
}
- String result = ICU.getDisplayScript(this, locale);
+ String result = ICU.getDisplayScript(this, inLocale);
if (result == null) { // TODO: do we need to do this, or does ICU do it for us?
- result = ICU.getDisplayScript(this, Locale.getDefault());
+ result = ICU.getDisplayScript(this, Locale.getDefault(Category.DISPLAY));
}
return result;
-
+ // Android-changed END
}
/**
* Returns a name for the locale's country that is appropriate for display to the
* user.
- * If possible, the name returned will be localized for the default locale.
- * For example, if the locale is fr_FR and the default locale
+ * If possible, the name returned will be localized for the default
+ * {@link Locale.Category#DISPLAY DISPLAY} locale.
+ * For example, if the locale is fr_FR and the default
+ * {@link Locale.Category#DISPLAY DISPLAY} locale
* is en_US, getDisplayCountry() will return "France"; if the locale is en_US and
- * the default locale is fr_FR, getDisplayCountry() will return "Etats-Unis".
- * If the name returned cannot be localized for the default locale,
+ * the default {@link Locale.Category#DISPLAY DISPLAY} locale is fr_FR,
+ * getDisplayCountry() will return "Etats-Unis".
+ * If the name returned cannot be localized for the default
+ * {@link Locale.Category#DISPLAY DISPLAY} locale,
* (say, we don't have a Japanese name for Croatia),
* this function falls back on the English name, and uses the ISO code as a last-resort
* value. If the locale doesn't specify a country, this function returns the empty string.
+ *
+ * @return The name of the country appropriate to the locale.
*/
public final String getDisplayCountry() {
return getDisplayCountry(getDefault(Category.DISPLAY));
}
+
+ // Android-changed BEGIN: Use ICU; documentation; added private helper methods.
/**
* Returns the name of this locale's country, localized to {@code locale}.
* Returns the empty string if this locale does not correspond to a specific
@@ -1798,24 +1868,31 @@
return true;
}
+ // Android-changed END
/**
* Returns a name for the locale's variant code that is appropriate for display to the
- * user. If possible, the name will be localized for the default locale. If the locale
+ * user. If possible, the name will be localized for the default
+ * {@link Locale.Category#DISPLAY DISPLAY} locale. If the locale
* doesn't specify a variant code, this function returns the empty string.
+ *
+ * @return The name of the display variant code appropriate to the locale.
*/
public final String getDisplayVariant() {
return getDisplayVariant(getDefault(Category.DISPLAY));
}
/**
- * Returns the full variant name in the specified {@code Locale} for the variant code
- * of this {@code Locale}. If there is no matching variant name, the variant code is
- * returned.
+ * Returns a name for the locale's variant code that is appropriate for display to the
+ * user. If possible, the name will be localized for inLocale. If the locale
+ * doesn't specify a variant code, this function returns the empty string.
*
- * @since 1.7
+ * @param inLocale The locale for which to retrieve the display variant code.
+ * @return The name of the display variant code appropriate to the given locale.
+ * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
*/
- public String getDisplayVariant(Locale locale) {
+ // Android-changed BEGIN: Use ICU; added private helper methods.
+ public String getDisplayVariant(Locale inLocale) {
String variantCode = baseLocale.getVariant();
if (variantCode.isEmpty()) {
return "";
@@ -1827,7 +1904,7 @@
return variantCode;
}
- String result = ICU.getDisplayVariant(this, locale);
+ String result = ICU.getDisplayVariant(this, inLocale);
if (result == null) { // TODO: do we need to do this, or does ICU do it for us?
result = ICU.getDisplayVariant(this, Locale.getDefault());
}
@@ -1878,6 +1955,7 @@
return false;
}
+ // Android-changed END
/**
* Returns a name for the locale that is appropriate for display to the
@@ -1893,13 +1971,16 @@
* country<br>
* </blockquote>
* depending on which fields are specified in the locale. If the
- * language, sacript, country, and variant fields are all empty,
+ * language, script, country, and variant fields are all empty,
* this function returns the empty string.
+ *
+ * @return The name of the locale appropriate to display.
*/
public final String getDisplayName() {
return getDisplayName(getDefault(Category.DISPLAY));
}
+ // Android-changed BEGIN: Use ICU.
/**
* Returns this locale's language name, country name, and variant, localized
* to {@code locale}. The exact output form depends on whether this locale
@@ -1961,17 +2042,19 @@
}
return buffer.toString();
}
+ // Android-changed END
/**
* Overrides Cloneable.
*/
+ @Override
public Object clone()
{
try {
Locale that = (Locale)super.clone();
return that;
} catch (CloneNotSupportedException e) {
- throw new InternalError();
+ throw new InternalError(e);
}
}
@@ -2028,9 +2111,11 @@
*/
private transient volatile int hashCodeValue = 0;
- private static Locale defaultLocale = null;
- private static Locale defaultDisplayLocale = null;
- private static Locale defaultFormatLocale = null;
+ private volatile static Locale defaultLocale = initDefault();
+ private volatile static Locale defaultDisplayLocale = null;
+ private volatile static Locale defaultFormatLocale = null;
+
+ private transient volatile String languageTag;
/**
* Format a list using given pattern strings.
@@ -2047,9 +2132,11 @@
// If we have no list patterns, compose the list in a simple,
// non-localized way.
if (listPattern == null || listCompositionPattern == null) {
- StringBuffer result = new StringBuffer();
- for (int i=0; i<stringList.length; ++i) {
- if (i>0) result.append(',');
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < stringList.length; ++i) {
+ if (i > 0) {
+ result.append(',');
+ }
result.append(stringList[i]);
}
return result.toString();
@@ -2096,6 +2183,13 @@
return composeList(format, newList);
}
+ // Duplicate of sun.util.locale.UnicodeLocaleExtension.isKey in order to
+ // avoid its class loading.
+ private static boolean isUnicodeExtensionKey(String s) {
+ // 2alphanum
+ return (s.length() == 2) && LocaleUtils.isAlphaNumericString(s);
+ }
+
/**
* @serialField language String
* language subtag in lower case. (See <a href="java/util/Locale.html#getLanguage()">getLanguage()</a>)
@@ -2157,6 +2251,8 @@
String variant = (String)fields.get("variant", "");
String extStr = (String)fields.get("extensions", "");
baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
+ // Android-changed: Handle null for backwards compatible deserialization. http://b/26387905
+ // was: if (extStr.length() > 0) {
if (extStr != null && extStr.length() > 0) {
try {
InternalLocaleBuilder bldr = new InternalLocaleBuilder();
@@ -2177,7 +2273,7 @@
* are exactly "ja", "JP", "JP" or "th", "TH", "TH" and script/extensions
* fields are empty, this method supplies <code>UNICODE_LOCALE_EXTENSION</code>
* "ca"/"japanese" (calendar type is "japanese") or "nu"/"thai" (number script
- * type is "thai"). See <a href="Locale.html#special_cases_constructor"/>Special Cases</a>
+ * type is "thai"). See <a href="Locale.html#special_cases_constructor">Special Cases</a>
* for more information.
*
* @return an instance of <code>Locale</code> equivalent to
@@ -2230,9 +2326,9 @@
return extensions;
}
- /**
- * @hide for internal use only.
- */
+ // Android-removed: Drop nested private class LocaleNameGetter.
+ // Android-added BEGIN: Add adjustLanguageCode(); for internal use only.
+ /** @hide for internal use only. */
public static String adjustLanguageCode(String languageCode) {
String adjusted = languageCode.toLowerCase(Locale.US);
// Map new language codes to the obsolete language
@@ -2247,6 +2343,7 @@
return adjusted;
}
+ // Android-added END
/**
* Enum for locale categories. These locale categories are used to get/set
@@ -2584,9 +2681,11 @@
* @see #setExtension(char, String)
*/
public Builder removeUnicodeLocaleAttribute(String attribute) {
+ // Android-added BEGIN
if (attribute == null) {
throw new NullPointerException("attribute == null");
}
+ // Android-added END
try {
localeBuilder.removeUnicodeLocaleAttribute(attribute);
diff --git a/ojluni/src/main/java/java/util/ResourceBundle.java b/ojluni/src/main/java/java/util/ResourceBundle.java
index bf73b03..886ffc1 100644
--- a/ojluni/src/main/java/java/util/ResourceBundle.java
+++ b/ojluni/src/main/java/java/util/ResourceBundle.java
@@ -58,7 +58,6 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.jar.JarEntry;
-import java.util.spi.ResourceBundleControlProvider;
import dalvik.system.VMStack;
import sun.reflect.CallerSensitive;
@@ -66,6 +65,7 @@
import sun.util.locale.LocaleObjectCache;
+// Android-changed: Removed reference to ResourceBundleControlProvider.
/**
*
* Resource bundles contain locale-specific objects. When your program needs a
@@ -205,17 +205,6 @@
* {@link #getBundle(String, Locale, ClassLoader, Control) getBundle}
* factory method for details.
*
- * <p><a name="modify_default_behavior">For the {@code getBundle} factory</a>
- * methods that take no {@link Control} instance, their <a
- * href="#default_behavior"> default behavior</a> of resource bundle loading
- * can be modified with <em>installed</em> {@link
- * ResourceBundleControlProvider} implementations. Any installed providers are
- * detected at the {@code ResourceBundle} class loading time. If any of the
- * providers provides a {@link Control} for the given base name, that {@link
- * Control} will be used instead of the default {@link Control}. If there is
- * more than one service provider installed for supporting the same base name,
- * the first one returned from {@link ServiceLoader} will be used.
- *
* <h3>Cache Management</h3>
*
* Resource bundle instances created by the <code>getBundle</code> factory
@@ -371,6 +360,7 @@
*/
private volatile Set<String> keySet;
+ /* Android-changed: Removed used of ResourceBundleControlProvider.
private static final List<ResourceBundleControlProvider> providers;
static {
@@ -385,6 +375,7 @@
}
providers = list;
}
+ */
/**
* Sole constructor. (For invocation by subclass constructors, typically
@@ -906,19 +897,14 @@
control);
}
+ // Android-changed: Removed references to ResourceBundleControlProvider.
/**
* Gets a resource bundle using the specified base name, locale, and class
* loader.
*
* <p>This method behaves the same as calling
* {@link #getBundle(String, Locale, ClassLoader, Control)} passing a
- * default instance of {@link Control} unless another {@link Control} is
- * provided with the {@link ResourceBundleControlProvider} SPI. Refer to the
- * description of <a href="#modify_default_behavior">modifying the default
- * behavior</a>.
- *
- * <p><a name="default_behavior">The following describes the default
- * behavior</a>.
+ * default instance of {@link Control}.
*
* <p><code>getBundle</code> uses the base name, the specified locale, and
* the default locale (obtained from {@link java.util.Locale#getDefault()
@@ -1314,14 +1300,7 @@
}
private static Control getDefaultControl(String baseName) {
- if (providers != null) {
- for (ResourceBundleControlProvider provider : providers) {
- Control control = provider.getControl(baseName);
- if (control != null) {
- return control;
- }
- }
- }
+ // Android-changed: Removed used of ResourceBundleControlProvider.
return Control.INSTANCE;
}
diff --git a/ojluni/src/main/java/java/util/spi/CurrencyNameProvider.java b/ojluni/src/main/java/java/util/spi/CurrencyNameProvider.java
deleted file mode 100644
index a0694bc..0000000
--- a/ojluni/src/main/java/java/util/spi/CurrencyNameProvider.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.spi;
-
-import java.util.Arrays;
-import java.util.Currency;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * An abstract class for service providers that
- * provide localized currency symbols and display names for the
- * {@link java.util.Currency Currency} class.
- * Note that currency symbols are considered names when determining
- * behaviors described in the
- * {@link java.util.spi.LocaleServiceProvider LocaleServiceProvider}
- * specification.
- *
- * @since 1.6
- */
-public abstract class CurrencyNameProvider extends LocaleServiceProvider {
-
- /**
- * Sole constructor. (For invocation by subclass constructors, typically
- * implicit.)
- */
- protected CurrencyNameProvider() {
- }
-
- /**
- * Gets the symbol of the given currency code for the specified locale.
- * For example, for "USD" (US Dollar), the symbol is "$" if the specified
- * locale is the US, while for other locales it may be "US$". If no
- * symbol can be determined, null should be returned.
- *
- * @param currencyCode the ISO 4217 currency code, which
- * consists of three upper-case letters between 'A' (U+0041) and
- * 'Z' (U+005A)
- * @param locale the desired locale
- * @return the symbol of the given currency code for the specified locale, or null if
- * the symbol is not available for the locale
- * @exception NullPointerException if <code>currencyCode</code> or
- * <code>locale</code> is null
- * @exception IllegalArgumentException if <code>currencyCode</code> is not in
- * the form of three upper-case letters, or <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @see java.util.Currency#getSymbol(java.util.Locale)
- */
- public abstract String getSymbol(String currencyCode, Locale locale);
-
- /**
- * Returns a name for the currency that is appropriate for display to the
- * user. The default implementation returns null.
- *
- * @param currencyCode the ISO 4217 currency code, which
- * consists of three upper-case letters between 'A' (U+0041) and
- * 'Z' (U+005A)
- * @param locale the desired locale
- * @return the name for the currency that is appropriate for display to the
- * user, or null if the name is not available for the locale
- * @exception IllegalArgumentException if <code>currencyCode</code> is not in
- * the form of three upper-case letters, or <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @exception NullPointerException if <code>currencyCode</code> or
- * <code>locale</code> is <code>null</code>
- * @since 1.7
- */
- public String getDisplayName(String currencyCode, Locale locale) {
- if (currencyCode == null || locale == null) {
- throw new NullPointerException();
- }
-
- // Check whether the currencyCode is valid
- char[] charray = currencyCode.toCharArray();
- if (charray.length != 3) {
- throw new IllegalArgumentException("The currencyCode is not in the form of three upper-case letters.");
- }
- for (char c : charray) {
- if (c < 'A' || c > 'Z') {
- throw new IllegalArgumentException("The currencyCode is not in the form of three upper-case letters.");
- }
- }
-
- // Check whether the locale is valid
- List<Locale> avail = Arrays.asList(getAvailableLocales());
- if (!avail.contains(locale)) {
- throw new IllegalArgumentException("The locale is not available");
- }
-
- return null;
- }
-}
diff --git a/ojluni/src/main/java/java/util/spi/LocaleNameProvider.java b/ojluni/src/main/java/java/util/spi/LocaleNameProvider.java
deleted file mode 100644
index 499aa0d..0000000
--- a/ojluni/src/main/java/java/util/spi/LocaleNameProvider.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.spi;
-
-import java.util.Locale;
-
-/**
- * An abstract class for service providers that
- * provide localized names for the
- * {@link java.util.Locale Locale} class.
- *
- * @since 1.6
- */
-public abstract class LocaleNameProvider extends LocaleServiceProvider {
-
- /**
- * Sole constructor. (For invocation by subclass constructors, typically
- * implicit.)
- */
- protected LocaleNameProvider() {
- }
-
- /**
- * Returns a localized name for the given <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
- * IETF BCP47</a> language code and the given locale that is appropriate for
- * display to the user.
- * For example, if <code>languageCode</code> is "fr" and <code>locale</code>
- * is en_US, getDisplayLanguage() will return "French"; if <code>languageCode</code>
- * is "en" and <code>locale</code> is fr_FR, getDisplayLanguage() will return "anglais".
- * If the name returned cannot be localized according to <code>locale</code>,
- * (say, the provider does not have a Japanese name for Croatian),
- * this method returns null.
- * @param languageCode the language code string in the form of two to eight
- * lower-case letters between 'a' (U+0061) and 'z' (U+007A)
- * @param locale the desired locale
- * @return the name of the given language code for the specified locale, or null if it's not
- * available.
- * @exception NullPointerException if <code>languageCode</code> or <code>locale</code> is null
- * @exception IllegalArgumentException if <code>languageCode</code> is not in the form of
- * two or three lower-case letters, or <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @see java.util.Locale#getDisplayLanguage(java.util.Locale)
- */
- public abstract String getDisplayLanguage(String languageCode, Locale locale);
-
- /**
- * Returns a localized name for the given <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
- * IETF BCP47</a> script code and the given locale that is appropriate for
- * display to the user.
- * For example, if <code>scriptCode</code> is "Latn" and <code>locale</code>
- * is en_US, getDisplayScript() will return "Latin"; if <code>scriptCode</code>
- * is "Cyrl" and <code>locale</code> is fr_FR, getDisplayScript() will return "cyrillique".
- * If the name returned cannot be localized according to <code>locale</code>,
- * (say, the provider does not have a Japanese name for Cyrillic),
- * this method returns null. The default implementation returns null.
- * @param scriptCode the four letter script code string in the form of title-case
- * letters (the first letter is upper-case character between 'A' (U+0041) and
- * 'Z' (U+005A) followed by three lower-case character between 'a' (U+0061)
- * and 'z' (U+007A)).
- * @param locale the desired locale
- * @return the name of the given script code for the specified locale, or null if it's not
- * available.
- * @exception NullPointerException if <code>scriptCode</code> or <code>locale</code> is null
- * @exception IllegalArgumentException if <code>scriptCode</code> is not in the form of
- * four title case letters, or <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @see java.util.Locale#getDisplayScript(java.util.Locale)
- * @since 1.7
- */
- public String getDisplayScript(String scriptCode, Locale locale) {
- return null;
- }
-
- /**
- * Returns a localized name for the given <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
- * IETF BCP47</a> region code (either ISO 3166 country code or UN M.49 area
- * codes) and the given locale that is appropriate for display to the user.
- * For example, if <code>countryCode</code> is "FR" and <code>locale</code>
- * is en_US, getDisplayCountry() will return "France"; if <code>countryCode</code>
- * is "US" and <code>locale</code> is fr_FR, getDisplayCountry() will return "Etats-Unis".
- * If the name returned cannot be localized according to <code>locale</code>,
- * (say, the provider does not have a Japanese name for Croatia),
- * this method returns null.
- * @param countryCode the country(region) code string in the form of two
- * upper-case letters between 'A' (U+0041) and 'Z' (U+005A) or the UN M.49 area code
- * in the form of three digit letters between '0' (U+0030) and '9' (U+0039).
- * @param locale the desired locale
- * @return the name of the given country code for the specified locale, or null if it's not
- * available.
- * @exception NullPointerException if <code>countryCode</code> or <code>locale</code> is null
- * @exception IllegalArgumentException if <code>countryCode</code> is not in the form of
- * two upper-case letters or three digit letters, or <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @see java.util.Locale#getDisplayCountry(java.util.Locale)
- */
- public abstract String getDisplayCountry(String countryCode, Locale locale);
-
- /**
- * Returns a localized name for the given variant code and the given locale that
- * is appropriate for display to the user.
- * If the name returned cannot be localized according to <code>locale</code>,
- * this method returns null.
- * @param variant the variant string
- * @param locale the desired locale
- * @return the name of the given variant string for the specified locale, or null if it's not
- * available.
- * @exception NullPointerException if <code>variant</code> or <code>locale</code> is null
- * @exception IllegalArgumentException if <code>locale</code> isn't
- * one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @see java.util.Locale#getDisplayVariant(java.util.Locale)
- */
- public abstract String getDisplayVariant(String variant, Locale locale);
-}
diff --git a/ojluni/src/main/java/java/util/spi/LocaleServiceProvider.java b/ojluni/src/main/java/java/util/spi/LocaleServiceProvider.java
deleted file mode 100644
index f2d89c7..0000000
--- a/ojluni/src/main/java/java/util/spi/LocaleServiceProvider.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.spi;
-
-import java.util.Locale;
-
-/**
- * <p>
- * This is the super class of all the locale sensitive service provider
- * interfaces (SPIs).
- * <p>
- * Locale sensitive service provider interfaces are interfaces that
- * correspond to locale sensitive classes in the <code>java.text</code>
- * and <code>java.util</code> packages. The interfaces enable the
- * construction of locale sensitive objects and the retrieval of
- * localized names for these packages. Locale sensitive factory methods
- * and methods for name retrieval in the <code>java.text</code> and
- * <code>java.util</code> packages use implementations of the provider
- * interfaces to offer support for locales beyond the set of locales
- * supported by the Java runtime environment itself.
- * <p>
- * <h4>Packaging of Locale Sensitive Service Provider Implementations</h4>
- * Implementations of these locale sensitive services are packaged using the
- * <a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/extensions/index.html">Java Extension Mechanism</a>
- * as installed extensions. A provider identifies itself with a
- * provider-configuration file in the resource directory META-INF/services,
- * using the fully qualified provider interface class name as the file name.
- * The file should contain a list of fully-qualified concrete provider class names,
- * one per line. A line is terminated by any one of a line feed ('\n'), a carriage
- * return ('\r'), or a carriage return followed immediately by a line feed. Space
- * and tab characters surrounding each name, as well as blank lines, are ignored.
- * The comment character is '#' ('\u0023'); on each line all characters following
- * the first comment character are ignored. The file must be encoded in UTF-8.
- * <p>
- * If a particular concrete provider class is named in more than one configuration
- * file, or is named in the same configuration file more than once, then the
- * duplicates will be ignored. The configuration file naming a particular provider
- * need not be in the same jar file or other distribution unit as the provider itself.
- * The provider must be accessible from the same class loader that was initially
- * queried to locate the configuration file; this is not necessarily the class loader
- * that loaded the file.
- * <p>
- * For example, an implementation of the
- * {@link java.text.spi.DateFormatProvider DateFormatProvider} class should
- * take the form of a jar file which contains the file:
- * <pre>
- * META-INF/services/java.text.spi.DateFormatProvider
- * </pre>
- * And the file <code>java.text.spi.DateFormatProvider</code> should have
- * a line such as:
- * <pre>
- * <code>com.foo.DateFormatProviderImpl</code>
- * </pre>
- * which is the fully qualified class name of the class implementing
- * <code>DateFormatProvider</code>.
- * <h4>Invocation of Locale Sensitive Services</h4>
- * <p>
- * Locale sensitive factory methods and methods for name retrieval in the
- * <code>java.text</code> and <code>java.util</code> packages invoke
- * service provider methods when needed to support the requested locale.
- * The methods first check whether the Java runtime environment itself
- * supports the requested locale, and use its support if available.
- * Otherwise, they call the <code>getAvailableLocales()</code> methods of
- * installed providers for the appropriate interface to find one that
- * supports the requested locale. If such a provider is found, its other
- * methods are called to obtain the requested object or name. When checking
- * whether a locale is supported, the locale's extensions are ignored.
- * If neither the Java runtime environment itself nor an installed provider
- * supports the requested locale, the methods go through a list of candidate
- * locales and repeat the availability check for each until a match is found.
- * The algorithm used for creating a list of candidate locales is same as
- * the one used by <code>ResourceBunlde</code> by default (see
- * {@link java.util.ResourceBundle.Control#getCandidateLocales getCandidateLocales}
- * for the details). Even if a locale is resolved from the candidate list,
- * methods that return requested objects or names are invoked with the original
- * requested locale including extensions. The Java runtime environment must
- * support the root locale for all locale sensitive services in order to
- * guarantee that this process terminates.
- * <p>
- * Providers of names (but not providers of other objects) are allowed to
- * return null for some name requests even for locales that they claim to
- * support by including them in their return value for
- * <code>getAvailableLocales</code>. Similarly, the Java runtime
- * environment itself may not have all names for all locales that it
- * supports. This is because the sets of objects for which names are
- * requested can be large and vary over time, so that it's not always
- * feasible to cover them completely. If the Java runtime environment or a
- * provider returns null instead of a name, the lookup will proceed as
- * described above as if the locale was not supported.
- *
- * @since 1.6
- */
-public abstract class LocaleServiceProvider {
-
- /**
- * Sole constructor. (For invocation by subclass constructors, typically
- * implicit.)
- */
- protected LocaleServiceProvider() {
- }
-
- /**
- * Returns an array of all locales for which this locale service provider
- * can provide localized objects or names.
- * <p>
- * <b>Note:</b> Extensions in a <code>Locale</code> are ignored during
- * service provider lookup. So the array returned by this method should
- * not include two or more <code>Locale</code> objects only differing in
- * their extensions.
- *
- * @return An array of all locales for which this locale service provider
- * can provide localized objects or names.
- */
- public abstract Locale[] getAvailableLocales();
-}
diff --git a/ojluni/src/main/java/java/util/spi/ResourceBundleControlProvider.java b/ojluni/src/main/java/java/util/spi/ResourceBundleControlProvider.java
deleted file mode 100644
index e731f0f..0000000
--- a/ojluni/src/main/java/java/util/spi/ResourceBundleControlProvider.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.spi;
-
-import java.util.ResourceBundle;
-
-/**
- * An interface for service providers that provide implementations of {@link
- * java.util.ResourceBundle.Control}. The <a
- * href="../ResourceBundle.html#default_behavior">default resource bundle loading
- * behavior</a> of the {@code ResourceBundle.getBundle} factory methods that take
- * no {@link java.util.ResourceBundle.Control} instance can be modified with {@code
- * ResourceBundleControlProvider} implementations.
- *
- * <p>Provider implementations must be packaged using the <a
- * href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/extensions/index.html">Java Extension
- * Mechanism</a> as installed extensions. Refer to {@link java.util.ServiceLoader}
- * for the extension packaging. Any installed {@code
- * ResourceBundleControlProvider} implementations are loaded using {@link
- * java.util.ServiceLoader} at the {@code ResourceBundle} class loading time.
- *
- * @author Masayoshi Okutsu
- * @since 1.8
- * @see ResourceBundle#getBundle(String, java.util.Locale, ClassLoader, ResourceBundle.Control)
- * ResourceBundle.getBundle
- * @see java.util.ServiceLoader#loadInstalled(Class)
- */
-public interface ResourceBundleControlProvider {
- /**
- * Returns a {@code ResourceBundle.Control} instance that is used
- * to handle resource bundle loading for the given {@code
- * baseName}. This method must return {@code null} if the given
- * {@code baseName} isn't handled by this provider.
- *
- * @param baseName the base name of the resource bundle
- * @return a {@code ResourceBundle.Control} instance,
- * or {@code null} if the given {@code baseName} is not
- * applicable to this provider.
- * @throws NullPointerException if {@code baseName} is {@code null}
- */
- public ResourceBundle.Control getControl(String baseName);
-}
diff --git a/ojluni/src/main/java/java/util/spi/TimeZoneNameProvider.java b/ojluni/src/main/java/java/util/spi/TimeZoneNameProvider.java
deleted file mode 100644
index 730b507..0000000
--- a/ojluni/src/main/java/java/util/spi/TimeZoneNameProvider.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.util.spi;
-
-import java.util.Locale;
-
-/**
- * An abstract class for service providers that
- * provide localized time zone names for the
- * {@link java.util.TimeZone TimeZone} class.
- * The localized time zone names available from the implementations of
- * this class are also the source for the
- * {@link java.text.DateFormatSymbols#getZoneStrings()
- * DateFormatSymbols.getZoneStrings()} method.
- *
- * @since 1.6
- */
-public abstract class TimeZoneNameProvider extends LocaleServiceProvider {
-
- /**
- * Sole constructor. (For invocation by subclass constructors, typically
- * implicit.)
- */
- protected TimeZoneNameProvider() {
- }
-
- /**
- * Returns a name for the given time zone ID that's suitable for
- * presentation to the user in the specified locale. The given time
- * zone ID is "GMT" or one of the names defined using "Zone" entries
- * in the "tz database", a public domain time zone database at
- * <a href="ftp://elsie.nci.nih.gov/pub/">ftp://elsie.nci.nih.gov/pub/</a>.
- * The data of this database is contained in a file whose name starts with
- * "tzdata", and the specification of the data format is part of the zic.8
- * man page, which is contained in a file whose name starts with "tzcode".
- * <p>
- * If <code>daylight</code> is true, the method should return a name
- * appropriate for daylight saving time even if the specified time zone
- * has not observed daylight saving time in the past.
- *
- * @param ID a time zone ID string
- * @param daylight if true, return the daylight saving name.
- * @param style either {@link java.util.TimeZone#LONG TimeZone.LONG} or
- * {@link java.util.TimeZone#SHORT TimeZone.SHORT}
- * @param locale the desired locale
- * @return the human-readable name of the given time zone in the
- * given locale, or null if it's not available.
- * @exception IllegalArgumentException if <code>style</code> is invalid,
- * or <code>locale</code> isn't one of the locales returned from
- * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
- * getAvailableLocales()}.
- * @exception NullPointerException if <code>ID</code> or <code>locale</code>
- * is null
- * @see java.util.TimeZone#getDisplayName(boolean, int, java.util.Locale)
- */
- public abstract String getDisplayName(String ID, boolean daylight, int style, Locale locale);
-}
diff --git a/ojluni/src/main/java/java/util/spi/package.html b/ojluni/src/main/java/java/util/spi/package.html
deleted file mode 100644
index ce49fb2..0000000
--- a/ojluni/src/main/java/java/util/spi/package.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head>
-<!--
-Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
-DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
-This code is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 2 only, as
-published by the Free Software Foundation. Oracle designates this
-particular file as subject to the "Classpath" exception as provided
-by Oracle in the LICENSE file that accompanied this code.
-
-This code is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-version 2 for more details (a copy is included in the LICENSE file that
-accompanied this code).
-
-You should have received a copy of the GNU General Public License version
-2 along with this work; if not, write to the Free Software Foundation,
-Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-or visit www.oracle.com if you need additional information or have any
-questions.
--->
-
-</head>
-<body bgcolor="white">
-Service provider classes for the classes in the java.util package.
-<!--
-<h2>Package Specification</h2>
-
-##### FILL IN ANY SPECS NEEDED BY JAVA COMPATIBILITY KIT #####
-<ul>
- <li><a href="">##### REFER TO ANY FRAMEMAKER SPECIFICATION HERE #####</a>
-</ul>
-
-<h2>Related Documentation</h2>
-
-For overviews, tutorials, examples, guides, and tool documentation, please see:
-<ul>
- <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
-</ul>
--->
-
-@since 1.6
-</body>
-</html>
diff --git a/ojluni/src/main/java/javax/crypto/CipherSpi.java b/ojluni/src/main/java/javax/crypto/CipherSpi.java
index e563e92..ce72581 100644
--- a/ojluni/src/main/java/javax/crypto/CipherSpi.java
+++ b/ojluni/src/main/java/javax/crypto/CipherSpi.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -62,17 +62,17 @@
* algorithm (e.g., <i>DES</i>), and may be followed by a feedback mode and
* padding scheme.
*
- * <p> A transformation is of the form:<p>
+ * <p> A transformation is of the form:
*
* <ul>
* <li>"<i>algorithm/mode/padding</i>" or
- * <p>
+ *
* <li>"<i>algorithm</i>"
* </ul>
*
* <P> (in the latter case,
* provider-specific default values for the mode and padding scheme are used).
- * For example, the following is a valid transformation:<p>
+ * For example, the following is a valid transformation:
*
* <pre>
* Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>");
@@ -129,7 +129,7 @@
* <i>DES/CBC/PKCS5Padding</i>, one that implements
* <i>DES/CFB/PKCS5Padding</i>, and yet another one that implements
* <i>DES/OFB/PKCS5Padding</i>. That provider would have the following
- * <code>Cipher</code> properties in its master class:<p>
+ * <code>Cipher</code> properties in its master class:
*
* <ul>
*
@@ -160,7 +160,7 @@
* and one for <i>OFB</i>), one class for <i>PKCS5Padding</i>,
* and a generic <i>DES</i> class that subclasses from <code>CipherSpi</code>.
* That provider would have the following
- * <code>Cipher</code> properties in its master class:<p>
+ * <code>Cipher</code> properties in its master class:
*
* <ul>
*
@@ -197,20 +197,20 @@
* Check if the provider has registered a subclass of <code>CipherSpi</code>
* for the specified "<i>algorithm/mode/padding</i>" transformation.
* <p>If the answer is YES, instantiate it.
- * <p>If the answer is NO, go to the next step.<p>
+ * <p>If the answer is NO, go to the next step.
* <li>
* Check if the provider has registered a subclass of <code>CipherSpi</code>
* for the sub-transformation "<i>algorithm/mode</i>".
* <p>If the answer is YES, instantiate it, and call
* <code>engineSetPadding(<i>padding</i>)</code> on the new instance.
- * <p>If the answer is NO, go to the next step.<p>
+ * <p>If the answer is NO, go to the next step.
* <li>
* Check if the provider has registered a subclass of <code>CipherSpi</code>
* for the sub-transformation "<i>algorithm//padding</i>" (note the double
* slashes).
* <p>If the answer is YES, instantiate it, and call
* <code>engineSetMode(<i>mode</i>)</code> on the new instance.
- * <p>If the answer is NO, go to the next step.<p>
+ * <p>If the answer is NO, go to the next step.
* <li>
* Check if the provider has registered a subclass of <code>CipherSpi</code>
* for the sub-transformation "<i>algorithm</i>".
@@ -347,6 +347,9 @@
* initializing this cipher, or requires
* algorithm parameters that cannot be
* determined from the given key.
+ * @throws UnsupportedOperationException if {@code opmode} is
+ * {@code WRAP_MODE} or {@code UNWRAP_MODE} is not implemented
+ * by the cipher.
*/
protected abstract void engineInit(int opmode, Key key,
SecureRandom random)
@@ -399,6 +402,9 @@
* parameters are inappropriate for this cipher,
* or if this cipher requires
* algorithm parameters and <code>params</code> is null.
+ * @throws UnsupportedOperationException if {@code opmode} is
+ * {@code WRAP_MODE} or {@code UNWRAP_MODE} is not implemented
+ * by the cipher.
*/
protected abstract void engineInit(int opmode, Key key,
AlgorithmParameterSpec params,
@@ -452,6 +458,9 @@
* parameters are inappropriate for this cipher,
* or if this cipher requires
* algorithm parameters and <code>params</code> is null.
+ * @throws UnsupportedOperationException if {@code opmode} is
+ * {@code WRAP_MODE} or {@code UNWRAP_MODE} is not implemented
+ * by the cipher.
*/
protected abstract void engineInit(int opmode, Key key,
AlgorithmParameters params,
@@ -777,7 +786,9 @@
int total = 0;
do {
int chunk = Math.min(inLen, inArray.length);
- input.get(inArray, 0, chunk);
+ if (chunk > 0) {
+ input.get(inArray, 0, chunk);
+ }
int n;
if (isUpdate || (inLen != chunk)) {
n = engineUpdate(inArray, 0, chunk, outArray, outOfs);
@@ -805,8 +816,9 @@
int total = 0;
boolean resized = false;
do {
- int chunk = Math.min(inLen, outSize);
- if ((a1 == false) && (resized == false)) {
+ int chunk =
+ Math.min(inLen, (outSize == 0? inArray.length : outSize));
+ if (!a1 && !resized && chunk > 0) {
input.get(inArray, 0, chunk);
inOfs = 0;
}
@@ -820,8 +832,10 @@
resized = false;
inOfs += chunk;
inLen -= chunk;
- output.put(outArray, 0, n);
- total += n;
+ if (n > 0) {
+ output.put(outArray, 0, n);
+ total += n;
+ }
} catch (ShortBufferException e) {
if (resized) {
// we just resized the output buffer, but it still
@@ -831,11 +845,13 @@
}
// output buffer is too small, realloc and try again
resized = true;
- int newOut = engineGetOutputSize(chunk);
- outArray = new byte[newOut];
+ outSize = engineGetOutputSize(chunk);
+ outArray = new byte[outSize];
}
} while (inLen > 0);
- input.position(inLimit);
+ if (a1) {
+ input.position(inLimit);
+ }
return total;
}
}
@@ -863,6 +879,8 @@
* @exception InvalidKeyException if it is impossible or unsafe to
* wrap the key with this cipher (e.g., a hardware protected key is
* being passed to a software-only cipher).
+ *
+ * @throws UnsupportedOperationException if this method is not supported.
*/
protected byte[] engineWrap(Key key)
throws IllegalBlockSizeException, InvalidKeyException
@@ -899,6 +917,8 @@
* @exception InvalidKeyException if <code>wrappedKey</code> does not
* represent a wrapped key of type <code>wrappedKeyType</code> for
* the <code>wrappedKeyAlgorithm</code>.
+ *
+ * @throws UnsupportedOperationException if this method is not supported.
*/
protected Key engineUnwrap(byte[] wrappedKey,
String wrappedKeyAlgorithm,
diff --git a/ojluni/src/main/java/sun/nio/fs/LinuxFileSystem.java b/ojluni/src/main/java/sun/nio/fs/LinuxFileSystem.java
index 48f68dc..bdd2f29 100644
--- a/ojluni/src/main/java/sun/nio/fs/LinuxFileSystem.java
+++ b/ojluni/src/main/java/sun/nio/fs/LinuxFileSystem.java
@@ -102,7 +102,9 @@
*/
@Override
Iterable<UnixMountEntry> getMountEntries() {
- return getMountEntries("/etc/mtab");
+ // Android-changed: As /etc/mtab is not available in Android, therefore, using /proc/mounts
+ // instead.
+ return getMountEntries("/proc/mounts");
}
diff --git a/ojluni/src/main/java/sun/security/action/PutAllAction.java b/ojluni/src/main/java/sun/security/action/PutAllAction.java
deleted file mode 100644
index b58da23..0000000
--- a/ojluni/src/main/java/sun/security/action/PutAllAction.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.action;
-
-import java.util.Map;
-
-import java.security.Provider;
-import java.security.PrivilegedAction;
-
-/**
- * A convenience PrivilegedAction class for setting the properties of
- * a provider. See the SunRsaSign provider for a usage example.
- *
- * @see sun.security.rsa.SunRsaSign
- * @author Andreas Sterbenz
- * @since 1.5
- */
-public class PutAllAction implements PrivilegedAction<Void> {
-
- private final Provider provider;
- private final Map map;
-
- public PutAllAction(Provider provider, Map map) {
- this.provider = provider;
- this.map = map;
- }
-
- public Void run() {
- provider.putAll(map);
- return null;
- }
-
-}
diff --git a/ojluni/src/main/java/sun/util/LocaleServiceProviderPool.java b/ojluni/src/main/java/sun/util/LocaleServiceProviderPool.java
deleted file mode 100644
index cbab860..0000000
--- a/ojluni/src/main/java/sun/util/LocaleServiceProviderPool.java
+++ /dev/null
@@ -1,547 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.util;
-
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.IllformedLocaleException;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Locale.Builder;
-import java.util.Map;
-import java.util.ResourceBundle.Control;
-import java.util.ServiceLoader;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.spi.LocaleServiceProvider;
-import libcore.icu.ICU;
-
-import sun.util.logging.PlatformLogger;
-import sun.util.resources.OpenListResourceBundle;
-
-/**
- * An instance of this class holds a set of the third party implementations of a particular
- * locale sensitive service, such as {@link java.util.spi.LocaleNameProvider}.
- *
- */
-public final class LocaleServiceProviderPool {
-
- /**
- * A Map that holds singleton instances of this class. Each instance holds a
- * set of provider implementations of a particular locale sensitive service.
- */
- private static ConcurrentMap<Class<? extends LocaleServiceProvider>, LocaleServiceProviderPool> poolOfPools =
- new ConcurrentHashMap<>();
-
- /**
- * A Set containing locale service providers that implement the
- * specified provider SPI
- */
- private Set<LocaleServiceProvider> providers =
- new LinkedHashSet<LocaleServiceProvider>();
-
- /**
- * A Map that retains Locale->provider mapping
- */
- private Map<Locale, LocaleServiceProvider> providersCache =
- new ConcurrentHashMap<Locale, LocaleServiceProvider>();
-
- /**
- * Available locales for this locale sensitive service. This also contains
- * JRE's available locales
- */
- private Set<Locale> availableLocales = null;
-
- /**
- * Available locales within this JRE. Currently this is declared as
- * static. This could be non-static later, so that they could have
- * different sets for each locale sensitive services.
- */
- private static volatile List<Locale> availableJRELocales = null;
-
- /**
- * Provider locales for this locale sensitive service.
- */
- private Set<Locale> providerLocales = null;
-
- /**
- * Special locale for ja_JP with Japanese calendar
- */
- private static Locale locale_ja_JP_JP = new Locale("ja", "JP", "JP");
-
- /**
- * Special locale for th_TH with Thai numbering system
- */
- private static Locale locale_th_TH_TH = new Locale("th", "TH", "TH");
-
- /**
- * A factory method that returns a singleton instance
- */
- public static LocaleServiceProviderPool getPool(Class<? extends LocaleServiceProvider> providerClass) {
- LocaleServiceProviderPool pool = poolOfPools.get(providerClass);
- if (pool == null) {
- LocaleServiceProviderPool newPool =
- new LocaleServiceProviderPool(providerClass);
- pool = poolOfPools.putIfAbsent(providerClass, newPool);
- if (pool == null) {
- pool = newPool;
- }
- }
-
- return pool;
- }
-
- /**
- * The sole constructor.
- *
- * @param c class of the locale sensitive service
- */
- private LocaleServiceProviderPool (final Class<? extends LocaleServiceProvider> c) {
- try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() {
- for (LocaleServiceProvider provider : ServiceLoader.loadInstalled(c)) {
- providers.add(provider);
- }
- return null;
- }
- });
- } catch (PrivilegedActionException e) {
- config(e.toString());
- }
- }
-
- private static void config(String message) {
- PlatformLogger logger = PlatformLogger.getLogger("sun.util.LocaleServiceProviderPool");
- logger.config(message);
- }
-
- /**
- * Lazy loaded set of available locales.
- * Loading all locales is a very long operation.
- *
- * We know "providerClasses" contains classes that extends LocaleServiceProvider,
- * but generic array creation is not allowed, thus the "unchecked" warning
- * is suppressed here.
- */
- private static class AllAvailableLocales {
- /**
- * Available locales for all locale sensitive services.
- * This also contains JRE's available locales
- */
- static final Locale[] allAvailableLocales;
-
- static {
- @SuppressWarnings("unchecked")
- Class<LocaleServiceProvider>[] providerClasses =
- (Class<LocaleServiceProvider>[]) new Class<?>[] {
- java.text.spi.BreakIteratorProvider.class,
- java.text.spi.CollatorProvider.class,
- java.text.spi.DateFormatProvider.class,
- java.text.spi.DateFormatSymbolsProvider.class,
- java.text.spi.DecimalFormatSymbolsProvider.class,
- java.text.spi.NumberFormatProvider.class,
- java.util.spi.CurrencyNameProvider.class,
- java.util.spi.LocaleNameProvider.class,
- java.util.spi.TimeZoneNameProvider.class,
- };
-
- // Normalize locales for look up
- Locale[] allLocales = ICU.getAvailableLocales();
- Set<Locale> all = new HashSet<Locale>(allLocales.length);
- for (Locale locale : allLocales) {
- all.add(getLookupLocale(locale));
- }
-
- for (Class<LocaleServiceProvider> providerClass : providerClasses) {
- LocaleServiceProviderPool pool =
- LocaleServiceProviderPool.getPool(providerClass);
- all.addAll(pool.getProviderLocales());
- }
-
- allAvailableLocales = all.toArray(new Locale[0]);
- }
- }
-
- /**
- * Returns an array of available locales for all the provider classes.
- * This array is a merged array of all the locales that are provided by each
- * provider, including the JRE.
- *
- * @return an array of the available locales for all provider classes
- */
- public static Locale[] getAllAvailableLocales() {
- return AllAvailableLocales.allAvailableLocales.clone();
- }
-
- /**
- * Returns an array of available locales. This array is a
- * merged array of all the locales that are provided by each
- * provider, including the JRE.
- *
- * @return an array of the available locales
- */
- public synchronized Locale[] getAvailableLocales() {
- if (availableLocales == null) {
- availableLocales = new HashSet<Locale>(getJRELocales());
- if (hasProviders()) {
- availableLocales.addAll(getProviderLocales());
- }
- }
- Locale[] tmp = new Locale[availableLocales.size()];
- availableLocales.toArray(tmp);
- return tmp;
- }
-
- /**
- * Returns an array of available locales (already normalized
- * for service lookup) from providers.
- * Note that this method does not return a defensive copy.
- *
- * @return list of the provider locales
- */
- private synchronized Set<Locale> getProviderLocales() {
- if (providerLocales == null) {
- providerLocales = new HashSet<Locale>();
- if (hasProviders()) {
- for (LocaleServiceProvider lsp : providers) {
- Locale[] locales = lsp.getAvailableLocales();
- for (Locale locale: locales) {
- providerLocales.add(getLookupLocale(locale));
- }
- }
- }
- }
- return providerLocales;
- }
-
- /**
- * Returns whether any provider for this locale sensitive
- * service is available or not.
- *
- * @return true if any provider is available
- */
- public boolean hasProviders() {
- return !providers.isEmpty();
- }
-
- /**
- * Returns an array of available locales (already normalized for
- * service lookup) supported by the JRE.
- * Note that this method does not return a defensive copy.
- *
- * @return list of the available JRE locales
- */
- private List<Locale> getJRELocales() {
- if (availableJRELocales == null) {
- synchronized (LocaleServiceProviderPool.class) {
- if (availableJRELocales == null) {
- Locale[] allLocales = ICU.getAvailableLocales();
- List<Locale> tmpList = new ArrayList<>(allLocales.length);
- for (Locale locale : allLocales) {
- tmpList.add(getLookupLocale(locale));
- }
- availableJRELocales = tmpList;
- }
- }
- }
- return availableJRELocales;
- }
-
- /**
- * Returns whether the given locale is supported by the JRE.
- *
- * @param locale the locale to test.
- * @return true, if the locale is supported by the JRE. false
- * otherwise.
- */
- private boolean isJRESupported(Locale locale) {
- List<Locale> locales = getJRELocales();
- return locales.contains(getLookupLocale(locale));
- }
-
- /**
- * Returns the provider's localized object for the specified
- * locale.
- *
- * @param getter an object on which getObject() method
- * is called to obtain the provider's instance.
- * @param locale the given locale that is used as the starting one
- * @param params provider specific parameters
- * @return provider's instance, or null.
- */
- public <P, S> S getLocalizedObject(LocalizedObjectGetter<P, S> getter,
- Locale locale,
- Object... params) {
- return getLocalizedObjectImpl(getter, locale, true, null, null, null, params);
- }
-
- /**
- * Returns the provider's localized name for the specified
- * locale.
- *
- * @param getter an object on which getObject() method
- * is called to obtain the provider's instance.
- * @param locale the given locale that is used as the starting one
- * @param bundle JRE resource bundle that contains
- * the localized names, or null for localized objects.
- * @param key the key string if bundle is supplied, otherwise null.
- * @param params provider specific parameters
- * @return provider's instance, or null.
- */
- public <P, S> S getLocalizedObject(LocalizedObjectGetter<P, S> getter,
- Locale locale,
- OpenListResourceBundle bundle,
- String key,
- Object... params) {
- return getLocalizedObjectImpl(getter, locale, false, null, bundle, key, params);
- }
-
- /**
- * Returns the provider's localized name for the specified
- * locale.
- *
- * @param getter an object on which getObject() method
- * is called to obtain the provider's instance.
- * @param locale the given locale that is used as the starting one
- * @param bundleKey JRE specific bundle key. e.g., "USD" is for currency
- symbol and "usd" is for currency display name in the JRE bundle.
- * @param bundle JRE resource bundle that contains
- * the localized names, or null for localized objects.
- * @param key the key string if bundle is supplied, otherwise null.
- * @param params provider specific parameters
- * @return provider's instance, or null.
- */
- public <P, S> S getLocalizedObject(LocalizedObjectGetter<P, S> getter,
- Locale locale,
- String bundleKey,
- OpenListResourceBundle bundle,
- String key,
- Object... params) {
- return getLocalizedObjectImpl(getter, locale, false, bundleKey, bundle, key, params);
- }
-
- private <P, S> S getLocalizedObjectImpl(LocalizedObjectGetter<P, S> getter,
- Locale locale,
- boolean isObjectProvider,
- String bundleKey,
- OpenListResourceBundle bundle,
- String key,
- Object... params) {
- if (hasProviders()) {
- if (bundleKey == null) {
- bundleKey = key;
- }
- Locale bundleLocale = (bundle != null ? bundle.getLocale() : null);
- List<Locale> lookupLocales = getLookupLocales(locale);
- S providersObj = null;
-
- // check whether a provider has an implementation that's closer
- // to the requested locale than the bundle we've found (for
- // localized names), or Java runtime's supported locale
- // (for localized objects)
- Set<Locale> provLoc = getProviderLocales();
- for (int i = 0; i < lookupLocales.size(); i++) {
- Locale current = lookupLocales.get(i);
- if (bundleLocale != null) {
- if (current.equals(bundleLocale)) {
- break;
- }
- } else {
- if (isJRESupported(current)) {
- break;
- }
- }
- if (provLoc.contains(current)) {
- // It is safe to assume that findProvider() returns the instance of type P.
- @SuppressWarnings("unchecked")
- P lsp = (P)findProvider(current);
- if (lsp != null) {
- providersObj = getter.getObject(lsp, locale, key, params);
- if (providersObj != null) {
- return providersObj;
- } else if (isObjectProvider) {
- config(
- "A locale sensitive service provider returned null for a localized objects, which should not happen. provider: " + lsp + " locale: " + locale);
- }
- }
- }
- }
-
- // look up the JRE bundle and its parent chain. Only
- // providers for localized names are checked hereafter.
- while (bundle != null) {
- bundleLocale = bundle.getLocale();
-
- if (bundle.handleGetKeys().contains(bundleKey)) {
- // JRE has it.
- return null;
- } else {
- // It is safe to assume that findProvider() returns the instance of type P.
- @SuppressWarnings("unchecked")
- P lsp = (P)findProvider(bundleLocale);
- if (lsp != null) {
- providersObj = getter.getObject(lsp, locale, key, params);
- if (providersObj != null) {
- return providersObj;
- }
- }
- }
-
- // try parent bundle
- bundle = bundle.getParent();
- }
- }
-
- // not found.
- return null;
- }
-
- /**
- * Returns a locale service provider instance that supports
- * the specified locale.
- *
- * @param locale the given locale
- * @return the provider, or null if there is
- * no provider available.
- */
- private LocaleServiceProvider findProvider(Locale locale) {
- if (!hasProviders()) {
- return null;
- }
-
- if (providersCache.containsKey(locale)) {
- LocaleServiceProvider provider = providersCache.get(locale);
- if (provider != NullProvider.INSTANCE) {
- return provider;
- }
- } else {
- for (LocaleServiceProvider lsp : providers) {
- Locale[] locales = lsp.getAvailableLocales();
- for (Locale available: locales) {
- // normalize
- available = getLookupLocale(available);
- if (locale.equals(available)) {
- LocaleServiceProvider providerInCache =
- providersCache.put(locale, lsp);
- return (providerInCache != null ?
- providerInCache :
- lsp);
- }
- }
- }
- providersCache.put(locale, NullProvider.INSTANCE);
- }
- return null;
- }
-
- /**
- * Returns a list of candidate locales for service look up.
- * @param locale the input locale
- * @return the list of candiate locales for the given locale
- */
- private static List<Locale> getLookupLocales(Locale locale) {
- // Note: We currently use the default implementation of
- // ResourceBundle.Control.getCandidateLocales. The result
- // returned by getCandidateLocales are already normalized
- // (no extensions) for service look up.
- List<Locale> lookupLocales = new Control(){}.getCandidateLocales("", locale);
- return lookupLocales;
- }
-
- /**
- * Returns an instance of Locale used for service look up.
- * The result Locale has no extensions except for ja_JP_JP
- * and th_TH_TH
- *
- * @param locale the locale
- * @return the locale used for service look up
- */
- private static Locale getLookupLocale(Locale locale) {
- Locale lookupLocale = locale;
- Set<Character> extensions = locale.getExtensionKeys();
- if (!extensions.isEmpty()
- && !locale.equals(locale_ja_JP_JP)
- && !locale.equals(locale_th_TH_TH)) {
- // remove extensions
- Builder locbld = new Builder();
- try {
- locbld.setLocale(locale);
- locbld.clearExtensions();
- lookupLocale = locbld.build();
- } catch (IllformedLocaleException e) {
- // A Locale with non-empty extensions
- // should have well-formed fields except
- // for ja_JP_JP and th_TH_TH. Therefore,
- // it should never enter in this catch clause.
- config("A locale(" + locale + ") has non-empty extensions, but has illformed fields.");
-
- // Fallback - script field will be lost.
- lookupLocale = new Locale(locale.getLanguage(), locale.getCountry(), locale.getVariant());
- }
- }
- return lookupLocale;
- }
-
- /**
- * A dummy locale service provider that indicates there is no
- * provider available
- */
- private static class NullProvider extends LocaleServiceProvider {
- private static final NullProvider INSTANCE = new NullProvider();
-
- public Locale[] getAvailableLocales() {
- throw new RuntimeException("Should not get called.");
- }
- }
-
- /**
- * An interface to get a localized object for each locale sensitve
- * service class.
- */
- public interface LocalizedObjectGetter<P, S> {
- /**
- * Returns an object from the provider
- *
- * @param lsp the provider
- * @param locale the locale
- * @param key key string to localize, or null if the provider is not
- * a name provider
- * @param params provider specific params
- * @return localized object from the provider
- */
- public S getObject(P lsp,
- Locale locale,
- String key,
- Object... params);
- }
-}
diff --git a/ojluni/src/main/java/sun/util/locale/LocaleUtils.java b/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
index 0258e5a..9a89dc0 100644
--- a/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
+++ b/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
@@ -196,7 +196,7 @@
return isAlpha(c) || isNumeric(c);
}
- static boolean isAlphaNumericString(String s) {
+ public static boolean isAlphaNumericString(String s) {
int len = s.length();
for (int i = 0; i < len; i++) {
if (!isAlphaNumeric(s.charAt(i))) {
diff --git a/ojluni/src/main/native/IOUtil.c b/ojluni/src/main/native/IOUtil.c
index ea8a3d1..390c0e6 100644
--- a/ojluni/src/main/native/IOUtil.c
+++ b/ojluni/src/main/native/IOUtil.c
@@ -36,14 +36,6 @@
#include "nio_util.h"
#include "JNIHelp.h"
-// Android-changed: Added missing CHECK_NULL definition.
-#define CHECK_NULL(value) \
-{ \
- if (value == NULL) { \
- JNU_ThrowNullPointerException(env, NULL); \
- return; \
- } \
-}
#define NATIVE_METHOD(className, functionName, signature) \
{ #functionName, signature, (void*)(className ## _ ## functionName) }
diff --git a/ojluni/src/main/native/Inet4AddressImpl.c b/ojluni/src/main/native/Inet4AddressImpl.c
deleted file mode 100644
index fce6d95..0000000
--- a/ojluni/src/main/native/Inet4AddressImpl.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <errno.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#ifdef _ALLBSD_SOURCE
-#include <unistd.h>
-#include <sys/param.h>
-#endif
-
-#include "jvm.h"
-#include "jni_util.h"
-#include "net_util.h"
-
-#include "JNIHelp.h"
-
-#define NATIVE_METHOD(className, functionName, signature) \
-{ #functionName, signature, (void*)(className ## _ ## functionName) }
-
-//#if defined(__GLIBC__) || (defined(__FreeBSD__) && (__FreeBSD_version >= 601104))
-#define HAS_GLIBC_GETHOSTBY_R 1
-//#endif
-
-#define SET_NONBLOCKING(fd) { \
- int flags = fcntl(fd, F_GETFL); \
- flags |= O_NONBLOCK; \
- fcntl(fd, F_SETFL, flags); \
-}
-
-/**
- * ping implementation.
- * Send a ICMP_ECHO_REQUEST packet every second until either the timeout
- * expires or a answer is received.
- * Returns true is an ECHO_REPLY is received, otherwise, false.
- */
-static jboolean
-ping4(JNIEnv *env, jint fd, struct sockaddr_in* him, jint timeout,
- struct sockaddr_in* netif, jint ttl) {
- jint size;
- jint n, hlen1, icmplen;
- socklen_t len;
- char sendbuf[1500];
- char recvbuf[1500];
- struct icmp *icmp;
- struct ip *ip;
- struct sockaddr_in sa_recv;
- jchar pid;
- jint tmout2, seq = 1;
- struct timeval tv;
- size_t plen;
-
- /* icmp_id is a 16 bit data type, therefore down cast the pid */
- pid = (jchar)getpid();
- size = 60*1024;
- setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
- /*
- * sets the ttl (max number of hops)
- */
- if (ttl > 0) {
- setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
- }
- /*
- * a specific interface was specified, so let's bind the socket
- * to that interface to ensure the requests are sent only through it.
- */
- if (netif != NULL) {
- if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {
- NET_ThrowNew(env, errno, "Can't bind socket");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
- }
- /*
- * Make the socket non blocking so we can use select
- */
- SET_NONBLOCKING(fd);
- do {
- /*
- * create the ICMP request
- */
- icmp = (struct icmp *) sendbuf;
- icmp->icmp_type = ICMP_ECHO;
- icmp->icmp_code = 0;
- icmp->icmp_id = htons(pid);
- icmp->icmp_seq = htons(seq);
- seq++;
- gettimeofday(&tv, NULL);
- memcpy(icmp->icmp_data, &tv, sizeof(tv));
- plen = ICMP_ADVLENMIN + sizeof(tv);
- icmp->icmp_cksum = 0;
- icmp->icmp_cksum = in_cksum((u_short *)icmp, plen);
- /*
- * send it
- */
- n = sendto(fd, sendbuf, plen, 0, (struct sockaddr *)him,
- sizeof(struct sockaddr));
- if (n < 0 && errno != EINPROGRESS ) {
-#ifdef __linux__
- if (errno != EINVAL && errno != EHOSTUNREACH)
- /*
- * On some Linux versions, when a socket is bound to the loopback
- * interface, sendto will fail and errno will be set to
- * EINVAL or EHOSTUNREACH. When that happens, don't throw an
- * exception, just return false.
- */
-#endif /*__linux__ */
- NET_ThrowNew(env, errno, "Can't send ICMP packet");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-
- tmout2 = timeout > 1000 ? 1000 : timeout;
- do {
- tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2);
- if (tmout2 >= 0) {
- len = sizeof(sa_recv);
- n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr *)&sa_recv, &len);
- ip = (struct ip*) recvbuf;
- hlen1 = (ip->ip_hl) << 2;
- icmp = (struct icmp *) (recvbuf + hlen1);
- icmplen = n - hlen1;
- /*
- * We did receive something, but is it what we were expecting?
- * I.E.: A ICMP_ECHOREPLY packet with the proper PID.
- */
- if (icmplen >= 8 && icmp->icmp_type == ICMP_ECHOREPLY
- && (ntohs(icmp->icmp_id) == pid)) {
- if ((him->sin_addr.s_addr == sa_recv.sin_addr.s_addr)) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- }
-
- if (him->sin_addr.s_addr == 0) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- }
- }
-
- }
- } while (tmout2 > 0);
- timeout -= 1000;
- } while (timeout >0);
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
-}
-
-/*
- * Class: java_net_Inet4AddressImpl
- * Method: isReachable0
- * Signature: ([bI[bI)Z
- */
-JNIEXPORT jboolean JNICALL
-Inet4AddressImpl_isReachable0(JNIEnv *env, jobject this,
- jbyteArray addrArray,
- jint timeout,
- jbyteArray ifArray,
- jint ttl) {
- jint addr;
- jbyte caddr[4];
- jint fd;
- struct sockaddr_in him;
- struct sockaddr_in* netif = NULL;
- struct sockaddr_in inf;
- int len = 0;
- int connect_rv = -1;
- int sz;
-
- memset((char *) caddr, 0, sizeof(caddr));
- memset((char *) &him, 0, sizeof(him));
- memset((char *) &inf, 0, sizeof(inf));
- sz = (*env)->GetArrayLength(env, addrArray);
- if (sz != 4) {
- return JNI_FALSE;
- }
- (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
- addr = ((caddr[0]<<24) & 0xff000000);
- addr |= ((caddr[1] <<16) & 0xff0000);
- addr |= ((caddr[2] <<8) & 0xff00);
- addr |= (caddr[3] & 0xff);
- addr = htonl(addr);
- him.sin_addr.s_addr = addr;
- him.sin_family = AF_INET;
- len = sizeof(him);
- /*
- * If a network interface was specified, let's create the address
- * for it.
- */
- if (!(IS_NULL(ifArray))) {
- memset((char *) caddr, 0, sizeof(caddr));
- (*env)->GetByteArrayRegion(env, ifArray, 0, 4, caddr);
- addr = ((caddr[0]<<24) & 0xff000000);
- addr |= ((caddr[1] <<16) & 0xff0000);
- addr |= ((caddr[2] <<8) & 0xff00);
- addr |= (caddr[3] & 0xff);
- addr = htonl(addr);
- inf.sin_addr.s_addr = addr;
- inf.sin_family = AF_INET;
- inf.sin_port = 0;
- netif = &inf;
- }
-
- /*
- * Let's try to create a RAW socket to send ICMP packets
- * This usually requires "root" privileges, so it's likely to fail.
- */
- fd = JVM_Socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- if (fd != -1) {
- /*
- * It didn't fail, so we can use ICMP_ECHO requests.
- */
- tagSocket(env, fd);
- return ping4(env, fd, &him, timeout, netif, ttl);
- }
-
- /*
- * Can't create a raw socket, so let's try a TCP socket
- */
- fd = JVM_Socket(AF_INET, SOCK_STREAM, 0);
- if (fd == JVM_IO_ERR) {
- /* note: if you run out of fds, you may not be able to load
- * the exception class, and get a NoClassDefFoundError
- * instead.
- */
- NET_ThrowNew(env, errno, "Can't create socket");
- return JNI_FALSE;
- }
- tagSocket(env, fd);
-
- if (ttl > 0) {
- setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
- }
-
- /*
- * A network interface was specified, so let's bind to it.
- */
- if (netif != NULL) {
- if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {
- NET_ThrowNew(env, errno, "Can't bind socket");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
- }
-
- /*
- * Make the socket non blocking so we can use select/poll.
- */
- SET_NONBLOCKING(fd);
-
- /* no need to use NET_Connect as non-blocking */
- him.sin_port = htons(7); /* Echo */
- connect_rv = JVM_Connect(fd, (struct sockaddr *)&him, len);
-
- /**
- * connection established or refused immediately, either way it means
- * we were able to reach the host!
- */
- if (connect_rv == 0 || errno == ECONNREFUSED) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- } else {
- int optlen;
-
- switch (errno) {
- case ENETUNREACH: /* Network Unreachable */
- case EAFNOSUPPORT: /* Address Family not supported */
- case EADDRNOTAVAIL: /* address is not available on the remote machine */
-#ifdef __linux__
- case EINVAL:
- case EHOSTUNREACH:
- /*
- * On some Linux versions, when a socket is bound to the loopback
- * interface, connect will fail and errno will be set to EINVAL
- * or EHOSTUNREACH. When that happens, don't throw an exception,
- * just return false.
- */
-#endif /* __linux__ */
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-
- if (errno != EINPROGRESS) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
- "connect failed");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-
- timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
- if (timeout >= 0) {
- /* has connection been established? */
- optlen = sizeof(connect_rv);
- if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
- &optlen) <0) {
- connect_rv = errno;
- }
- if (connect_rv == 0 || connect_rv == ECONNREFUSED) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- }
- }
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-}
diff --git a/ojluni/src/main/native/Inet6AddressImpl.c b/ojluni/src/main/native/Inet6AddressImpl.c
deleted file mode 100644
index 85f2314..0000000
--- a/ojluni/src/main/native/Inet6AddressImpl.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <errno.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <string.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <ctype.h>
-#ifdef _ALLBSD_SOURCE
-#include <unistd.h> /* gethostname */
-#endif
-
-#include "jvm.h"
-#include "jni_util.h"
-#include "net_util.h"
-#ifndef IPV6_DEFS_H
-#include <netinet/icmp6.h>
-#endif
-
-#include "java_net_Inet4AddressImpl.h"
-#include "JNIHelp.h"
-
-#define NATIVE_METHOD(className, functionName, signature) \
-{ #functionName, signature, (void*)(className ## _ ## functionName) }
-
-/* the initial size of our hostent buffers */
-#ifndef NI_MAXHOST
-#define NI_MAXHOST 1025
-#endif
-
-
-/************************************************************************
- * Inet6AddressImpl
- */
-
-static jclass ni_iacls;
-static jclass ni_ia4cls;
-static jclass ni_ia6cls;
-static jmethodID ni_ia4ctrID;
-static jmethodID ni_ia6ctrID;
-
-/*
- * Class: java_net_Inet6AddressImpl
- * Method: getHostByAddr
- * Signature: (I)Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL
-Inet6AddressImpl_getHostByAddr0(JNIEnv *env, jobject this,
- jbyteArray addrArray) {
-
- jstring ret = NULL;
-
-#ifdef AF_INET6
- char host[NI_MAXHOST+1];
- int error = 0;
- int len = 0;
- jbyte caddr[16];
-
- if (NET_addrtransAvailable()) {
- struct sockaddr_in him4;
- struct sockaddr_in6 him6;
- struct sockaddr *sa;
-
- /*
- * For IPv4 addresses construct a sockaddr_in structure.
- */
- if ((*env)->GetArrayLength(env, addrArray) == 4) {
- jint addr;
- (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
- addr = ((caddr[0]<<24) & 0xff000000);
- addr |= ((caddr[1] <<16) & 0xff0000);
- addr |= ((caddr[2] <<8) & 0xff00);
- addr |= (caddr[3] & 0xff);
- memset((void *) &him4, 0, sizeof(him4));
- him4.sin_addr.s_addr = (uint32_t) htonl(addr);
- him4.sin_family = AF_INET;
- sa = (struct sockaddr *) &him4;
- len = sizeof(him4);
- } else {
- /*
- * For IPv6 address construct a sockaddr_in6 structure.
- */
- (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
- memset((void *) &him6, 0, sizeof(him6));
- memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
- him6.sin6_family = AF_INET6;
- sa = (struct sockaddr *) &him6 ;
- len = sizeof(him6) ;
- }
-
- error = (*getnameinfo_ptr)(sa, len, host, NI_MAXHOST, NULL, 0,
- NI_NAMEREQD);
-
- if (!error) {
- ret = (*env)->NewStringUTF(env, host);
- }
- }
-#endif /* AF_INET6 */
-
- if (ret == NULL) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
- }
-
- return ret;
-}
-
-#define SET_NONBLOCKING(fd) { \
- int flags = fcntl(fd, F_GETFL); \
- flags |= O_NONBLOCK; \
- fcntl(fd, F_SETFL, flags); \
-}
-
-#ifdef AF_INET6
-static jboolean
-ping6(JNIEnv *env, jint fd, struct sockaddr_in6* him, jint timeout,
- struct sockaddr_in6* netif, jint ttl) {
- jint size;
- jint n;
- socklen_t len;
- char sendbuf[1500];
- unsigned char recvbuf[1500];
- struct icmp6_hdr *icmp6;
- struct sockaddr_in6 sa_recv;
- jbyte *caddr, *recv_caddr;
- jchar pid;
- jint tmout2, seq = 1;
- struct timeval tv;
- size_t plen;
-
-#ifdef __linux__
- {
- int csum_offset;
- /**
- * For some strange reason, the linux kernel won't calculate the
- * checksum of ICMPv6 packets unless you set this socket option
- */
- csum_offset = 2;
- setsockopt(fd, SOL_RAW, IPV6_CHECKSUM, &csum_offset, sizeof(int));
- }
-#endif
-
- caddr = (jbyte *)&(him->sin6_addr);
-
- /* icmp_id is a 16 bit data type, therefore down cast the pid */
- pid = (jchar)getpid();
- size = 60*1024;
- setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
- if (ttl > 0) {
- setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
- }
- if (netif != NULL) {
- if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
- NET_ThrowNew(env, errno, "Can't bind socket");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
- }
- SET_NONBLOCKING(fd);
-
- do {
- icmp6 = (struct icmp6_hdr *) sendbuf;
- icmp6->icmp6_type = ICMP6_ECHO_REQUEST;
- icmp6->icmp6_code = 0;
- /* let's tag the ECHO packet with our pid so we can identify it */
- icmp6->icmp6_id = htons(pid);
- icmp6->icmp6_seq = htons(seq);
- seq++;
- icmp6->icmp6_cksum = 0;
- gettimeofday(&tv, NULL);
- memcpy(sendbuf + sizeof(struct icmp6_hdr), &tv, sizeof(tv));
- plen = sizeof(struct icmp6_hdr) + sizeof(tv);
- n = sendto(fd, sendbuf, plen, 0, (struct sockaddr*) him, sizeof(struct sockaddr_in6));
- if (n < 0 && errno != EINPROGRESS) {
-#ifdef __linux__
- if (errno != EINVAL && errno != EHOSTUNREACH)
- /*
- * On some Linux versions, when a socket is bound to the
- * loopback interface, sendto will fail and errno will be
- * set to EINVAL or EHOSTUNREACH.
- * When that happens, don't throw an exception, just return false.
- */
-#endif /*__linux__ */
- NET_ThrowNew(env, errno, "Can't send ICMP packet");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-
- tmout2 = timeout > 1000 ? 1000 : timeout;
- do {
- tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2);
-
- if (tmout2 >= 0) {
- len = sizeof(sa_recv);
- n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*) &sa_recv, &len);
- icmp6 = (struct icmp6_hdr *) (recvbuf);
- recv_caddr = (jbyte *)&(sa_recv.sin6_addr);
- /*
- * We did receive something, but is it what we were expecting?
- * I.E.: An ICMP6_ECHO_REPLY packet with the proper PID and
- * from the host that we are trying to determine is reachable.
- */
- if (n >= 8 && icmp6->icmp6_type == ICMP6_ECHO_REPLY &&
- (ntohs(icmp6->icmp6_id) == pid)) {
- if (NET_IsEqual(caddr, recv_caddr)) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- }
- if (NET_IsZeroAddr(caddr)) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- }
- }
- }
- } while (tmout2 > 0);
- timeout -= 1000;
- } while (timeout > 0);
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
-}
-#endif /* AF_INET6 */
-
-/*
- * Class: java_net_Inet6AddressImpl
- * Method: isReachable0
- * Signature: ([bII[bI)Z
- */
-JNIEXPORT jboolean JNICALL
-Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this,
- jbyteArray addrArray,
- jint scope,
- jint timeout,
- jbyteArray ifArray,
- jint ttl, jint if_scope) {
-#ifdef AF_INET6
- jbyte caddr[16];
- jint fd, sz;
- struct sockaddr_in6 him6;
- struct sockaddr_in6 inf6;
- struct sockaddr_in6* netif = NULL;
- int len = 0;
- int connect_rv = -1;
-
- /*
- * If IPv6 is not enable, then we can't reach an IPv6 address, can we?
- */
- if (!ipv6_available()) {
- return JNI_FALSE;
- }
- /*
- * If it's an IPv4 address, ICMP won't work with IPv4 mapped address,
- * therefore, let's delegate to the Inet4Address method.
- */
- sz = (*env)->GetArrayLength(env, addrArray);
- if (sz == 4) {
- return Inet4AddressImpl_isReachable0(env, this,
- addrArray,
- timeout,
- ifArray, ttl);
- }
-
- memset((void *) caddr, 0, 16);
- memset((void *) &him6, 0, sizeof(him6));
- (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
- memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
- him6.sin6_family = AF_INET6;
-
- // Android-change: Don't try and figure out a default scope ID if one isn't
- // set. It's only useful for link local addresses anyway, and callers are
- // expected to call isReachable with a specific NetworkInterface if they
- // want to query the reachability of an address that's local to that IF.
- if (scope > 0)
- him6.sin6_scope_id = scope;
- len = sizeof(struct sockaddr_in6);
- /*
- * If a network interface was specified, let's create the address
- * for it.
- */
- if (!(IS_NULL(ifArray))) {
- memset((void *) caddr, 0, 16);
- memset((void *) &inf6, 0, sizeof(inf6));
- (*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr);
- memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) );
- inf6.sin6_family = AF_INET6;
- inf6.sin6_scope_id = if_scope;
- netif = &inf6;
- }
- /*
- * If we can create a RAW socket, then when can use the ICMP ECHO_REQUEST
- * otherwise we'll try a tcp socket to the Echo port (7).
- * Note that this is empiric, and not connecting could mean it's blocked
- * or the echo service has been disabled.
- */
-
- fd = JVM_Socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
-
- if (fd != -1) { /* Good to go, let's do a ping */
- tagSocket(env, fd);
- return ping6(env, fd, &him6, timeout, netif, ttl);
- }
-
- /* No good, let's fall back on TCP */
- fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0);
- if (fd == JVM_IO_ERR) {
- /* note: if you run out of fds, you may not be able to load
- * the exception class, and get a NoClassDefFoundError
- * instead.
- */
- NET_ThrowNew(env, errno, "Can't create socket");
- return JNI_FALSE;
- }
- tagSocket(env, fd);
-
- if (ttl > 0) {
- setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
- }
-
- /*
- * A network interface was specified, so let's bind to it.
- */
- if (netif != NULL) {
- if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
- NET_ThrowNew(env, errno, "Can't bind socket");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
- }
- SET_NONBLOCKING(fd);
-
- /* no need to use NET_Connect as non-blocking */
- him6.sin6_port = htons((short) 7); /* Echo port */
- connect_rv = JVM_Connect(fd, (struct sockaddr *)&him6, len);
-
- /**
- * connection established or refused immediately, either way it means
- * we were able to reach the host!
- */
- if (connect_rv == 0 || errno == ECONNREFUSED) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- } else {
- int optlen;
-
- switch (errno) {
- case ENETUNREACH: /* Network Unreachable */
- case EAFNOSUPPORT: /* Address Family not supported */
- case EADDRNOTAVAIL: /* address is not available on the remote machine */
-#ifdef __linux__
- case EINVAL:
- case EHOSTUNREACH:
- /*
- * On some Linuxes, when bound to the loopback interface, connect
- * loopback interface, connect will fail and errno will
- * be set to EINVAL or EHOSTUNREACH. When that happens,
- * don't throw an exception, just return false.
- */
-#endif /* __linux__ */
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-
- if (errno != EINPROGRESS) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
- "connect failed");
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-
- timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
-
- if (timeout >= 0) {
- /* has connection been established */
- optlen = sizeof(connect_rv);
- if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
- &optlen) <0) {
- connect_rv = errno;
- }
- if (connect_rv == 0 || ECONNREFUSED) {
- untagSocket(env, fd);
- close(fd);
- return JNI_TRUE;
- }
- }
- untagSocket(env, fd);
- close(fd);
- return JNI_FALSE;
- }
-#else /* AF_INET6 */
- return JNI_FALSE;
-#endif /* AF_INET6 */
-}
-
-static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Inet6AddressImpl, isReachable0, "([BII[BII)Z"),
- NATIVE_METHOD(Inet6AddressImpl, getHostByAddr0, "([B)Ljava/lang/String;"),
-};
-
-void register_java_net_Inet6AddressImpl(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/net/Inet6AddressImpl", gMethods, NELEM(gMethods));
-}
diff --git a/ojluni/src/main/native/ObjectInputStream.c b/ojluni/src/main/native/ObjectInputStream.c
index 55cebba..95eeec4 100644
--- a/ojluni/src/main/native/ObjectInputStream.c
+++ b/ojluni/src/main/native/ObjectInputStream.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2000, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/native/ObjectOutputStream.c b/ojluni/src/main/native/ObjectOutputStream.c
index d74e31f..25ee3bf 100644
--- a/ojluni/src/main/native/ObjectOutputStream.c
+++ b/ojluni/src/main/native/ObjectOutputStream.c
@@ -192,4 +192,3 @@
void register_java_io_ObjectOutputStream(JNIEnv* env) {
jniRegisterNativeMethods(env, "java/io/ObjectOutputStream", gMethods, NELEM(gMethods));
}
-
diff --git a/ojluni/src/main/native/Register.cpp b/ojluni/src/main/native/Register.cpp
index 0d31d02..c7d3ce1 100644
--- a/ojluni/src/main/native/Register.cpp
+++ b/ojluni/src/main/native/Register.cpp
@@ -25,12 +25,13 @@
#define LOG_TAG "libcore" // We'll be next to "dalvikvm" in the log; make the distinction clear.
-#include "cutils/log.h"
+#include <stdlib.h>
+
+#include <android/log.h>
+
#include "JniConstants.h"
#include "ScopedLocalFrame.h"
-#include <stdlib.h>
-
extern "C" {
extern void register_java_io_Console(JNIEnv* env);
@@ -54,7 +55,6 @@
extern void register_java_net_DatagramPacket(JNIEnv*);
extern void register_java_net_Inet4Address(JNIEnv*);
extern void register_java_net_Inet6Address(JNIEnv*);
-extern void register_java_net_Inet6AddressImpl(JNIEnv*);
extern void register_java_net_InetAddress(JNIEnv*);
extern void register_java_net_PlainDatagramSocketImpl(JNIEnv*);
extern void register_java_net_PlainSocketImpl(JNIEnv*);
@@ -131,7 +131,6 @@
register_java_net_PlainSocketImpl(env);
register_java_net_PlainDatagramSocketImpl(env);
register_java_net_DatagramPacket(env);
- register_java_net_Inet6AddressImpl(env);
register_java_net_SocketInputStream(env);
register_java_net_SocketOutputStream(env);
register_java_nio_Bits(env);
diff --git a/ojluni/src/main/native/System.c b/ojluni/src/main/native/System.c
index 4c547c0..863a8c5 100644
--- a/ojluni/src/main/native/System.c
+++ b/ojluni/src/main/native/System.c
@@ -22,19 +22,22 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-#include <string.h>
-#include <stdlib.h>
+#define LOG_TAG "libcore"
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <android/log.h>
+
+#include "io_util.h"
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
-#include "io_util.h"
-
#include "openssl/opensslv.h"
#include "zlib.h"
#include "JNIHelp.h"
-#include "cutils/log.h"
#if defined(__ANDROID__)
void android_get_LD_LIBRARY_PATH(char*, size_t);
#endif
diff --git a/ojluni/src/main/native/UnixFileSystem_md.c b/ojluni/src/main/native/UnixFileSystem_md.c
index ebed636..61f907c 100644
--- a/ojluni/src/main/native/UnixFileSystem_md.c
+++ b/ojluni/src/main/native/UnixFileSystem_md.c
@@ -82,7 +82,7 @@
WITH_PLATFORM_STRING(env, pathname, path) {
char canonicalPath[JVM_MAXPATHLEN];
- if (canonicalize(JVM_NativePath((char *)path),
+ if (canonicalize((char *)path,
canonicalPath, JVM_MAXPATHLEN) < 0) {
JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
} else {
@@ -133,6 +133,7 @@
return rv;
}
+// Android-changed: Name changed because of added thread policy check
JNIEXPORT jboolean JNICALL
Java_java_io_UnixFileSystem_checkAccess0(JNIEnv *env, jobject this,
jobject file, jint a)
@@ -140,6 +141,7 @@
jboolean rv = JNI_FALSE;
int mode = 0;
switch (a) {
+ // Android-changed: Added ACCESS_OK case
case java_io_FileSystem_ACCESS_OK:
mode = F_OK;
break;
@@ -162,7 +164,7 @@
return rv;
}
-
+// Android-changed: Name changed because of added thread policy check
JNIEXPORT jboolean JNICALL
Java_java_io_UnixFileSystem_setPermission0(JNIEnv *env, jobject this,
jobject file,
@@ -210,6 +212,7 @@
return rv;
}
+// Android-changed: Name changed because of added thread policy check
JNIEXPORT jlong JNICALL
Java_java_io_UnixFileSystem_getLastModifiedTime0(JNIEnv *env, jobject this,
jobject file)
@@ -225,7 +228,7 @@
return rv;
}
-
+// Android-changed: Name changed because of added thread policy check
JNIEXPORT jlong JNICALL
Java_java_io_UnixFileSystem_getLength0(JNIEnv *env, jobject this,
jobject file)
@@ -244,7 +247,7 @@
/* -- File operations -- */
-
+// Android-changed: Name changed because of added thread policy check
JNIEXPORT jboolean JNICALL
Java_java_io_UnixFileSystem_createFileExclusively0(JNIEnv *env, jclass cls,
jstring pathname)
@@ -252,19 +255,18 @@
jboolean rv = JNI_FALSE;
WITH_PLATFORM_STRING(env, pathname, path) {
- int fd;
- if (!strcmp (path, "/")) {
- fd = JVM_EEXIST; /* The root directory always exists */
- } else {
- fd = JVM_Open(path, JVM_O_RDWR | JVM_O_CREAT | JVM_O_EXCL, 0666);
- }
- if (fd < 0) {
- if (fd != JVM_EEXIST) {
- JNU_ThrowIOExceptionWithLastError(env, path);
+ FD fd;
+ /* The root directory always exists */
+ if (strcmp (path, "/")) {
+ fd = handleOpen(path, O_RDWR | O_CREAT | O_EXCL, 0666);
+ if (fd < 0) {
+ if (errno != EEXIST)
+ JNU_ThrowIOExceptionWithLastError(env, path);
+ } else {
+ if (close(fd) == -1)
+ JNU_ThrowIOExceptionWithLastError(env, path);
+ rv = JNI_TRUE;
}
- } else {
- JVM_Close(fd);
- rv = JNI_TRUE;
}
} END_PLATFORM_STRING(env, path);
return rv;
@@ -285,7 +287,7 @@
return rv;
}
-
+// Android-changed: Name changed because of added thread policy check
JNIEXPORT jobjectArray JNICALL
Java_java_io_UnixFileSystem_list0(JNIEnv *env, jobject this,
jobject file)
@@ -295,6 +297,11 @@
struct dirent64 *result;
int len, maxlen;
jobjectArray rv, old;
+ jclass str_class;
+
+ str_class = JNU_ClassString(env);
+ CHECK_NULL_RETURN(str_class, NULL);
+
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
dir = opendir(path);
@@ -311,7 +318,7 @@
/* Allocate an initial String array */
len = 0;
maxlen = 16;
- rv = (*env)->NewObjectArray(env, maxlen, JNU_ClassString(env), NULL);
+ rv = (*env)->NewObjectArray(env, maxlen, str_class, NULL);
if (rv == NULL) goto error;
/* Scan the directory */
@@ -321,8 +328,7 @@
continue;
if (len == maxlen) {
old = rv;
- rv = (*env)->NewObjectArray(env, maxlen <<= 1,
- JNU_ClassString(env), NULL);
+ rv = (*env)->NewObjectArray(env, maxlen <<= 1, str_class, NULL);
if (rv == NULL) goto error;
if (JNU_CopyObjectArray(env, rv, old, len) < 0) goto error;
(*env)->DeleteLocalRef(env, old);
@@ -341,7 +347,7 @@
/* Copy the final results into an appropriately-sized array */
old = rv;
- rv = (*env)->NewObjectArray(env, len, JNU_ClassString(env), NULL);
+ rv = (*env)->NewObjectArray(env, len, str_class, NULL);
if (rv == NULL) {
return NULL;
}
@@ -356,7 +362,7 @@
return NULL;
}
-
+// Android-changed: Name changed because of added thread policy check
JNIEXPORT jboolean JNICALL
Java_java_io_UnixFileSystem_createDirectory0(JNIEnv *env, jobject this,
jobject file)
@@ -388,6 +394,7 @@
return rv;
}
+// Android-changed: Name changed because of added thread policy check
JNIEXPORT jboolean JNICALL
Java_java_io_UnixFileSystem_setLastModifiedTime0(JNIEnv *env, jobject this,
jobject file, jlong time)
@@ -416,7 +423,7 @@
return rv;
}
-
+// Android-changed: Name changed because of added thread policy check
JNIEXPORT jboolean JNICALL
Java_java_io_UnixFileSystem_setReadOnly0(JNIEnv *env, jobject this,
jobject file)
@@ -434,6 +441,7 @@
return rv;
}
+// Android-changed: Name changed because of added thread policy check
JNIEXPORT jlong JNICALL
Java_java_io_UnixFileSystem_getSpace0(JNIEnv *env, jobject this,
jobject file, jint t)
diff --git a/ojluni/src/main/native/canonicalize_md.c b/ojluni/src/main/native/canonicalize_md.c
index 8fdacc9..832cae3 100644
--- a/ojluni/src/main/native/canonicalize_md.c
+++ b/ojluni/src/main/native/canonicalize_md.c
@@ -233,6 +233,7 @@
/* The subpath has a canonical path */
break;
}
+ // Android-changed: Added ENOTCONN case (b/26645585, b/26070583)
else if (errno == ENOENT || errno == ENOTDIR || errno == EACCES || errno == ENOTCONN) {
/* If the lookup of a particular subpath fails because the file
does not exist, because it is of the wrong type, or because
diff --git a/ojluni/src/main/native/io_util_md.c b/ojluni/src/main/native/io_util_md.c
index 430e983..8b8a687 100644
--- a/ojluni/src/main/native/io_util_md.c
+++ b/ojluni/src/main/native/io_util_md.c
@@ -62,6 +62,29 @@
}
#endif
+FD
+handleOpen(const char *path, int oflag, int mode) {
+ FD fd;
+ RESTARTABLE(open64(path, oflag, mode), fd);
+ if (fd != -1) {
+ struct stat64 buf64;
+ int result;
+ RESTARTABLE(fstat64(fd, &buf64), result);
+ if (result != -1) {
+ if (S_ISDIR(buf64.st_mode)) {
+ close(fd);
+ errno = EISDIR;
+ fd = -1;
+ }
+ } else {
+ close(fd);
+ fd = -1;
+ }
+ }
+ return fd;
+}
+
+
void
fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags)
{
@@ -74,26 +97,12 @@
while ((p > ps) && (*p == '/'))
*p-- = '\0';
#endif
- fd = JVM_Open(ps, flags, 0666);
- if (fd >= 0) {
- // BEGIN android
- // Posix open(2) fails with EISDIR only if you ask for write permission.
- // Java disallows reading directories too.
- struct stat stat;
- fstat(fd, &stat);
-
- if (S_ISDIR(stat.st_mode)) {
- close(fd);
- errno = EISDIR; // For Exception message
- throwFileNotFoundException(env, path);
- } else {
- // END android
- SET_FD(this, fd, fid);
- }
+ fd = handleOpen(ps, flags, 0666);
+ if (fd != -1) {
+ SET_FD(this, fd, fid);
} else {
throwFileNotFoundException(env, path);
}
-
} END_PLATFORM_STRING(env, ps);
}
diff --git a/ojluni/src/main/native/io_util_md.h b/ojluni/src/main/native/io_util_md.h
index ca7ab43..d2ceffc 100644
--- a/ojluni/src/main/native/io_util_md.h
+++ b/ojluni/src/main/native/io_util_md.h
@@ -32,6 +32,13 @@
#define FD jint
/*
+ * Prototypes for functions in io_util_md.c called from io_util.c,
+ * FileDescriptor.c, FileInputStream.c, FileOutputStream.c,
+ * UnixFileSystem_md.c
+ */
+FD handleOpen(const char *path, int oflag, int mode);
+
+/*
* Macros to set/get fd from the java.io.FileDescriptor. These
* macros rely on having an appropriately defined 'this' object
* within the scope in which they're used.
@@ -68,6 +75,15 @@
#define SET_HANDLE(fd) return (jlong)-1
/*
+ * Retry the operation if it is interrupted
+ */
+#define RESTARTABLE(_cmd, _result) do { \
+ do { \
+ _result = _cmd; \
+ } while((_result == -1) && (errno == EINTR)); \
+} while(0)
+
+/*
* IO helper function(s)
*/
void fileClose(JNIEnv *env, jobject this, jfieldID fid);
diff --git a/ojluni/src/main/native/java_net_Inet4AddressImpl.h b/ojluni/src/main/native/java_net_Inet4AddressImpl.h
deleted file mode 100644
index 8ee8820..0000000
--- a/ojluni/src/main/native/java_net_Inet4AddressImpl.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* This file was generated from java/net/Inet4AddressImpl.java and
- * is licensed under the same terms. The copyright and license information
- * for java/net/Inet4AddressImpl.java follows.
- *
- * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class java_net_Inet4AddressImpl */
-
-#ifndef _Included_java_net_Inet4AddressImpl
-#define _Included_java_net_Inet4AddressImpl
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: java_net_Inet4AddressImpl
- * Method: getLocalHostName
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL Inet4AddressImpl_getLocalHostName
- (JNIEnv *, jobject);
-
-/*
- * Class: java_net_Inet4AddressImpl
- * Method: lookupAllHostAddr
- * Signature: (Ljava/lang/String;)[Ljava/net/InetAddress;
- */
-JNIEXPORT jobjectArray JNICALL Inet4AddressImpl_lookupAllHostAddr
- (JNIEnv *, jobject, jstring);
-
-/*
- * Class: java_net_Inet4AddressImpl
- * Method: getHostByAddr
- * Signature: ([B)Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL Inet4AddressImpl_getHostByAddr
- (JNIEnv *, jobject, jbyteArray);
-
-/*
- * Class: java_net_Inet4AddressImpl
- * Method: isReachable0
- * Signature: ([BI[BI)Z
- */
-JNIEXPORT jboolean JNICALL Inet4AddressImpl_isReachable0
- (JNIEnv *, jobject, jbyteArray, jint, jbyteArray, jint);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/ojluni/src/main/native/jni_util.h b/ojluni/src/main/native/jni_util.h
index f82b5fd..d9f3848 100644
--- a/ojluni/src/main/native/jni_util.h
+++ b/ojluni/src/main/native/jni_util.h
@@ -278,6 +278,25 @@
#define IS_NULL(obj) ((obj) == NULL)
#define JNU_IsNull(env,obj) ((obj) == NULL)
+/************************************************************************
+ * Miscellaneous utilities used by the class libraries to return from
+ * a function if a value is NULL or an exception is pending.
+ */
+
+#define CHECK_NULL(x) \
+ do { \
+ if ((x) == NULL) { \
+ return; \
+ } \
+ } while (0) \
+
+#define CHECK_NULL_RETURN(x, y) \
+ do { \
+ if ((x) == NULL) { \
+ return (y); \
+ } \
+ } while (0) \
+
/************************************************************************
* Debugging utilities
diff --git a/ojluni/src/main/native/net_util.h b/ojluni/src/main/native/net_util.h
index 8888877..4b7310b 100644
--- a/ojluni/src/main/native/net_util.h
+++ b/ojluni/src/main/native/net_util.h
@@ -42,9 +42,6 @@
#define NET_ERROR(env, ex, msg) \
{ if (!(*env)->ExceptionOccurred(env)) JNU_ThrowByName(env, ex, msg); }
-#define CHECK_NULL(x) if ((x) == NULL) return;
-#define CHECK_NULL_RETURN(x, y) if ((x) == NULL) return y;
-
/************************************************************************
* Cached field IDs
*
diff --git a/ojluni/src/main/native/openjdksub.mk b/ojluni/src/main/native/openjdksub.mk
index 3a3fcb0..c68b01c 100644
--- a/ojluni/src/main/native/openjdksub.mk
+++ b/ojluni/src/main/native/openjdksub.mk
@@ -1,4 +1,4 @@
-\# -*- mode: makefile -*-
+# -*- mode: makefile -*-
# This file is included by the top-level libcore Android.mk.
# It's not a normal makefile, so we don't include CLEAR_VARS
# or BUILD_*_LIBRARY.
@@ -54,8 +54,6 @@
PlainSocketImpl.c \
PlainDatagramSocketImpl.c \
DatagramPacket.c \
- Inet4AddressImpl.c \
- Inet6AddressImpl.c \
ServerSocketChannelImpl.c \
SocketInputStream.c \
SocketOutputStream.c \
diff --git a/ojluni/src/main/native/sun_nio_fs_LinuxNativeDispatcher.h b/ojluni/src/main/native/sun_nio_fs_LinuxNativeDispatcher.h
index 6accb11..5295d4a 100644
--- a/ojluni/src/main/native/sun_nio_fs_LinuxNativeDispatcher.h
+++ b/ojluni/src/main/native/sun_nio_fs_LinuxNativeDispatcher.h
@@ -14,9 +14,6 @@
#undef sun_nio_fs_LinuxNativeDispatcher_SUPPORTS_BIRTHTIME
#define sun_nio_fs_LinuxNativeDispatcher_SUPPORTS_BIRTHTIME 65536L
-#define CHECK_NULL(x) if ((x) == NULL) return;
-#define CHECK_NULL_RETURN(x, y) if ((x) == NULL) return y;
-
/*
* Class: sun_nio_fs_LinuxNativeDispatcher
* Method: setmntent0
diff --git a/ojluni/src/main/native/sun_nio_fs_UnixNativeDispatcher.h b/ojluni/src/main/native/sun_nio_fs_UnixNativeDispatcher.h
index d67dfb9..efeba3e 100644
--- a/ojluni/src/main/native/sun_nio_fs_UnixNativeDispatcher.h
+++ b/ojluni/src/main/native/sun_nio_fs_UnixNativeDispatcher.h
@@ -14,9 +14,6 @@
#undef sun_nio_fs_UnixNativeDispatcher_SUPPORTS_BIRTHTIME
#define sun_nio_fs_UnixNativeDispatcher_SUPPORTS_BIRTHTIME 65536L
-#define CHECK_NULL(x) if ((x) == NULL) return;
-#define CHECK_NULL_RETURN(x, y) if ((x) == NULL) return y;
-
/*
* Class: sun_nio_fs_UnixNativeDispatcher
* Method: getcwd
diff --git a/openjdk_java_files.mk b/openjdk_java_files.mk
index c8cfc95..c3d2b17 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -1172,17 +1172,6 @@
ojluni/src/main/java/java/lang/invoke/MethodTypeForm.java \
ojluni/src/main/java/java/lang/invoke/Stable.java \
ojluni/src/main/java/java/lang/invoke/WrongMethodTypeException.java \
- ojluni/src/main/java/java/text/spi/BreakIteratorProvider.java \
- ojluni/src/main/java/java/text/spi/CollatorProvider.java \
- ojluni/src/main/java/java/text/spi/DateFormatProvider.java \
- ojluni/src/main/java/java/text/spi/DateFormatSymbolsProvider.java \
- ojluni/src/main/java/java/text/spi/DecimalFormatSymbolsProvider.java \
- ojluni/src/main/java/java/text/spi/NumberFormatProvider.java \
- ojluni/src/main/java/java/util/spi/CurrencyNameProvider.java \
- ojluni/src/main/java/java/util/spi/LocaleNameProvider.java \
- ojluni/src/main/java/java/util/spi/LocaleServiceProvider.java \
- ojluni/src/main/java/java/util/spi/ResourceBundleControlProvider.java \
- ojluni/src/main/java/java/util/spi/TimeZoneNameProvider.java \
ojluni/src/main/java/jdk/net/ExtendedSocketOptions.java \
ojluni/src/main/java/jdk/net/NetworkPermission.java \
ojluni/src/main/java/jdk/net/SocketFlow.java \
@@ -1432,7 +1421,6 @@
ojluni/src/main/java/sun/security/action/GetIntegerAction.java \
ojluni/src/main/java/sun/security/action/GetPropertyAction.java \
ojluni/src/main/java/sun/security/action/LoadLibraryAction.java \
- ojluni/src/main/java/sun/security/action/PutAllAction.java \
ojluni/src/main/java/sun/security/jca/GetInstance.java \
ojluni/src/main/java/sun/security/jca/JCAUtil.java \
ojluni/src/main/java/sun/security/jca/ProviderConfig.java \
@@ -1599,7 +1587,6 @@
ojluni/src/main/java/sun/util/locale/LocaleSyntaxException.java \
ojluni/src/main/java/sun/util/locale/LocaleUtils.java \
ojluni/src/main/java/sun/util/locale/ParseStatus.java \
- ojluni/src/main/java/sun/util/LocaleServiceProviderPool.java \
ojluni/src/main/java/sun/util/locale/StringTokenIterator.java \
ojluni/src/main/java/sun/util/locale/UnicodeLocaleExtension.java \
ojluni/src/main/java/sun/util/logging/LoggingProxy.java \
diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java
index 1f6756e..42faad7 100644
--- a/support/src/test/java/libcore/java/security/StandardNames.java
+++ b/support/src/test/java/libcore/java/security/StandardNames.java
@@ -222,6 +222,10 @@
provide("Mac", "HmacSHA256");
provide("Mac", "HmacSHA384");
provide("Mac", "HmacSHA512");
+ provide("Mac", "PBEWITHHMACSHA224");
+ provide("Mac", "PBEWITHHMACSHA256");
+ provide("Mac", "PBEWITHHMACSHA384");
+ provide("Mac", "PBEWITHHMACSHA512");
// If adding a new MessageDigest, consider adding it to JarVerifier
provide("MessageDigest", "MD2");
provide("MessageDigest", "MD5");
@@ -244,6 +248,10 @@
provide("SecretKeyFactory", "PBEWithSHA1AndDESede");
provide("SecretKeyFactory", "PBEWithSHA1AndRC2_40");
provide("SecretKeyFactory", "PBKDF2WithHmacSHA1");
+ provide("SecretKeyFactory", "PBKDF2WithHmacSHA224");
+ provide("SecretKeyFactory", "PBKDF2WithHmacSHA256");
+ provide("SecretKeyFactory", "PBKDF2WithHmacSHA384");
+ provide("SecretKeyFactory", "PBKDF2WithHmacSHA512");
provide("SecretKeyFactory", "PBKDF2WithHmacSHA1And8bit");
provide("SecureRandom", "SHA1PRNG");
provide("Signature", "MD2withRSA");
diff --git a/support/src/test/java/libcore/tlswire/handshake/ClientHello.java b/support/src/test/java/libcore/tlswire/handshake/ClientHello.java
index ec88662..dd42cb1 100644
--- a/support/src/test/java/libcore/tlswire/handshake/ClientHello.java
+++ b/support/src/test/java/libcore/tlswire/handshake/ClientHello.java
@@ -18,12 +18,12 @@
import libcore.tlswire.util.TlsProtocolVersion;
import libcore.tlswire.util.IoUtils;
-import libcore.util.HexEncoding;
import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
+import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
@@ -98,8 +98,8 @@
@Override
public String toString() {
return "ClientHello{client version: " + clientVersion
- + ", random: " + new String(HexEncoding.encode(random))
- + ", sessionId: " + new String(HexEncoding.encode(sessionId))
+ + ", random: " + new BigInteger(1, random).toString(16)
+ + ", sessionId: " + new BigInteger(1, sessionId).toString(16)
+ ", cipher suites: " + cipherSuites
+ ", compression methods: " + compressionMethods
+ ((extensions != null) ? (", extensions: " + String.valueOf(extensions)) : "")
diff --git a/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java b/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java
index 2a77687..567c082 100644
--- a/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java
+++ b/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java
@@ -17,9 +17,9 @@
package libcore.tlswire.handshake;
import libcore.tlswire.util.IoUtils;
-import libcore.util.HexEncoding;
import java.io.DataInput;
import java.io.IOException;
+import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
@@ -100,6 +100,7 @@
@Override
public String toString() {
- return "HelloExtension{type: " + name + ", data: " + HexEncoding.encode(data) + "}";
+ return "HelloExtension{type: " + name + ", data: " + new BigInteger(1, data).toString(16)
+ + "}";
}
}
diff --git a/support/src/test/java/org/apache/harmony/xnet/tests/support/mySSLSession.java b/support/src/test/java/org/apache/harmony/xnet/tests/support/mySSLSession.java
index 6ca6177..b0efb91d 100644
--- a/support/src/test/java/org/apache/harmony/xnet/tests/support/mySSLSession.java
+++ b/support/src/test/java/org/apache/harmony/xnet/tests/support/mySSLSession.java
@@ -63,7 +63,7 @@
}
public long getCreationTime() {
- return 1000l;
+ return 1000L;
}
public byte[] getId() {
@@ -71,7 +71,7 @@
}
public long getLastAccessedTime() {
- return 2000l;
+ return 2000L;
}
public Certificate[] getLocalCertificates() {
diff --git a/support/src/test/java/tests/support/Support_ClassLoader.java b/support/src/test/java/tests/support/Support_ClassLoader.java
index 3ba1d7e..1c372d4 100644
--- a/support/src/test/java/tests/support/Support_ClassLoader.java
+++ b/support/src/test/java/tests/support/Support_ClassLoader.java
@@ -19,8 +19,6 @@
import java.net.URL;
import java.net.URLClassLoader;
-import dalvik.system.DexClassLoader;
-
/**
* Support class for creating a file-based ClassLoader. Delegates to either
* Dalvik's PathClassLoader or the RI's URLClassLoader, but does so by-name.
@@ -34,12 +32,13 @@
try {
Support_ClassLoader factory;
+ String packageName = Support_ClassLoader.class.getPackage().getName();
if ("Dalvik".equals(System.getProperty("java.vm.name"))) {
factory = (Support_ClassLoader)Class.forName(
- "tests.support.Support_ClassLoader$Dalvik").newInstance();
+ packageName + ".Support_ClassLoaderDalvik").newInstance();
} else {
factory = (Support_ClassLoader)Class.forName(
- "tests.support.Support_ClassLoader$RefImpl").newInstance();
+ packageName + ".Support_ClassLoader$RefImpl").newInstance();
}
return factory.getClassLoader(url, parent);
@@ -49,29 +48,6 @@
}
/**
- * Implementation for Dalvik. Uses the DexClassLoader, so we can write
- * temporary DEX files to a special directory. We don't want to spoil the
- * system's DEX cache with our files. Also, we might not have write access
- * to the system's DEX cache at all (which is the case when we're running
- * CTS).
- */
- static class Dalvik extends Support_ClassLoader {
-
- private static File tmp;
-
- static {
- tmp = new File(System.getProperty("java.io.tmpdir"), "dex-cache");
- tmp.mkdirs();
- }
-
- @Override
- public ClassLoader getClassLoader(URL url, ClassLoader parent) {
- return new DexClassLoader(url.getPath(), tmp.getAbsolutePath(),
- null, parent);
- }
- }
-
- /**
* Implementation for the reference implementation. Nothing interesting to
* see here. Please get along.
*/
diff --git a/support/src/test/java/tests/support/Support_ClassLoaderDalvik.java b/support/src/test/java/tests/support/Support_ClassLoaderDalvik.java
new file mode 100644
index 0000000..17a4b13
--- /dev/null
+++ b/support/src/test/java/tests/support/Support_ClassLoaderDalvik.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 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 tests.support;
+
+import java.io.File;
+import java.net.URL;
+
+import dalvik.system.DexClassLoader;
+
+/**
+ * Implementation for Dalvik. Uses the DexClassLoader, so we can write
+ * temporary DEX files to a special directory. We don't want to spoil the
+ * system's DEX cache with our files. Also, we might not have write access
+ * to the system's DEX cache at all (which is the case when we're running
+ * CTS).
+ */
+class Support_ClassLoaderDalvik extends Support_ClassLoader {
+
+ private static File tmp;
+
+ static {
+ tmp = new File(System.getProperty("java.io.tmpdir"), "dex-cache");
+ tmp.mkdirs();
+ }
+
+ @Override
+ public ClassLoader getClassLoader(URL url, ClassLoader parent) {
+ return new DexClassLoader(url.getPath(), tmp.getAbsolutePath(),
+ null, parent);
+ }
+}
diff --git a/support/src/test/java/tests/support/Support_GetPutFields.java b/support/src/test/java/tests/support/Support_GetPutFields.java
index 3cf0d91..d4f49a6 100644
--- a/support/src/test/java/tests/support/Support_GetPutFields.java
+++ b/support/src/test/java/tests/support/Support_GetPutFields.java
@@ -79,7 +79,7 @@
charValue = 'B';
doubleValue = 424242.42;
floatValue = 24.12f;
- longValue = 6700654321l;
+ longValue = 6700654321L;
intValue = 77777;
objectValue = new SimpleClass(1965, "Hello Mars");
shortValue = 1234;
diff --git a/support/src/test/java/tests/support/Support_GetPutFieldsDefaulted.java b/support/src/test/java/tests/support/Support_GetPutFieldsDefaulted.java
index 25b7417..a093134 100644
--- a/support/src/test/java/tests/support/Support_GetPutFieldsDefaulted.java
+++ b/support/src/test/java/tests/support/Support_GetPutFieldsDefaulted.java
@@ -90,7 +90,7 @@
charValue = 'D';
doubleValue = 523452.4532;
floatValue = 298.54f;
- longValue = 1234567890l;
+ longValue = 1234567890L;
intValue = 999999;
objectValue = new SimpleClass(1965, "Hello Jupiter");
shortValue = 4321;
@@ -121,7 +121,7 @@
charValue = getField.get("charValue", (char) 'D');
doubleValue = getField.get("doubleValue", 523452.4532);
floatValue = getField.get("floatValue", 298.54f);
- longValue = getField.get("longValue", (long) 1234567890l);
+ longValue = getField.get("longValue", (long) 1234567890L);
intValue = getField.get("intValue", 999999);
objectValue = (Support_GetPutFieldsDefaulted.SimpleClass)
getField.get("objectValue",
diff --git a/support/src/test/java/tests/support/Support_GetPutFieldsDeprecated.java b/support/src/test/java/tests/support/Support_GetPutFieldsDeprecated.java
index 0f54e3e..19e9181 100644
--- a/support/src/test/java/tests/support/Support_GetPutFieldsDeprecated.java
+++ b/support/src/test/java/tests/support/Support_GetPutFieldsDeprecated.java
@@ -81,7 +81,7 @@
charValue = 'A';
doubleValue = 1231.342;
floatValue = 43.22f;
- longValue = 1560732321l;
+ longValue = 1560732321L;
intValue = 33333;
objectValue = new SimpleClass(2001, "A Space Odyssey");
shortValue = 3078;
diff --git a/test-rules/src/main/java/libcore/junit/junit3/TestCaseWithRules.java b/test-rules/src/main/java/libcore/junit/junit3/TestCaseWithRules.java
new file mode 100644
index 0000000..b5acc82
--- /dev/null
+++ b/test-rules/src/main/java/libcore/junit/junit3/TestCaseWithRules.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 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.junit.junit3;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import junit.framework.TestCase;
+import org.junit.Rule;
+import org.junit.rules.MethodRule;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.MultipleFailureException;
+import org.junit.runners.model.Statement;
+import org.junit.runners.model.TestClass;
+
+import static org.junit.internal.runners.rules.RuleFieldValidator.RULE_VALIDATOR;
+
+/**
+ * A {@link TestCase} that supports the @Rule annotation from JUnit 4.
+ *
+ * <p>It supports both {@link TestRule} and {@link MethodRule} based rules when used with the
+ * {@code @Rule} annotation on public fields. The rules encapsulate the {@link TestCase#runBare()}
+ * method and so are run before the {@link TestCase#setUp()} and after the
+ * {@link TestCase#tearDown()} methods.
+ *
+ * <p>Classes that extend this must have a single no argument constructor.
+ */
+public abstract class TestCaseWithRules extends TestCase {
+
+ private final TestClass testClass;
+
+ private final List<Throwable> validationErrors;
+
+ public TestCaseWithRules() {
+ testClass = new TestClass(getClass());
+
+ validationErrors = new ArrayList<>();
+ RULE_VALIDATOR.validate(testClass, validationErrors);
+ }
+
+ @Override
+ public void runBare() throws Throwable {
+ if (!validationErrors.isEmpty()) {
+ throw new MultipleFailureException(validationErrors);
+ }
+
+ Statement statement = new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ superRunBare();
+ }
+ };
+
+ final String name = getName();
+ FrameworkMethod frameworkMethod;
+ try {
+ Method method = getClass().getMethod(name, (Class[]) null);
+ frameworkMethod = new FrameworkMethod(method);
+ } catch (NoSuchMethodException e) {
+ frameworkMethod = new FrameworkMethod(null) {
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public Annotation[] getAnnotations() {
+ return new Annotation[0];
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
+ return null;
+ }
+ };
+ }
+ Description description =
+ Description.createTestDescription(getClass(), frameworkMethod.getName(),
+ frameworkMethod.getAnnotations());
+
+ List<Object> rules = testClass.getAnnotatedFieldValues(this, Rule.class, Object.class);
+ for (Object rule : rules) {
+ if (rule instanceof TestRule) {
+ statement = ((TestRule) rule).apply(statement, description);
+ } else {
+ statement = ((MethodRule) rule).apply(statement, frameworkMethod, this);
+ }
+ }
+
+ statement.evaluate();
+ }
+
+ private void superRunBare() throws Throwable {
+ super.runBare();
+ }
+}
diff --git a/test-rules/src/main/java/libcore/junit/util/ResourceLeakageDetector.java b/test-rules/src/main/java/libcore/junit/util/ResourceLeakageDetector.java
new file mode 100644
index 0000000..dae7978
--- /dev/null
+++ b/test-rules/src/main/java/libcore/junit/util/ResourceLeakageDetector.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2016 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.junit.util;
+
+import java.lang.reflect.Method;
+import java.util.function.BiConsumer;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Provides support for testing classes that own resources which must not leak.
+ *
+ * <p><strong>This will not detect any resource leakages in OpenJDK</strong></p>
+ */
+public class ResourceLeakageDetector {
+ private static final LeakageDetectorRule LEAKAGE_DETECTOR_RULE;
+ private static final BiConsumer<Object, Integer> FINALIZER_CHECKER;
+
+ static {
+ LeakageDetectorRule leakageDetectorRule;
+ BiConsumer<Object, Integer> finalizerChecker;
+ try {
+ // Make sure that the CloseGuard class exists; this ensures that this is not
+ // running on a RI JVM.
+ Class.forName("dalvik.system.CloseGuard");
+
+ // Access the underlying support class using reflection in order to prevent any compile
+ // time dependencies on it so as to allow this to compile on OpenJDK.
+ Class<?> closeGuardSupportClass = Class.forName("dalvik.system.CloseGuardSupport");
+ Method method = closeGuardSupportClass.getMethod("getRule");
+ leakageDetectorRule = new LeakageDetectorRule((TestRule) method.invoke(null));
+
+ finalizerChecker = getFinalizerChecker(closeGuardSupportClass);
+
+ } catch (ReflectiveOperationException e) {
+ System.err.println("Resource leakage will not be detected; "
+ + "this is expected in the reference implementation");
+ e.printStackTrace(System.err);
+
+ // Could not access the class for some reason so have a rule that does nothing and a
+ // finalizer checker that checks nothing. This should ensure that tests work properly
+ // on OpenJDK even though it does not support CloseGuard.
+ leakageDetectorRule = new LeakageDetectorRule(RuleChain.emptyRuleChain());
+ finalizerChecker = new BiConsumer<Object, Integer>() {
+ @Override
+ public void accept(Object o, Integer integer) {
+ // Do nothing.
+ }
+ };
+ }
+
+ LEAKAGE_DETECTOR_RULE = leakageDetectorRule;
+ FINALIZER_CHECKER = finalizerChecker;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static BiConsumer<Object, Integer> getFinalizerChecker(Class<?> closeGuardSupportClass)
+ throws ReflectiveOperationException {
+ Method method = closeGuardSupportClass.getMethod("getFinalizerChecker");
+ return (BiConsumer<Object, Integer>) method.invoke(null);
+ }
+
+ /**
+ * @return the {@link LeakageDetectorRule}
+ */
+ public static LeakageDetectorRule getRule() {
+ return LEAKAGE_DETECTOR_RULE;
+ }
+
+ /**
+ * A {@link TestRule} that will fail a test if it detects any resources that were allocated
+ * during the test but were not released.
+ *
+ * <p>This only tracks resources that were allocated on the test thread, although it does not
+ * care what thread they were released on. This avoids flaky false positives where a background
+ * thread allocates a resource during a test but releases it after the test.
+ *
+ * <p>It is still possible to have a false positive in the case where the test causes a caching
+ * mechanism to open a resource and hold it open past the end of the test. In that case if there
+ * is no way to clear the cached data then it should be relatively simple to move the code that
+ * invokes the caching mechanism to outside the scope of this rule. i.e.
+ *
+ * <pre>{@code
+ * @Rule
+ * public final TestRule ruleChain = org.junit.rules.RuleChain
+ * .outerRule(new ...invoke caching mechanism...)
+ * .around(CloseGuardSupport.getRule());
+ * }</pre>
+ *
+ * @return a {@link TestRule} that detects resource leakages, or one that does nothing if
+ * resource leakage detection is not supported.
+ */
+ public static class LeakageDetectorRule implements TestRule {
+
+ private final TestRule leakageDetectorRule;
+
+ private LeakageDetectorRule(TestRule leakageDetectorRule) {
+ this.leakageDetectorRule = leakageDetectorRule;
+ }
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return leakageDetectorRule.apply(base, description);
+ }
+
+ /**
+ * Ensure that when the supplied object is finalized that it detects the expected number of
+ * unreleased resources.
+ *
+ * <p>This helps ensure that classes which own resources protected using {@code CloseGuard}
+ * support leakage detection.
+ *
+ * <p>This must only be called from within the test currently being run otherwise it will
+ * fail if the resource leakage detected mechanism is disabled, e.g. in CTS.
+ *
+ * <p>Use as follows:
+ * <pre>
+ * Object object = ...create and 'open' an object encapsulating a protected resource...;
+ * // Check to make sure that the object reports a resource leak when it is finalized.
+ * assertUnreleasedResourceCount(object, 1);
+ *
+ * object = ... create, 'open' and then 'close' another object ...;
+ * // Check to make sure that the object does not have any unreleased resources.
+ * assertUnreleasedResourceCount(object, 0);
+ * </pre>
+ *
+ * @param owner the object that owns the resource and uses {@code CloseGuard} object to detect
+ * when the resource is not released.
+ * @param expectedCount the expected number of unreleased resources.
+ */
+ public void assertUnreleasedResourceCount(Object owner, int expectedCount) {
+ FINALIZER_CHECKER.accept(owner, expectedCount);
+ }
+ }
+}