From 6f5991fa38f314220a67b01f07ab500aa62c4446 Mon Sep 17 00:00:00 2001 From: Jon Masamitsu Date: Thu, 3 Jan 2013 15:03:27 -0800 Subject: [PATCH 001/158] 8004895: NPG: JMapPermCore test failure caused by warnings about missing field Reviewed-by: johnc --- .../compactibleFreeListSpace.cpp | 14 +++++++++----- .../compactibleFreeListSpace.hpp | 2 +- .../concurrentMarkSweep/vmStructs_cms.hpp | 8 +++----- .../src/share/vm/memory/binaryTreeDictionary.cpp | 6 +++--- .../src/share/vm/memory/binaryTreeDictionary.hpp | 4 ++++ hotspot/src/share/vm/runtime/vmStructs.cpp | 3 +-- 6 files changed, 21 insertions(+), 16 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index 45e53170859..c2a9cbe330b 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -102,7 +102,7 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, // temporarily disabled). switch (dictionaryChoice) { case FreeBlockDictionary::dictionaryBinaryTree: - _dictionary = new BinaryTreeDictionary(mr); + _dictionary = new AFLBinaryTreeDictionary(mr); break; case FreeBlockDictionary::dictionarySplayTree: case FreeBlockDictionary::dictionarySkipList: @@ -122,7 +122,8 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, // moved to its new location before the klass is moved. // Set the _refillSize for the linear allocation blocks if (!use_adaptive_freelists) { - FreeChunk* fc = _dictionary->get_chunk(mr.word_size()); + FreeChunk* fc = _dictionary->get_chunk(mr.word_size(), + FreeBlockDictionary::atLeast); // The small linAB initially has all the space and will allocate // a chunk of any size. HeapWord* addr = (HeapWord*) fc; @@ -1647,7 +1648,8 @@ CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size, FreeChunk* CompactibleFreeListSpace::getChunkFromDictionary(size_t size) { assert_locked(); - FreeChunk* fc = _dictionary->get_chunk(size); + FreeChunk* fc = _dictionary->get_chunk(size, + FreeBlockDictionary::atLeast); if (fc == NULL) { return NULL; } @@ -1664,7 +1666,8 @@ CompactibleFreeListSpace::getChunkFromDictionary(size_t size) { FreeChunk* CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) { assert_locked(); - FreeChunk* fc = _dictionary->get_chunk(size); + FreeChunk* fc = _dictionary->get_chunk(size, + FreeBlockDictionary::atLeast); if (fc == NULL) { return fc; } @@ -1677,7 +1680,8 @@ CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) { if (fc->size() < size + MinChunkSize) { // Return the chunk to the dictionary and go get a bigger one. returnChunkToDictionary(fc); - fc = _dictionary->get_chunk(size + MinChunkSize); + fc = _dictionary->get_chunk(size + MinChunkSize, + FreeBlockDictionary::atLeast); if (fc == NULL) { return NULL; } diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp index 1b3d93ed248..23c95897cfa 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp @@ -131,7 +131,7 @@ class CompactibleFreeListSpace: public CompactibleSpace { LinearAllocBlock _smallLinearAllocBlock; FreeBlockDictionary::DictionaryChoice _dictionaryChoice; - FreeBlockDictionary* _dictionary; // ptr to dictionary for large size blocks + AFLBinaryTreeDictionary* _dictionary; // ptr to dictionary for large size blocks AdaptiveFreeList _indexedFreeList[IndexSetSize]; // indexed array for small size blocks diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp index a67e19d89d2..3a8499b27e3 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp @@ -25,8 +25,6 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_VMSTRUCTS_CMS_HPP #define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_VMSTRUCTS_CMS_HPP -typedef BinaryTreeDictionary AFLBinaryTreeDictionary; - #define VM_STRUCTS_CMS(nonstatic_field, \ volatile_nonstatic_field, \ static_field) \ @@ -42,6 +40,7 @@ typedef BinaryTreeDictionary AFLBinaryTreeDictionar static_field(ConcurrentMarkSweepThread, _collector, CMSCollector*) \ nonstatic_field(LinearAllocBlock, _word_size, size_t) \ nonstatic_field(AFLBinaryTreeDictionary, _total_size, size_t) \ + nonstatic_field(CompactibleFreeListSpace, _dictionary, AFLBinaryTreeDictionary*) \ nonstatic_field(CompactibleFreeListSpace, _indexedFreeList[0], FreeList) \ nonstatic_field(CompactibleFreeListSpace, _smallLinearAllocBlock, LinearAllocBlock) @@ -62,10 +61,9 @@ typedef BinaryTreeDictionary AFLBinaryTreeDictionar declare_toplevel_type(SurrogateLockerThread*) \ declare_toplevel_type(CompactibleFreeListSpace*) \ declare_toplevel_type(CMSCollector*) \ - declare_toplevel_type(AFLBinaryTreeDictionary*) \ + declare_toplevel_type(AFLBinaryTreeDictionary) \ declare_toplevel_type(LinearAllocBlock) \ - declare_toplevel_type(FreeBlockDictionary) \ - declare_type(AFLBinaryTreeDictionary, FreeBlockDictionary) + declare_toplevel_type(FreeBlockDictionary) #define VM_INT_CONSTANTS_CMS(declare_constant) \ declare_constant(Generation::ConcurrentMarkSweep) \ diff --git a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp index 725a71925dc..1bb78ca99fd 100644 --- a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp +++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp @@ -873,7 +873,7 @@ void BinaryTreeDictionary::dict_census_update(size_t size, #ifndef SERIALGC template <> -void BinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){ +void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){ TreeList* nd = find_list(size); if (nd) { if (split) { @@ -911,7 +911,7 @@ bool BinaryTreeDictionary::coal_dict_over_populated(size_t #ifndef SERIALGC template <> -bool BinaryTreeDictionary::coal_dict_over_populated(size_t size) { +bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) { if (FLSAlwaysCoalesceLarge) return true; TreeList* list_of_size = find_list(size); @@ -1288,7 +1288,7 @@ void BinaryTreeDictionary::print_dict_census(void) const { #ifndef SERIALGC template <> -void BinaryTreeDictionary::print_dict_census(void) const { +void AFLBinaryTreeDictionary::print_dict_census(void) const { gclog_or_tty->print("\nBinaryTree\n"); AdaptiveFreeList::print_labels_on(gclog_or_tty, "size"); diff --git a/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp b/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp index 757eb4fdac9..460a4ea29e1 100644 --- a/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp +++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.hpp @@ -43,6 +43,10 @@ template class FreeList_t> class AscendTreeCens template class FreeList_t> class DescendTreeCensusClosure; template class FreeList_t> class DescendTreeSearchClosure; +class FreeChunk; +template class AdaptiveFreeList; +typedef BinaryTreeDictionary AFLBinaryTreeDictionary; + template class FreeList_t> class TreeList : public FreeList_t { friend class TreeChunk; diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index e180f7d449f..70e5d2b9281 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -2087,8 +2087,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_toplevel_type(FreeBlockDictionary*) \ declare_toplevel_type(FreeList*) \ declare_toplevel_type(FreeList) \ - declare_toplevel_type(MetablockTreeDictionary*) \ - declare_type(MetablockTreeDictionary, FreeBlockDictionary) + declare_type(MetablockTreeDictionary, FreeBlockDictionary) //-------------------------------------------------------------------------------- From 99039568f9c461b5c35a328c10504863e0f840c2 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 23 Jan 2013 10:34:29 -0500 Subject: [PATCH 002/158] 8006040: NPG: on_stack processing wastes space in ConstantPool Added on_stack bit to flags. Also MetadataMarkOnStack is used for more than JVMTI so had to be moved. Reviewed-by: dholmes, stefank --- .../share/vm/classfile/classLoaderData.cpp | 5 +- .../vm/classfile/metadataOnStackMark.cpp | 69 +++++++++++++++++++ .../vm/classfile/metadataOnStackMark.hpp | 45 ++++++++++++ .../src/share/vm/interpreter/linkResolver.cpp | 4 +- hotspot/src/share/vm/oops/constantPool.cpp | 24 +++---- hotspot/src/share/vm/oops/constantPool.hpp | 42 ++++++----- hotspot/src/share/vm/oops/method.cpp | 6 +- .../share/vm/prims/jvmtiRedefineClasses.cpp | 38 +--------- .../share/vm/prims/jvmtiRedefineClasses.hpp | 15 +--- 9 files changed, 152 insertions(+), 96 deletions(-) create mode 100644 hotspot/src/share/vm/classfile/metadataOnStackMark.cpp create mode 100644 hotspot/src/share/vm/classfile/metadataOnStackMark.hpp diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index 22cc8cf9bb1..0560d3f4886 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -50,11 +50,12 @@ #include "classfile/classLoaderData.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/javaClasses.hpp" +#include "classfile/metadataOnStackMark.hpp" #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceShared.hpp" -#include "prims/jvmtiRedefineClasses.hpp" +#include "memory/oopFactory.hpp" #include "runtime/jniHandles.hpp" #include "runtime/mutex.hpp" #include "runtime/safepoint.hpp" diff --git a/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp b/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp new file mode 100644 index 00000000000..1f24042f5cb --- /dev/null +++ b/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 "precompiled.hpp" +#include "classfile/metadataOnStackMark.hpp" +#include "code/codeCache.hpp" +#include "compiler/compileBroker.hpp" +#include "oops/metadata.hpp" +#include "runtime/synchronizer.hpp" +#include "runtime/thread.hpp" +#include "utilities/growableArray.hpp" + + +// Keep track of marked on-stack metadata so it can be cleared. +GrowableArray* _marked_objects = NULL; +NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;) + +// Walk metadata on the stack and mark it so that redefinition doesn't delete +// it. Class unloading also walks the previous versions and might try to +// delete it, so this class is used by class unloading also. +MetadataOnStackMark::MetadataOnStackMark() { + assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); + NOT_PRODUCT(_is_active = true;) + if (_marked_objects == NULL) { + _marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray(1000, true); + } + Threads::metadata_do(Metadata::mark_on_stack); + CodeCache::alive_nmethods_do(nmethod::mark_on_stack); + CompileBroker::mark_on_stack(); +} + +MetadataOnStackMark::~MetadataOnStackMark() { + assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); + // Unmark everything that was marked. Can't do the same walk because + // redefine classes messes up the code cache so the set of methods + // might not be the same. + for (int i = 0; i< _marked_objects->length(); i++) { + _marked_objects->at(i)->set_on_stack(false); + } + _marked_objects->clear(); // reuse growable array for next time. + NOT_PRODUCT(_is_active = false;) +} + +// Record which objects are marked so we can unmark the same objects. +void MetadataOnStackMark::record(Metadata* m) { + assert(_is_active, "metadata on stack marking is active"); + _marked_objects->push(m); +} diff --git a/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp b/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp new file mode 100644 index 00000000000..5a4fda2f332 --- /dev/null +++ b/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + * + */ + +#ifndef SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP +#define SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP + +#include "memory/allocation.hpp" + +class Metadata; + +// Helper class to mark and unmark metadata used on the stack as either handles +// or executing methods, so that it can't be deleted during class redefinition +// and class unloading. +// This is also used for other things that can be deallocated, like class +// metadata during parsing, relocated methods, and methods in backtraces. +class MetadataOnStackMark : public StackObj { + NOT_PRODUCT(static bool _is_active;) + public: + MetadataOnStackMark(); + ~MetadataOnStackMark(); + static void record(Metadata* m); +}; + +#endif // SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index 959388fc693..efb2a164fa2 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -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 @@ -1241,7 +1241,7 @@ void LinkResolver::resolve_handle_call(CallInfo& result, KlassHandle resolved_kl void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { assert(EnableInvokeDynamic, ""); - pool->set_invokedynamic(); // mark header to flag active call sites + pool->set_has_invokedynamic(); // mark header to flag active call sites //resolve_pool(, method_name, method_signature, current_klass, pool, index, CHECK); Symbol* method_name = pool->name_ref_at(index); diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index 770510c7880..d4fa72032df 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "classfile/classLoaderData.hpp" #include "classfile/javaClasses.hpp" +#include "classfile/metadataOnStackMark.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" @@ -34,7 +35,6 @@ #include "oops/constantPool.hpp" #include "oops/instanceKlass.hpp" #include "oops/objArrayKlass.hpp" -#include "prims/jvmtiRedefineClasses.hpp" #include "runtime/fieldType.hpp" #include "runtime/init.hpp" #include "runtime/javaCalls.hpp" @@ -65,11 +65,10 @@ ConstantPool::ConstantPool(Array* tags) { set_operands(NULL); set_pool_holder(NULL); set_flags(0); + // only set to non-zero if constant pool is merged by RedefineClasses set_version(0); set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock")); - // all fields are initialized; needed for GC - set_on_stack(false); // initialize tag array int length = tags->length(); @@ -100,18 +99,6 @@ void ConstantPool::release_C_heap_structures() { set_lock(NULL); } -void ConstantPool::set_flag_at(FlagBit fb) { - const int MAX_STATE_CHANGES = 2; - for (int i = MAX_STATE_CHANGES + 10; i > 0; i--) { - int oflags = _flags; - int nflags = oflags | (1 << (int)fb); - if (Atomic::cmpxchg(nflags, &_flags, oflags) == oflags) - return; - } - assert(false, "failed to cmpxchg flags"); - _flags |= (1 << (int)fb); // better than nothing -} - objArrayOop ConstantPool::resolved_references() const { return (objArrayOop)JNIHandles::resolve(_resolved_references); } @@ -1755,7 +1742,11 @@ int ConstantPool::copy_cpool_bytes(int cpool_size, void ConstantPool::set_on_stack(const bool value) { - _on_stack = value; + if (value) { + _flags |= _on_stack; + } else { + _flags &= ~_on_stack; + } if (value) MetadataOnStackMark::record(this); } @@ -1827,6 +1818,7 @@ void ConstantPool::print_on(outputStream* st) const { if (has_pseudo_string()) st->print(" has_pseudo_string"); if (has_invokedynamic()) st->print(" has_invokedynamic"); if (has_preresolution()) st->print(" has_preresolution"); + if (on_stack()) st->print(" on_stack"); st->cr(); } if (pool_holder() != NULL) { diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index 65546021553..ea4b13f0f9d 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -95,10 +95,15 @@ class ConstantPool : public Metadata { jobject _resolved_references; Array* _reference_map; - int _flags; // a few header bits to describe contents for GC - int _length; // number of elements in the array + enum { + _has_invokedynamic = 1, // Flags + _has_pseudo_string = 2, + _has_preresolution = 4, + _on_stack = 8 + }; - bool _on_stack; // Redefined method still executing refers to this constant pool. + int _flags; // old fashioned bit twiddling + int _length; // number of elements in the array union { // set for CDS to restore resolved references @@ -115,17 +120,8 @@ class ConstantPool : public Metadata { void set_operands(Array* operands) { _operands = operands; } - enum FlagBit { - FB_has_invokedynamic = 1, - FB_has_pseudo_string = 2, - FB_has_preresolution = 3 - }; - - int flags() const { return _flags; } - void set_flags(int f) { _flags = f; } - bool flag_at(FlagBit fb) const { return (_flags & (1 << (int)fb)) != 0; } - void set_flag_at(FlagBit fb); - // no clear_flag_at function; they only increase + int flags() const { return _flags; } + void set_flags(int f) { _flags = f; } private: intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(ConstantPool)); } @@ -178,18 +174,20 @@ class ConstantPool : public Metadata { Array* tags() const { return _tags; } Array* operands() const { return _operands; } - bool has_pseudo_string() const { return flag_at(FB_has_pseudo_string); } - bool has_invokedynamic() const { return flag_at(FB_has_invokedynamic); } - bool has_preresolution() const { return flag_at(FB_has_preresolution); } - void set_pseudo_string() { set_flag_at(FB_has_pseudo_string); } - void set_invokedynamic() { set_flag_at(FB_has_invokedynamic); } - void set_preresolution() { set_flag_at(FB_has_preresolution); } + bool has_invokedynamic() const { return (_flags & _has_invokedynamic) != 0; } + void set_has_invokedynamic() { _flags |= _has_invokedynamic; } + + bool has_pseudo_string() const { return (_flags & _has_pseudo_string) != 0; } + void set_has_pseudo_string() { _flags |= _has_pseudo_string; } + + bool has_preresolution() const { return (_flags & _has_preresolution) != 0; } + void set_has_preresolution() { _flags |= _has_preresolution; } // Redefine classes support. If a method refering to this constant pool // is on the executing stack, or as a handle in vm code, this constant pool // can't be removed from the set of previous versions saved in the instance // class. - bool on_stack() const { return _on_stack; } + bool on_stack() const { return (_flags &_on_stack) != 0; } void set_on_stack(const bool value); // Klass holding pool @@ -457,7 +455,7 @@ class ConstantPool : public Metadata { void pseudo_string_at_put(int which, int obj_index, oop x) { assert(EnableInvokeDynamic, ""); - set_pseudo_string(); // mark header + set_has_pseudo_string(); // mark header assert(tag_at(which).is_string(), "Corrupted constant pool"); string_at_put(which, obj_index, x); // this works just fine } diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 936090f50c0..88645cb15e7 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -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 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/metadataOnStackMark.hpp" #include "classfile/systemDictionary.hpp" #include "code/debugInfoRec.hpp" #include "gc_interface/collectedHeap.inline.hpp" @@ -41,7 +42,6 @@ #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "prims/jvmtiExport.hpp" -#include "prims/jvmtiRedefineClasses.hpp" #include "prims/methodHandles.hpp" #include "prims/nativeLookup.hpp" #include "runtime/arguments.hpp" @@ -1027,7 +1027,7 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid, cp->set_pool_holder(InstanceKlass::cast(holder())); cp->symbol_at_put(_imcp_invoke_name, name); cp->symbol_at_put(_imcp_invoke_signature, signature); - cp->set_preresolution(); + cp->set_has_preresolution(); // decide on access bits: public or not? int flags_bits = (JVM_ACC_NATIVE | JVM_ACC_SYNTHETIC | JVM_ACC_FINAL); diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index 7e68f2b1059..7255579280b 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/metadataOnStackMark.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/verifier.hpp" #include "code/codeCache.hpp" @@ -115,43 +116,6 @@ bool VM_RedefineClasses::doit_prologue() { return true; } -// Keep track of marked on-stack metadata so it can be cleared. -GrowableArray* _marked_objects = NULL; -NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;) - -// Walk metadata on the stack and mark it so that redefinition doesn't delete -// it. Class unloading also walks the previous versions and might try to -// delete it, so this class is used by class unloading also. -MetadataOnStackMark::MetadataOnStackMark() { - assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); - NOT_PRODUCT(_is_active = true;) - if (_marked_objects == NULL) { - _marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray(1000, true); - } - Threads::metadata_do(Metadata::mark_on_stack); - CodeCache::alive_nmethods_do(nmethod::mark_on_stack); - CompileBroker::mark_on_stack(); -} - -MetadataOnStackMark::~MetadataOnStackMark() { - assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); - // Unmark everything that was marked. Can't do the same walk because - // redefine classes messes up the code cache so the set of methods - // might not be the same. - for (int i = 0; i< _marked_objects->length(); i++) { - _marked_objects->at(i)->set_on_stack(false); - } - _marked_objects->clear(); // reuse growable array for next time. - NOT_PRODUCT(_is_active = false;) -} - -// Record which objects are marked so we can unmark the same objects. -void MetadataOnStackMark::record(Metadata* m) { - assert(_is_active, "metadata on stack marking is active"); - _marked_objects->push(m); -} - - void VM_RedefineClasses::doit() { Thread *thread = Thread::current(); diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp index 7164413c8fa..23839670d98 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -487,17 +487,4 @@ class VM_RedefineClasses: public VM_Operation { // and redefine implementation static bool is_modifiable_class(oop klass_mirror); }; - - -// Helper class to mark and unmark metadata used on the stack as either handles -// or executing methods, so that it can't be deleted during class redefinition -// and class unloading. -class MetadataOnStackMark : public StackObj { - NOT_PRODUCT(static bool _is_active;) - public: - MetadataOnStackMark() NOT_JVMTI_RETURN; - ~MetadataOnStackMark() NOT_JVMTI_RETURN; - static void record(Metadata* m) NOT_JVMTI_RETURN; -}; - #endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSES_HPP From 698fba94effa2296ce5f46360dc9899f9f8f1f89 Mon Sep 17 00:00:00 2001 From: Joseph Provino Date: Wed, 23 Jan 2013 13:02:39 -0500 Subject: [PATCH 003/158] 8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS Rename INCLUDE_ALTERNATE_GCS to INCLUDE_ALL_GCS and replace SERIALGC with INCLUDE_ALL_GCS. Reviewed-by: coleenp, stefank --- hotspot/make/bsd/makefiles/minimal1.make | 2 +- hotspot/make/excludeSrc.make | 8 ++-- hotspot/make/linux/makefiles/minimal1.make | 2 +- .../src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp | 9 ++-- .../src/cpu/sparc/vm/c1_Runtime1_sparc.cpp | 5 +- .../src/cpu/sparc/vm/cppInterpreter_sparc.cpp | 5 +- .../src/cpu/sparc/vm/macroAssembler_sparc.cpp | 9 ++-- .../src/cpu/sparc/vm/macroAssembler_sparc.hpp | 5 +- .../sparc/vm/templateInterpreter_sparc.cpp | 5 +- .../src/cpu/sparc/vm/templateTable_sparc.cpp | 5 +- hotspot/src/cpu/x86/vm/assembler_x86.cpp | 5 +- hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp | 9 ++-- hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp | 5 +- hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp | 5 +- hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp | 9 ++-- hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp | 5 +- .../cpu/x86/vm/templateInterpreter_x86_32.cpp | 5 +- .../cpu/x86/vm/templateInterpreter_x86_64.cpp | 5 +- .../src/cpu/x86/vm/templateTable_x86_32.cpp | 5 +- .../src/cpu/x86/vm/templateTable_x86_64.cpp | 5 +- hotspot/src/cpu/zero/vm/assembler_zero.cpp | 5 +- .../src/cpu/zero/vm/cppInterpreter_zero.cpp | 5 +- hotspot/src/share/vm/c1/c1_CodeStubs.hpp | 5 +- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 21 +++++---- hotspot/src/share/vm/ci/ciEnv.cpp | 1 + hotspot/src/share/vm/ci/ciReplay.cpp | 1 + .../g1/g1SATBCardTableModRefBS.hpp | 5 +- .../vm/gc_implementation/g1/heapRegion.hpp | 5 +- .../shared/allocationStats.cpp | 5 +- .../shared/allocationStats.hpp | 5 +- .../shared/concurrentGCThread.hpp | 5 +- .../shared/gSpaceCounters.cpp | 5 +- .../shared/gSpaceCounters.hpp | 5 +- .../shared/gcAdaptivePolicyCounters.hpp | 5 +- .../shared/hSpaceCounters.hpp | 5 +- .../shared/immutableSpace.cpp | 5 +- .../shared/isGCActiveMark.hpp | 5 +- .../shared/markSweep.inline.hpp | 5 +- .../shared/mutableNUMASpace.hpp | 5 +- .../gc_implementation/shared/mutableSpace.cpp | 5 +- .../shared/spaceCounters.cpp | 5 +- .../shared/spaceCounters.hpp | 5 +- .../shared/vmGCOperations.cpp | 5 +- .../share/vm/memory/binaryTreeDictionary.cpp | 46 ++++++++++--------- .../src/share/vm/memory/cardTableModRefBS.cpp | 7 +-- hotspot/src/share/vm/memory/cardTableRS.cpp | 7 +-- .../src/share/vm/memory/collectorPolicy.cpp | 5 +- .../src/share/vm/memory/collectorPolicy.hpp | 15 +++--- .../share/vm/memory/freeBlockDictionary.cpp | 10 ++-- hotspot/src/share/vm/memory/freeList.cpp | 9 ++-- .../src/share/vm/memory/genCollectedHeap.cpp | 27 +++++------ .../src/share/vm/memory/generationSpec.cpp | 9 ++-- .../src/share/vm/memory/heapInspection.cpp | 5 +- .../src/share/vm/memory/heapInspection.hpp | 1 + hotspot/src/share/vm/memory/space.cpp | 5 +- hotspot/src/share/vm/memory/space.hpp | 5 +- .../vm/memory/specialized_oop_closures.hpp | 27 +++++------ .../src/share/vm/memory/tenuredGeneration.cpp | 11 +++-- .../src/share/vm/memory/tenuredGeneration.hpp | 9 ++-- hotspot/src/share/vm/memory/universe.cpp | 23 +++++----- hotspot/src/share/vm/oops/cpCache.cpp | 5 +- .../vm/oops/instanceClassLoaderKlass.cpp | 17 +++---- .../vm/oops/instanceClassLoaderKlass.hpp | 5 +- hotspot/src/share/vm/oops/instanceKlass.cpp | 21 +++++---- hotspot/src/share/vm/oops/instanceKlass.hpp | 5 +- .../src/share/vm/oops/instanceMirrorKlass.cpp | 21 +++++---- .../src/share/vm/oops/instanceMirrorKlass.hpp | 5 +- .../src/share/vm/oops/instanceRefKlass.cpp | 21 +++++---- .../src/share/vm/oops/instanceRefKlass.hpp | 5 +- hotspot/src/share/vm/oops/klass.cpp | 5 +- hotspot/src/share/vm/oops/klass.hpp | 13 +++--- hotspot/src/share/vm/oops/klassPS.hpp | 8 ++-- hotspot/src/share/vm/oops/objArrayKlass.cpp | 13 +++--- hotspot/src/share/vm/oops/objArrayKlass.hpp | 5 +- .../share/vm/oops/objArrayKlass.inline.hpp | 9 ++-- hotspot/src/share/vm/oops/oop.hpp | 15 +++--- hotspot/src/share/vm/oops/oop.inline.hpp | 5 +- hotspot/src/share/vm/oops/oop.pcgc.inline.hpp | 5 +- hotspot/src/share/vm/oops/oop.psgc.inline.hpp | 5 +- hotspot/src/share/vm/oops/typeArrayKlass.cpp | 9 ++-- .../src/share/vm/precompiled/precompiled.hpp | 5 +- hotspot/src/share/vm/prims/jni.cpp | 9 ++-- hotspot/src/share/vm/prims/jvmtiEnvBase.hpp | 1 + hotspot/src/share/vm/prims/jvmtiExport.cpp | 5 +- hotspot/src/share/vm/prims/jvmtiExport.hpp | 1 + hotspot/src/share/vm/prims/jvmtiTagMap.cpp | 5 +- hotspot/src/share/vm/prims/nativeLookup.cpp | 1 + hotspot/src/share/vm/prims/unsafe.cpp | 13 +++--- hotspot/src/share/vm/prims/whitebox.cpp | 13 +++--- hotspot/src/share/vm/runtime/arguments.cpp | 37 ++++++++------- hotspot/src/share/vm/runtime/fprofiler.hpp | 1 + hotspot/src/share/vm/runtime/globals.cpp | 9 ++-- .../share/vm/runtime/globals_extension.hpp | 9 ++-- hotspot/src/share/vm/runtime/init.cpp | 1 + hotspot/src/share/vm/runtime/java.cpp | 5 +- hotspot/src/share/vm/runtime/safepoint.cpp | 13 +++--- .../src/share/vm/runtime/sharedRuntime.cpp | 5 +- .../src/share/vm/runtime/sharedRuntime.hpp | 5 +- hotspot/src/share/vm/runtime/thread.cpp | 45 +++++++++--------- hotspot/src/share/vm/runtime/thread.hpp | 23 +++++----- hotspot/src/share/vm/runtime/vmStructs.cpp | 29 ++++++------ .../src/share/vm/services/attachListener.hpp | 1 + .../share/vm/services/classLoadingService.cpp | 1 + .../share/vm/services/classLoadingService.hpp | 1 + .../share/vm/services/diagnosticCommand.cpp | 1 + .../share/vm/services/diagnosticCommand.hpp | 1 + .../src/share/vm/services/g1MemoryPool.hpp | 5 +- hotspot/src/share/vm/services/heapDumper.cpp | 5 +- hotspot/src/share/vm/services/management.cpp | 1 + hotspot/src/share/vm/services/memReporter.hpp | 1 + hotspot/src/share/vm/services/memoryPool.cpp | 5 +- hotspot/src/share/vm/services/memoryPool.hpp | 9 ++-- .../src/share/vm/services/memoryService.cpp | 45 +++++++++--------- .../src/share/vm/services/psMemoryPool.hpp | 5 +- .../src/share/vm/services/runtimeService.cpp | 1 + hotspot/src/share/vm/utilities/macros.hpp | 22 ++++----- hotspot/src/share/vm/utilities/top.hpp | 4 +- .../share/vm/utilities/yieldingWorkgroup.cpp | 5 +- .../share/vm/utilities/yieldingWorkgroup.hpp | 5 +- 119 files changed, 560 insertions(+), 447 deletions(-) diff --git a/hotspot/make/bsd/makefiles/minimal1.make b/hotspot/make/bsd/makefiles/minimal1.make index 9494f78bcdd..abfbc4c9490 100644 --- a/hotspot/make/bsd/makefiles/minimal1.make +++ b/hotspot/make/bsd/makefiles/minimal1.make @@ -30,7 +30,7 @@ INCLUDE_VM_STRUCTS ?= false INCLUDE_JNI_CHECK ?= false INCLUDE_SERVICES ?= false INCLUDE_MANAGEMENT ?= false -INCLUDE_ALTERNATE_GCS ?= false +INCLUDE_ALL_GCS ?= false INCLUDE_NMT ?= false INCLUDE_CDS ?= false diff --git a/hotspot/make/excludeSrc.make b/hotspot/make/excludeSrc.make index 721aea5c7e5..589c262ca3c 100644 --- a/hotspot/make/excludeSrc.make +++ b/hotspot/make/excludeSrc.make @@ -72,12 +72,10 @@ ifeq ($(INCLUDE_CDS), false) Src_Files_EXCLUDE += metaspaceShared.cpp endif -ifeq ($(INCLUDE_ALTERNATE_GCS), false) - CXXFLAGS += -DINCLUDE_ALTERNATE_GCS=0 - CFLAGS += -DINCLUDE_ALTERNATE_GCS=0 +ifeq ($(INCLUDE_ALL_GCS), false) + CXXFLAGS += -DINCLUDE_ALL_GCS=0 + CFLAGS += -DINCLUDE_ALL_GCS=0 - CXXFLAGS += -DSERIALGC - CFLAGS += -DSERIALGC Src_Files_EXCLUDE += \ cmsAdaptiveSizePolicy.cpp cmsCollectorPolicy.cpp \ cmsGCAdaptivePolicyCounters.cpp cmsLockVerifier.cpp cmsPermGen.cpp compactibleFreeListSpace.cpp \ diff --git a/hotspot/make/linux/makefiles/minimal1.make b/hotspot/make/linux/makefiles/minimal1.make index 9494f78bcdd..abfbc4c9490 100644 --- a/hotspot/make/linux/makefiles/minimal1.make +++ b/hotspot/make/linux/makefiles/minimal1.make @@ -30,7 +30,7 @@ INCLUDE_VM_STRUCTS ?= false INCLUDE_JNI_CHECK ?= false INCLUDE_SERVICES ?= false INCLUDE_MANAGEMENT ?= false -INCLUDE_ALTERNATE_GCS ?= false +INCLUDE_ALL_GCS ?= false INCLUDE_NMT ?= false INCLUDE_CDS ?= false diff --git a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp index fa5ce4fa6be..6d936b376e0 100644 --- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp @@ -30,10 +30,11 @@ #include "c1/c1_Runtime1.hpp" #include "nativeInst_sparc.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/macros.hpp" #include "vmreg_sparc.inline.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif +#endif // INCLUDE_ALL_GCS #define __ ce->masm()-> @@ -420,7 +421,7 @@ void ArrayCopyStub::emit_code(LIR_Assembler* ce) { /////////////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void G1PreBarrierStub::emit_code(LIR_Assembler* ce) { // At this point we know that marking is in progress. @@ -483,7 +484,7 @@ void G1PostBarrierStub::emit_code(LIR_Assembler* ce) { __ delayed()->nop(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS /////////////////////////////////////////////////////////////////////////////////// #undef __ diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp index 017baa61d0a..b8c838b1620 100644 --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @@ -35,6 +35,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/macros.hpp" #include "vmreg_sparc.inline.hpp" // Implementation of StubAssembler @@ -822,7 +823,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { } break; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case g1_pre_barrier_slow_id: { // G4: previous value of memory BarrierSet* bs = Universe::heap()->barrier_set(); @@ -984,7 +985,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ delayed()->restore(); } break; -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS default: { __ set_info("unimplemented entry", dont_gc_arguments); diff --git a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp index 6066c2019d5..4918746db13 100644 --- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp @@ -45,6 +45,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #ifdef SHARK #include "shark/shark_globals.hpp" #endif @@ -551,7 +552,7 @@ address InterpreterGenerator::generate_accessor_entry(void) { } address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { // We need to generate have a routine that generates code to: // * load the value in the referent field @@ -563,7 +564,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) { // field as live. Unimplemented(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp index 3690a9272e4..251e42cd6af 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp @@ -36,11 +36,12 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ @@ -3867,7 +3868,7 @@ void MacroAssembler::bang_stack_size(Register Rsize, Register Rtsp, } /////////////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS static address satb_log_enqueue_with_frame = NULL; static u_char* satb_log_enqueue_with_frame_end = NULL; @@ -4231,7 +4232,7 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val bind(filtered); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS /////////////////////////////////////////////////////////////////////////////////// void MacroAssembler::card_write_barrier_post(Register store_addr, Register new_val, Register tmp) { diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp index dffef7e794b..26605cbfa4c 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp @@ -26,6 +26,7 @@ #define CPU_SPARC_VM_MACROASSEMBLER_SPARC_HPP #include "asm/assembler.hpp" +#include "utilities/macros.hpp" // promises that the system will not use traps 16-31 #define ST_RESERVED_FOR_USER_0 0x10 @@ -1181,13 +1182,13 @@ public: void card_write_barrier_post(Register store_addr, Register new_val, Register tmp); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // General G1 pre-barrier generator. void g1_write_barrier_pre(Register obj, Register index, int offset, Register pre_val, Register tmp, bool preserve_o_regs); // General G1 post-barrier generator void g1_write_barrier_post(Register store_addr, Register new_val, Register tmp); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // pushes double TOS element of FPU stack on CPU stack; pops from FPU stack void push_fTOS(); diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp index ed46aa9cdc4..b5cfa00f975 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp @@ -44,6 +44,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #ifndef CC_INTERP #ifndef FAST_DISPATCH @@ -734,7 +735,7 @@ address InterpreterGenerator::generate_accessor_entry(void) { // Method entry for java.lang.ref.Reference.get. address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Code: _aload_0, _getfield, _areturn // parameter size = 1 // @@ -805,7 +806,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) { (void) generate_normal_entry(false); return entry; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index 931342ded12..d32a2493cfb 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -34,6 +34,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" +#include "utilities/macros.hpp" #ifndef CC_INTERP #define __ _masm-> @@ -53,7 +54,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, assert(tmp != val && tmp != base && tmp != index, "register collision"); assert(index == noreg || offset == 0, "only one offset"); switch (barrier) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: { @@ -82,7 +83,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, } } break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: { diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index 8b474ba2409..3b445ef8d2d 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -36,11 +36,12 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ diff --git a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp index 53c7cbacd1c..806bce01bfa 100644 --- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp @@ -30,10 +30,11 @@ #include "c1/c1_Runtime1.hpp" #include "nativeInst_x86.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/macros.hpp" #include "vmreg_x86.inline.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif +#endif // INCLUDE_ALL_GCS #define __ ce->masm()-> @@ -482,7 +483,7 @@ void ArrayCopyStub::emit_code(LIR_Assembler* ce) { } ///////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void G1PreBarrierStub::emit_code(LIR_Assembler* ce) { // At this point we know that marking is in progress. @@ -528,7 +529,7 @@ void G1PostBarrierStub::emit_code(LIR_Assembler* ce) { __ jmp(_continuation); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ///////////////////////////////////////////////////////////////////////////// #undef __ diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp index e02d5f6af7f..d3ac75e4013 100644 --- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp @@ -36,6 +36,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/macros.hpp" #include "vmreg_x86.inline.hpp" @@ -1607,7 +1608,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { } break; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case g1_pre_barrier_slow_id: { StubFrame f(sasm, "g1_pre_barrier", dont_gc_arguments); @@ -1804,7 +1805,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { } break; -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS default: { StubFrame f(sasm, "unimplemented entry", dont_gc_arguments); diff --git a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp index 9c3a2f31aeb..55b29fb2f6c 100644 --- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp +++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp @@ -45,6 +45,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #ifdef SHARK #include "shark/shark_globals.hpp" #endif @@ -938,7 +939,7 @@ address InterpreterGenerator::generate_accessor_entry(void) { } address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { // We need to generate have a routine that generates code to: // * load the value in the referent field @@ -950,7 +951,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) { // field as live. Unimplemented(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index e9e414077f5..239be0940ab 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -37,11 +37,12 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ @@ -3207,7 +3208,7 @@ void MacroAssembler::vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src ////////////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void MacroAssembler::g1_write_barrier_pre(Register obj, Register pre_val, @@ -3417,7 +3418,7 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr, bind(done); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ////////////////////////////////////////////////////////////////////////////////// diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp index 3afcf23ebae..ae4bc8656ef 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -26,6 +26,7 @@ #define CPU_X86_VM_MACROASSEMBLER_X86_HPP #include "asm/assembler.hpp" +#include "utilities/macros.hpp" // MacroAssembler extends Assembler by frequently used macros. @@ -294,7 +295,7 @@ class MacroAssembler: public Assembler { void store_check(Register obj); // store check for obj - register is destroyed afterwards void store_check(Register obj, Address dst); // same as above, dst is exact store location (reg. is destroyed) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void g1_write_barrier_pre(Register obj, Register pre_val, @@ -309,7 +310,7 @@ class MacroAssembler: public Assembler { Register tmp, Register tmp2); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // split store_check(Register obj) to enhance instruction interleaving void store_check_part_1(Register obj); diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp index aabc3dbbacd..a562bee3e53 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp @@ -44,6 +44,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #define __ _masm-> @@ -761,7 +762,7 @@ address InterpreterGenerator::generate_accessor_entry(void) { // Method entry for java.lang.ref.Reference.get. address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Code: _aload_0, _getfield, _areturn // parameter size = 1 // @@ -844,7 +845,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) { return entry; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp index 3e3cc0fc1f5..26eadba79b2 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp @@ -44,6 +44,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #define __ _masm-> @@ -742,7 +743,7 @@ address InterpreterGenerator::generate_accessor_entry(void) { // Method entry for java.lang.ref.Reference.get. address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Code: _aload_0, _getfield, _areturn // parameter size = 1 // @@ -821,7 +822,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) { return entry; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp index e2a20531f82..371517c0537 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp @@ -35,6 +35,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" +#include "utilities/macros.hpp" #ifndef CC_INTERP #define __ _masm-> @@ -125,7 +126,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, bool precise) { assert(val == noreg || val == rax, "parameter is just for looks"); switch (barrier) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: { @@ -164,7 +165,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, } break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: { diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp index eedab0b4b22..d1e22d25990 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp @@ -35,6 +35,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" +#include "utilities/macros.hpp" #ifndef CC_INTERP @@ -136,7 +137,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, bool precise) { assert(val == noreg || val == rax, "parameter is just for looks"); switch (barrier) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: { @@ -167,7 +168,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, } break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: { diff --git a/hotspot/src/cpu/zero/vm/assembler_zero.cpp b/hotspot/src/cpu/zero/vm/assembler_zero.cpp index d70a2adc746..ad1107ed12f 100644 --- a/hotspot/src/cpu/zero/vm/assembler_zero.cpp +++ b/hotspot/src/cpu/zero/vm/assembler_zero.cpp @@ -36,11 +36,12 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS int AbstractAssembler::code_fill_byte() { return 0; diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index c6f82cd74a8..a199d037cbc 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -47,6 +47,7 @@ #include "runtime/vframeArray.hpp" #include "stack_zero.inline.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #ifdef SHARK #include "shark/shark_globals.hpp" #endif @@ -791,7 +792,7 @@ address InterpreterGenerator::generate_accessor_entry() { } address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { // We need to generate have a routine that generates code to: // * load the value in the referent field @@ -803,7 +804,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) { // field as live. Unimplemented(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff --git a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp index 5b46ce1b6d0..9fbeb29b5a4 100644 --- a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp +++ b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp @@ -31,6 +31,7 @@ #include "c1/c1_LIR.hpp" #include "c1/c1_Runtime1.hpp" #include "utilities/array.hpp" +#include "utilities/macros.hpp" class CodeEmitInfo; class LIR_Assembler; @@ -515,7 +516,7 @@ class ArrayCopyStub: public CodeStub { }; ////////////////////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Code stubs for Garbage-First barriers. class G1PreBarrierStub: public CodeStub { @@ -608,7 +609,7 @@ class G1PostBarrierStub: public CodeStub { #endif // PRODUCT }; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ////////////////////////////////////////////////////////////////////////////////////////// #endif // SHARE_VM_C1_C1_CODESTUBS_HPP diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 65bc34e3de6..b46acec1474 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -35,9 +35,10 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/bitMap.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef ASSERT #define __ gen()->lir(__FILE__, __LINE__)-> @@ -1417,12 +1418,12 @@ void LIRGenerator::pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val, bool do_load, bool patch, CodeEmitInfo* info) { // Do the pre-write barrier, if any. switch (_bs->kind()) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: G1SATBCardTableModRef_pre_barrier(addr_opr, pre_val, do_load, patch, info); break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: // No pre barriers @@ -1439,12 +1440,12 @@ void LIRGenerator::pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val, void LIRGenerator::post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { switch (_bs->kind()) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: G1SATBCardTableModRef_post_barrier(addr, new_val); break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: CardTableModRef_post_barrier(addr, new_val); @@ -1459,7 +1460,7 @@ void LIRGenerator::post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { } //////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void LIRGenerator::G1SATBCardTableModRef_pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val, bool do_load, bool patch, CodeEmitInfo* info) { @@ -1575,7 +1576,7 @@ void LIRGenerator::G1SATBCardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_Opr __ branch_destination(slow->continuation()); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS //////////////////////////////////////////////////////////////////////// void LIRGenerator::CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { @@ -2181,7 +2182,7 @@ void LIRGenerator::do_UnsafeGetObject(UnsafeGetObject* x) { get_Object_unsafe(value, src.result(), off.result(), type, x->is_volatile()); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // We might be reading the value of the referent field of a // Reference object in order to attach it back to the live // object graph. If G1 is enabled then we need to record @@ -2311,7 +2312,7 @@ void LIRGenerator::do_UnsafeGetObject(UnsafeGetObject* x) { __ branch_destination(Lcont->label()); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS if (x->is_volatile() && os::is_MP()) __ membar_acquire(); } diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index bb51f88c7b9..4be11083bec 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -52,6 +52,7 @@ #include "runtime/reflection.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/dtrace.hpp" +#include "utilities/macros.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" #endif diff --git a/hotspot/src/share/vm/ci/ciReplay.cpp b/hotspot/src/share/vm/ci/ciReplay.cpp index f2e77241960..a92f540ecb1 100644 --- a/hotspot/src/share/vm/ci/ciReplay.cpp +++ b/hotspot/src/share/vm/ci/ciReplay.cpp @@ -30,6 +30,7 @@ #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "utilities/copy.hpp" +#include "utilities/macros.hpp" #ifndef PRODUCT diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp index dde3ba4be31..6f887583cab 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp @@ -28,8 +28,9 @@ #include "memory/cardTableModRefBS.hpp" #include "memory/memRegion.hpp" #include "oops/oop.inline.hpp" +#include "utilities/macros.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS class DirtyCardQueueSet; @@ -120,6 +121,6 @@ class G1SATBCardTableLoggingModRefBS: public G1SATBCardTableModRefBS { }; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1SATBCARDTABLEMODREFBS_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index 4f1c5493fc5..7c79195d3e5 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -32,8 +32,9 @@ #include "gc_implementation/shared/spaceDecorator.hpp" #include "memory/space.inline.hpp" #include "memory/watermark.hpp" +#include "utilities/macros.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // A HeapRegion is the smallest piece of a G1CollectedHeap that // can be collected independently. @@ -837,6 +838,6 @@ class HeapRegionClosure : public StackObj { bool complete() { return _complete; } }; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_HPP diff --git a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.cpp b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.cpp index c24fc3bbf1a..7cc37fd9453 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.cpp @@ -23,10 +23,11 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/allocationStats.hpp" #include "utilities/ostream.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Technically this should be derived from machine speed, and // ideally it would be dynamically adjusted. diff --git a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp index df1ee1ea2e5..cf7cd3ae0f2 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp @@ -25,11 +25,12 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_ALLOCATIONSTATS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_ALLOCATIONSTATS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/gcUtil.hpp" #include "memory/allocation.hpp" #include "utilities/globalDefinitions.hpp" -#endif +#endif // INCLUDE_ALL_GCS class AllocationStats VALUE_OBJ_CLASS_SPEC { // A duration threshold (in ms) used to filter diff --git a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp index 77d041d70ca..6530d23b624 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp @@ -25,9 +25,10 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "runtime/thread.hpp" -#endif +#endif // INCLUDE_ALL_GCS class VoidClosure; diff --git a/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp b/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp index 4a8f85ab2a1..506322de521 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp @@ -23,11 +23,12 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/gSpaceCounters.hpp" #include "memory/generation.hpp" #include "memory/resourceArea.hpp" -#endif +#endif // INCLUDE_ALL_GCS GSpaceCounters::GSpaceCounters(const char* name, int ordinal, size_t max_size, Generation* g, GenerationCounters* gc, diff --git a/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp b/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp index 745dac7417b..c54e773c364 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp @@ -25,11 +25,12 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GSPACECOUNTERS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GSPACECOUNTERS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/generationCounters.hpp" #include "memory/generation.hpp" #include "runtime/perfData.hpp" -#endif +#endif // INCLUDE_ALL_GCS // A GSpaceCounter is a holder class for performance counters // that track a space; diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp b/hotspot/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp index c1758a2fc19..5024ab9e7ab 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp @@ -25,10 +25,11 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCADAPTIVEPOLICYCOUNTERS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCADAPTIVEPOLICYCOUNTERS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/adaptiveSizePolicy.hpp" #include "gc_implementation/shared/gcPolicyCounters.hpp" -#endif +#endif // INCLUDE_ALL_GCS // This class keeps statistical information and computes the // size of the heap. diff --git a/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp b/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp index f3b956ee67a..034d319b078 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp @@ -25,11 +25,12 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_HSPACECOUNTERS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_HSPACECOUNTERS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/generationCounters.hpp" #include "memory/generation.hpp" #include "runtime/perfData.hpp" -#endif +#endif // INCLUDE_ALL_GCS // A HSpaceCounter is a holder class for performance counters // that track a collections (logical spaces) in a heap; diff --git a/hotspot/src/share/vm/gc_implementation/shared/immutableSpace.cpp b/hotspot/src/share/vm/gc_implementation/shared/immutableSpace.cpp index 30eb04df6a8..c844a3e596d 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/immutableSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/immutableSpace.cpp @@ -23,11 +23,12 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/immutableSpace.hpp" #include "memory/universe.hpp" #include "oops/oop.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS void ImmutableSpace::initialize(MemRegion mr) { HeapWord* bottom = mr.start(); diff --git a/hotspot/src/share/vm/gc_implementation/shared/isGCActiveMark.hpp b/hotspot/src/share/vm/gc_implementation/shared/isGCActiveMark.hpp index 4d36417244c..c56cbafeb2e 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/isGCActiveMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/isGCActiveMark.hpp @@ -25,9 +25,10 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_ISGCACTIVEMARK_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_ISGCACTIVEMARK_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS // This class provides a method for block structured setting of the // _is_gc_active state without requiring accessors in CollectedHeap diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp index 3a3cbdd8c96..9752291959a 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp @@ -28,9 +28,10 @@ #include "gc_implementation/shared/markSweep.hpp" #include "gc_interface/collectedHeap.hpp" #include "utilities/stack.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" -#endif +#endif // INCLUDE_ALL_GCS inline void MarkSweep::mark_object(oop obj) { // some marks may contain information we need to preserve so we store them away diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp index 8b8f8d65e21..5621c077c38 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp @@ -25,10 +25,11 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_MUTABLENUMASPACE_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_MUTABLENUMASPACE_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/gcUtil.hpp" #include "gc_implementation/shared/mutableSpace.hpp" -#endif +#endif // INCLUDE_ALL_GCS /* * The NUMA-aware allocator (MutableNUMASpace) is basically a modification diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp index e573e02dfd6..d50edac13ca 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp @@ -23,13 +23,14 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/mutableSpace.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" #include "oops/oop.inline.hpp" #include "runtime/safepoint.hpp" #include "runtime/thread.hpp" -#endif +#endif // INCLUDE_ALL_GCS MutableSpace::MutableSpace(size_t alignment): ImmutableSpace(), _top(NULL), _alignment(alignment) { assert(MutableSpace::alignment() >= 0 && diff --git a/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.cpp b/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.cpp index 48dddd85b9d..f606e99e9a1 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.cpp @@ -23,10 +23,11 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/spaceCounters.hpp" #include "memory/resourceArea.hpp" -#endif +#endif // INCLUDE_ALL_GCS SpaceCounters::SpaceCounters(const char* name, int ordinal, size_t max_size, MutableSpace* m, GenerationCounters* gc) : diff --git a/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.hpp b/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.hpp index 6b13e5acfd2..17302d420b2 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.hpp @@ -25,12 +25,13 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_SPACECOUNTERS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_SPACECOUNTERS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/generationCounters.hpp" #include "gc_implementation/shared/immutableSpace.hpp" #include "gc_implementation/shared/mutableSpace.hpp" #include "runtime/perfData.hpp" -#endif +#endif // INCLUDE_ALL_GCS // A SpaceCounter is a holder class for performance counters // that track a space; diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp index ee1be4a6490..234f81da62c 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp @@ -36,9 +36,10 @@ #include "runtime/interfaceSupport.hpp" #include "utilities/dtrace.hpp" #include "utilities/preserveException.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifndef USDT2 HS_DTRACE_PROBE_DECL1(hotspot, gc__begin, bool); diff --git a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp index 725a71925dc..aab4cf85c41 100644 --- a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp +++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "utilities/macros.hpp" #include "gc_implementation/shared/allocationStats.hpp" #include "memory/binaryTreeDictionary.hpp" #include "memory/freeList.hpp" @@ -31,12 +32,13 @@ #include "memory/metachunk.hpp" #include "runtime/globals.hpp" #include "utilities/ostream.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp" #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS //////////////////////////////////////////////////////////////////////////////// // A binary tree based search structure for free blocks. @@ -118,7 +120,7 @@ TreeList::as_TreeList(HeapWord* addr, size_t size) { } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Specialize for AdaptiveFreeList which tries to avoid // splitting a chunk of a size that is under populated in favor of // an over populated size. The general get_better_list() just returns @@ -160,7 +162,7 @@ TreeList::get_better_list( } return curTL; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS template class FreeList_t> TreeList* @@ -871,7 +873,7 @@ size_t BinaryTreeDictionary::total_nodes_in_tree(TreeList class FreeList_t> void BinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template <> void BinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){ TreeList* nd = find_list(size); @@ -900,7 +902,7 @@ void BinaryTreeDictionary::dict_census_update(size_ // This is a birth associated with a LinAB. The chunk // for the LinAB is not in the dictionary. } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS template class FreeList_t> bool BinaryTreeDictionary::coal_dict_over_populated(size_t size) { @@ -909,7 +911,7 @@ bool BinaryTreeDictionary::coal_dict_over_populated(size_t return true; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template <> bool BinaryTreeDictionary::coal_dict_over_populated(size_t size) { if (FLSAlwaysCoalesceLarge) return true; @@ -919,7 +921,7 @@ bool BinaryTreeDictionary::coal_dict_over_populated return list_of_size == NULL || list_of_size->coal_desired() <= 0 || list_of_size->count() > list_of_size->coal_desired(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Closures for walking the binary tree. // do_list() walks the free list in a node applying the closure @@ -979,7 +981,7 @@ class BeginSweepClosure : public AscendTreeCensusClosure { void do_list(FreeList* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { double coalSurplusPercent = _percentage; fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate); @@ -987,7 +989,7 @@ class BeginSweepClosure : public AscendTreeCensusClosure { fl->set_before_sweep(fl->count()); fl->set_bfr_surp(fl->surplus()); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; // Used to search the tree until a condition is met. @@ -1134,13 +1136,13 @@ class setTreeSurplusClosure : public AscendTreeCensusClosure* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { double splitSurplusPercent = percentage; fl->set_surplus(fl->count() - (ssize_t)((double)fl->desired() * splitSurplusPercent)); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; template class FreeList_t> @@ -1157,7 +1159,7 @@ class setTreeHintsClosure : public DescendTreeCensusClosure setTreeHintsClosure(size_t v) { hint = v; } void do_list(FreeList* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { fl->set_hint(hint); assert(fl->hint() == 0 || fl->hint() > fl->size(), @@ -1166,7 +1168,7 @@ class setTreeHintsClosure : public DescendTreeCensusClosure hint = fl->size(); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; template class FreeList_t> @@ -1180,7 +1182,7 @@ template class FreeList_t> class clearTreeCensusClosure : public AscendTreeCensusClosure { void do_list(FreeList* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { fl->set_prev_sweep(fl->count()); fl->set_coal_births(0); @@ -1188,7 +1190,7 @@ class clearTreeCensusClosure : public AscendTreeCensusClosureset_split_births(0); fl->set_split_deaths(0); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; template class FreeList_t> @@ -1252,7 +1254,7 @@ class PrintTreeCensusClosure : public AscendTreeCensusClosureset_count( total()->count() + fl->count() ); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { if (++_print_line >= 40) { FreeList_t::print_labels_on(gclog_or_tty, "size"); @@ -1271,7 +1273,7 @@ class PrintTreeCensusClosure : public AscendTreeCensusClosureset_split_births(total()->split_births() + fl->split_births()); total()->set_split_deaths(total()->split_deaths() + fl->split_deaths()); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; template class FreeList_t> @@ -1286,7 +1288,7 @@ void BinaryTreeDictionary::print_dict_census(void) const { FreeList_t::print_labels_on(gclog_or_tty, " "); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template <> void BinaryTreeDictionary::print_dict_census(void) const { @@ -1308,7 +1310,7 @@ void BinaryTreeDictionary::print_dict_census(void) (double)(total->desired() - total->count()) /(total->desired() != 0 ? (double)total->desired() : 1.0)); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS template class FreeList_t> class PrintFreeListsClosure : public AscendTreeCensusClosure { @@ -1414,10 +1416,10 @@ template class BinaryTreeDictionary; template class TreeChunk; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Explicitly instantiate these types for FreeChunk. template class TreeList; template class BinaryTreeDictionary; template class TreeChunk; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS diff --git a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp index bd0c79ed439..d3fa82d8566 100644 --- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp +++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp @@ -34,6 +34,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/virtualspace.hpp" #include "services/memTracker.hpp" +#include "utilities/macros.hpp" #ifdef COMPILER1 #include "c1/c1_LIR.hpp" #include "c1/c1_LIRGenerator.hpp" @@ -499,13 +500,13 @@ void CardTableModRefBS::non_clean_card_iterate_possibly_parallel(Space* sp, int n_threads = SharedHeap::heap()->n_par_threads(); bool is_par = n_threads > 0; if (is_par) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS assert(SharedHeap::heap()->n_par_threads() == SharedHeap::heap()->workers()->active_workers(), "Mismatch"); non_clean_card_iterate_parallel_work(sp, mr, cl, ct, n_threads); -#else // SERIALGC +#else // INCLUDE_ALL_GCS fatal("Parallel gc not supported here."); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { // We do not call the non_clean_card_iterate_serial() version below because // we want to clear the cards (which non_clean_card_iterate_serial() does not diff --git a/hotspot/src/share/vm/memory/cardTableRS.cpp b/hotspot/src/share/vm/memory/cardTableRS.cpp index d16b3ec0be5..d92de481644 100644 --- a/hotspot/src/share/vm/memory/cardTableRS.cpp +++ b/hotspot/src/share/vm/memory/cardTableRS.cpp @@ -31,10 +31,11 @@ #include "oops/oop.inline.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/concurrentMark.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif +#endif // INCLUDE_ALL_GCS CardTableRS::CardTableRS(MemRegion whole_heap, int max_covered_regions) : @@ -42,7 +43,7 @@ CardTableRS::CardTableRS(MemRegion whole_heap, _cur_youngergen_card_val(youngergenP1_card), _regions_to_iterate(max_covered_regions - 1) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { _ct_bs = new G1SATBCardTableLoggingModRefBS(whole_heap, max_covered_regions); diff --git a/hotspot/src/share/vm/memory/collectorPolicy.cpp b/hotspot/src/share/vm/memory/collectorPolicy.cpp index b13d9761120..2d286b372e1 100644 --- a/hotspot/src/share/vm/memory/collectorPolicy.cpp +++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp @@ -39,10 +39,11 @@ #include "runtime/java.hpp" #include "runtime/thread.inline.hpp" #include "runtime/vmThread.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp" #include "gc_implementation/concurrentMarkSweep/cmsGCAdaptivePolicyCounters.hpp" -#endif +#endif // INCLUDE_ALL_GCS // CollectorPolicy methods. diff --git a/hotspot/src/share/vm/memory/collectorPolicy.hpp b/hotspot/src/share/vm/memory/collectorPolicy.hpp index a079f71b95b..b17d2a7ba34 100644 --- a/hotspot/src/share/vm/memory/collectorPolicy.hpp +++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp @@ -29,6 +29,7 @@ #include "memory/barrierSet.hpp" #include "memory/generationSpec.hpp" #include "memory/genRemSet.hpp" +#include "utilities/macros.hpp" // This class (or more correctly, subtypes of this class) // are used to define global garbage collector attributes. @@ -48,10 +49,10 @@ class GenCollectorPolicy; class TwoGenerationCollectorPolicy; class AdaptiveSizePolicy; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS class ConcurrentMarkSweepPolicy; class G1CollectorPolicy; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS class GCPolicyCounters; class MarkSweepPolicy; @@ -134,21 +135,21 @@ class CollectorPolicy : public CHeapObj { virtual GenCollectorPolicy* as_generation_policy() { return NULL; } virtual TwoGenerationCollectorPolicy* as_two_generation_policy() { return NULL; } virtual MarkSweepPolicy* as_mark_sweep_policy() { return NULL; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS virtual ConcurrentMarkSweepPolicy* as_concurrent_mark_sweep_policy() { return NULL; } virtual G1CollectorPolicy* as_g1_policy() { return NULL; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Note that these are not virtual. bool is_generation_policy() { return as_generation_policy() != NULL; } bool is_two_generation_policy() { return as_two_generation_policy() != NULL; } bool is_mark_sweep_policy() { return as_mark_sweep_policy() != NULL; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS bool is_concurrent_mark_sweep_policy() { return as_concurrent_mark_sweep_policy() != NULL; } bool is_g1_policy() { return as_g1_policy() != NULL; } -#else // SERIALGC +#else // INCLUDE_ALL_GCS bool is_concurrent_mark_sweep_policy() { return false; } bool is_g1_policy() { return false; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS virtual BarrierSet::Name barrier_set_name() = 0; diff --git a/hotspot/src/share/vm/memory/freeBlockDictionary.cpp b/hotspot/src/share/vm/memory/freeBlockDictionary.cpp index 918a80f1fb3..713036ea500 100644 --- a/hotspot/src/share/vm/memory/freeBlockDictionary.cpp +++ b/hotspot/src/share/vm/memory/freeBlockDictionary.cpp @@ -23,13 +23,15 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #include "memory/freeBlockDictionary.hpp" #include "memory/metablock.hpp" #include "memory/metachunk.hpp" #include "runtime/thread.inline.hpp" +#include "utilities/macros.hpp" #ifndef PRODUCT template Mutex* FreeBlockDictionary::par_lock() const { @@ -56,7 +58,7 @@ template void FreeBlockDictionary::verify_par_locked() cons template class FreeBlockDictionary; template class FreeBlockDictionary; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Explicitly instantiate for FreeChunk template class FreeBlockDictionary; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS diff --git a/hotspot/src/share/vm/memory/freeList.cpp b/hotspot/src/share/vm/memory/freeList.cpp index f5cd80545c0..05e4ef0a290 100644 --- a/hotspot/src/share/vm/memory/freeList.cpp +++ b/hotspot/src/share/vm/memory/freeList.cpp @@ -31,10 +31,11 @@ #include "runtime/globals.hpp" #include "runtime/mutex.hpp" #include "runtime/vmThread.hpp" +#include "utilities/macros.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Free list. A FreeList is used to access a linked list of chunks // of space in the heap. The head and tail are maintained so that @@ -341,6 +342,6 @@ void FreeList::print_on(outputStream* st, const char* c) const { template class FreeList; template class FreeList; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template class FreeList; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp index 13778b06d50..9d65cc15701 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp @@ -51,10 +51,11 @@ #include "services/memoryService.hpp" #include "utilities/vmError.hpp" #include "utilities/workgroup.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp" -#endif +#endif // INCLUDE_ALL_GCS GenCollectedHeap* GenCollectedHeap::_gch; NOT_PRODUCT(size_t GenCollectedHeap::_skip_header_HeapWords = 0;) @@ -141,14 +142,14 @@ jint GenCollectedHeap::initialize() { } clear_incremental_collection_failed(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // If we are running CMS, create the collector responsible // for collecting the CMS generations. if (collector_policy()->is_concurrent_mark_sweep_policy()) { bool success = create_cms_collector(); if (!success) return JNI_ENOMEM; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS return JNI_OK; } @@ -686,12 +687,12 @@ size_t GenCollectedHeap::unsafe_max_alloc() { void GenCollectedHeap::collect(GCCause::Cause cause) { if (should_do_concurrent_full_gc(cause)) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // mostly concurrent full collection collect_mostly_concurrent(cause); -#else // SERIALGC +#else // INCLUDE_ALL_GCS ShouldNotReachHere(); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { #ifdef ASSERT if (cause == GCCause::_scavenge_alot) { @@ -736,7 +737,7 @@ void GenCollectedHeap::collect_locked(GCCause::Cause cause, int max_level) { } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS bool GenCollectedHeap::create_cms_collector() { assert(((_gens[1]->kind() == Generation::ConcurrentMarkSweep) || @@ -772,7 +773,7 @@ void GenCollectedHeap::collect_mostly_concurrent(GCCause::Cause cause) { VMThread::execute(&op); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs) { do_full_collection(clear_all_soft_refs, _n_gens - 1); @@ -1116,22 +1117,22 @@ void GenCollectedHeap::gc_threads_do(ThreadClosure* tc) const { if (workers() != NULL) { workers()->threads_do(tc); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseConcMarkSweepGC) { ConcurrentMarkSweepThread::threads_do(tc); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } void GenCollectedHeap::print_gc_threads_on(outputStream* st) const { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseParNewGC) { workers()->print_worker_threads_on(st); } if (UseConcMarkSweepGC) { ConcurrentMarkSweepThread::print_all_on(st); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } void GenCollectedHeap::print_tracing_info() const { diff --git a/hotspot/src/share/vm/memory/generationSpec.cpp b/hotspot/src/share/vm/memory/generationSpec.cpp index 30c79ea6f29..d97a56fbbcc 100644 --- a/hotspot/src/share/vm/memory/generationSpec.cpp +++ b/hotspot/src/share/vm/memory/generationSpec.cpp @@ -30,11 +30,12 @@ #include "memory/generationSpec.hpp" #include "memory/tenuredGeneration.hpp" #include "runtime/java.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parNew/asParNewGeneration.hpp" #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" #include "gc_implementation/parNew/parNewGeneration.hpp" -#endif +#endif // INCLUDE_ALL_GCS Generation* GenerationSpec::init(ReservedSpace rs, int level, GenRemSet* remset) { @@ -45,7 +46,7 @@ Generation* GenerationSpec::init(ReservedSpace rs, int level, case Generation::MarkSweepCompact: return new TenuredGeneration(rs, init_size(), level, remset); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ParNew: return new ParNewGeneration(rs, init_size(), level); @@ -94,7 +95,7 @@ Generation* GenerationSpec::init(ReservedSpace rs, int level, return g; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS default: guarantee(false, "unrecognized GenerationName"); diff --git a/hotspot/src/share/vm/memory/heapInspection.cpp b/hotspot/src/share/vm/memory/heapInspection.cpp index 71674fcb2d5..aba6676a608 100644 --- a/hotspot/src/share/vm/memory/heapInspection.cpp +++ b/hotspot/src/share/vm/memory/heapInspection.cpp @@ -29,9 +29,10 @@ #include "memory/resourceArea.hpp" #include "runtime/os.hpp" #include "utilities/globalDefinitions.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS // HeapInspection diff --git a/hotspot/src/share/vm/memory/heapInspection.hpp b/hotspot/src/share/vm/memory/heapInspection.hpp index 72e675850d4..bff3e9fe6b9 100644 --- a/hotspot/src/share/vm/memory/heapInspection.hpp +++ b/hotspot/src/share/vm/memory/heapInspection.hpp @@ -27,6 +27,7 @@ #include "memory/allocation.inline.hpp" #include "oops/oop.inline.hpp" +#include "utilities/macros.hpp" #if INCLUDE_SERVICES diff --git a/hotspot/src/share/vm/memory/space.cpp b/hotspot/src/share/vm/memory/space.cpp index ca3882df0ef..7eb462ecccc 100644 --- a/hotspot/src/share/vm/memory/space.cpp +++ b/hotspot/src/share/vm/memory/space.cpp @@ -40,6 +40,7 @@ #include "runtime/safepoint.hpp" #include "utilities/copy.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" void SpaceMemRegionOopsIterClosure::do_oop(oop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); } void SpaceMemRegionOopsIterClosure::do_oop(narrowOop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); } @@ -658,7 +659,7 @@ void ContiguousSpace::object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl) } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define ContigSpace_PAR_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ \ void ContiguousSpace::par_oop_iterate(MemRegion mr, OopClosureType* blk) {\ @@ -673,7 +674,7 @@ void ContiguousSpace::object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl) ALL_PAR_OOP_ITERATE_CLOSURES(ContigSpace_PAR_OOP_ITERATE_DEFN) #undef ContigSpace_PAR_OOP_ITERATE_DEFN -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void ContiguousSpace::oop_iterate(ExtendedOopClosure* blk) { if (is_empty()) return; diff --git a/hotspot/src/share/vm/memory/space.hpp b/hotspot/src/share/vm/memory/space.hpp index 1dade4a26ed..a434b0a337a 100644 --- a/hotspot/src/share/vm/memory/space.hpp +++ b/hotspot/src/share/vm/memory/space.hpp @@ -34,6 +34,7 @@ #include "oops/markOop.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/prefetch.hpp" +#include "utilities/macros.hpp" #include "utilities/workgroup.hpp" #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" @@ -884,14 +885,14 @@ class ContiguousSpace: public CompactibleSpace { } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // In support of parallel oop_iterate. #define ContigSpace_PAR_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \ void par_oop_iterate(MemRegion mr, OopClosureType* blk); ALL_PAR_OOP_ITERATE_CLOSURES(ContigSpace_PAR_OOP_ITERATE_DECL) #undef ContigSpace_PAR_OOP_ITERATE_DECL -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Compaction support virtual void reset_after_compaction() { diff --git a/hotspot/src/share/vm/memory/specialized_oop_closures.hpp b/hotspot/src/share/vm/memory/specialized_oop_closures.hpp index a13660d406a..2aed587f054 100644 --- a/hotspot/src/share/vm/memory/specialized_oop_closures.hpp +++ b/hotspot/src/share/vm/memory/specialized_oop_closures.hpp @@ -26,9 +26,10 @@ #define SHARE_VM_MEMORY_SPECIALIZED_OOP_CLOSURES_HPP #include "runtime/atomic.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1_specialized_oop_closures.hpp" -#endif +#endif // INCLUDE_ALL_GCS // The following OopClosure types get specialized versions of // "oop_oop_iterate" that invoke the closures' do_oop methods @@ -80,20 +81,20 @@ class NoHeaderExtendedOopClosure; f(FastScanClosure,_nv) \ f(FilteringClosure,_nv) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) \ f(ParScanWithBarrierClosure,_nv) \ f(ParScanWithoutBarrierClosure,_nv) -#else // SERIALGC +#else // INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(f) \ f(NoHeaderExtendedOopClosure,_nv) \ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(f) \ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) \ f(MarkRefsIntoAndScanClosure,_nv) \ f(Par_MarkRefsIntoAndScanClosure,_nv) \ @@ -104,9 +105,9 @@ class NoHeaderExtendedOopClosure; f(CMSKeepAliveClosure,_nv) \ f(CMSInnerParMarkAndPushClosure,_nv) \ FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES(f) -#else // SERIALGC +#else // INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // We separate these out, because sometime the general one has @@ -120,7 +121,7 @@ class NoHeaderExtendedOopClosure; #define ALL_OOP_OOP_ITERATE_CLOSURES_2(f) \ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // This macro applies an argument macro to all OopClosures for which we // want specialized bodies of a family of methods related to // "par_oop_iterate". The arguments to f are the same as above. @@ -136,7 +137,7 @@ class NoHeaderExtendedOopClosure; #define ALL_PAR_OOP_ITERATE_CLOSURES(f) \ f(ExtendedOopClosure,_v) \ SPECIALIZED_PAR_OOP_ITERATE_CLOSURES(f) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // This macro applies an argument macro to all OopClosures for which we // want specialized bodies of a family of methods related to @@ -155,14 +156,14 @@ class NoHeaderExtendedOopClosure; f(ScanClosure,_nv) \ f(FastScanClosure,_nv) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f) \ f(ParScanWithBarrierClosure,_nv) \ f(ParScanWithoutBarrierClosure,_nv) \ FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(f) -#else // SERIALGC +#else // INCLUDE_ALL_GCS #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(f) \ SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_S(f) \ diff --git a/hotspot/src/share/vm/memory/tenuredGeneration.cpp b/hotspot/src/share/vm/memory/tenuredGeneration.cpp index f47ea307dd8..1e15d65503a 100644 --- a/hotspot/src/share/vm/memory/tenuredGeneration.cpp +++ b/hotspot/src/share/vm/memory/tenuredGeneration.cpp @@ -33,6 +33,7 @@ #include "memory/tenuredGeneration.hpp" #include "oops/oop.inline.hpp" #include "runtime/java.hpp" +#include "utilities/macros.hpp" TenuredGeneration::TenuredGeneration(ReservedSpace rs, size_t initial_byte_size, int level, @@ -61,7 +62,7 @@ TenuredGeneration::TenuredGeneration(ReservedSpace rs, _space_counters = new CSpaceCounters(gen_name, 0, _virtual_space.reserved_size(), _the_space, _gen_counters); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseParNewGC) { typedef ParGCAllocBufferWithBOT* ParGCAllocBufferWithBOTPtr; _alloc_buffers = NEW_C_HEAP_ARRAY(ParGCAllocBufferWithBOTPtr, @@ -77,7 +78,7 @@ TenuredGeneration::TenuredGeneration(ReservedSpace rs, } else { _alloc_buffers = NULL; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } @@ -339,7 +340,7 @@ void TenuredGeneration::update_counters() { } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS oop TenuredGeneration::par_promote(int thread_num, oop old, markOop m, size_t word_sz) { @@ -423,10 +424,10 @@ void TenuredGeneration::verify_alloc_buffers_clean() { } } -#else // SERIALGC +#else // INCLUDE_ALL_GCS void TenuredGeneration::retire_alloc_buffers_before_full_gc() {} void TenuredGeneration::verify_alloc_buffers_clean() {} -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS bool TenuredGeneration::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const { size_t available = max_contiguous_available(); diff --git a/hotspot/src/share/vm/memory/tenuredGeneration.hpp b/hotspot/src/share/vm/memory/tenuredGeneration.hpp index 3a1541e7923..b948a1b0b94 100644 --- a/hotspot/src/share/vm/memory/tenuredGeneration.hpp +++ b/hotspot/src/share/vm/memory/tenuredGeneration.hpp @@ -29,6 +29,7 @@ #include "gc_implementation/shared/gcStats.hpp" #include "gc_implementation/shared/generationCounters.hpp" #include "memory/generation.hpp" +#include "utilities/macros.hpp" // TenuredGeneration models the heap containing old (promoted/tenured) objects. @@ -45,11 +46,11 @@ class TenuredGeneration: public OneContigSpaceCardGeneration { size_t _capacity_at_prologue; size_t _used_at_prologue; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // To support parallel promotion: an array of parallel allocation // buffers, one per thread, initially NULL. ParGCAllocBufferWithBOT** _alloc_buffers; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Retire all alloc buffers before a full GC, so that they will be // re-allocated at the start of the next young GC. @@ -93,14 +94,14 @@ class TenuredGeneration: public OneContigSpaceCardGeneration { size_t size, bool is_tlab); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Overrides. virtual oop par_promote(int thread_num, oop obj, markOop m, size_t word_sz); virtual void par_promote_alloc_undo(int thread_num, HeapWord* obj, size_t word_sz); virtual void par_promote_alloc_done(int thread_num); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Performance Counter support void update_counters(); diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index c528d270c64..93598ae2bbe 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -70,13 +70,14 @@ #include "utilities/events.hpp" #include "utilities/hashtable.inline.hpp" #include "utilities/preserveException.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp" #include "gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy.hpp" #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Known objects Klass* Universe::_boolArrayKlassObj = NULL; @@ -740,20 +741,20 @@ char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) { jint Universe::initialize_heap() { if (UseParallelGC) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS Universe::_collectedHeap = new ParallelScavengeHeap(); -#else // SERIALGC +#else // INCLUDE_ALL_GCS fatal("UseParallelGC not supported in this VM."); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else if (UseG1GC) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS G1CollectorPolicy* g1p = new G1CollectorPolicy(); G1CollectedHeap* g1h = new G1CollectedHeap(g1p); Universe::_collectedHeap = g1h; -#else // SERIALGC +#else // INCLUDE_ALL_GCS fatal("UseG1GC not supported in java kernel vm."); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { GenCollectorPolicy *gc_policy; @@ -761,15 +762,15 @@ jint Universe::initialize_heap() { if (UseSerialGC) { gc_policy = new MarkSweepPolicy(); } else if (UseConcMarkSweepGC) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseAdaptiveSizePolicy) { gc_policy = new ASConcurrentMarkSweepPolicy(); } else { gc_policy = new ConcurrentMarkSweepPolicy(); } -#else // SERIALGC +#else // INCLUDE_ALL_GCS fatal("UseConcMarkSweepGC not supported in this VM."); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { // default old generation gc_policy = new MarkSweepPolicy(); } diff --git a/hotspot/src/share/vm/oops/cpCache.cpp b/hotspot/src/share/vm/oops/cpCache.cpp index 06c70cd02e3..7d6d36b6881 100644 --- a/hotspot/src/share/vm/oops/cpCache.cpp +++ b/hotspot/src/share/vm/oops/cpCache.cpp @@ -33,9 +33,10 @@ #include "prims/jvmtiRedefineClassesTrace.hpp" #include "prims/methodHandles.hpp" #include "runtime/handles.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS # include "gc_implementation/parallelScavenge/psPromotionManager.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Implememtation of ConstantPoolCacheEntry diff --git a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp index def7d10e595..507206fc854 100644 --- a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp @@ -36,12 +36,13 @@ #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "runtime/handles.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parNew/parOopClosures.inline.hpp" #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS #define if_do_metadata_checked(closure, nv_suffix) \ /* Make sure the non-virtual and the virtual versions match. */ \ @@ -73,7 +74,7 @@ oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { return size; \ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ int InstanceClassLoaderKlass:: \ @@ -83,7 +84,7 @@ oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { int size = InstanceKlass::oop_oop_iterate_backwards##nv_suffix(obj, closure); \ return size; \ } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ @@ -111,10 +112,10 @@ oop_oop_iterate##nv_suffix##_m(oop obj, ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m) @@ -129,7 +130,7 @@ void InstanceClassLoaderKlass::oop_follow_contents(oop obj) { } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceClassLoaderKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { InstanceKlass::oop_follow_contents(cm, obj); @@ -155,5 +156,5 @@ int InstanceClassLoaderKlass::oop_update_pointers(ParCompactionManager* cm, oop } return size_helper(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS diff --git a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp index c9f7f026a0e..d93f2a5c32a 100644 --- a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_OOPS_INSTANCECLASSLOADERKLASS_HPP #include "oops/instanceKlass.hpp" +#include "utilities/macros.hpp" // An InstanceClassLoaderKlass is a specialization of the InstanceKlass. It does // not add any field. It is added to walk the dependencies for the class loader @@ -61,13 +62,13 @@ public: ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk); ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Garbage collection void oop_follow_contents(oop obj); diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index b0b7038e35b..831e5483c7a 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -55,7 +55,8 @@ #include "runtime/thread.inline.hpp" #include "services/threadService.hpp" #include "utilities/dtrace.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" @@ -66,7 +67,7 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_Compiler.hpp" #endif @@ -2042,7 +2043,7 @@ void InstanceKlass::oop_follow_contents(oop obj) { assert_is_in_closed_subset) } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { assert(obj != NULL, "can't follow the content of NULL object"); @@ -2054,7 +2055,7 @@ void InstanceKlass::oop_follow_contents(ParCompactionManager* cm, PSParallelCompact::mark_and_push(cm, p), \ assert_is_in) } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // closure's do_metadata() method dictates whether the given closure should be // applied to the klass ptr in the object header. @@ -2082,7 +2083,7 @@ int InstanceKlass::oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) return size_helper(); \ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ int InstanceKlass::oop_oop_iterate_backwards##nv_suffix(oop obj, \ @@ -2100,7 +2101,7 @@ int InstanceKlass::oop_oop_iterate_backwards##nv_suffix(oop obj, assert_is_in_closed_subset) \ return size_helper(); \ } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #define InstanceKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ \ @@ -2124,10 +2125,10 @@ ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DEFN_m) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS int InstanceKlass::oop_adjust_pointers(oop obj) { int size = size_helper(); @@ -2139,7 +2140,7 @@ int InstanceKlass::oop_adjust_pointers(oop obj) { return size; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { InstanceKlass_OOP_MAP_REVERSE_ITERATE( \ obj, \ @@ -2159,7 +2160,7 @@ int InstanceKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { return size; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) { assert(is_loader_alive(is_alive), "this klass should be live"); diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 97b3dd23313..5474052256c 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -36,6 +36,7 @@ #include "runtime/os.hpp" #include "utilities/accessFlags.hpp" #include "utilities/bitMap.inline.hpp" +#include "utilities/macros.hpp" // An InstanceKlass is the VM level representation of a Java class. // It contains all information needed for at class at execution runtime. @@ -932,13 +933,13 @@ class InstanceKlass: public Klass { ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk); ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS u2 idnum_allocated_count() const { return _idnum_allocated_count; } private: diff --git a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp index 4e63075c423..3eabba70a1a 100644 --- a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp @@ -35,7 +35,8 @@ #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "runtime/handles.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" @@ -45,7 +46,7 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS int InstanceMirrorKlass::_offset_of_static_fields = 0; @@ -168,7 +169,7 @@ void InstanceMirrorKlass::oop_follow_contents(oop obj) { assert_is_in_closed_subset) } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceMirrorKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { InstanceKlass::oop_follow_contents(cm, obj); @@ -189,7 +190,7 @@ void InstanceMirrorKlass::oop_follow_contents(ParCompactionManager* cm, PSParallelCompact::mark_and_push(cm, p), \ assert_is_in) } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS int InstanceMirrorKlass::oop_adjust_pointers(oop obj) { int size = oop_size(obj); @@ -262,7 +263,7 @@ oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { } \ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ int InstanceMirrorKlass:: \ @@ -278,7 +279,7 @@ oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(oop, nv_suffix); \ } \ } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #define InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ @@ -310,14 +311,14 @@ oop_oop_iterate##nv_suffix##_m(oop obj, ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceMirrorKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { // Note that we don't have to follow the mirror -> klass pointer, since all // klasses that are dirty will be scavenged when we iterate over the @@ -353,7 +354,7 @@ int InstanceMirrorKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) assert_nothing) return size; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS int InstanceMirrorKlass::instance_size(KlassHandle k) { if (k() != NULL && k->oop_is_instance()) { diff --git a/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp b/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp index db1d8de2565..38f2dc81787 100644 --- a/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp @@ -28,6 +28,7 @@ #include "classfile/systemDictionary.hpp" #include "oops/instanceKlass.hpp" #include "runtime/handles.hpp" +#include "utilities/macros.hpp" // An InstanceMirrorKlass is a specialized InstanceKlass for // java.lang.Class instances. These instances are special because @@ -107,13 +108,13 @@ class InstanceMirrorKlass: public InstanceKlass { ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk); ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS }; #endif // SHARE_VM_OOPS_INSTANCEMIRRORKLASS_HPP diff --git a/hotspot/src/share/vm/oops/instanceRefKlass.cpp b/hotspot/src/share/vm/oops/instanceRefKlass.cpp index 1784609e3f2..cb5f8965521 100644 --- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp @@ -33,7 +33,8 @@ #include "oops/instanceRefKlass.hpp" #include "oops/oop.inline.hpp" #include "utilities/preserveException.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" #include "gc_implementation/g1/g1RemSet.inline.hpp" @@ -42,7 +43,7 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS template void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj) { @@ -120,7 +121,7 @@ void InstanceRefKlass::oop_follow_contents(oop obj) { } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template void specialized_oop_follow_contents(InstanceRefKlass* ref, ParCompactionManager* cm, @@ -194,7 +195,7 @@ void InstanceRefKlass::oop_follow_contents(ParCompactionManager* cm, specialized_oop_follow_contents(this, cm, obj); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #ifdef ASSERT template void trace_reference_gc(const char *s, oop obj, @@ -317,7 +318,7 @@ oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { } \ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ int InstanceRefKlass:: \ @@ -333,7 +334,7 @@ oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains); \ } \ } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #define InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ @@ -354,14 +355,14 @@ oop_oop_iterate##nv_suffix##_m(oop obj, ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template void specialized_oop_push_contents(InstanceRefKlass *ref, PSPromotionManager* pm, oop obj) { @@ -444,7 +445,7 @@ int InstanceRefKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { } return size_helper(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void InstanceRefKlass::update_nonstatic_oop_maps(Klass* k) { // Clear the nonstatic oop-map entries corresponding to referent diff --git a/hotspot/src/share/vm/oops/instanceRefKlass.hpp b/hotspot/src/share/vm/oops/instanceRefKlass.hpp index fd565ecd823..d8771608f73 100644 --- a/hotspot/src/share/vm/oops/instanceRefKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceRefKlass.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_OOPS_INSTANCEREFKLASS_HPP #include "oops/instanceKlass.hpp" +#include "utilities/macros.hpp" // An InstanceRefKlass is a specialized InstanceKlass for Java // classes that are subclasses of java/lang/ref/Reference. @@ -83,13 +84,13 @@ class InstanceRefKlass: public InstanceKlass { ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk); ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS static void release_and_notify_pending_list_lock(BasicLock *pending_list_basic_lock); static void acquire_pending_list_lock(BasicLock *pending_list_basic_lock); diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 21bfb6bda69..ef5eefaeb47 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -37,11 +37,12 @@ #include "oops/oop.inline2.hpp" #include "runtime/atomic.hpp" #include "utilities/stack.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" #include "gc_implementation/parallelScavenge/psPromotionManager.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" -#endif +#endif // INCLUDE_ALL_GCS void Klass::set_name(Symbol* n) { _name = n; diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index be5d0c5293d..3d60b2fa3a9 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -35,11 +35,12 @@ #include "runtime/orderAccess.hpp" #include "trace/traceMacros.hpp" #include "utilities/accessFlags.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp" #include "gc_implementation/g1/g1OopClosures.hpp" #include "gc_implementation/parNew/parOopClosures.hpp" -#endif +#endif // INCLUDE_ALL_GCS // // A Klass provides: @@ -625,13 +626,13 @@ class Klass : public Metadata { return oop_oop_iterate(obj, blk); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // In case we don't have a specialized backward scanner use forward // iteration. virtual int oop_oop_iterate_backwards_v(oop obj, ExtendedOopClosure* blk) { return oop_oop_iterate_v(obj, blk); } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Iterates "blk" over all the oops in "obj" (of type "this") within "mr". // (I don't see why the _m should be required, but without it the Solaris @@ -663,7 +664,7 @@ class Klass : public Metadata { SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_DECL) SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define Klass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ virtual int oop_oop_iterate_backwards##nv_suffix(oop obj, \ OopClosureType* blk) { \ @@ -673,7 +674,7 @@ class Klass : public Metadata { SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_BACKWARDS_DECL) SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS virtual void array_klasses_do(void f(Klass* k)) {} virtual void with_array_klasses_do(void f(Klass* k)); diff --git a/hotspot/src/share/vm/oops/klassPS.hpp b/hotspot/src/share/vm/oops/klassPS.hpp index 0aa7a580d4c..5fb17b6e801 100644 --- a/hotspot/src/share/vm/oops/klassPS.hpp +++ b/hotspot/src/share/vm/oops/klassPS.hpp @@ -27,7 +27,9 @@ // Expands to Parallel Scavenge and Parallel Old declarations -#ifndef SERIALGC +#include "utilities/macros.hpp" + +#if INCLUDE_ALL_GCS #define PARALLEL_GC_DECLS \ virtual void oop_push_contents(PSPromotionManager* pm, oop obj); \ /* Parallel Old GC support \ @@ -44,9 +46,9 @@ virtual void oop_push_contents(PSPromotionManager* pm, oop obj) = 0; \ virtual void oop_follow_contents(ParCompactionManager* cm, oop obj) = 0; \ virtual int oop_update_pointers(ParCompactionManager* cm, oop obj) = 0; -#else // SERIALGC +#else // INCLUDE_ALL_GCS #define PARALLEL_GC_DECLS #define PARALLEL_GC_DECLS_PV -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_OOPS_KLASSPS_HPP diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp index 434fb74abcf..f040206391e 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp @@ -43,7 +43,8 @@ #include "runtime/handles.inline.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/copy.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" @@ -54,7 +55,7 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n, KlassHandle klass_handle, Symbol* name, TRAPS) { assert(ObjArrayKlass::header_size() <= InstanceKlass::header_size(), @@ -461,7 +462,7 @@ void ObjArrayKlass::oop_follow_contents(oop obj) { } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void ObjArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { assert(obj->is_array(), "obj must be array"); @@ -472,7 +473,7 @@ void ObjArrayKlass::oop_follow_contents(ParCompactionManager* cm, objarray_follow_contents(cm, obj, 0); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #define if_do_metadata_checked(closure, nv_suffix) \ /* Make sure the non-virtual and the virtual versions match. */ \ @@ -573,7 +574,7 @@ int ObjArrayKlass::oop_adjust_pointers(oop obj) { return size; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void ObjArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { assert(obj->is_objArray(), "obj must be obj array"); ObjArrayKlass_OOP_ITERATE( \ @@ -591,7 +592,7 @@ int ObjArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { ObjArrayKlass_OOP_ITERATE(a, p, PSParallelCompact::adjust_pointer(p)) return size; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // JVM support diff --git a/hotspot/src/share/vm/oops/objArrayKlass.hpp b/hotspot/src/share/vm/oops/objArrayKlass.hpp index 2234aa8314d..74aa4f8d76d 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.hpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp @@ -28,6 +28,7 @@ #include "classfile/classLoaderData.hpp" #include "memory/specialized_oop_closures.hpp" #include "oops/arrayKlass.hpp" +#include "utilities/macros.hpp" // ObjArrayKlass is the klass for objArrays @@ -111,11 +112,11 @@ class ObjArrayKlass : public ArrayKlass { // Parallel Scavenge and Parallel Old PARALLEL_GC_DECLS -#ifndef SERIALGC +#if INCLUDE_ALL_GCS inline void oop_follow_contents(ParCompactionManager* cm, oop obj, int index); template inline void objarray_follow_contents(ParCompactionManager* cm, oop obj, int index); -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Iterators int oop_oop_iterate(oop obj, ExtendedOopClosure* blk) { diff --git a/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp b/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp index 4a948d82eac..23e809a7e0f 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp @@ -27,10 +27,11 @@ #include "gc_implementation/shared/markSweep.inline.hpp" #include "oops/objArrayKlass.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psCompactionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" -#endif +#endif // INCLUDE_ALL_GCS void ObjArrayKlass::oop_follow_contents(oop obj, int index) { if (UseCompressedOops) { @@ -63,7 +64,7 @@ void ObjArrayKlass::objarray_follow_contents(oop obj, int index) { } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void ObjArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj, int index) { if (UseCompressedOops) { @@ -96,6 +97,6 @@ void ObjArrayKlass::objarray_follow_contents(ParCompactionManager* cm, oop obj, cm->push_objarray(a, end_index); // Push the continuation. } } -#endif // #ifndef SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_OOPS_OBJARRAYKLASS_INLINE_HPP diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp index 7cb04ff4c00..94e68ed3263 100644 --- a/hotspot/src/share/vm/oops/oop.hpp +++ b/hotspot/src/share/vm/oops/oop.hpp @@ -29,6 +29,7 @@ #include "memory/memRegion.hpp" #include "memory/specialized_oop_closures.hpp" #include "oops/metadata.hpp" +#include "utilities/macros.hpp" #include "utilities/top.hpp" // oopDesc is the top baseclass for objects classes. The {name}Desc classes describe @@ -298,7 +299,7 @@ class oopDesc { // reference field in "this". void follow_contents(void); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Parallel Scavenge void push_contents(PSPromotionManager* pm); @@ -306,7 +307,7 @@ class oopDesc { void update_contents(ParCompactionManager* cm); void follow_contents(ParCompactionManager* cm); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS bool is_scavengable() const; @@ -316,13 +317,13 @@ class oopDesc { void forward_to(oop p); bool cas_forward_to(oop p, markOop compare); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Like "forward_to", but inserts the forwarding pointer atomically. // Exactly one thread succeeds in inserting the forwarding pointer, and // this call returns "NULL" for that thread; any other thread has the // value of the forwarding pointer returned and does not modify "this". oop forward_to_atomic(oop p); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS oop forwardee() const; @@ -334,10 +335,10 @@ class oopDesc { // return the size of this oop. This is used by the MarkSweep collector. int adjust_pointers(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Parallel old void update_header(ParCompactionManager* cm); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // mark-sweep support void follow_body(int begin, int end); @@ -354,7 +355,7 @@ class oopDesc { ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_iterate_backwards(OopClosureType* blk); diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index c097617478d..9dbed732d2a 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -40,6 +40,7 @@ #include "oops/oop.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_ARCH_x86 # include "bytes_x86.hpp" #endif @@ -760,7 +761,7 @@ inline int oopDesc::oop_iterate_no_header(OopClosure* blk, MemRegion mr) { ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_DEFN) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ inline int oopDesc::oop_iterate_backwards(OopClosureType* blk) { \ @@ -770,6 +771,6 @@ inline int oopDesc::oop_iterate_backwards(OopClosureType* blk) { \ ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_BACKWARDS_DEFN) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_OOPS_OOP_INLINE_HPP diff --git a/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp b/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp index 050678185f3..d8e40477f79 100644 --- a/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp @@ -25,14 +25,15 @@ #ifndef SHARE_VM_OOPS_OOP_PCGC_INLINE_HPP #define SHARE_VM_OOPS_OOP_PCGC_INLINE_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parNew/parNewGeneration.hpp" #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" #include "gc_implementation/parallelScavenge/psCompactionManager.hpp" #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS inline void oopDesc::update_contents(ParCompactionManager* cm) { // The klass field must be updated before anything else diff --git a/hotspot/src/share/vm/oops/oop.psgc.inline.hpp b/hotspot/src/share/vm/oops/oop.psgc.inline.hpp index 4d8c3d63da0..ea184f36339 100644 --- a/hotspot/src/share/vm/oops/oop.psgc.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.psgc.inline.hpp @@ -25,11 +25,12 @@ #ifndef SHARE_VM_OOPS_OOP_PSGC_INLINE_HPP #define SHARE_VM_OOPS_OOP_PSGC_INLINE_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS // ParallelScavengeHeap methods diff --git a/hotspot/src/share/vm/oops/typeArrayKlass.cpp b/hotspot/src/share/vm/oops/typeArrayKlass.cpp index 9b6ec260cda..56863a02469 100644 --- a/hotspot/src/share/vm/oops/typeArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/typeArrayKlass.cpp @@ -39,6 +39,7 @@ #include "oops/typeArrayKlass.hpp" #include "oops/typeArrayOop.hpp" #include "runtime/handles.inline.hpp" +#include "utilities/macros.hpp" bool TypeArrayKlass::compute_is_subtype_of(Klass* k) { if (!k->oop_is_typeArray()) { @@ -208,13 +209,13 @@ void TypeArrayKlass::oop_follow_contents(oop obj) { // know that Universe::TypeArrayKlass never moves. } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void TypeArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { assert(obj->is_typeArray(),"must be a type array"); // Performance tweak: We skip iterating over the klass pointer since we // know that Universe::TypeArrayKlass never moves. } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS int TypeArrayKlass::oop_adjust_pointers(oop obj) { assert(obj->is_typeArray(),"must be a type array"); @@ -240,7 +241,7 @@ int TypeArrayKlass::oop_oop_iterate_m(oop obj, ExtendedOopClosure* blk, MemRegio return t->object_size(); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void TypeArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { ShouldNotReachHere(); assert(obj->is_typeArray(),"must be a type array"); @@ -251,7 +252,7 @@ TypeArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { assert(obj->is_typeArray(),"must be a type array"); return typeArrayOop(obj)->object_size(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void TypeArrayKlass::initialize(TRAPS) { // Nothing to do. Having this function is handy since objArrayKlasses can be diff --git a/hotspot/src/share/vm/precompiled/precompiled.hpp b/hotspot/src/share/vm/precompiled/precompiled.hpp index 1bbc5599b75..118fe9c1bde 100644 --- a/hotspot/src/share/vm/precompiled/precompiled.hpp +++ b/hotspot/src/share/vm/precompiled/precompiled.hpp @@ -24,6 +24,7 @@ // Precompiled headers are turned off for Sun Studion, // or if the user passes USE_PRECOMPILED_HEADER=0 to the makefiles. + #ifndef DONT_USE_PRECOMPILED_HEADER # include "asm/assembler.hpp" @@ -285,7 +286,7 @@ # include "c1/c1_ValueType.hpp" # include "c1/c1_globals.hpp" #endif // COMPILER1 -#ifndef SERIALGC +#if INCLUDE_ALL_GCS # include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp" # include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" # include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" @@ -314,6 +315,6 @@ # include "gc_implementation/shared/gcAdaptivePolicyCounters.hpp" # include "gc_implementation/shared/gcPolicyCounters.hpp" # include "gc_implementation/shared/parGCAllocBuffer.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #endif // !DONT_USE_PRECOMPILED_HEADER diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index ddbde753f1c..f45568a7ca7 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -32,9 +32,10 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "interpreter/linkResolver.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "memory/gcLocker.inline.hpp" @@ -2641,7 +2642,7 @@ JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false); } jobject ret = JNIHandles::make_local(env, o->obj_field(offset)); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // If G1 is enabled and we are accessing the value of the referent // field in a reference object then we need to register a non-null // referent with the SATB barrier. @@ -2660,7 +2661,7 @@ JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID G1SATBCardTableModRefBS::enqueue(referent); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetObjectField__return, ret); #else /* USDT2 */ diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp index d7b7d7cf63c..929dcf22260 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp @@ -35,6 +35,7 @@ #include "runtime/thread.hpp" #include "runtime/vm_operations.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" // // Forward Declarations diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index cb5a1f454d9..8d3cba16e9c 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -50,9 +50,10 @@ #include "runtime/vframe.hpp" #include "services/attachListener.hpp" #include "services/serviceUtil.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psMarkSweep.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef JVMTI_TRACE #define EVT_TRACE(evt,out) if ((JvmtiTrace::event_trace_flags(evt) & JvmtiTrace::SHOW_EVENT_SENT) != 0) { SafeResourceMark rm; tty->print_cr out; } diff --git a/hotspot/src/share/vm/prims/jvmtiExport.hpp b/hotspot/src/share/vm/prims/jvmtiExport.hpp index 1100d526995..a1e0e0bd44a 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.hpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp @@ -34,6 +34,7 @@ #include "runtime/handles.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" // Must be included after jvmti.h. #include "code/jvmticmlr.h" diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp index 3dbc70adf62..5d72029d264 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp @@ -45,9 +45,10 @@ #include "runtime/vmThread.hpp" #include "runtime/vm_operations.hpp" #include "services/serviceUtil.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS // JvmtiTagHashmapEntry // diff --git a/hotspot/src/share/vm/prims/nativeLookup.cpp b/hotspot/src/share/vm/prims/nativeLookup.cpp index 5fdd070aaa4..6162ae85032 100644 --- a/hotspot/src/share/vm/prims/nativeLookup.cpp +++ b/hotspot/src/share/vm/prims/nativeLookup.cpp @@ -40,6 +40,7 @@ #include "runtime/javaCalls.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" #endif diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index e56277b65d7..18252c15453 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -24,9 +24,10 @@ #include "precompiled.hpp" #include "classfile/vmSymbols.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #include "memory/allocation.inline.hpp" #include "prims/jni.h" #include "prims/jvm.h" @@ -189,7 +190,7 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject140(JNIEnv *env, jobject unsafe, jobject o if (obj == NULL) THROW_0(vmSymbols::java_lang_NullPointerException()); GET_OOP_FIELD(obj, offset, v) jobject ret = JNIHandles::make_local(env, v); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // We could be accessing the referent field in a reference // object. If G1 is enabled then we need to register a non-null // referent with the SATB barrier. @@ -212,7 +213,7 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject140(JNIEnv *env, jobject unsafe, jobject o G1SATBCardTableModRefBS::enqueue(referent); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS return ret; UNSAFE_END @@ -247,7 +248,7 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, UnsafeWrapper("Unsafe_GetObject"); GET_OOP_FIELD(obj, offset, v) jobject ret = JNIHandles::make_local(env, v); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // We could be accessing the referent field in a reference // object. If G1 is enabled then we need to register non-null // referent with the SATB barrier. @@ -270,7 +271,7 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, G1SATBCardTableModRefBS::enqueue(referent); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS return ret; UNSAFE_END diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 6c60be19f10..fbfde6dc11f 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -36,12 +36,13 @@ #include "runtime/interfaceSupport.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/concurrentMark.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS bool WhiteBox::_used = false; @@ -85,7 +86,7 @@ WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name)) return closure.found(); WB_END -#ifndef SERIALGC +#if INCLUDE_ALL_GCS WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj)) G1CollectedHeap* g1 = G1CollectedHeap::heap(); oop result = JNIHandles::resolve(obj); @@ -108,7 +109,7 @@ WB_END WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o)) return (jint)HeapRegion::GrainBytes; WB_END -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, @@ -171,12 +172,12 @@ static JNINativeMethod methods[] = { CC "(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;", (void*) &WB_ParseCommandLine }, -#ifndef SERIALGC +#if INCLUDE_ALL_GCS {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark}, {CC"g1IsHumongous", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous }, {CC"g1NumFreeRegions", CC"()J", (void*)&WB_G1NumFreeRegions }, {CC"g1RegionSize", CC"()I", (void*)&WB_G1RegionSize }, -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS }; #undef CC diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 5978382e9fe..2d5824c43f5 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -38,6 +38,7 @@ #include "services/management.hpp" #include "services/memTracker.hpp" #include "utilities/defaultStream.hpp" +#include "utilities/macros.hpp" #include "utilities/taskqueue.hpp" #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" @@ -51,9 +52,9 @@ #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Note: This is a special bug reporting site for the JVM #define DEFAULT_VENDOR_URL_BUG "http://bugreport.sun.com/bugreport/crash.jsp" @@ -1072,7 +1073,7 @@ void Arguments::set_tiered_flags() { } } -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS static void disable_adaptive_size_policy(const char* collector_name) { if (UseAdaptiveSizePolicy) { if (FLAG_IS_CMDLINE(UseAdaptiveSizePolicy)) { @@ -1284,7 +1285,7 @@ void Arguments::set_cms_and_parnew_gc_flags() { tty->print_cr("ConcGCThreads: %u", ConcGCThreads); } } -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS void set_object_alignment() { // Object alignment. @@ -1301,10 +1302,10 @@ void set_object_alignment() { // Oop encoding heap max OopEncodingHeapMax = (uint64_t(max_juint) + 1) << LogMinObjAlignmentInBytes; -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS // Set CMS global values CompactibleFreeListSpace::set_cms_values(); -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS } bool verify_object_alignment() { @@ -1976,7 +1977,7 @@ bool Arguments::check_vm_args_consistency() { status = status && verify_min_value(ParGCArrayScanChunk, 1, "ParGCArrayScanChunk"); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { status = status && verify_percentage(InitiatingHeapOccupancyPercent, "InitiatingHeapOccupancyPercent"); @@ -1985,7 +1986,7 @@ bool Arguments::check_vm_args_consistency() { status = status && verify_min_value((intx)G1ConcMarkStepDurationMillis, 1, "G1ConcMarkStepDurationMillis"); } -#endif +#endif // INCLUDE_ALL_GCS status = status && verify_interval(RefDiscoveryPolicy, ReferenceProcessor::DiscoveryPolicyMin, @@ -3157,7 +3158,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) { UNSUPPORTED_OPTION(UseLargePages, "-XX:+UseLargePages"); #endif -#if !INCLUDE_ALTERNATE_GCS +#if !INCLUDE_ALL_GCS if (UseParallelGC) { warning("Parallel GC is not supported in this VM. Using Serial GC."); } @@ -3170,7 +3171,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) { if (UseParNewGC) { warning("Par New GC is not supported in this VM. Using Serial GC."); } -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS #ifndef PRODUCT if (TraceBytecodesAt != 0) { @@ -3217,9 +3218,9 @@ jint Arguments::parse(const JavaVMInitArgs* args) { // Set object alignment values. set_object_alignment(); -#ifdef SERIALGC +#if !INCLUDE_ALL_GCS force_serial_gc(); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #if !INCLUDE_CDS no_shared_spaces(); #endif // INCLUDE_CDS @@ -3247,7 +3248,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) { // Set heap size based on available physical memory set_heap_size(); -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS // Set per-collector flags if (UseParallelGC || UseParallelOldGC) { set_parallel_gc_flags(); @@ -3259,11 +3260,9 @@ jint Arguments::parse(const JavaVMInitArgs* args) { set_g1_gc_flags(); } check_deprecated_gcs(); -#endif // INCLUDE_ALTERNATE_GCS - -#ifdef SERIALGC +#else // INCLUDE_ALL_GCS assert(verify_serial_gc_flags(), "SerialGC unset"); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Set bytecode rewriting flags set_bytecode_flags(); @@ -3357,7 +3356,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) { } jint Arguments::adjust_after_os() { -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS if (UseParallelGC || UseParallelOldGC) { if (UseNUMA) { if (FLAG_IS_DEFAULT(MinHeapDeltaBytes)) { @@ -3368,7 +3367,7 @@ jint Arguments::adjust_after_os() { UseNUMAInterleaving = true; } } -#endif +#endif // INCLUDE_ALL_GCS return JNI_OK; } diff --git a/hotspot/src/share/vm/runtime/fprofiler.hpp b/hotspot/src/share/vm/runtime/fprofiler.hpp index c06a505630b..429b32e7f33 100644 --- a/hotspot/src/share/vm/runtime/fprofiler.hpp +++ b/hotspot/src/share/vm/runtime/fprofiler.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_VM_RUNTIME_FPROFILER_HPP #define SHARE_VM_RUNTIME_FPROFILER_HPP +#include "utilities/macros.hpp" #include "runtime/timer.hpp" // a simple flat profiler for Java diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp index 569a3f4bef8..dd32cb3754c 100644 --- a/hotspot/src/share/vm/runtime/globals.cpp +++ b/hotspot/src/share/vm/runtime/globals.cpp @@ -29,10 +29,11 @@ #include "runtime/globals.hpp" #include "runtime/globals_extension.hpp" #include "utilities/ostream.hpp" +#include "utilities/macros.hpp" #include "utilities/top.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1_globals.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_globals.hpp" #endif @@ -256,9 +257,9 @@ void Flag::print_as_flag(outputStream* st) { static Flag flagTable[] = { RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT, RUNTIME_LP64_PRODUCT_FLAG_STRUCT) RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS G1_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, C1_PD_DEVELOP_FLAG_STRUCT, C1_PRODUCT_FLAG_STRUCT, C1_PD_PRODUCT_FLAG_STRUCT, C1_NOTPRODUCT_FLAG_STRUCT) #endif diff --git a/hotspot/src/share/vm/runtime/globals_extension.hpp b/hotspot/src/share/vm/runtime/globals_extension.hpp index 4d8666821a3..00d06fe276c 100644 --- a/hotspot/src/share/vm/runtime/globals_extension.hpp +++ b/hotspot/src/share/vm/runtime/globals_extension.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_RUNTIME_GLOBALS_EXTENSION_HPP #include "runtime/globals.hpp" +#include "utilities/macros.hpp" #include "utilities/top.hpp" // Construct enum of Flag_ constants. @@ -94,9 +95,9 @@ typedef enum { RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER, RUNTIME_LP64_PRODUCT_FLAG_MEMBER) RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER) -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER) -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 C1_FLAGS(C1_DEVELOP_FLAG_MEMBER, C1_PD_DEVELOP_FLAG_MEMBER, C1_PRODUCT_FLAG_MEMBER, C1_PD_PRODUCT_FLAG_MEMBER, C1_NOTPRODUCT_FLAG_MEMBER) #endif @@ -187,7 +188,7 @@ typedef enum { RUNTIME_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE, RUNTIME_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE, RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE) -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE, RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE, RUNTIME_PRODUCT_FLAG_MEMBER_WITH_TYPE, @@ -197,7 +198,7 @@ typedef enum { RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE, RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE, RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE) -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 C1_FLAGS(C1_DEVELOP_FLAG_MEMBER_WITH_TYPE, C1_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE, diff --git a/hotspot/src/share/vm/runtime/init.cpp b/hotspot/src/share/vm/runtime/init.cpp index 541cb08676f..7ef17204bb2 100644 --- a/hotspot/src/share/vm/runtime/init.cpp +++ b/hotspot/src/share/vm/runtime/init.cpp @@ -34,6 +34,7 @@ #include "runtime/init.hpp" #include "runtime/safepoint.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/macros.hpp" // Initialization done by VM thread in vm_init_globals() void check_ThreadShadow(); diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index fd9050d9cb1..f9be22344b1 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -64,6 +64,7 @@ #include "utilities/dtrace.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/histogram.hpp" +#include "utilities/macros.hpp" #include "utilities/vmError.hpp" #ifdef TARGET_ARCH_x86 # include "vm_version_x86.hpp" @@ -80,11 +81,11 @@ #ifdef TARGET_ARCH_ppc # include "vm_version_ppc.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_Compiler.hpp" #include "c1/c1_Runtime1.hpp" diff --git a/hotspot/src/share/vm/runtime/safepoint.cpp b/hotspot/src/share/vm/runtime/safepoint.cpp index bf2d38c20e8..37ee19a8fbe 100644 --- a/hotspot/src/share/vm/runtime/safepoint.cpp +++ b/hotspot/src/share/vm/runtime/safepoint.cpp @@ -52,6 +52,7 @@ #include "services/memTracker.hpp" #include "services/runtimeService.hpp" #include "utilities/events.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_ARCH_x86 # include "nativeInst_x86.hpp" # include "vmreg_x86.inline.hpp" @@ -72,10 +73,10 @@ # include "nativeInst_ppc.hpp" # include "vmreg_ppc.inline.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/shared/concurrentGCThread.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_globals.hpp" #endif @@ -103,7 +104,7 @@ void SafepointSynchronize::begin() { _ts_of_current_safepoint = tty->time_stamp().seconds(); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseConcMarkSweepGC) { // In the future we should investigate whether CMS can use the // more-general mechanism below. DLD (01/05). @@ -111,7 +112,7 @@ void SafepointSynchronize::begin() { } else if (UseG1GC) { ConcurrentGCThread::safepoint_synchronize(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // By getting the Threads_lock, we assure that no threads are about to start or // exit. It is released again in SafepointSynchronize::end(). @@ -480,14 +481,14 @@ void SafepointSynchronize::end() { Threads_lock->unlock(); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // If there are any concurrent GC threads resume them. if (UseConcMarkSweepGC) { ConcurrentMarkSweepThread::desynchronize(false); } else if (UseG1GC) { ConcurrentGCThread::safepoint_desynchronize(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // record this time so VMThread can keep track how much time has elasped // since last safepoint. _end_of_last_safepoint = os::javaTimeMillis(); diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 7d2b816fe63..11eb0d04aa8 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -56,6 +56,7 @@ #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #include "utilities/hashtable.inline.hpp" +#include "utilities/macros.hpp" #include "utilities/xmlstream.hpp" #ifdef TARGET_ARCH_x86 # include "nativeInst_x86.hpp" @@ -212,7 +213,7 @@ void SharedRuntime::print_ic_miss_histogram() { } #endif // PRODUCT -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // G1 write-barrier pre: executed before a pointer store. JRT_LEAF(void, SharedRuntime::g1_wb_pre(oopDesc* orig, JavaThread *thread)) @@ -230,7 +231,7 @@ JRT_LEAF(void, SharedRuntime::g1_wb_post(void* card_addr, JavaThread* thread)) thread->dirty_card_queue().enqueue(card_addr); JRT_END -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS JRT_LEAF(jlong, SharedRuntime::lmul(jlong y, jlong x)) diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index 54448890e0b..e6867645ae6 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -32,6 +32,7 @@ #include "memory/resourceArea.hpp" #include "runtime/threadLocalStorage.hpp" #include "utilities/hashtable.hpp" +#include "utilities/macros.hpp" class AdapterHandlerEntry; class AdapterHandlerTable; @@ -168,11 +169,11 @@ class SharedRuntime: AllStatic { static address raw_exception_handler_for_return_address(JavaThread* thread, address return_address); static address exception_handler_for_return_address(JavaThread* thread, address return_address); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // G1 write barriers static void g1_wb_pre(oopDesc* orig, JavaThread *thread); static void g1_wb_post(void* card_addr, JavaThread* thread); -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // exception handling and implicit exceptions static address compute_compiled_exc_handler(nmethod* nm, address ret_pc, Handle& exception, diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index ff6adde6eee..442e7fb2026 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -82,6 +82,7 @@ #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #include "utilities/preserveException.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" #endif @@ -94,11 +95,11 @@ #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" #include "gc_implementation/parallelScavenge/pcTasks.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_Compiler.hpp" #endif @@ -1482,17 +1483,17 @@ void JavaThread::initialize() { pd_initialize(); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS SATBMarkQueueSet JavaThread::_satb_mark_queue_set; DirtyCardQueueSet JavaThread::_dirty_card_queue_set; -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS JavaThread::JavaThread(bool is_attaching_via_jni) : Thread() -#ifndef SERIALGC +#if INCLUDE_ALL_GCS , _satb_mark_queue(&_satb_mark_queue_set), _dirty_card_queue(&_dirty_card_queue_set) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS { initialize(); if (is_attaching_via_jni) { @@ -1547,10 +1548,10 @@ static void compiler_thread_entry(JavaThread* thread, TRAPS); JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) : Thread() -#ifndef SERIALGC +#if INCLUDE_ALL_GCS , _satb_mark_queue(&_satb_mark_queue_set), _dirty_card_queue(&_dirty_card_queue_set) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS { if (TraceThreadEvents) { tty->print_cr("creating thread %p", this); @@ -1896,19 +1897,19 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { JvmtiExport::cleanup_thread(this); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // We must flush G1-related buffers before removing a thread from // the list of active threads. if (UseG1GC) { flush_barrier_queues(); } -#endif +#endif // INCLUDE_ALL_GCS // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread Threads::remove(this); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Flush G1-related queues. void JavaThread::flush_barrier_queues() { satb_mark_queue().flush(); @@ -1936,7 +1937,7 @@ void JavaThread::initialize_queues() { // active field set to true. assert(dirty_queue.is_active(), "dirty card queue should be active"); } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS void JavaThread::cleanup_failed_attach_current_thread() { if (get_thread_profiler() != NULL) { @@ -1964,11 +1965,11 @@ void JavaThread::cleanup_failed_attach_current_thread() { tlab().make_parsable(true); // retire TLAB, if any } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { flush_barrier_queues(); } -#endif +#endif // INCLUDE_ALL_GCS Threads::remove(this); delete this; @@ -3600,7 +3601,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Support for ConcurrentMarkSweep. This should be cleaned up // and better encapsulated. The ugly nested if test would go away // once things are properly refactored. XXX YSR @@ -3614,7 +3615,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Always call even when there are not JVMTI environments yet, since environments // may be attached late and JVMTI must track phases of VM execution @@ -4209,7 +4210,7 @@ void Threads::possibly_parallel_oops_do(OopClosure* f, CLDToOopClosure* cld_f, C } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Used by ParallelScavenge void Threads::create_thread_roots_tasks(GCTaskQueue* q) { ALL_JAVA_THREADS(p) { @@ -4225,7 +4226,7 @@ void Threads::create_thread_roots_marking_tasks(GCTaskQueue* q) { } q->enqueue(new ThreadRootsMarkingTask(VMThread::vm_thread())); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void Threads::nmethods_do(CodeBlobClosure* cf) { ALL_JAVA_THREADS(p) { @@ -4333,13 +4334,13 @@ void Threads::print_on(outputStream* st, bool print_stacks, bool internal_format ); st->cr(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Dump concurrent locks ConcurrentLocksDump concurrent_locks; if (print_concurrent_locks) { concurrent_locks.dump_at_safepoint(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ALL_JAVA_THREADS(p) { ResourceMark rm; @@ -4352,11 +4353,11 @@ void Threads::print_on(outputStream* st, bool print_stacks, bool internal_format } } st->cr(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (print_concurrent_locks) { concurrent_locks.print_locks_on(p, st); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } VMThread::vm_thread()->print_on(st); diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 627000c7233..98f8d254545 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -41,6 +41,7 @@ #include "runtime/stubRoutines.hpp" #include "runtime/threadLocalStorage.hpp" #include "runtime/unhandledOops.hpp" +#include "utilities/macros.hpp" #if INCLUDE_NMT #include "services/memRecorder.hpp" @@ -49,10 +50,10 @@ #include "trace/tracing.hpp" #include "utilities/exceptions.hpp" #include "utilities/top.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/dirtyCardQueue.hpp" #include "gc_implementation/g1/satbQueue.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef ZERO #ifdef TARGET_ARCH_zero # include "stack_zero.hpp" @@ -929,7 +930,7 @@ class JavaThread: public Thread { } _jmp_ring[ jump_ring_buffer_size ]; #endif /* PRODUCT */ -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Support for G1 barriers ObjPtrQueue _satb_mark_queue; // Thread-local log for SATB barrier. @@ -941,7 +942,7 @@ class JavaThread: public Thread { static DirtyCardQueueSet _dirty_card_queue_set; void flush_barrier_queues(); -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS friend class VMThread; friend class ThreadWaitTransition; @@ -1345,10 +1346,10 @@ class JavaThread: public Thread { return byte_offset_of(JavaThread, _should_post_on_exceptions_flag); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS static ByteSize satb_mark_queue_offset() { return byte_offset_of(JavaThread, _satb_mark_queue); } static ByteSize dirty_card_queue_offset() { return byte_offset_of(JavaThread, _dirty_card_queue); } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Returns the jni environment for this thread JNIEnv* jni_environment() { return &_jni_environment; } @@ -1637,7 +1638,7 @@ public: _stack_size_at_create = value; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // SATB marking queue support ObjPtrQueue& satb_mark_queue() { return _satb_mark_queue; } static SATBMarkQueueSet& satb_mark_queue_set() { @@ -1649,7 +1650,7 @@ public: static DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // This method initializes the SATB and dirty card queues before a // JavaThread is added to the Java thread list. Right now, we don't @@ -1668,11 +1669,11 @@ public: // might happen between the JavaThread constructor being called and the // thread being added to the Java thread list (an example of this is // when the structure for the DestroyJavaVM thread is created). -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void initialize_queues(); -#else // !SERIALGC +#else // INCLUDE_ALL_GCS void initialize_queues() { } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Machine dependent stuff #ifdef TARGET_OS_ARCH_linux_x86 diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index e180f7d449f..024e9268235 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -101,6 +101,7 @@ #include "utilities/array.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/hashtable.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_ARCH_x86 # include "vmStructs_x86.hpp" #endif @@ -146,7 +147,7 @@ #ifdef TARGET_OS_ARCH_bsd_zero # include "vmStructs_bsd_zero.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" @@ -161,7 +162,7 @@ #include "gc_implementation/parallelScavenge/psYoungGen.hpp" #include "gc_implementation/parallelScavenge/vmStructs_parallelgc.hpp" #include "gc_implementation/g1/vmStructs_g1.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER2 #include "opto/addnode.hpp" #include "opto/block.hpp" @@ -2785,7 +2786,7 @@ VMStructEntry VMStructs::localHotSpotVMStructs[] = { GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS VM_STRUCTS_PARALLELGC(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY) @@ -2795,7 +2796,7 @@ VMStructEntry VMStructs::localHotSpotVMStructs[] = { VM_STRUCTS_G1(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS VM_STRUCTS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY, @@ -2829,7 +2830,7 @@ VMTypeEntry VMStructs::localHotSpotVMTypes[] = { GENERATE_C2_VM_TYPE_ENTRY, GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS VM_TYPES_PARALLELGC(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY) @@ -2840,7 +2841,7 @@ VMTypeEntry VMStructs::localHotSpotVMTypes[] = { VM_TYPES_G1(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS VM_TYPES_CPU(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY, @@ -2871,11 +2872,11 @@ VMIntConstantEntry VMStructs::localHotSpotVMIntConstants[] = { GENERATE_C2_VM_INT_CONSTANT_ENTRY, GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS VM_INT_CONSTANTS_CMS(GENERATE_VM_INT_CONSTANT_ENTRY) VM_INT_CONSTANTS_PARNEW(GENERATE_VM_INT_CONSTANT_ENTRY) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS VM_INT_CONSTANTS_CPU(GENERATE_VM_INT_CONSTANT_ENTRY, GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, @@ -2929,7 +2930,7 @@ VMStructs::init() { CHECK_NO_OP, CHECK_NO_OP); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS VM_STRUCTS_PARALLELGC(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY); @@ -2939,7 +2940,7 @@ VMStructs::init() { VM_STRUCTS_G1(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS VM_STRUCTS_CPU(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY, @@ -2968,7 +2969,7 @@ VMStructs::init() { CHECK_C2_VM_TYPE_ENTRY, CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS VM_TYPES_PARALLELGC(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP); @@ -2979,7 +2980,7 @@ VMStructs::init() { VM_TYPES_G1(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS VM_TYPES_CPU(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, @@ -3034,7 +3035,7 @@ VMStructs::init() { ENSURE_C2_FIELD_TYPE_PRESENT, CHECK_NO_OP, CHECK_NO_OP)); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS debug_only(VM_STRUCTS_PARALLELGC(ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT)); debug_only(VM_STRUCTS_CMS(ENSURE_FIELD_TYPE_PRESENT, @@ -3042,7 +3043,7 @@ VMStructs::init() { ENSURE_FIELD_TYPE_PRESENT)); debug_only(VM_STRUCTS_G1(ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT)); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS debug_only(VM_STRUCTS_CPU(ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT, CHECK_NO_OP, diff --git a/hotspot/src/share/vm/services/attachListener.hpp b/hotspot/src/share/vm/services/attachListener.hpp index 1916e8cacb8..df471aae795 100644 --- a/hotspot/src/share/vm/services/attachListener.hpp +++ b/hotspot/src/share/vm/services/attachListener.hpp @@ -28,6 +28,7 @@ #include "memory/allocation.hpp" #include "utilities/debug.hpp" #include "utilities/ostream.hpp" +#include "utilities/macros.hpp" // The AttachListener thread services a queue of operations that are enqueued // by client tools. Each operation is identified by a name and has up to 3 diff --git a/hotspot/src/share/vm/services/classLoadingService.cpp b/hotspot/src/share/vm/services/classLoadingService.cpp index 04dfca89211..b06890808ab 100644 --- a/hotspot/src/share/vm/services/classLoadingService.cpp +++ b/hotspot/src/share/vm/services/classLoadingService.cpp @@ -31,6 +31,7 @@ #include "services/classLoadingService.hpp" #include "services/memoryService.hpp" #include "utilities/dtrace.hpp" +#include "utilities/macros.hpp" #ifdef DTRACE_ENABLED diff --git a/hotspot/src/share/vm/services/classLoadingService.hpp b/hotspot/src/share/vm/services/classLoadingService.hpp index 1ea177f8352..a7f2c4c254a 100644 --- a/hotspot/src/share/vm/services/classLoadingService.hpp +++ b/hotspot/src/share/vm/services/classLoadingService.hpp @@ -28,6 +28,7 @@ #include "runtime/handles.hpp" #include "runtime/perfData.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" class InstanceKlass; diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index 52a098a2613..7b8673ab89c 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -30,6 +30,7 @@ #include "services/diagnosticFramework.hpp" #include "services/heapDumper.hpp" #include "services/management.hpp" +#include "utilities/macros.hpp" void DCmdRegistrant::register_dcmds(){ // Registration of the diagnostic commands diff --git a/hotspot/src/share/vm/services/diagnosticCommand.hpp b/hotspot/src/share/vm/services/diagnosticCommand.hpp index 99d75a92f33..c7490c07930 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.hpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp @@ -35,6 +35,7 @@ #include "services/diagnosticCommand.hpp" #include "services/diagnosticFramework.hpp" #include "services/diagnosticCommand_ext.hpp" +#include "utilities/macros.hpp" class HelpDCmd : public DCmdWithParser { protected: diff --git a/hotspot/src/share/vm/services/g1MemoryPool.hpp b/hotspot/src/share/vm/services/g1MemoryPool.hpp index c84ecb2d555..abe67e2f91c 100644 --- a/hotspot/src/share/vm/services/g1MemoryPool.hpp +++ b/hotspot/src/share/vm/services/g1MemoryPool.hpp @@ -25,11 +25,12 @@ #ifndef SHARE_VM_SERVICES_G1MEMORYPOOL_HPP #define SHARE_VM_SERVICES_G1MEMORYPOOL_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1MonitoringSupport.hpp" #include "services/memoryPool.hpp" #include "services/memoryUsage.hpp" -#endif +#endif // INCLUDE_ALL_GCS // This file contains the three classes that represent the memory // pools of the G1 spaces: G1EdenPool, G1SurvivorPool, and diff --git a/hotspot/src/share/vm/services/heapDumper.cpp b/hotspot/src/share/vm/services/heapDumper.cpp index 0dbe2e86589..cf3dae96ce0 100644 --- a/hotspot/src/share/vm/services/heapDumper.cpp +++ b/hotspot/src/share/vm/services/heapDumper.cpp @@ -40,9 +40,10 @@ #include "services/heapDumper.hpp" #include "services/threadService.hpp" #include "utilities/ostream.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS /* * HPROF binary format - description copied from: diff --git a/hotspot/src/share/vm/services/management.cpp b/hotspot/src/share/vm/services/management.cpp index a5b68d9b655..549622e9210 100644 --- a/hotspot/src/share/vm/services/management.cpp +++ b/hotspot/src/share/vm/services/management.cpp @@ -53,6 +53,7 @@ #include "services/memoryService.hpp" #include "services/runtimeService.hpp" #include "services/threadService.hpp" +#include "utilities/macros.hpp" PerfVariable* Management::_begin_vm_creation_time = NULL; PerfVariable* Management::_end_vm_creation_time = NULL; diff --git a/hotspot/src/share/vm/services/memReporter.hpp b/hotspot/src/share/vm/services/memReporter.hpp index 38f1e60bd89..86d4b52efdf 100644 --- a/hotspot/src/share/vm/services/memReporter.hpp +++ b/hotspot/src/share/vm/services/memReporter.hpp @@ -29,6 +29,7 @@ #include "services/memBaseline.hpp" #include "services/memTracker.hpp" #include "utilities/ostream.hpp" +#include "utilities/macros.hpp" #if INCLUDE_NMT diff --git a/hotspot/src/share/vm/services/memoryPool.cpp b/hotspot/src/share/vm/services/memoryPool.cpp index dc608c49214..e2895b1f816 100644 --- a/hotspot/src/share/vm/services/memoryPool.cpp +++ b/hotspot/src/share/vm/services/memoryPool.cpp @@ -32,6 +32,7 @@ #include "services/management.hpp" #include "services/memoryManager.hpp" #include "services/memoryPool.hpp" +#include "utilities/macros.hpp" MemoryPool::MemoryPool(const char* name, PoolType type, @@ -208,7 +209,7 @@ MemoryUsage SurvivorContiguousSpacePool::get_memory_usage() { return MemoryUsage(initial_size(), used, committed, maxSize); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS CompactibleFreeListSpacePool::CompactibleFreeListSpacePool(CompactibleFreeListSpace* space, const char* name, PoolType type, @@ -225,7 +226,7 @@ MemoryUsage CompactibleFreeListSpacePool::get_memory_usage() { return MemoryUsage(initial_size(), used, committed, maxSize); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS GenerationPool::GenerationPool(Generation* gen, const char* name, diff --git a/hotspot/src/share/vm/services/memoryPool.hpp b/hotspot/src/share/vm/services/memoryPool.hpp index c97fdbfa7b3..82606185340 100644 --- a/hotspot/src/share/vm/services/memoryPool.hpp +++ b/hotspot/src/share/vm/services/memoryPool.hpp @@ -30,9 +30,10 @@ #include "memory/heap.hpp" #include "memory/space.hpp" #include "services/memoryUsage.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" -#endif +#endif // INCLUDE_ALL_GCS // A memory pool represents the memory area that the VM manages. // The Java virtual machine has at least one memory pool @@ -185,7 +186,7 @@ public: } }; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS class CompactibleFreeListSpacePool : public CollectedMemoryPool { private: CompactibleFreeListSpace* _space; @@ -199,7 +200,7 @@ public: MemoryUsage get_memory_usage(); size_t used_in_bytes() { return _space->used(); } }; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS class GenerationPool : public CollectedMemoryPool { diff --git a/hotspot/src/share/vm/services/memoryService.cpp b/hotspot/src/share/vm/services/memoryService.cpp index 03af9b99885..0040f9d96fc 100644 --- a/hotspot/src/share/vm/services/memoryService.cpp +++ b/hotspot/src/share/vm/services/memoryService.cpp @@ -43,7 +43,8 @@ #include "services/memoryPool.hpp" #include "services/memoryService.hpp" #include "utilities/growableArray.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/parNew/parNewGeneration.hpp" @@ -52,7 +53,7 @@ #include "gc_implementation/parallelScavenge/psYoungGen.hpp" #include "services/g1MemoryPool.hpp" #include "services/psMemoryPool.hpp" -#endif +#endif // INCLUDE_ALL_GCS GrowableArray* MemoryService::_pools_list = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(init_pools_list_size, true); @@ -83,7 +84,7 @@ void MemoryService::set_universe_heap(CollectedHeap* heap) { add_gen_collected_heap_info(GenCollectedHeap::heap()); break; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case CollectedHeap::ParallelScavengeHeap : { add_parallel_scavenge_heap_info(ParallelScavengeHeap::heap()); break; @@ -92,7 +93,7 @@ void MemoryService::set_universe_heap(CollectedHeap* heap) { add_g1_heap_info(G1CollectedHeap::heap()); break; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS default: { guarantee(false, "Unrecognized kind of heap"); } @@ -130,22 +131,22 @@ void MemoryService::add_gen_collected_heap_info(GenCollectedHeap* heap) { case Generation::DefNew: _minor_gc_manager = MemoryManager::get_copy_memory_manager(); break; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ParNew: case Generation::ASParNew: _minor_gc_manager = MemoryManager::get_parnew_memory_manager(); break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS default: guarantee(false, "Unrecognized generation spec"); break; } if (policy->is_mark_sweep_policy()) { _major_gc_manager = MemoryManager::get_msc_memory_manager(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS } else if (policy->is_concurrent_mark_sweep_policy()) { _major_gc_manager = MemoryManager::get_cms_memory_manager(); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { guarantee(false, "Unknown two-gen policy"); } @@ -159,7 +160,7 @@ void MemoryService::add_gen_collected_heap_info(GenCollectedHeap* heap) { add_generation_memory_pool(heap->get_gen(major), _major_gc_manager); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Add memory pools for ParallelScavengeHeap // This function currently only supports two generations collected heap. // The collector for ParallelScavengeHeap will have two memory managers. @@ -185,7 +186,7 @@ void MemoryService::add_g1_heap_info(G1CollectedHeap* g1h) { add_g1YoungGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager); add_g1OldGen_memory_pool(g1h, _major_gc_manager); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS MemoryPool* MemoryService::add_gen(Generation* gen, const char* name, @@ -222,7 +223,7 @@ MemoryPool* MemoryService::add_survivor_spaces(DefNewGeneration* gen, return (MemoryPool*) pool; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS MemoryPool* MemoryService::add_cms_space(CompactibleFreeListSpace* space, const char* name, bool is_heap, @@ -233,7 +234,7 @@ MemoryPool* MemoryService::add_cms_space(CompactibleFreeListSpace* space, _pools_list->append(pool); return (MemoryPool*) pool; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Add memory pool(s) for one generation void MemoryService::add_generation_memory_pool(Generation* gen, @@ -261,7 +262,7 @@ void MemoryService::add_generation_memory_pool(Generation* gen, break; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ParNew: case Generation::ASParNew: { @@ -282,7 +283,7 @@ void MemoryService::add_generation_memory_pool(Generation* gen, break; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case Generation::MarkSweepCompact: { assert(major_mgr != NULL && minor_mgr == NULL, "Should have only one manager"); @@ -293,7 +294,7 @@ void MemoryService::add_generation_memory_pool(Generation* gen, break; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ConcurrentMarkSweep: case Generation::ASConcurrentMarkSweep: { @@ -306,7 +307,7 @@ void MemoryService::add_generation_memory_pool(Generation* gen, true /* support_usage_threshold */); break; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS default: assert(false, "should not reach here"); @@ -326,7 +327,7 @@ void MemoryService::add_generation_memory_pool(Generation* gen, } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void MemoryService::add_psYoung_memory_pool(PSYoungGen* gen, MemoryManager* major_mgr, MemoryManager* minor_mgr) { assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers"); @@ -384,7 +385,7 @@ void MemoryService::add_g1OldGen_memory_pool(G1CollectedHeap* g1h, mgr->add_pool(old_gen); _pools_list->append(old_gen); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void MemoryService::add_code_heap_memory_pool(CodeHeap* heap) { _code_heap_pool = new CodeHeapPool(heap, @@ -534,17 +535,17 @@ Handle MemoryService::create_MemoryUsage_obj(MemoryUsage usage, TRAPS) { TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind, GCCause::Cause cause) { switch (kind) { case Generation::DefNew: -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ParNew: case Generation::ASParNew: -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS _fullGC=false; break; case Generation::MarkSweepCompact: -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ConcurrentMarkSweep: case Generation::ASConcurrentMarkSweep: -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS _fullGC=true; break; default: diff --git a/hotspot/src/share/vm/services/psMemoryPool.hpp b/hotspot/src/share/vm/services/psMemoryPool.hpp index 2fd193f70d0..080b49161f2 100644 --- a/hotspot/src/share/vm/services/psMemoryPool.hpp +++ b/hotspot/src/share/vm/services/psMemoryPool.hpp @@ -25,7 +25,8 @@ #ifndef SHARE_VM_SERVICES_PSMEMORYPOOL_HPP #define SHARE_VM_SERVICES_PSMEMORYPOOL_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psOldGen.hpp" #include "gc_implementation/parallelScavenge/psYoungGen.hpp" #include "gc_implementation/shared/mutableSpace.hpp" @@ -34,7 +35,7 @@ #include "memory/space.hpp" #include "services/memoryPool.hpp" #include "services/memoryUsage.hpp" -#endif +#endif // INCLUDE_ALL_GCS class PSGenerationPool : public CollectedMemoryPool { private: diff --git a/hotspot/src/share/vm/services/runtimeService.cpp b/hotspot/src/share/vm/services/runtimeService.cpp index bba6a95af73..49997dfc5b3 100644 --- a/hotspot/src/share/vm/services/runtimeService.cpp +++ b/hotspot/src/share/vm/services/runtimeService.cpp @@ -29,6 +29,7 @@ #include "services/runtimeService.hpp" #include "utilities/dtrace.hpp" #include "utilities/exceptions.hpp" +#include "utilities/macros.hpp" #ifndef USDT2 HS_DTRACE_PROBE_DECL(hs_private, safepoint__begin); diff --git a/hotspot/src/share/vm/utilities/macros.hpp b/hotspot/src/share/vm/utilities/macros.hpp index 64e331d90b0..a97e9e7d039 100644 --- a/hotspot/src/share/vm/utilities/macros.hpp +++ b/hotspot/src/share/vm/utilities/macros.hpp @@ -130,23 +130,23 @@ #endif // INCLUDE_MANAGEMENT /* - * When INCLUDE_ALTERNATE_GCS is false the only garbage collectors + * When INCLUDE_ALL_GCS is false the only garbage collectors * included in the JVM are defaultNewGeneration and markCompact. * - * When INCLUDE_ALTERNATE_GCS is true all garbage collectors are + * When INCLUDE_ALL_GCS is true all garbage collectors are * included in the JVM. */ -#ifndef INCLUDE_ALTERNATE_GCS -#define INCLUDE_ALTERNATE_GCS 1 -#endif // INCLUDE_ALTERNATE_GCS +#ifndef INCLUDE_ALL_GCS +#define INCLUDE_ALL_GCS 1 +#endif // INCLUDE_ALL_GCS -#if INCLUDE_ALTERNATE_GCS -#define NOT_ALTERNATE_GCS_RETURN /* next token must be ; */ -#define NOT_ALTERNATE_GCS_RETURN_(code) /* next token must be ; */ +#if INCLUDE_ALL_GCS +#define NOT_ALL_GCS_RETURN /* next token must be ; */ +#define NOT_ALL_GCS_RETURN_(code) /* next token must be ; */ #else -#define NOT_ALTERNATE_GCS_RETURN {} -#define NOT_ALTERNATE_GCS_RETURN_(code) { return code; } -#endif // INCLUDE_ALTERNATE_GCS +#define NOT_ALL_GCS_RETURN {} +#define NOT_ALL_GCS_RETURN_(code) { return code; } +#endif // INCLUDE_ALL_GCS #ifndef INCLUDE_NMT #define INCLUDE_NMT 1 diff --git a/hotspot/src/share/vm/utilities/top.hpp b/hotspot/src/share/vm/utilities/top.hpp index 034148a50db..b1abbc2f6a5 100644 --- a/hotspot/src/share/vm/utilities/top.hpp +++ b/hotspot/src/share/vm/utilities/top.hpp @@ -33,9 +33,9 @@ #include "utilities/macros.hpp" #include "utilities/ostream.hpp" #include "utilities/sizes.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1_globals.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_globals.hpp" #endif diff --git a/hotspot/src/share/vm/utilities/yieldingWorkgroup.cpp b/hotspot/src/share/vm/utilities/yieldingWorkgroup.cpp index 7e594232af4..e344aea4bbf 100644 --- a/hotspot/src/share/vm/utilities/yieldingWorkgroup.cpp +++ b/hotspot/src/share/vm/utilities/yieldingWorkgroup.cpp @@ -23,9 +23,10 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "utilities/yieldingWorkgroup.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Forward declaration of classes declared here. diff --git a/hotspot/src/share/vm/utilities/yieldingWorkgroup.hpp b/hotspot/src/share/vm/utilities/yieldingWorkgroup.hpp index f9646f91f7f..5a626ce7fa3 100644 --- a/hotspot/src/share/vm/utilities/yieldingWorkgroup.hpp +++ b/hotspot/src/share/vm/utilities/yieldingWorkgroup.hpp @@ -25,9 +25,10 @@ #ifndef SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP #define SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "utilities/workgroup.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Forward declarations From 27c881b2fbb927f27ab3bb2f0f22c69ec947620b Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Thu, 24 Jan 2013 10:57:38 -0800 Subject: [PATCH 004/158] 8006280: Need to reorder metadata structures to reduce size (64-bit) Reordered Klass, InstanceKlass and Method to save 8 bytes each Reviewed-by: coleenp, jiangli --- hotspot/src/share/vm/oops/instanceKlass.hpp | 19 ++++++++++--------- hotspot/src/share/vm/oops/klass.hpp | 16 ++++++++-------- hotspot/src/share/vm/oops/method.hpp | 2 +- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 97b3dd23313..2d3aa4835f0 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -256,6 +256,16 @@ class InstanceKlass: public Klass { // JVMTI fields can be moved to their own structure - see 6315920 unsigned char * _cached_class_file_bytes; // JVMTI: cached class file, before retransformable agent modified it in CFLH jint _cached_class_file_len; // JVMTI: length of above + + volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change + + // Class states are defined as ClassState (see above). + // Place the _init_state here to utilize the unused 2-byte after + // _idnum_allocated_count. + u1 _init_state; // state of class + u1 _reference_type; // reference type + + JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration // Method array. @@ -281,15 +291,6 @@ class InstanceKlass: public Klass { // ... Array* _fields; - volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change - - // Class states are defined as ClassState (see above). - // Place the _init_state here to utilize the unused 2-byte after - // _idnum_allocated_count. - u1 _init_state; // state of class - - u1 _reference_type; // reference type - // embedded Java vtable follows here // embedded Java itables follows here // embedded static fields follows here diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index be5d0c5293d..245499e39da 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -75,11 +75,11 @@ // [class_loader_data] // [modifier_flags] // [access_flags ] -// [verify_count ] - not in product -// [alloc_count ] // [last_biased_lock_bulk_revocation_time] (64 bits) // [prototype_header] // [biased_lock_revocation_count] +// [verify_count ] - not in product +// [alloc_count ] // [_modified_oops] // [_accumulated_modified_oops] // [trace_id] @@ -164,18 +164,18 @@ class Klass : public Metadata { jint _modifier_flags; // Processed access flags, for use by Class.getModifiers. AccessFlags _access_flags; // Access flags. The class/interface distinction is stored here. -#ifndef PRODUCT - int _verify_count; // to avoid redundant verifies -#endif - - juint _alloc_count; // allocation profiling support - // Biased locking implementation and statistics // (the 64-bit chunk goes first, to avoid some fragmentation) jlong _last_biased_lock_bulk_revocation_time; markOop _prototype_header; // Used when biased locking is both enabled and disabled for this type jint _biased_lock_revocation_count; +#ifndef PRODUCT + int _verify_count; // to avoid redundant verifies +#endif + + juint _alloc_count; // allocation profiling support + TRACE_DEFINE_KLASS_TRACE_ID; // Remembered sets support for the oops in the klasses. diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 72a4faf11d7..802467b8ec2 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -127,8 +127,8 @@ class Method : public Metadata { InvocationCounter _backedge_counter; // Incremented before each backedge taken - used to trigger frequencey-based optimizations #ifdef TIERED - jlong _prev_time; // Previous time the rate was acquired float _rate; // Events (invocation and backedge counter increments) per millisecond + jlong _prev_time; // Previous time the rate was acquired #endif #ifndef PRODUCT From 020fe75e6778dbf5033ec7e965b42fc1de17a9e2 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Thu, 24 Jan 2013 22:13:32 -0800 Subject: [PATCH 005/158] 8005128: JSR 292: the mlvm redefineClassInBootstrap test crashes in ConstantPool::compare_entry_to When constant pool is copied in merge_constant_pools the invokedynamic operands must be copied before. Reviewed-by: coleenp, twisti --- hotspot/src/share/vm/oops/constantPool.cpp | 62 +++++++++++-------- hotspot/src/share/vm/oops/constantPool.hpp | 1 + .../share/vm/prims/jvmtiRedefineClasses.cpp | 13 +++- 3 files changed, 46 insertions(+), 30 deletions(-) diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index d4fa72032df..3dd91fed4fb 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -1098,32 +1098,9 @@ bool ConstantPool::compare_entry_to(int index1, constantPoolHandle cp2, } // end compare_entry_to() -// Copy this constant pool's entries at start_i to end_i (inclusive) -// to the constant pool to_cp's entries starting at to_i. A total of -// (end_i - start_i) + 1 entries are copied. -void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, - constantPoolHandle to_cp, int to_i, TRAPS) { - - int dest_i = to_i; // leave original alone for debug purposes - - for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) { - copy_entry_to(from_cp, src_i, to_cp, dest_i, CHECK); - - switch (from_cp->tag_at(src_i).value()) { - case JVM_CONSTANT_Double: - case JVM_CONSTANT_Long: - // double and long take two constant pool entries - src_i += 2; - dest_i += 2; - break; - - default: - // all others take one constant pool entry - src_i++; - dest_i++; - break; - } - } +void ConstantPool::copy_operands(constantPoolHandle from_cp, + constantPoolHandle to_cp, + TRAPS) { int from_oplen = operand_array_length(from_cp->operands()); int old_oplen = operand_array_length(to_cp->operands()); @@ -1179,8 +1156,39 @@ void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int to_cp->set_operands(new_operands); } } +} // end copy_operands() -} // end copy_cp_to() + +// Copy this constant pool's entries at start_i to end_i (inclusive) +// to the constant pool to_cp's entries starting at to_i. A total of +// (end_i - start_i) + 1 entries are copied. +void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, + constantPoolHandle to_cp, int to_i, TRAPS) { + + + int dest_i = to_i; // leave original alone for debug purposes + + for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) { + copy_entry_to(from_cp, src_i, to_cp, dest_i, CHECK); + + switch (from_cp->tag_at(src_i).value()) { + case JVM_CONSTANT_Double: + case JVM_CONSTANT_Long: + // double and long take two constant pool entries + src_i += 2; + dest_i += 2; + break; + + default: + // all others take one constant pool entry + src_i++; + dest_i++; + break; + } + } + copy_operands(from_cp, to_cp, CHECK); + +} // end copy_cp_to_impl() // Copy this constant pool's entry at from_i to the constant pool diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index ea4b13f0f9d..de38d727b6b 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -781,6 +781,7 @@ class ConstantPool : public Metadata { } static void copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS); static void copy_entry_to(constantPoolHandle from_cp, int from_i, constantPoolHandle to_cp, int to_i, TRAPS); + static void copy_operands(constantPoolHandle from_cp, constantPoolHandle to_cp, TRAPS); int find_matching_entry(int pattern_i, constantPoolHandle search_cp, TRAPS); int version() const { return _saved._version; } void set_version(int version) { _saved._version = version; } diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index 7255579280b..bae742b535d 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -1122,6 +1122,8 @@ bool VM_RedefineClasses::merge_constant_pools(constantPoolHandle old_cp, } } // end for each old_cp entry + ConstantPool::copy_operands(old_cp, *merge_cp_p, CHECK_0); + // We don't need to sanity check that *merge_cp_length_p is within // *merge_cp_p bounds since we have the minimum on-entry check above. (*merge_cp_length_p) = old_i; @@ -1305,8 +1307,12 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( _index_map_count = 0; _index_map_p = new intArray(scratch_cp->length(), -1); + // reference to the cp holder is needed for copy_operands() + merge_cp->set_pool_holder(scratch_class()); bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp, &merge_cp_length, THREAD); + merge_cp->set_pool_holder(NULL); + if (!result) { // The merge can fail due to memory allocation failure or due // to robustness checks. @@ -2380,13 +2386,14 @@ void VM_RedefineClasses::set_new_constant_pool( assert(version != 0, "sanity check"); smaller_cp->set_version(version); + // attach klass to new constant pool + // reference to the cp holder is needed for copy_operands() + smaller_cp->set_pool_holder(scratch_class()); + scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD); scratch_cp = smaller_cp; // attach new constant pool to klass - scratch_cp->set_pool_holder(scratch_class()); - - // attach klass to new constant pool scratch_class->set_constants(scratch_cp()); int i; // for portability From 19303cc71d772a97ac56d490ba220637597c3b56 Mon Sep 17 00:00:00 2001 From: Yunda Date: Thu, 24 Jan 2013 23:30:45 -0800 Subject: [PATCH 006/158] 8005278: Serviceability Agent: jmap -heap and jstack -m fail BinaryTreeDictionary is typedef'ed as AFLBinaryTreeDictionary in vmStructs and in SA we still use old name for that. FreeList now is a template based class which is not reflect in SA type library. When SA does calculation of heap for CMS, the former will cause failure to retrieve BinaryTreeDictionary sine the rename. The later will fail wherever it is used in SA. Reviewed-by: dholmes, sla, coleenp --- ...eeDictionary.java => AFLBinaryTreeDictionary.java} | 10 +++++----- .../jvm/hotspot/memory/CompactibleFreeListSpace.java | 6 +++--- .../classes/sun/jvm/hotspot/memory/FreeList.java | 4 ++-- .../concurrentMarkSweep/vmStructs_cms.hpp | 11 ++++++----- 4 files changed, 16 insertions(+), 15 deletions(-) rename hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/{BinaryTreeDictionary.java => AFLBinaryTreeDictionary.java} (85%) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/AFLBinaryTreeDictionary.java similarity index 85% rename from hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java rename to hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/AFLBinaryTreeDictionary.java index 802af91bbc7..5b56cf5f815 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/AFLBinaryTreeDictionary.java @@ -1,6 +1,6 @@ /* * @(#)BinaryTreeDictionary.java - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -30,7 +30,7 @@ import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.runtime.*; -public class BinaryTreeDictionary extends VMObject { +public class AFLBinaryTreeDictionary extends VMObject { static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -40,8 +40,8 @@ public class BinaryTreeDictionary extends VMObject { } private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("BinaryTreeDictionary"); - totalSizeField = type.getCIntegerField("_totalSize"); + Type type = db.lookupType("AFLBinaryTreeDictionary"); + totalSizeField = type.getCIntegerField("_total_size"); } // Fields @@ -53,7 +53,7 @@ public class BinaryTreeDictionary extends VMObject { } // Constructor - public BinaryTreeDictionary(Address addr) { + public AFLBinaryTreeDictionary(Address addr) { super(addr); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java index c2e8200b694..f47f0e81127 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -117,9 +117,9 @@ public class CompactibleFreeListSpace extends CompactibleSpace { } // large block - BinaryTreeDictionary bfbd = (BinaryTreeDictionary) VMObjectFactory.newObject(BinaryTreeDictionary.class, + AFLBinaryTreeDictionary aflbd = (AFLBinaryTreeDictionary) VMObjectFactory.newObject(AFLBinaryTreeDictionary.class, dictionaryField.getValue(addr)); - size += bfbd.size(); + size += aflbd.size(); // linear block in TLAB diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java index 23d7c3d34ee..2d0024e1d2d 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java @@ -1,7 +1,7 @@ /* * @(#)FreeList.java * - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -41,7 +41,7 @@ public class FreeList extends VMObject { } private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("FreeList"); + Type type = db.lookupType("FreeList"); sizeField = type.getCIntegerField("_size"); countField = type.getCIntegerField("_count"); headerSize = type.getSize(); diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp index a67e19d89d2..cc0a33f4013 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -34,16 +34,17 @@ typedef BinaryTreeDictionary AFLBinaryTreeDictionar nonstatic_field(CompactibleFreeListSpace, _bt, BlockOffsetArrayNonContigSpace) \ \ nonstatic_field(CMSBitMap, _bmWordSize, size_t) \ - nonstatic_field(CMSBitMap, _shifter, const int) \ - nonstatic_field(CMSBitMap, _bm, BitMap) \ - nonstatic_field(CMSBitMap, _virtual_space, VirtualSpace) \ + nonstatic_field(CMSBitMap, _shifter, const int) \ + nonstatic_field(CMSBitMap, _bm, BitMap) \ + nonstatic_field(CMSBitMap, _virtual_space, VirtualSpace) \ nonstatic_field(CMSCollector, _markBitMap, CMSBitMap) \ nonstatic_field(ConcurrentMarkSweepGeneration, _cmsSpace, CompactibleFreeListSpace*) \ static_field(ConcurrentMarkSweepThread, _collector, CMSCollector*) \ nonstatic_field(LinearAllocBlock, _word_size, size_t) \ nonstatic_field(AFLBinaryTreeDictionary, _total_size, size_t) \ nonstatic_field(CompactibleFreeListSpace, _indexedFreeList[0], FreeList) \ - nonstatic_field(CompactibleFreeListSpace, _smallLinearAllocBlock, LinearAllocBlock) + nonstatic_field(CompactibleFreeListSpace, _smallLinearAllocBlock, LinearAllocBlock) \ + nonstatic_field(CompactibleFreeListSpace, _dictionary, FreeBlockDictionary*) #define VM_TYPES_CMS(declare_type, \ From 25189c1a6a17cd7e8e3440d07803afa61f9d3a30 Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Fri, 25 Jan 2013 10:14:22 +0100 Subject: [PATCH 007/158] 8006413: Add utility classes for writing better multiprocess tests in jtreg Add a few utility classes to test/testlibrary to support multi process testing in jtreg tests. Added a test case for one of the utility classes. Also reviewed by Vitaly Davidovich Reviewed-by: brutisso, dholmes, vlivanov, nloodin, mgerdin --- .../test/testlibrary/OutputAnalyzerTest.java | 108 ++++++++++ .../java/testlibrary/JDKToolFinder.java | 50 +++++ .../java/testlibrary/OutputAnalyzer.java | 191 ++++++++++++++++++ .../oracle/java/testlibrary/OutputBuffer.java | 59 ++++++ .../oracle/java/testlibrary/ProcessTools.java | 141 +++++++++++++ .../oracle/java/testlibrary/StreamPumper.java | 76 +++++++ 6 files changed, 625 insertions(+) create mode 100644 hotspot/test/testlibrary/OutputAnalyzerTest.java create mode 100644 hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java create mode 100644 hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java create mode 100644 hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java create mode 100644 hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java create mode 100644 hotspot/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java diff --git a/hotspot/test/testlibrary/OutputAnalyzerTest.java b/hotspot/test/testlibrary/OutputAnalyzerTest.java new file mode 100644 index 00000000000..cc48fd3ff43 --- /dev/null +++ b/hotspot/test/testlibrary/OutputAnalyzerTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @summary Test the OutputAnalyzer utility class + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class OutputAnalyzerTest { + + public static void main(String args[]) throws Exception { + + String stdout = "aaaaaa"; + String stderr = "bbbbbb"; + + OutputAnalyzer output = new OutputAnalyzer(stdout, stderr); + + if (!stdout.equals(output.getStdout())) { + throw new Exception("getStdout() returned '" + output.getStdout() + "', expected '" + stdout + "'"); + } + + if (!stderr.equals(output.getStderr())) { + throw new Exception("getStderr() returned '" + output.getStderr() + "', expected '" + stderr + "'"); + } + + try { + output.shouldContain(stdout); + output.stdoutShouldContain(stdout); + output.shouldContain(stderr); + output.stderrShouldContain(stderr); + } catch (RuntimeException e) { + throw new Exception("shouldContain() failed", e); + } + + try { + output.shouldContain("cccc"); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldContain(stderr); + throw new Exception("stdoutShouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stderrShouldContain(stdout); + throw new Exception("stdoutShouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.shouldNotContain("cccc"); + output.stdoutShouldNotContain("cccc"); + output.stderrShouldNotContain("cccc"); + } catch (RuntimeException e) { + throw new Exception("shouldNotContain() failed", e); + } + + try { + output.shouldNotContain(stdout); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldNotContain(stdout); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stderrShouldNotContain(stderr); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java new file mode 100644 index 00000000000..91ad6a8c8a9 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 com.oracle.java.testlibrary; + +import java.io.File; + +public final class JDKToolFinder { + + private JDKToolFinder() { + } + + /** + * Returns the full path to an executable in jdk/bin based on System property + * test.jdk (set by jtreg test suite) + * + * @return Full path to an executable in jdk/bin + */ + public static String getJDKTool(String tool) { + String binPath = System.getProperty("test.jdk"); + if (binPath == null) { + throw new RuntimeException("System property 'test.jdk' not set. This property is normally set by jtreg. " + + "When running test separately, set this property using '-Dtest.jdk=/path/to/jdk'."); + } + + binPath += File.separatorChar + "bin" + File.separatorChar + tool; + + return binPath; + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java new file mode 100644 index 00000000000..469d0c24a70 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 com.oracle.java.testlibrary; + +import java.io.IOException; + +public final class OutputAnalyzer { + + private final String stdout; + private final String stderr; + private final int exitValue; + + /** + * Create an OutputAnalyzer, a utility class for verifying output and exit + * value from a Process + * + * @param process Process to analyze + * @throws IOException If an I/O error occurs. + */ + public OutputAnalyzer(Process process) throws IOException { + OutputBuffer output = ProcessTools.getOutput(process); + exitValue = process.exitValue(); + this.stdout = output.getStdout(); + this.stderr = output.getStderr(); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param buf String buffer to analyze + */ + public OutputAnalyzer(String buf) { + this(buf, buf); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param stdout stdout buffer to analyze + * @param stderr stderr buffer to analyze + */ + public OutputAnalyzer(String stdout, String stderr) { + this.stdout = stdout; + this.stderr = stderr; + exitValue = -1; + } + + /** + * Verify that the stdout and stderr contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public void shouldContain(String expectedString) { + if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr: [" + stdout + stderr + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public void stdoutShouldContain(String expectedString) { + if (!stdout.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + "' missing from stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public void stderrShouldContain(String expectedString) { + if (!stderr.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + "' missing from stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout and stderr contents of output buffer does not contain the string + * + * @param expectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public void shouldNotContain(String notExpectedString) { + if (stdout.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stdout: [" + stdout + "]\n"); + } + if (stderr.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer does not contain the string + * + * @param expectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public void stdoutShouldNotContain(String notExpectedString) { + if (stdout.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer does not contain the string + * + * @param expectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public void stderrShouldNotContain(String notExpectedString) { + if (stderr.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** + * Verifiy the exit value of the process + * + * @param expectedExitValue Expected exit value from process + * @throws RuntimeException If the exit value from the process did not match the expected value + */ + public void shouldHaveExitValue(int expectedExitValue) { + if (getExitValue() != expectedExitValue) { + throw new RuntimeException("Exit value " + getExitValue() + " , expected to get " + expectedExitValue); + } + } + + /** + * Get the contents of the output buffer (stdout and stderr) + * + * @return Content of the output buffer + */ + public String getOutput() { + return stdout + stderr; + } + + /** + * Get the contents of the stdout buffer + * + * @return Content of the stdout buffer + */ + public String getStdout() { + return stdout; + } + + /** + * Get the contents of the stderr buffer + * + * @return Content of the stderr buffer + */ + public String getStderr() { + return stderr; + } + + /** + * Get the process exit value + * + * @return Process exit value + */ + public int getExitValue() { + return exitValue; + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java new file mode 100644 index 00000000000..b98d05650f5 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 com.oracle.java.testlibrary; + +public class OutputBuffer { + private final String stdout; + private final String stderr; + + /** + * Create an OutputBuffer, a class for storing and managing stdout and stderr + * results separately + * + * @param stdout stdout result + * @param stderr stderr result + */ + public OutputBuffer(String stdout, String stderr) { + this.stdout = stdout; + this.stderr = stderr; + } + + /** + * Returns the stdout result + * + * @return stdout result + */ + public String getStdout() { + return stdout; + } + + /** + * Returns the stderr result + * + * @return stderr result + */ + public String getStderr() { + return stderr; + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java new file mode 100644 index 00000000000..42203d17ff0 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 com.oracle.java.testlibrary; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; + +import sun.management.VMManagement; + +public final class ProcessTools { + + private ProcessTools() { + } + + /** + * Pumps stdout and stderr from running the process into a String. + * + * @param processHandler ProcessHandler to run. + * @return Output from process. + * @throws IOException If an I/O error occurs. + */ + public static OutputBuffer getOutput(ProcessBuilder processBuilder) throws IOException { + return getOutput(processBuilder.start()); + } + + /** + * Pumps stdout and stderr the running process into a String. + * + * @param process Process to pump. + * @return Output from process. + * @throws IOException If an I/O error occurs. + */ + public static OutputBuffer getOutput(Process process) throws IOException { + ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream(); + ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream(); + StreamPumper outPumper = new StreamPumper(process.getInputStream(), stdoutBuffer); + StreamPumper errPumper = new StreamPumper(process.getErrorStream(), stderrBuffer); + Thread outPumperThread = new Thread(outPumper); + Thread errPumperThread = new Thread(errPumper); + + outPumperThread.setDaemon(true); + errPumperThread.setDaemon(true); + + outPumperThread.start(); + errPumperThread.start(); + + try { + process.waitFor(); + outPumperThread.join(); + errPumperThread.join(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return null; + } + + return new OutputBuffer(stdoutBuffer.toString(), stderrBuffer.toString()); + } + + /** + * Get the process id of the current running Java process + * + * @return Process id + */ + public static int getProcessId() throws Exception { + + // Get the current process id using a reflection hack + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + Field jvm = runtime.getClass().getDeclaredField("jvm"); + + jvm.setAccessible(true); + VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime); + + Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId"); + + pid_method.setAccessible(true); + + int pid = (Integer) pid_method.invoke(mgmt); + + return pid; + } + + /** + * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris) + * + * @return String[] with platform specific arguments, empty if there are none + */ + public static String[] getPlatformSpecificVMArgs() { + String osName = System.getProperty("os.name"); + String dataModel = System.getProperty("sun.arch.data.model"); + + if (osName.equals("SunOS") && dataModel.equals("64")) { + return new String[] { "-d64" }; + } + + return new String[] {}; + } + + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested and + * with any platform specific arguments prepended + */ + public static ProcessBuilder createJavaProcessBuilder(String... command) throws Exception { + String javapath = JDKToolFinder.getJDKTool("java"); + + ArrayList args = new ArrayList<>(); + args.add(javapath); + Collections.addAll(args, getPlatformSpecificVMArgs()); + Collections.addAll(args, command); + + return new ProcessBuilder(args.toArray(new String[args.size()])); + + } + +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java new file mode 100644 index 00000000000..4631bce6175 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 com.oracle.java.testlibrary; + +import java.io.OutputStream; +import java.io.InputStream; +import java.io.IOException; + +public final class StreamPumper implements Runnable { + + private static final int BUF_SIZE = 256; + + private final OutputStream out; + private final InputStream in; + + /** + * Create a StreamPumper that reads from in and writes to out. + * + * @param in The stream to read from. + * @param out The stream to write to. + */ + public StreamPumper(InputStream in, OutputStream out) { + this.in = in; + this.out = out; + } + + /** + * Implements Thread.run(). Continuously read from in and write + * to out until in has reached end of stream. Abort + * on interruption. Abort on IOExceptions. + */ + @Override + public void run() { + int length; + InputStream localIn = in; + OutputStream localOut = out; + byte[] buffer = new byte[BUF_SIZE]; + + try { + while (!Thread.interrupted() && (length = localIn.read(buffer)) > 0) { + localOut.write(buffer, 0, length); + } + } catch (IOException e) { + // Just abort if something like this happens. + e.printStackTrace(); + } finally { + try { + localOut.flush(); + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} From 0c7d523859b5fb9ec6256599add317a6607de387 Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 25 Jan 2013 03:03:23 -0800 Subject: [PATCH 008/158] 8006827: new hotspot build - hs25-b18 Reviewed-by: jcoomes --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index c47d3d18289..6f09485a3a3 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2013 HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=17 +HS_BUILD_NUMBER=18 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 From fc0efc91c80fecca6e8ee15b4e6054f0af9eea6d Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Fri, 25 Jan 2013 10:04:08 -0500 Subject: [PATCH 009/158] 8000692: Remove old KERNEL code Removed depreciated kernel VM source code from hotspot VM Reviewed-by: dholmes, acorn --- hotspot/make/Makefile | 54 +----------- hotspot/make/bsd/makefiles/dtrace.make | 12 +-- hotspot/make/solaris/Makefile | 22 +---- hotspot/make/solaris/makefiles/dtrace.make | 12 +-- hotspot/make/solaris/makefiles/kernel.make | 32 ------- hotspot/make/windows/build.bat | 5 +- hotspot/make/windows/create_obj_files.sh | 7 +- hotspot/make/windows/makefiles/defs.make | 17 +--- .../windows/makefiles/projectcreator.make | 59 +------------ hotspot/make/windows/makefiles/vm.make | 6 +- hotspot/src/cpu/x86/vm/assembler_x86.hpp | 4 +- .../share/vm/classfile/systemDictionary.cpp | 83 +------------------ .../share/vm/classfile/systemDictionary.hpp | 6 +- hotspot/src/share/vm/classfile/vmSymbols.hpp | 3 +- hotspot/src/share/vm/prims/jniCheck.hpp | 4 +- hotspot/src/share/vm/prims/jvm.cpp | 4 - .../share/vm/prims/jvmtiCodeBlobEvents.hpp | 4 +- hotspot/src/share/vm/prims/jvmtiEnv.cpp | 6 +- hotspot/src/share/vm/prims/jvmtiEnvBase.cpp | 12 +-- hotspot/src/share/vm/prims/jvmtiExport.cpp | 6 +- .../src/share/vm/prims/jvmtiExtensions.hpp | 4 +- hotspot/src/share/vm/prims/jvmtiImpl.cpp | 6 +- hotspot/src/share/vm/prims/jvmtiImpl.hpp | 5 +- .../src/share/vm/prims/jvmtiRawMonitor.hpp | 4 +- .../share/vm/prims/jvmtiRedefineClasses.cpp | 2 - hotspot/src/share/vm/prims/jvmtiTagMap.hpp | 4 +- hotspot/src/share/vm/runtime/arguments.cpp | 35 +------- hotspot/src/share/vm/runtime/arguments.hpp | 7 +- hotspot/src/share/vm/runtime/thread.cpp | 24 +----- hotspot/src/share/vm/runtime/vmStructs.hpp | 4 +- hotspot/src/share/vm/runtime/vm_version.cpp | 6 +- .../src/share/vm/services/attachListener.cpp | 6 +- .../src/share/vm/services/attachListener.hpp | 5 +- 33 files changed, 40 insertions(+), 430 deletions(-) delete mode 100644 hotspot/make/solaris/makefiles/kernel.make diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index fe5a6b684d6..a1d8cb9dde6 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -87,7 +87,6 @@ endif # Typical C1/C2 targets made available with this Makefile C1_VM_TARGETS=product1 fastdebug1 optimized1 jvmg1 C2_VM_TARGETS=product fastdebug optimized jvmg -KERNEL_VM_TARGETS=productkernel fastdebugkernel optimizedkernel jvmgkernel ZERO_VM_TARGETS=productzero fastdebugzero optimizedzero jvmgzero SHARK_VM_TARGETS=productshark fastdebugshark optimizedshark jvmgshark MINIMAL1_VM_TARGETS=productminimal1 fastdebugminimal1 jvmgminimal1 @@ -161,11 +160,6 @@ $(C2_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ $(MAKE) BUILD_FLAVOR=$@ VM_TARGET=$@ generic_build2 $(ALT_OUT) -$(KERNEL_VM_TARGETS): - $(CD) $(GAMMADIR)/make; \ - $(MAKE) BUILD_FLAVOR=$(@:%kernel=%) VM_TARGET=$@ \ - generic_buildkernel $(ALT_OUT) - $(ZERO_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ $(MAKE) BUILD_FLAVOR=$(@:%zero=%) VM_TARGET=$@ \ @@ -223,24 +217,6 @@ else $(MAKE_ARGS) $(VM_TARGET) endif -generic_buildkernel: - $(MKDIR) -p $(OUTPUTDIR) -ifeq ($(OSNAME),windows) - ifeq ($(ARCH_DATA_MODEL), 32) - $(CD) $(OUTPUTDIR); \ - $(NMAKE) -f $(ABS_OS_MAKEFILE) \ - Variant=kernel \ - WorkSpace=$(ABS_GAMMADIR) \ - BootStrapDir=$(ABS_BOOTDIR) \ - BuildUser=$(USERNAME) \ - $(MAKE_ARGS) $(VM_TARGET:%kernel=%) - else - @$(ECHO) "No kernel ($(VM_TARGET)) for ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)" - endif -else - @$(ECHO) "No kernel ($(VM_TARGET)) for OS_NAME=$(OSNAME)" -endif - generic_buildzero: $(MKDIR) -p $(OUTPUTDIR) $(CD) $(OUTPUTDIR); \ @@ -314,12 +290,10 @@ XUSAGE=$(HS_SRC_DIR)/share/vm/Xusage.txt DOCS_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_docs C1_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_compiler1 C2_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_compiler2 -KERNEL_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_kernel ZERO_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_zero SHARK_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_shark C1_DIR=$(C1_BASE_DIR)/$(VM_SUBDIR) C2_DIR=$(C2_BASE_DIR)/$(VM_SUBDIR) -KERNEL_DIR=$(KERNEL_BASE_DIR)/$(VM_SUBDIR) ZERO_DIR=$(ZERO_BASE_DIR)/$(VM_SUBDIR) SHARK_DIR=$(SHARK_BASE_DIR)/$(VM_SUBDIR) MINIMAL1_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_minimal1 @@ -333,10 +307,6 @@ ifeq ($(JVM_VARIANT_CLIENT), true) MISC_DIR=$(C1_DIR) GEN_DIR=$(C1_BASE_DIR)/generated endif -ifeq ($(JVM_VARIANT_KERNEL), true) - MISC_DIR=$(C2_DIR) - GEN_DIR=$(C2_BASE_DIR)/generated -endif ifeq ($(JVM_VARIANT_ZEROSHARK), true) MISC_DIR=$(SHARK_DIR) GEN_DIR=$(SHARK_BASE_DIR)/generated @@ -386,16 +356,6 @@ $(EXPORT_SERVER_DIR)/%.pdb: $(C2_DIR)/%.pdb $(install-file) $(EXPORT_SERVER_DIR)/%.map: $(C2_DIR)/%.map $(install-file) - -# Kernel files always come from kernel area -$(EXPORT_KERNEL_DIR)/%.diz: $(KERNEL_DIR)/%.diz - $(install-file) -$(EXPORT_KERNEL_DIR)/%.dll: $(KERNEL_DIR)/%.dll - $(install-file) -$(EXPORT_KERNEL_DIR)/%.pdb: $(KERNEL_DIR)/%.pdb - $(install-file) -$(EXPORT_KERNEL_DIR)/%.map: $(KERNEL_DIR)/%.map - $(install-file) endif # Minimal JVM files always come from minimal area @@ -538,7 +498,7 @@ $(EXPORT_DOCS_DIR)/platform/jvmti/%: $(DOCS_DIR)/% $(install-file) # Xusage file -$(EXPORT_SERVER_DIR)/Xusage.txt $(EXPORT_CLIENT_DIR)/Xusage.txt $(EXPORT_KERNEL_DIR)/Xusage.txt $(EXPORT_MINIMAL_DIR)/Xusage.txt: $(XUSAGE) +$(EXPORT_SERVER_DIR)/Xusage.txt $(EXPORT_CLIENT_DIR)/Xusage.txt $(EXPORT_MINIMAL_DIR)/Xusage.txt: $(XUSAGE) $(prep-target) $(RM) $@.temp $(SED) 's/\(separated by \)[;:]/\1$(PATH_SEP)/g' $< > $@.temp @@ -551,7 +511,6 @@ clobber clean: clean_build clean_export clean_jdk clean_build: $(RM) -r $(C1_DIR) $(RM) -r $(C2_DIR) - $(RM) -r $(KERNEL_DIR) $(RM) -r $(ZERO_DIR) $(RM) -r $(SHARK_DIR) $(RM) -r $(MINIMAL1_DIR) @@ -586,10 +545,6 @@ test_jdk: $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -server -Xinternalversion $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -server -version endif - ifeq ($(JVM_VARIANT_KERNEL), true) - $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -kernel -Xinternalversion - $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -kernel -version - endif copy_product_jdk:: $(RM) -r $(JDK_IMAGE_DIR) @@ -665,7 +620,6 @@ target_help: @$(ECHO) "Other targets are:" @$(ECHO) " $(C1_VM_TARGETS)" @$(ECHO) " $(C2_VM_TARGETS)" - @$(ECHO) " $(KERNEL_VM_TARGETS)" @$(ECHO) " $(MINIMAL1_VM_TARGETS)" # Variable help (only common ones used by this workspace) @@ -761,8 +715,8 @@ endif include $(GAMMADIR)/make/jprt.gmk .PHONY: all world clobber clean help $(C1_VM_TARGETS) $(C2_VM_TARGETS) \ - $(KERNEL_VM_TARGETS) $(MINIMAL1_VM_TARGETS) \ - generic_build1 generic_build2 generic_buildkernel generic_buildminimal1 generic_export \ + $(MINIMAL1_VM_TARGETS) \ + generic_build1 generic_build2 generic_buildminimal1 generic_export \ export_product export_fastdebug export_debug export_optimized \ export_jdk_product export_jdk_fastdebug export_jdk_debug \ create_jdk copy_jdk update_jdk test_jdk \ diff --git a/hotspot/make/bsd/makefiles/dtrace.make b/hotspot/make/bsd/makefiles/dtrace.make index d325f2082dd..1c53841b56c 100644 --- a/hotspot/make/bsd/makefiles/dtrace.make +++ b/hotspot/make/bsd/makefiles/dtrace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -25,10 +25,9 @@ # Rules to build jvm_db/dtrace, used by vm.make # We build libjvm_dtrace/libjvm_db/dtrace for COMPILER1 and COMPILER2 -# but not for CORE or KERNEL configurations. +# but not for CORE configuration. ifneq ("${TYPE}", "CORE") -ifneq ("${TYPE}", "KERNEL") ifeq ($(OS_VENDOR), Darwin) # we build dtrace for macosx using USDT2 probes @@ -280,13 +279,6 @@ endif # ifneq ("${dtraceFound}", "") endif # ifeq ($(OS_VENDOR), Darwin) -else # KERNEL build - -dtraceCheck: - $(QUIETLY) echo "**NOTICE** Dtrace support disabled for KERNEL builds" - -endif # ifneq ("${TYPE}", "KERNEL") - else # CORE build dtraceCheck: diff --git a/hotspot/make/solaris/Makefile b/hotspot/make/solaris/Makefile index 4a47cb93716..83e4df66579 100644 --- a/hotspot/make/solaris/Makefile +++ b/hotspot/make/solaris/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 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 @@ -157,13 +157,11 @@ SUBDIRS_C1 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler1/,$(TARGETS)) SUBDIRS_C2 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler2/,$(TARGETS)) SUBDIRS_TIERED = $(addprefix $(OSNAME)_$(BUILDARCH)_tiered/,$(TARGETS)) SUBDIRS_CORE = $(addprefix $(OSNAME)_$(BUILDARCH)_core/,$(TARGETS)) -SUBDIRS_KERNEL = $(addprefix $(OSNAME)_$(BUILDARCH)_kernel/,$(TARGETS)) TARGETS_C2 = $(TARGETS) TARGETS_C1 = $(addsuffix 1,$(TARGETS)) TARGETS_TIERED = $(addsuffix tiered,$(TARGETS)) TARGETS_CORE = $(addsuffix core,$(TARGETS)) -TARGETS_KERNEL = $(addsuffix kernel,$(TARGETS)) BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) ARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) @@ -229,10 +227,6 @@ $(SUBDIRS_CORE): $(BUILDTREE_MAKE) $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=core -$(SUBDIRS_KERNEL): $(BUILDTREE_MAKE) - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks - $(BUILDTREE) VARIANT=kernel - # Define INSTALL=y at command line to automatically copy JVM into JAVA_HOME $(TARGETS_C2): $(SUBDIRS_C2) @@ -271,20 +265,10 @@ ifdef INSTALL cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS) install endif -$(TARGETS_KERNEL): $(SUBDIRS_KERNEL) - cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && $(MAKE) $(MFLAGS) -ifeq ($(TEST_IN_BUILD),true) - cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && ./test_gamma -endif -ifdef INSTALL - cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && $(MAKE) $(MFLAGS) install -endif - # Just build the tree, and nothing else: tree: $(SUBDIRS_C2) tree1: $(SUBDIRS_C1) treecore: $(SUBDIRS_CORE) -treekernel: $(SUBDIRS_KERNEL) # Doc target. This is the same for all build options. # Hence create a docs directory beside ...$(ARCH)_[...] @@ -304,10 +288,10 @@ core: jvmgcore productcore clean_docs: rm -rf $(SUBDIR_DOCS) -clean_compiler1 clean_compiler2 clean_core clean_kernel: +clean_compiler1 clean_compiler2 clean_core: rm -rf $(OSNAME)_$(BUILDARCH)_$(subst clean_,,$@) -clean: clean_compiler2 clean_compiler1 clean_core clean_docs clean_kernel +clean: clean_compiler2 clean_compiler1 clean_core clean_docs include $(GAMMADIR)/make/cscope.make diff --git a/hotspot/make/solaris/makefiles/dtrace.make b/hotspot/make/solaris/makefiles/dtrace.make index 111acdb0d96..b57365b93dc 100644 --- a/hotspot/make/solaris/makefiles/dtrace.make +++ b/hotspot/make/solaris/makefiles/dtrace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -25,10 +25,9 @@ # Rules to build jvm_db/dtrace, used by vm.make # We build libjvm_dtrace/libjvm_db/dtrace for COMPILER1 and COMPILER2 -# but not for CORE or KERNEL configurations. +# but not for CORE configuration. ifneq ("${TYPE}", "CORE") -ifneq ("${TYPE}", "KERNEL") ifdef USE_GCC @@ -362,13 +361,6 @@ endif # ifneq ("${dtraceFound}", "") endif # ifdef USE_GCC -else # KERNEL build - -dtraceCheck: - $(QUIETLY) echo "**NOTICE** Dtrace support disabled for KERNEL builds" - -endif # ifneq ("${TYPE}", "KERNEL") - else # CORE build dtraceCheck: diff --git a/hotspot/make/solaris/makefiles/kernel.make b/hotspot/make/solaris/makefiles/kernel.make deleted file mode 100644 index 40728e669f1..00000000000 --- a/hotspot/make/solaris/makefiles/kernel.make +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright (c) 2007, 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. -# -# 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. -# -# -# -# Sets make macros for making kernel version of VM. -# This target on solaris is just tempoarily for debugging the kernel build. - -TYPE=KERNEL - -VM_SUBDIR = client - -CFLAGS += -DKERNEL diff --git a/hotspot/make/windows/build.bat b/hotspot/make/windows/build.bat index e4eab3abf0c..5df20dd4f1e 100644 --- a/hotspot/make/windows/build.bat +++ b/hotspot/make/windows/build.bat @@ -1,6 +1,6 @@ @echo off REM -REM Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. +REM Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. REM REM This code is free software; you can redistribute it and/or modify it @@ -67,7 +67,6 @@ goto usage :test1 if "%2" == "core" goto test2 -if "%2" == "kernel" goto test2 if "%2" == "compiler1" goto test2 if "%2" == "compiler2" goto test2 if "%2" == "tiered" goto test2 @@ -109,7 +108,7 @@ echo Usage: build flavor version workspace bootstrap_dir [build_id] [windbg_home echo. echo where: echo flavor is "product", "debug" or "fastdebug", -echo version is "core", "kernel", "compiler1", "compiler2", or "tiered", +echo version is "core", "compiler1", "compiler2", or "tiered", echo workspace is source directory without trailing slash, echo bootstrap_dir is a full path to a JDK in which bin/java echo and bin/javac are present and working, and build_id is an diff --git a/hotspot/make/windows/create_obj_files.sh b/hotspot/make/windows/create_obj_files.sh index 78fabc06ddc..14a7087f2aa 100644 --- a/hotspot/make/windows/create_obj_files.sh +++ b/hotspot/make/windows/create_obj_files.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 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 @@ -107,7 +107,6 @@ COMPILER2_PATHS="${COMPILER2_PATHS} ${GENERATED}/adfiles" # Include dirs per type. case "${TYPE}" in "core") Src_Dirs="${CORE_PATHS}" ;; - "kernel") Src_Dirs="${BASE_PATHS} ${COMPILER1_PATHS}" ;; "compiler1") Src_Dirs="${CORE_PATHS} ${COMPILER1_PATHS}" ;; "compiler2") Src_Dirs="${CORE_PATHS} ${COMPILER2_PATHS}" ;; "tiered") Src_Dirs="${CORE_PATHS} ${COMPILER1_PATHS} ${COMPILER2_PATHS}" ;; @@ -120,16 +119,12 @@ COMPILER1_SPECIFIC_FILES="c1_*" SHARK_SPECIFIC_FILES="shark" ZERO_SPECIFIC_FILES="zero" -# These files need to be excluded when building the kernel target. -KERNEL_EXCLUDED_FILES="attachListener.cpp attachListener_windows.cpp metaspaceShared_${Platform_arch_model}.cpp forte.cpp fprofiler.cpp heapDumper.cpp heapInspection.cpp jniCheck.cpp jvmtiCodeBlobEvents.cpp jvmtiExtensions.cpp jvmtiImpl.cpp jvmtiRawMonitor.cpp jvmtiTagMap.cpp jvmtiTrace.cpp vmStructs.cpp g1MemoryPool.cpp psMemoryPool.cpp gcAdaptivePolicyCounters.cpp concurrentGCThread.cpp metaspaceShared.cpp mutableNUMASpace.cpp allocationStats.cpp gSpaceCounters.cpp immutableSpace.cpp mutableSpace.cpp spaceCounters.cpp yieldingWorkgroup.cpp" - # Always exclude these. Src_Files_EXCLUDE="jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp" # Exclude per type. case "${TYPE}" in "core") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;; - "kernel") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ${KERNEL_EXCLUDED_FILES} ciTypeFlow.cpp" ;; "compiler1") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;; "compiler2") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES}" ;; "tiered") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES}" ;; diff --git a/hotspot/make/windows/makefiles/defs.make b/hotspot/make/windows/makefiles/defs.make index e637c00335d..5d58e699bf2 100644 --- a/hotspot/make/windows/makefiles/defs.make +++ b/hotspot/make/windows/makefiles/defs.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -157,7 +157,7 @@ endif MAKE_ARGS += RM="$(RM)" MAKE_ARGS += ZIPEXE=$(ZIPEXE) -# On 32 bit windows we build server, client and kernel, on 64 bit just server. +# On 32 bit windows we build server and client, on 64 bit just server. ifeq ($(JVM_VARIANTS),) ifeq ($(ARCH_DATA_MODEL), 32) JVM_VARIANTS:=client,server @@ -250,7 +250,6 @@ endif EXPORT_SERVER_DIR = $(EXPORT_JRE_BIN_DIR)/server EXPORT_CLIENT_DIR = $(EXPORT_JRE_BIN_DIR)/client -EXPORT_KERNEL_DIR = $(EXPORT_JRE_BIN_DIR)/kernel ifeq ($(JVM_VARIANT_SERVER),true) EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt @@ -277,18 +276,6 @@ ifeq ($(JVM_VARIANT_CLIENT),true) endif endif endif -ifeq ($(JVM_VARIANT_KERNEL),true) - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/Xusage.txt - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.$(LIBRARY_SUFFIX) - ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) - ifeq ($(ZIP_DEBUGINFO_FILES),1) - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.diz - else - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.pdb - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.map - endif - endif -endif EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar diff --git a/hotspot/make/windows/makefiles/projectcreator.make b/hotspot/make/windows/makefiles/projectcreator.make index 5d71de6618a..68d098d0de3 100644 --- a/hotspot/make/windows/makefiles/projectcreator.make +++ b/hotspot/make/windows/makefiles/projectcreator.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -166,63 +166,6 @@ ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ $(ProjectCreatorIDEOptionsIgnoreCompiler1:TARGET=core) \ $(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=core) -################################################## -# JKERNEL specific options -################################################## -ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ - -define_kernel KERNEL \ -$(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=kernel) \ - -ignorePath_kernel src/share/vm/gc_implementation/parallelScavenge \ - -ignorePath_kernel src/share/vm/gc_implementation/parNew \ - -ignorePath_kernel src/share/vm/gc_implementation/concurrentMarkSweep \ - -ignorePath_kernel src/share/vm/gc_implementation/g1 \ - -ignoreFile_kernel attachListener.cpp \ - -ignoreFile_kernel attachListener_windows.cpp \ - -ignoreFile_kernel dump.cpp \ - -ignoreFile_kernel dump_$(Platform_arch_model).cpp \ - -ignoreFile_kernel forte.cpp \ - -ignoreFile_kernel fprofiler.cpp \ - -ignoreFile_kernel heapDumper.cpp \ - -ignoreFile_kernel heapInspection.cpp \ - -ignoreFile_kernel jniCheck.cpp \ - -ignoreFile_kernel jvmtiCodeBlobEvents.cpp \ - -ignoreFile_kernel jvmtiExtensions.cpp \ - -ignoreFile_kernel jvmtiImpl.cpp \ - -ignoreFile_kernel jvmtiRawMonitor.cpp \ - -ignoreFile_kernel jvmtiTagMap.cpp \ - -ignoreFile_kernel jvmtiTrace.cpp \ - -ignoreFile_kernel jvmtiTrace.hpp \ - -ignoreFile_kernel restore.cpp \ - -ignoreFile_kernel serialize.cpp \ - -ignoreFile_kernel vmStructs.cpp \ - -ignoreFile_kernel g1MemoryPool.cpp \ - -ignoreFile_kernel g1MemoryPool.hpp \ - -ignoreFile_kernel psMemoryPool.cpp \ - -ignoreFile_kernel psMemoryPool.hpp \ - -ignoreFile_kernel gcAdaptivePolicyCounters.cpp \ - -ignoreFile_kernel concurrentGCThread.cpp \ - -ignoreFile_kernel mutableNUMASpace.cpp \ - -ignoreFile_kernel ciTypeFlow.cpp \ - -ignoreFile_kernel ciTypeFlow.hpp \ - -ignoreFile_kernel oop.pcgc.inline.hpp \ - -ignoreFile_kernel oop.psgc.inline.hpp \ - -ignoreFile_kernel allocationStats.cpp \ - -ignoreFile_kernel allocationStats.hpp \ - -ignoreFile_kernel concurrentGCThread.hpp \ - -ignoreFile_kernel gSpaceCounters.cpp \ - -ignoreFile_kernel gSpaceCounters.hpp \ - -ignoreFile_kernel gcAdaptivePolicyCounters.hpp \ - -ignoreFile_kernel immutableSpace.cpp \ - -ignoreFile_kernel mutableNUMASpace.hpp \ - -ignoreFile_kernel mutableSpace.cpp \ - -ignoreFile_kernel spaceCounters.cpp \ - -ignoreFile_kernel spaceCounters.hpp \ - -ignoreFile_kernel yieldingWorkgroup.cpp \ - -ignoreFile_kernel yieldingWorkgroup.hpp \ - -ignorePath_kernel vmStructs_ \ - -ignoreFile_kernel $(Platform_arch_model).ad \ - -additionalFile_kernel gcTaskManager.hpp - ################################################## # Client(C1) compiler specific options ################################################## diff --git a/hotspot/make/windows/makefiles/vm.make b/hotspot/make/windows/makefiles/vm.make index b1e71de0e5a..2e501a7b9f7 100644 --- a/hotspot/make/windows/makefiles/vm.make +++ b/hotspot/make/windows/makefiles/vm.make @@ -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 @@ -44,10 +44,6 @@ CXX_FLAGS=$(CXX_FLAGS) /D "ASSERT" # No need to define anything, CORE is defined as !COMPILER1 && !COMPILER2 !endif -!if "$(Variant)" == "kernel" -CXX_FLAGS=$(CXX_FLAGS) /D "KERNEL" -!endif - !if "$(Variant)" == "compiler1" CXX_FLAGS=$(CXX_FLAGS) /D "COMPILER1" !endif diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index bcef330e4cf..ec4137c53d7 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -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 @@ -543,7 +543,7 @@ class Assembler : public AbstractAssembler { // of instructions are freely declared without the need for wrapping them an ifdef. // (Some dangerous instructions are ifdef's out of inappropriate jvm's.) // In the .cpp file the implementations are wrapped so that they are dropped out - // of the resulting jvm. This is done mostly to keep the footprint of KERNEL + // of the resulting jvm. This is done mostly to keep the footprint of MINIMAL // to the size it was prior to merging up the 32bit and 64bit assemblers. // // This does mean you'll get a linker/runtime error if you use a 64bit only instruction diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 54601625056..a7370fcce29 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -1199,66 +1199,6 @@ instanceKlassHandle SystemDictionary::load_shared_class( return ik; } -#ifdef KERNEL -// Some classes on the bootstrap class path haven't been installed on the -// system yet. Call the DownloadManager method to make them appear in the -// bootstrap class path and try again to load the named class. -// Note that with delegation class loaders all classes in another loader will -// first try to call this so it'd better be fast!! -static instanceKlassHandle download_and_retry_class_load( - Symbol* class_name, - TRAPS) { - - Klass* dlm = SystemDictionary::DownloadManager_klass(); - instanceKlassHandle nk; - - // If download manager class isn't loaded just return. - if (dlm == NULL) return nk; - - { HandleMark hm(THREAD); - ResourceMark rm(THREAD); - Handle s = java_lang_String::create_from_symbol(class_name, CHECK_(nk)); - Handle class_string = java_lang_String::externalize_classname(s, CHECK_(nk)); - - // return value - JavaValue result(T_OBJECT); - - // Call the DownloadManager. We assume that it has a lock because - // multiple classes could be not found and downloaded at the same time. - // class sun.misc.DownloadManager; - // public static String getBootClassPathEntryForClass(String className); - JavaCalls::call_static(&result, - KlassHandle(THREAD, dlm), - vmSymbols::getBootClassPathEntryForClass_name(), - vmSymbols::string_string_signature(), - class_string, - CHECK_(nk)); - - // Get result.string and add to bootclasspath - assert(result.get_type() == T_OBJECT, "just checking"); - oop obj = (oop) result.get_jobject(); - if (obj == NULL) { return nk; } - - Handle h_obj(THREAD, obj); - char* new_class_name = java_lang_String::as_platform_dependent_str(h_obj, - CHECK_(nk)); - - // lock the loader - // we use this lock because JVMTI does. - Handle loader_lock(THREAD, SystemDictionary::system_loader_lock()); - - ObjectLocker ol(loader_lock, THREAD); - // add the file to the bootclasspath - ClassLoader::update_class_path_entry_list(new_class_name, true); - } // end HandleMark - - if (TraceClassLoading) { - ClassLoader::print_bootclasspath(); - } - return ClassLoader::load_classfile(class_name, CHECK_(nk)); -} -#endif // KERNEL - instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) { instanceKlassHandle nh = instanceKlassHandle(); // null Handle @@ -1278,15 +1218,6 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha k = ClassLoader::load_classfile(class_name, CHECK_(nh)); } -#ifdef KERNEL - // If the VM class loader has failed to load the class, call the - // DownloadManager class to make it magically appear on the classpath - // and try again. This is only configured with the Kernel VM. - if (k.is_null()) { - k = download_and_retry_class_load(class_name, CHECK_(nh)); - } -#endif // KERNEL - // find_or_define_instance_class may return a different InstanceKlass if (!k.is_null()) { k = find_or_define_instance_class(class_name, class_loader, k, CHECK_(nh)); @@ -1822,13 +1753,7 @@ bool SystemDictionary::initialize_wk_klass(WKID id, int init_opt, TRAPS) { Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid); Klass** klassp = &_well_known_klasses[id]; bool must_load = (init_opt < SystemDictionary::Opt); - bool try_load = true; - if (init_opt == SystemDictionary::Opt_Kernel) { -#ifndef KERNEL - try_load = false; -#endif //KERNEL - } - if ((*klassp) == NULL && try_load) { + if ((*klassp) == NULL) { if (must_load) { (*klassp) = resolve_or_fail(symbol, true, CHECK_0); // load required class } else { @@ -1918,12 +1843,6 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { //_box_klasses[T_OBJECT] = WK_KLASS(object_klass); //_box_klasses[T_ARRAY] = WK_KLASS(object_klass); -#ifdef KERNEL - if (DownloadManager_klass() == NULL) { - warning("Cannot find sun/jkernel/DownloadManager"); - } -#endif // KERNEL - { // Compute whether we should use loadClass or loadClassInternal when loading classes. Method* method = InstanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature()); _has_loadClassInternal = (method != NULL); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index e2f660ee171..d415c9b1e4f 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -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 @@ -168,8 +168,6 @@ class SymbolPropertyTable; /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ do_klass(nio_Buffer_klass, java_nio_Buffer, Opt ) \ \ - do_klass(DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel ) \ - \ do_klass(PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt ) \ \ /* Preload boxing klasses */ \ @@ -211,7 +209,6 @@ class SystemDictionary : AllStatic { Opt, // preload tried; NULL if not present Opt_Only_JDK14NewRef, // preload tried; use only with NewReflection Opt_Only_JDK15, // preload tried; use only with JDK1.5+ - Opt_Kernel, // preload tried only #ifdef KERNEL OPTION_LIMIT, CEIL_LG_OPTION_LIMIT = 4 // OPTION_LIMIT <= (1<is_attachable = AttachListener::is_attach_supported(); -#ifdef KERNEL - info->is_kernel_jvm = 1; // true; -#else // KERNEL info->is_kernel_jvm = 0; // false; -#endif // KERNEL } JVM_END diff --git a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.hpp b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.hpp index 92adaaf80e8..00da7ca6ca1 100644 --- a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.hpp +++ b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -25,9 +25,7 @@ #ifndef SHARE_VM_PRIMS_JVMTICODEBLOBEVENTS_HPP #define SHARE_VM_PRIMS_JVMTICODEBLOBEVENTS_HPP -#ifndef JVMTI_KERNEL #include "jvmtifiles/jvmti.h" -#endif // forward declaration class JvmtiEnv; diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index cb3b3db1e1c..318fe4e0b7e 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -647,8 +647,6 @@ JvmtiEnv::GetJLocationFormat(jvmtiJlocationFormat* format_ptr) { return JVMTI_ERROR_NONE; } /* end GetJLocationFormat */ -#ifndef JVMTI_KERNEL - // // Thread functions // @@ -3436,5 +3434,3 @@ JvmtiEnv::SetSystemProperty(const char* property, const char* value_ptr) { } return err; } /* end SetSystemProperty */ - -#endif // !JVMTI_KERNEL diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp index eed31268141..56387634179 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -74,10 +74,8 @@ JvmtiEnvBase::globally_initialize() { JvmtiManageCapabilities::initialize(); -#ifndef JVMTI_KERNEL // register extension functions and events JvmtiExtensions::register_extensions(); -#endif // !JVMTI_KERNEL #ifdef JVMTI_TRACE JvmtiTrace::initialize(); @@ -236,14 +234,12 @@ JvmtiEnvBase::env_dispose() { // Same situation as with events (see above) set_native_method_prefixes(0, NULL); -#ifndef JVMTI_KERNEL JvmtiTagMap* tag_map_to_deallocate = _tag_map; set_tag_map(NULL); // A tag map can be big, deallocate it now if (tag_map_to_deallocate != NULL) { delete tag_map_to_deallocate; } -#endif // !JVMTI_KERNEL _needs_clean_up = true; } @@ -255,14 +251,12 @@ JvmtiEnvBase::~JvmtiEnvBase() { // There is a small window of time during which the tag map of a // disposed environment could have been reallocated. // Make sure it is gone. -#ifndef JVMTI_KERNEL JvmtiTagMap* tag_map_to_deallocate = _tag_map; set_tag_map(NULL); // A tag map can be big, deallocate it now if (tag_map_to_deallocate != NULL) { delete tag_map_to_deallocate; } -#endif // !JVMTI_KERNEL _magic = BAD_MAGIC; } @@ -593,8 +587,6 @@ JvmtiEnvBase::get_jni_class_non_null(Klass* k) { return (jclass)jni_reference(k->java_mirror()); } -#ifndef JVMTI_KERNEL - // // Field Information // @@ -1482,5 +1474,3 @@ JvmtiMonitorClosure::do_monitor(ObjectMonitor* mon) { } } } - -#endif // !JVMTI_KERNEL diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index cb5a1f454d9..1b92193fd55 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -677,7 +677,6 @@ void JvmtiExport::report_unsupported(bool on) { } -#ifndef JVMTI_KERNEL static inline Klass* oop_to_klass(oop obj) { Klass* k = obj->klass(); @@ -2178,7 +2177,6 @@ extern "C" { typedef jint (JNICALL *OnAttachEntry_t)(JavaVM*, char *, void *); } -#ifndef SERVICES_KERNEL jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) { char ebuf[1024]; char buffer[JVM_MAXPATHLEN]; @@ -2259,7 +2257,6 @@ jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) { } return result; } -#endif // SERVICES_KERNEL //////////////////////////////////////////////////////////////////////////////////////////////// @@ -2457,4 +2454,3 @@ JvmtiGCMarker::~JvmtiGCMarker() { JvmtiExport::post_garbage_collection_finish(); } } -#endif // JVMTI_KERNEL diff --git a/hotspot/src/share/vm/prims/jvmtiExtensions.hpp b/hotspot/src/share/vm/prims/jvmtiExtensions.hpp index a5e3433315e..f85003f6bf6 100644 --- a/hotspot/src/share/vm/prims/jvmtiExtensions.hpp +++ b/hotspot/src/share/vm/prims/jvmtiExtensions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -25,11 +25,9 @@ #ifndef SHARE_VM_PRIMS_JVMTIEXTENSIONS_HPP #define SHARE_VM_PRIMS_JVMTIEXTENSIONS_HPP -#ifndef JVMTI_KERNEL #include "jvmtifiles/jvmti.h" #include "jvmtifiles/jvmtiEnv.hpp" #include "memory/allocation.hpp" -#endif // JvmtiExtensions // diff --git a/hotspot/src/share/vm/prims/jvmtiImpl.cpp b/hotspot/src/share/vm/prims/jvmtiImpl.cpp index bb7714d4932..4a1747e1bd2 100644 --- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp +++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -905,8 +905,6 @@ void JvmtiSuspendControl::print() { #endif } -#ifndef KERNEL - JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_load_event( nmethod* nm) { JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_LOAD); @@ -1098,5 +1096,3 @@ void JvmtiDeferredEventQueue::process_pending_events() { } } } - -#endif // ndef KERNEL diff --git a/hotspot/src/share/vm/prims/jvmtiImpl.hpp b/hotspot/src/share/vm/prims/jvmtiImpl.hpp index d785930be0d..204bd83f124 100644 --- a/hotspot/src/share/vm/prims/jvmtiImpl.hpp +++ b/hotspot/src/share/vm/prims/jvmtiImpl.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -25,8 +25,6 @@ #ifndef SHARE_VM_PRIMS_JVMTIIMPL_HPP #define SHARE_VM_PRIMS_JVMTIIMPL_HPP -#ifndef JVMTI_KERNEL - #include "classfile/systemDictionary.hpp" #include "jvmtifiles/jvmti.h" #include "oops/objArrayOop.hpp" @@ -435,7 +433,6 @@ public: static void print(); }; -#endif // !JVMTI_KERNEL /** * When a thread (such as the compiler thread or VM thread) cannot post a diff --git a/hotspot/src/share/vm/prims/jvmtiRawMonitor.hpp b/hotspot/src/share/vm/prims/jvmtiRawMonitor.hpp index e5b25fa3a82..8c182f318ec 100644 --- a/hotspot/src/share/vm/prims/jvmtiRawMonitor.hpp +++ b/hotspot/src/share/vm/prims/jvmtiRawMonitor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -25,10 +25,8 @@ #ifndef SHARE_VM_PRIMS_JVMTIRAWMONITOR_HPP #define SHARE_VM_PRIMS_JVMTIRAWMONITOR_HPP -#ifndef JVMTI_KERNEL #include "runtime/objectMonitor.hpp" #include "utilities/growableArray.hpp" -#endif // // class JvmtiRawMonitor diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index 7255579280b..01b92ade637 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -3104,11 +3104,9 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, Klass* the_class_oop = java_lang_Class::as_Klass(the_class_mirror); instanceKlassHandle the_class = instanceKlassHandle(THREAD, the_class_oop); -#ifndef JVMTI_KERNEL // Remove all breakpoints in methods of this class JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); jvmti_breakpoints.clearall_in_class_at_safepoint(the_class_oop); -#endif // !JVMTI_KERNEL if (the_class_oop == Universe::reflect_invoke_cache()->klass()) { // We are redefining java.lang.reflect.Method. Method.invoke() is diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.hpp b/hotspot/src/share/vm/prims/jvmtiTagMap.hpp index 6435f6251c7..89e3947807d 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.hpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -27,14 +27,12 @@ #ifndef SHARE_VM_PRIMS_JVMTITAGMAP_HPP #define SHARE_VM_PRIMS_JVMTITAGMAP_HPP -#ifndef JVMTI_KERNEL #include "gc_interface/collectedHeap.hpp" #include "jvmtifiles/jvmti.h" #include "jvmtifiles/jvmtiEnv.hpp" #include "memory/allocation.hpp" #include "memory/genCollectedHeap.hpp" #include "memory/universe.hpp" -#endif // forward references class JvmtiTagHashmap; diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 9b5d7f9122d..5e6ad6e21bb 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2472,10 +2472,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, // -Xshare:dump } else if (match_option(option, "-Xshare:dump", &tail)) { -#if defined(KERNEL) - vm_exit_during_initialization( - "Dumping a shared archive is not supported on the Kernel JVM.", NULL); -#elif !INCLUDE_CDS +#if !INCLUDE_CDS vm_exit_during_initialization( "Dumping a shared archive is not supported in this VM.", NULL); #else @@ -3463,36 +3460,6 @@ void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, c PropertyList_add(plist, k, v); } -#ifdef KERNEL -char *Arguments::get_kernel_properties() { - // Find properties starting with kernel and append them to string - // We need to find out how long they are first because the URL's that they - // might point to could get long. - int length = 0; - SystemProperty* prop; - for (prop = _system_properties; prop != NULL; prop = prop->next()) { - if (strncmp(prop->key(), "kernel.", 7 ) == 0) { - length += (strlen(prop->key()) + strlen(prop->value()) + 5); // "-D =" - } - } - // Add one for null terminator. - char *props = AllocateHeap(length + 1, mtInternal); - if (length != 0) { - int pos = 0; - for (prop = _system_properties; prop != NULL; prop = prop->next()) { - if (strncmp(prop->key(), "kernel.", 7 ) == 0) { - jio_snprintf(&props[pos], length-pos, - "-D%s=%s ", prop->key(), prop->value()); - pos = strlen(props); - } - } - } - // null terminate props in case of null - props[length] = '\0'; - return props; -} -#endif // KERNEL - // Copies src into buf, replacing "%%" with "%" and "%p" with pid // Returns true if all of the source pointed by src has been copied over to // the destination buffer pointed by buf. Otherwise, returns false. diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index 71e6e3001e9..c116e2028bb 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -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 @@ -540,11 +540,6 @@ class Arguments : AllStatic { // Utility: copies src into buf, replacing "%%" with "%" and "%p" with pid. static bool copy_expand_pid(const char* src, size_t srclen, char* buf, size_t buflen); - -#ifdef KERNEL - // For java kernel vm, return property string for kernel properties. - static char *get_kernel_properties(); -#endif // KERNEL }; #endif // SHARE_VM_RUNTIME_ARGUMENTS_HPP diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index ff6adde6eee..7fe01ae8555 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -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 @@ -3739,28 +3739,6 @@ static OnLoadEntry_t lookup_on_load(AgentLibrary* agent, const char *on_load_sym name)) { library = os::dll_load(buffer, ebuf, sizeof ebuf); } -#ifdef KERNEL - // Download instrument dll - if (library == NULL && strcmp(name, "instrument") == 0) { - char *props = Arguments::get_kernel_properties(); - char *home = Arguments::get_java_home(); - const char *fmt = "%s/bin/java %s -Dkernel.background.download=false" - " sun.jkernel.DownloadManager -download client_jvm"; - size_t length = strlen(props) + strlen(home) + strlen(fmt) + 1; - char *cmd = NEW_C_HEAP_ARRAY(char, length, mtThread); - jio_snprintf(cmd, length, fmt, home, props); - int status = os::fork_and_exec(cmd); - FreeHeap(props); - if (status == -1) { - warning(cmd); - vm_exit_during_initialization("fork_and_exec failed: %s", - strerror(errno)); - } - FREE_C_HEAP_ARRAY(char, cmd, mtThread); - // when this comes back the instrument.dll should be where it belongs. - library = os::dll_load(buffer, ebuf, sizeof ebuf); - } -#endif // KERNEL if (library == NULL) { // Try the local directory char ns[1] = {0}; if (os::dll_build_name(buffer, sizeof(buffer), ns, name)) { diff --git a/hotspot/src/share/vm/runtime/vmStructs.hpp b/hotspot/src/share/vm/runtime/vmStructs.hpp index b1070a406e2..5c4c93a1f77 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.hpp +++ b/hotspot/src/share/vm/runtime/vmStructs.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -25,9 +25,7 @@ #ifndef SHARE_VM_RUNTIME_VMSTRUCTS_HPP #define SHARE_VM_RUNTIME_VMSTRUCTS_HPP -#ifndef VM_STRUCTS_KERNEL #include "utilities/debug.hpp" -#endif #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/vm_version.cpp b/hotspot/src/share/vm/runtime/vm_version.cpp index 2d105a97baf..ef03c76f62b 100644 --- a/hotspot/src/share/vm/runtime/vm_version.cpp +++ b/hotspot/src/share/vm/runtime/vm_version.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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,9 +111,6 @@ void Abstract_VM_Version::initialize() { #endif #ifndef VMTYPE - #ifdef KERNEL - #define VMTYPE "Kernel" - #else // KERNEL #ifdef TIERED #define VMTYPE "Server" #else // TIERED @@ -128,7 +125,6 @@ void Abstract_VM_Version::initialize() { COMPILER2_PRESENT("Server") #endif // ZERO #endif // TIERED - #endif // KERNEL #endif #ifndef HOTSPOT_VM_DISTRO diff --git a/hotspot/src/share/vm/services/attachListener.cpp b/hotspot/src/share/vm/services/attachListener.cpp index 80dfd7effd4..da93859bb94 100644 --- a/hotspot/src/share/vm/services/attachListener.cpp +++ b/hotspot/src/share/vm/services/attachListener.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -170,7 +170,6 @@ static jint jcmd(AttachOperation* op, outputStream* out) { return JNI_OK; } -#ifndef SERVICES_KERNEL // Heap dumping not supported // Implementation of "dumpheap" command. // See also: HeapDumpDCmd class // @@ -212,7 +211,6 @@ jint dump_heap(AttachOperation* op, outputStream* out) { } return JNI_OK; } -#endif // SERVICES_KERNEL // Implementation of "inspectheap" command // See also: ClassHistogramDCmd class @@ -382,9 +380,7 @@ static jint print_flag(AttachOperation* op, outputStream* out) { static AttachOperationFunctionInfo funcs[] = { { "agentProperties", get_agent_properties }, { "datadump", data_dump }, -#ifndef SERVICES_KERNEL { "dumpheap", dump_heap }, -#endif // SERVICES_KERNEL { "load", JvmtiExport::load_agent_library }, { "properties", get_system_properties }, { "threaddump", thread_dump }, diff --git a/hotspot/src/share/vm/services/attachListener.hpp b/hotspot/src/share/vm/services/attachListener.hpp index 1916e8cacb8..c69ff1820e7 100644 --- a/hotspot/src/share/vm/services/attachListener.hpp +++ b/hotspot/src/share/vm/services/attachListener.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -38,8 +38,6 @@ // complets the result value and any result data is returned to the client // tool. -#ifndef SERVICES_KERNEL - class AttachOperation; typedef jint (*AttachOperationFunction)(AttachOperation* op, outputStream* out); @@ -48,7 +46,6 @@ struct AttachOperationFunctionInfo { const char* name; AttachOperationFunction func; }; -#endif // SERVICES_KERNEL class AttachListener: AllStatic { public: From 93b845e21bcb991c3e6c05072db3fafc476d0e8a Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Fri, 25 Jan 2013 15:06:18 -0500 Subject: [PATCH 010/158] 6479360: PrintClassHistogram improvements Jcmd GC.class_stats (UnlockDiagnosticVMOptions) Reviewed-by: coleenp, hseigel, sla, acorn --- .../share/vm/classfile/classLoaderData.cpp | 4 +- .../share/vm/classfile/classLoaderData.hpp | 4 +- .../shared/vmGCOperations.cpp | 6 +- .../shared/vmGCOperations.hpp | 14 +- .../src/share/vm/memory/heapInspection.cpp | 279 ++++++++++++++++-- .../src/share/vm/memory/heapInspection.hpp | 235 ++++++++++++++- hotspot/src/share/vm/oops/annotations.cpp | 47 ++- hotspot/src/share/vm/oops/annotations.hpp | 10 +- hotspot/src/share/vm/oops/arrayKlass.hpp | 10 +- hotspot/src/share/vm/oops/constMethod.cpp | 15 +- hotspot/src/share/vm/oops/constMethod.hpp | 6 +- hotspot/src/share/vm/oops/constantPool.cpp | 15 + hotspot/src/share/vm/oops/constantPool.hpp | 5 + hotspot/src/share/vm/oops/instanceKlass.cpp | 49 ++- hotspot/src/share/vm/oops/instanceKlass.hpp | 5 +- hotspot/src/share/vm/oops/klass.cpp | 14 +- hotspot/src/share/vm/oops/klass.hpp | 6 +- hotspot/src/share/vm/oops/method.cpp | 17 ++ hotspot/src/share/vm/oops/method.hpp | 6 +- hotspot/src/share/vm/oops/methodData.cpp | 12 +- hotspot/src/share/vm/oops/methodData.hpp | 6 +- .../share/vm/services/diagnosticCommand.cpp | 70 ++++- .../share/vm/services/diagnosticCommand.hpp | 25 +- 23 files changed, 807 insertions(+), 53 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index 0560d3f4886..e74a88d7d33 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -724,13 +724,13 @@ void ClassLoaderDataGraph::dump_on(outputStream * const out) { } MetaspaceAux::dump(out); } +#endif // PRODUCT void ClassLoaderData::print_value_on(outputStream* out) const { if (class_loader() == NULL) { - out->print_cr("NULL class_loader"); + out->print("NULL class_loader"); } else { out->print("class loader "PTR_FORMAT, this); class_loader()->print_value_on(out); } } -#endif // PRODUCT diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp index 9525658e67a..f72645db1c4 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -220,7 +220,7 @@ class ClassLoaderData : public CHeapObj { void set_jmethod_ids(JNIMethodBlock* new_block) { _jmethod_ids = new_block; } void print_value() { print_value_on(tty); } - void print_value_on(outputStream* out) const PRODUCT_RETURN; + void print_value_on(outputStream* out) const; void dump(outputStream * const out) PRODUCT_RETURN; void verify(); const char* loader_name(); diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp index ee1be4a6490..941811c358b 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -167,7 +167,9 @@ void VM_GC_HeapInspection::doit() { ch->collect_as_vm_thread(GCCause::_heap_inspection); } } - HeapInspection::heap_inspection(_out, _need_prologue /* need_prologue */); + HeapInspection inspect(_csv_format, _print_help, _print_class_stats, + _columns); + inspect.heap_inspection(_out, _need_prologue /* need_prologue */); } diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp index 285ef97e378..2a416f22843 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -130,6 +130,10 @@ class VM_GC_HeapInspection: public VM_GC_Operation { outputStream* _out; bool _full_gc; bool _need_prologue; + bool _csv_format; // "comma separated values" format for spreadsheet. + bool _print_help; + bool _print_class_stats; + const char* _columns; public: VM_GC_HeapInspection(outputStream* out, bool request_full_gc, bool need_prologue) : @@ -140,6 +144,10 @@ class VM_GC_HeapInspection: public VM_GC_Operation { _out = out; _full_gc = request_full_gc; _need_prologue = need_prologue; + _csv_format = false; + _print_help = false; + _print_class_stats = false; + _columns = NULL; } ~VM_GC_HeapInspection() {} @@ -147,6 +155,10 @@ class VM_GC_HeapInspection: public VM_GC_Operation { virtual bool skip_operation() const; virtual bool doit_prologue(); virtual void doit(); + void set_csv_format(bool value) {_csv_format = value;} + void set_print_help(bool value) {_print_help = value;} + void set_print_class_stats(bool value) {_print_class_stats = value;} + void set_columns(const char* value) {_columns = value;} }; diff --git a/hotspot/src/share/vm/memory/heapInspection.cpp b/hotspot/src/share/vm/memory/heapInspection.cpp index 71674fcb2d5..9275fe5b999 100644 --- a/hotspot/src/share/vm/memory/heapInspection.cpp +++ b/hotspot/src/share/vm/memory/heapInspection.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/classLoaderData.hpp" #include "gc_interface/collectedHeap.hpp" #include "memory/genCollectedHeap.hpp" #include "memory/heapInspection.hpp" @@ -41,12 +42,24 @@ int KlassInfoEntry::compare(KlassInfoEntry* e1, KlassInfoEntry* e2) { } else if(e1->_instance_words < e2->_instance_words) { return 1; } - return 0; + // Sort alphabetically, note 'Z' < '[' < 'a', but it's better to group + // the array classes before all the instance classes. + ResourceMark rm; + const char* name1 = e1->klass()->external_name(); + const char* name2 = e2->klass()->external_name(); + bool d1 = (name1[0] == '['); + bool d2 = (name2[0] == '['); + if (d1 && !d2) { + return -1; + } else if (d2 && !d1) { + return 1; + } else { + return strcmp(name1, name2); + } } -void KlassInfoEntry::print_on(outputStream* st) const { - ResourceMark rm; - const char* name;; +const char* KlassInfoEntry::name() const { + const char* name; if (_klass->name() != NULL) { name = _klass->external_name(); } else { @@ -60,11 +73,17 @@ void KlassInfoEntry::print_on(outputStream* st) const { if (_klass == Universe::longArrayKlassObj()) name = ""; else name = ""; } + return name; +} + +void KlassInfoEntry::print_on(outputStream* st) const { + ResourceMark rm; + // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit st->print_cr(INT64_FORMAT_W(13) " " UINT64_FORMAT_W(13) " %s", (jlong) _instance_count, (julong) _instance_words * HeapWordSize, - name); + name()); } KlassInfoEntry* KlassInfoBucket::lookup(Klass* const k) { @@ -101,7 +120,14 @@ void KlassInfoBucket::empty() { } } -KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) { +void KlassInfoTable::AllClassesFinder::do_klass(Klass* k) { + // This has the SIDE EFFECT of creating a KlassInfoEntry + // for , if one doesn't exist yet. + _table->lookup(k); +} + +KlassInfoTable::KlassInfoTable(int size, HeapWord* ref, + bool need_class_stats) { _size = 0; _ref = ref; _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size, mtInternal); @@ -110,6 +136,10 @@ KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) { for (int index = 0; index < _size; index++) { _buckets[index].initialize(); } + if (need_class_stats) { + AllClassesFinder finder(this); + ClassLoaderDataGraph::classes_do(&finder); + } } } @@ -165,7 +195,8 @@ int KlassInfoHisto::sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2) { return (*e1)->compare(*e1,*e2); } -KlassInfoHisto::KlassInfoHisto(const char* title, int estimatedCount) : +KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit, const char* title, int estimatedCount) : + _cit(cit), _title(title) { _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(estimatedCount,true); } @@ -196,9 +227,205 @@ void KlassInfoHisto::print_elements(outputStream* st) const { total, totalw * HeapWordSize); } -void KlassInfoHisto::print_on(outputStream* st) const { - st->print_cr("%s",title()); - print_elements(st); +#define MAKE_COL_NAME(field, name, help) #name, +#define MAKE_COL_HELP(field, name, help) help, + +static const char *name_table[] = { + HEAP_INSPECTION_COLUMNS_DO(MAKE_COL_NAME) +}; + +static const char *help_table[] = { + HEAP_INSPECTION_COLUMNS_DO(MAKE_COL_HELP) +}; + +bool KlassInfoHisto::is_selected(const char *col_name) { + if (_selected_columns == NULL) { + return true; + } + if (strcmp(_selected_columns, col_name) == 0) { + return true; + } + + const char *start = strstr(_selected_columns, col_name); + if (start == NULL) { + return false; + } + + // The following must be true, because _selected_columns != col_name + if (start > _selected_columns && start[-1] != ',') { + return false; + } + char x = start[strlen(col_name)]; + if (x != ',' && x != '\0') { + return false; + } + + return true; +} + +void KlassInfoHisto::print_title(outputStream* st, bool csv_format, + bool selected[], int width_table[], + const char *name_table[]) { + if (csv_format) { + st->print("Index,Super"); + for (int c=0; cprint(",%s", name_table[c]);} + } + st->print(",ClassName"); + } else { + st->print("Index Super"); + for (int c=0; cprint(str_fmt(width_table[c]), name_table[c]);} + } + st->print(" ClassName"); + } + + if (is_selected("ClassLoader")) { + st->print(",ClassLoader"); + } + st->cr(); +} + +void KlassInfoHisto::print_class_stats(outputStream* st, + bool csv_format, const char *columns) { + ResourceMark rm; + KlassSizeStats sz, sz_sum; + int i; + julong *col_table = (julong*)(&sz); + julong *colsum_table = (julong*)(&sz_sum); + int width_table[KlassSizeStats::_num_columns]; + bool selected[KlassSizeStats::_num_columns]; + + _selected_columns = columns; + + memset(&sz_sum, 0, sizeof(sz_sum)); + for (int c=0; clength(); i++) { + elements()->at(i)->set_index(i+1); + } + + for (int pass=1; pass<=2; pass++) { + if (pass == 2) { + print_title(st, csv_format, selected, width_table, name_table); + } + for(i=0; i < elements()->length(); i++) { + KlassInfoEntry* e = (KlassInfoEntry*)elements()->at(i); + const Klass* k = e->klass(); + + memset(&sz, 0, sizeof(sz)); + sz._inst_count = e->count(); + sz._inst_bytes = HeapWordSize * e->words(); + k->collect_statistics(&sz); + sz._total_bytes = sz._ro_bytes + sz._rw_bytes; + + if (pass == 1) { + for (int c=0; coop_is_instance()) { + Klass* super = ((InstanceKlass*)k)->java_super(); + if (super) { + KlassInfoEntry* super_e = _cit->lookup(super); + if (super_e) { + super_index = super_e->index(); + } + } + } + + if (csv_format) { + st->print("%d,%d", e->index(), super_index); + for (int c=0; cprint("," JULONG_FORMAT, col_table[c]);} + } + st->print(",%s",e->name()); + } else { + st->print("%5d %5d", e->index(), super_index); + for (int c=0; cprint(" %s", e->name()); + } + if (is_selected("ClassLoader")) { + ClassLoaderData* loader_data = k->class_loader_data(); + st->print(","); + loader_data->print_value_on(st); + } + st->cr(); + } + } + + if (pass == 1) { + for (int c=0; cprint(","); + for (int c=0; cprint("," JULONG_FORMAT, colsum_table[c]);} + } + } else { + st->print(" "); + for (int c=0; cprint(" Total"); + if (sz_sum._total_bytes > 0) { + st->cr(); + st->print(" "); + for (int c=0; cprint(str_fmt(width_table[c]), "-"); + break; + default: + { + double perc = (double)(100) * (double)(colsum_table[c]) / (double)sz_sum._total_bytes; + st->print(perc_fmt(width_table[c]), perc); + } + } + } + } + } + } + st->cr(); + + if (!csv_format) { + print_title(st, csv_format, selected, width_table, name_table); + } +} + +julong KlassInfoHisto::annotations_bytes(Array* p) const { + julong bytes = 0; + if (p != NULL) { + for (int i = 0; i < p->length(); i++) { + bytes += count_bytes_array(p->at(i)); + } + bytes += count_bytes_array(p); + } + return bytes; +} + +void KlassInfoHisto::print_histo_on(outputStream* st, bool print_stats, + bool csv_format, const char *columns) { + if (print_stats) { + print_class_stats(st, csv_format, columns); + } else { + st->print_cr("%s",title()); + print_elements(st); + } } class HistoClosure : public KlassInfoClosure { @@ -236,8 +463,26 @@ void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { CollectedHeap* heap = Universe::heap(); bool is_shared_heap = false; + if (_print_help) { + for (int c=0; cprint("%s:\n\t", name_table[c]); + const int max_col = 60; + int col = 0; + for (const char *p = help_table[c]; *p; p++,col++) { + if (col >= max_col && *p == ' ') { + st->print("\n\t"); + col = 0; + } else { + st->print("%c", *p); + } + } + st->print_cr(".\n"); + } + return; + } + // Collect klass instance info - KlassInfoTable cit(KlassInfoTable::cit_size, ref); + KlassInfoTable cit(KlassInfoTable::cit_size, ref, _print_class_stats); if (!cit.allocation_failed()) { // Iterate over objects in the heap RecordInstanceClosure ric(&cit); @@ -252,14 +497,14 @@ void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { missed_count); } // Sort and print klass instance info - KlassInfoHisto histo("\n" - " num #instances #bytes class name\n" - "----------------------------------------------", - KlassInfoHisto::histo_initial_size); + const char *title = "\n" + " num #instances #bytes class name\n" + "----------------------------------------------"; + KlassInfoHisto histo(&cit, title, KlassInfoHisto::histo_initial_size); HistoClosure hc(&histo); cit.iterate(&hc); histo.sort(); - histo.print_on(st); + histo.print_histo_on(st, _print_class_stats, _csv_format, _columns); } else { st->print_cr("WARNING: Ran out of C-heap; histogram not generated"); } diff --git a/hotspot/src/share/vm/memory/heapInspection.hpp b/hotspot/src/share/vm/memory/heapInspection.hpp index 72e675850d4..388e04242af 100644 --- a/hotspot/src/share/vm/memory/heapInspection.hpp +++ b/hotspot/src/share/vm/memory/heapInspection.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -27,6 +27,7 @@ #include "memory/allocation.inline.hpp" #include "oops/oop.inline.hpp" +#include "oops/annotations.hpp" #if INCLUDE_SERVICES @@ -44,16 +45,144 @@ // to KlassInfoEntry's and is used to sort // the entries. +#define HEAP_INSPECTION_COLUMNS_DO(f) \ + f(inst_size, InstSize, \ + "Size of each object instance of the Java class") \ + f(inst_count, InstCount, \ + "Number of object instances of the Java class") \ + f(inst_bytes, InstBytes, \ + "This is usually (InstSize * InstNum). The only exception is " \ + "java.lang.Class, whose InstBytes also includes the slots " \ + "used to store static fields. InstBytes is not counted in " \ + "ROAll, RWAll or Total") \ + f(mirror_bytes, Mirror, \ + "Size of the Klass::java_mirror() object") \ + f(klass_bytes, KlassBytes, \ + "Size of the InstanceKlass or ArrayKlass for this class. " \ + "Note that this includes VTab, ITab, OopMap") \ + f(secondary_supers_bytes, K_secondary_supers, \ + "Number of bytes used by the Klass::secondary_supers() array") \ + f(vtab_bytes, VTab, \ + "Size of the embedded vtable in InstanceKlass") \ + f(itab_bytes, ITab, \ + "Size of the embedded itable in InstanceKlass") \ + f(nonstatic_oopmap_bytes, OopMap, \ + "Size of the embedded nonstatic_oop_map in InstanceKlass") \ + f(methods_array_bytes, IK_methods, \ + "Number of bytes used by the InstanceKlass::methods() array") \ + f(method_ordering_bytes, IK_method_ordering, \ + "Number of bytes used by the InstanceKlass::method_ordering() array") \ + f(local_interfaces_bytes, IK_local_interfaces, \ + "Number of bytes used by the InstanceKlass::local_interfaces() array") \ + f(transitive_interfaces_bytes, IK_transitive_interfaces, \ + "Number of bytes used by the InstanceKlass::transitive_interfaces() array") \ + f(fields_bytes, IK_fields, \ + "Number of bytes used by the InstanceKlass::fields() array") \ + f(inner_classes_bytes, IK_inner_classes, \ + "Number of bytes used by the InstanceKlass::inner_classes() array") \ + f(signers_bytes, IK_signers, \ + "Number of bytes used by the InstanceKlass::singers() array") \ + f(class_annotations_bytes, class_annotations, \ + "Size of class annotations") \ + f(fields_annotations_bytes, fields_annotations, \ + "Size of field annotations") \ + f(methods_annotations_bytes, methods_annotations, \ + "Size of method annotations") \ + f(methods_parameter_annotations_bytes, methods_parameter_annotations, \ + "Size of method parameter annotations") \ + f(methods_default_annotations_bytes, methods_default_annotations, \ + "Size of methods default annotations") \ + f(type_annotations_bytes, type_annotations, \ + "Size of type annotations") \ + f(annotations_bytes, annotations, \ + "Size of all annotations") \ + f(cp_bytes, Cp, \ + "Size of InstanceKlass::constants()") \ + f(cp_tags_bytes, CpTags, \ + "Size of InstanceKlass::constants()->tags()") \ + f(cp_cache_bytes, CpCache, \ + "Size of InstanceKlass::constants()->cache()") \ + f(cp_operands_bytes, CpOperands, \ + "Size of InstanceKlass::constants()->operands()") \ + f(cp_refmap_bytes, CpRefMap, \ + "Size of InstanceKlass::constants()->reference_map()") \ + f(cp_all_bytes, CpAll, \ + "Sum of Cp + CpTags + CpCache + CpOperands + CpRefMap") \ + f(method_count, MethodCount, \ + "Number of methods in this class") \ + f(method_bytes, MethodBytes, \ + "Size of the Method object") \ + f(const_method_bytes, ConstMethod, \ + "Size of the ConstMethod object") \ + f(method_data_bytes, MethodData, \ + "Size of the MethodData object") \ + f(stackmap_bytes, StackMap, \ + "Size of the stackmap_data") \ + f(bytecode_bytes, Bytecodes, \ + "Of the MethodBytes column, how much are the space taken up by bytecodes") \ + f(method_all_bytes, MethodAll, \ + "Sum of MethodBytes + Constmethod + Stackmap + Methoddata") \ + f(ro_bytes, ROAll, \ + "Size of all class meta data that could (potentially) be placed " \ + "in read-only memory. (This could change with CDS design)") \ + f(rw_bytes, RWAll, \ + "Size of all class meta data that must be placed in read/write " \ + "memory. (This could change with CDS design) ") \ + f(total_bytes, Total, \ + "ROAll + RWAll. Note that this does NOT include InstBytes.") + +// Size statistics for a Klass - filled in by Klass::collect_statistics() +class KlassSizeStats { +public: +#define COUNT_KLASS_SIZE_STATS_FIELD(field, name, help) _index_ ## field, +#define DECLARE_KLASS_SIZE_STATS_FIELD(field, name, help) julong _ ## field; + + enum { + HEAP_INSPECTION_COLUMNS_DO(COUNT_KLASS_SIZE_STATS_FIELD) + _num_columns + }; + + HEAP_INSPECTION_COLUMNS_DO(DECLARE_KLASS_SIZE_STATS_FIELD) + + static int count(oop x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + static int count_array(objArrayOop x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + template static int count(T* x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + template static int count_array(T* x) { + if (x == NULL) { + return 0; + } + if (x->length() == 0) { + // This is a shared array, e.g., Universe::the_empty_int_array(). Don't + // count it to avoid double-counting. + return 0; + } + return HeapWordSize * x->size(); + } +}; + + + + class KlassInfoEntry: public CHeapObj { private: KlassInfoEntry* _next; Klass* _klass; long _instance_count; size_t _instance_words; + long _index; public: KlassInfoEntry(Klass* k, KlassInfoEntry* next) : - _klass(k), _instance_count(0), _instance_words(0), _next(next) + _klass(k), _instance_count(0), _instance_words(0), _next(next), _index(-1) {} KlassInfoEntry* next() { return _next; } bool is_equal(Klass* k) { return k == _klass; } @@ -62,8 +191,11 @@ class KlassInfoEntry: public CHeapObj { void set_count(long ct) { _instance_count = ct; } size_t words() { return _instance_words; } void set_words(size_t wds) { _instance_words = wds; } + void set_index(long index) { _index = index; } + long index() { return _index; } int compare(KlassInfoEntry* e1, KlassInfoEntry* e2); void print_on(outputStream* st) const; + const char* name() const; }; class KlassInfoClosure: public StackObj { @@ -95,45 +227,132 @@ class KlassInfoTable: public StackObj { KlassInfoBucket* _buckets; uint hash(Klass* p); - KlassInfoEntry* lookup(Klass* const k); + KlassInfoEntry* lookup(Klass* const k); // allocates if not found! + + class AllClassesFinder : public KlassClosure { + KlassInfoTable *_table; + public: + AllClassesFinder(KlassInfoTable* table) : _table(table) {} + virtual void do_klass(Klass* k); + }; public: // Table size enum { cit_size = 20011 }; - KlassInfoTable(int size, HeapWord* ref); + KlassInfoTable(int size, HeapWord* ref, bool need_class_stats); ~KlassInfoTable(); bool record_instance(const oop obj); void iterate(KlassInfoClosure* cic); bool allocation_failed() { return _buckets == NULL; } + + friend class KlassInfoHisto; }; class KlassInfoHisto : public StackObj { private: + KlassInfoTable *_cit; GrowableArray* _elements; GrowableArray* elements() const { return _elements; } const char* _title; const char* title() const { return _title; } static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2); void print_elements(outputStream* st) const; + void print_class_stats(outputStream* st, bool csv_format, const char *columns); + julong annotations_bytes(Array* p) const; + const char *_selected_columns; + bool is_selected(const char *col_name); + void print_title(outputStream* st, bool csv_format, + bool selected_columns_table[], int width_table[], + const char *name_table[]); + + template static int count_bytes(T* x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + template static int count_bytes_array(T* x) { + if (x == NULL) { + return 0; + } + if (x->length() == 0) { + // This is a shared array, e.g., Universe::the_empty_int_array(). Don't + // count it to avoid double-counting. + return 0; + } + return HeapWordSize * x->size(); + } + + // returns a format string to print a julong with the given width. E.g, + // printf(num_fmt(6), julong(10)) would print out the number 10 with 4 + // leading spaces. + static void print_julong(outputStream* st, int width, julong n) { + int num_spaces = width - julong_width(n); + if (num_spaces > 0) { + st->print(str_fmt(num_spaces), ""); + } + st->print(JULONG_FORMAT, n); + } + + static char* perc_fmt(int width) { + static char buf[32]; + jio_snprintf(buf, sizeof(buf), "%%%d.1f%%%%", width-1); + return buf; + } + + static char* str_fmt(int width) { + static char buf[32]; + jio_snprintf(buf, sizeof(buf), "%%%ds", width); + return buf; + } + + static int julong_width(julong n) { + if (n == 0) { + return 1; + } + int w = 0; + while (n > 0) { + n /= 10; + w += 1; + } + return w; + } + + static int col_width(julong n, const char *name) { + int w = julong_width(n); + int min = (int)(strlen(name)); + if (w < min) { + w = min; + } + // add a leading space for separation. + return w + 1; + } + public: enum { histo_initial_size = 1000 }; - KlassInfoHisto(const char* title, + KlassInfoHisto(KlassInfoTable* cit, const char* title, int estimatedCount); ~KlassInfoHisto(); void add(KlassInfoEntry* cie); - void print_on(outputStream* st) const; + void print_histo_on(outputStream* st, bool print_class_stats, bool csv_format, const char *columns); void sort(); }; #endif // INCLUDE_SERVICES -class HeapInspection : public AllStatic { +class HeapInspection : public StackObj { + bool _csv_format; // "comma separated values" format for spreadsheet. + bool _print_help; + bool _print_class_stats; + const char* _columns; public: - static void heap_inspection(outputStream* st, bool need_prologue) NOT_SERVICES_RETURN; + HeapInspection(bool csv_format, bool print_help, + bool print_class_stats, const char *columns) : + _csv_format(csv_format), _print_help(print_help), + _print_class_stats(print_class_stats), _columns(columns) {} + void heap_inspection(outputStream* st, bool need_prologue) NOT_SERVICES_RETURN; static void find_instances_at_safepoint(Klass* k, GrowableArray* result) NOT_SERVICES_RETURN; }; diff --git a/hotspot/src/share/vm/oops/annotations.cpp b/hotspot/src/share/vm/oops/annotations.cpp index 72c5737f056..9e5d6ef3701 100644 --- a/hotspot/src/share/vm/oops/annotations.cpp +++ b/hotspot/src/share/vm/oops/annotations.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/classLoaderData.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/annotations.hpp" @@ -114,6 +115,50 @@ void Annotations::print_value_on(outputStream* st) const { st->print("Anotations(" INTPTR_FORMAT ")", this); } +#if INCLUDE_SERVICES +// Size Statistics + +julong Annotations::count_bytes(Array* p) { + julong bytes = 0; + if (p != NULL) { + for (int i = 0; i < p->length(); i++) { + bytes += KlassSizeStats::count_array(p->at(i)); + } + bytes += KlassSizeStats::count_array(p); + } + return bytes; +} + +void Annotations::collect_statistics(KlassSizeStats *sz) const { + sz->_annotations_bytes = sz->count(this); + sz->_class_annotations_bytes = sz->count(class_annotations()); + sz->_fields_annotations_bytes = count_bytes(fields_annotations()); + sz->_methods_annotations_bytes = count_bytes(methods_annotations()); + sz->_methods_parameter_annotations_bytes = + count_bytes(methods_parameter_annotations()); + sz->_methods_default_annotations_bytes = + count_bytes(methods_default_annotations()); + + const Annotations* type_anno = type_annotations(); + if (type_anno != NULL) { + sz->_type_annotations_bytes = sz->count(type_anno); + sz->_type_annotations_bytes += sz->count(type_anno->class_annotations()); + sz->_type_annotations_bytes += count_bytes(type_anno->fields_annotations()); + sz->_type_annotations_bytes += count_bytes(type_anno->methods_annotations()); + } + + sz->_annotations_bytes += + sz->_class_annotations_bytes + + sz->_fields_annotations_bytes + + sz->_methods_annotations_bytes + + sz->_methods_parameter_annotations_bytes + + sz->_methods_default_annotations_bytes + + sz->_type_annotations_bytes; + + sz->_ro_bytes += sz->_annotations_bytes; +} +#endif // INCLUDE_SERVICES + #define BULLET " - " #ifndef PRODUCT diff --git a/hotspot/src/share/vm/oops/annotations.hpp b/hotspot/src/share/vm/oops/annotations.hpp index 07d05467ba1..82d701ac584 100644 --- a/hotspot/src/share/vm/oops/annotations.hpp +++ b/hotspot/src/share/vm/oops/annotations.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -34,6 +34,7 @@ class ClassLoaderData; class outputStream; +class KlassSizeStats; typedef Array AnnotationArray; @@ -82,7 +83,12 @@ class Annotations: public MetaspaceObj { Array* mda, TRAPS); void deallocate_contents(ClassLoaderData* loader_data); DEBUG_ONLY(bool on_stack() { return false; }) // for template + + // Sizing (in words) static int size() { return sizeof(Annotations) / wordSize; } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif // Constructor to initialize to null Annotations() : _class_annotations(NULL), @@ -142,7 +148,7 @@ class Annotations: public MetaspaceObj { void set_methods_annotations_of(instanceKlassHandle ik, int idnum, AnnotationArray* anno, Array** md_p, TRAPS); - + static julong count_bytes(Array* p); public: const char* internal_name() const { return "{constant pool}"; } #ifndef PRODUCT diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index 38a5340e366..f37a4d500ae 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -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 @@ -106,6 +106,14 @@ class ArrayKlass: public Klass { static int header_size() { return sizeof(ArrayKlass)/HeapWordSize; } static int static_size(int header_size); +#if INCLUDE_SERVICES + virtual void collect_statistics(KlassSizeStats *sz) const { + Klass::collect_statistics(sz); + // Do nothing for now, but remember to modify if you add new + // stuff to ArrayKlass. + } +#endif + // Java vtable klassVtable* vtable() const; // return new klassVtable int vtable_length() const { return _vtable_len; } diff --git a/hotspot/src/share/vm/oops/constMethod.cpp b/hotspot/src/share/vm/oops/constMethod.cpp index 79c10c0e62a..3358d225e2a 100644 --- a/hotspot/src/share/vm/oops/constMethod.cpp +++ b/hotspot/src/share/vm/oops/constMethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "interpreter/interpreter.hpp" #include "memory/gcLocker.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "oops/constMethod.hpp" #include "oops/method.hpp" @@ -330,6 +331,18 @@ void ConstMethod::print_value_on(outputStream* st) const { method()->print_value_on(st); } +#if INCLUDE_SERVICES +// Size Statistics +void ConstMethod::collect_statistics(KlassSizeStats *sz) const { + int n1, n2, n3; + sz->_const_method_bytes += (n1 = sz->count(this)); + sz->_bytecode_bytes += (n2 = code_size()); + sz->_stackmap_bytes += (n3 = sz->count_array(stackmap_data())); + + sz->_method_all_bytes += n1 + n3; // note: n2 is part of n3 + sz->_ro_bytes += n1 + n3; +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/constMethod.hpp b/hotspot/src/share/vm/oops/constMethod.hpp index 8b593982140..bd3acd23188 100644 --- a/hotspot/src/share/vm/oops/constMethod.hpp +++ b/hotspot/src/share/vm/oops/constMethod.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -130,6 +130,7 @@ class MethodParametersElement VALUE_OBJ_CLASS_SPEC { u2 flags_lo; }; +class KlassSizeStats; class ConstMethod : public MetaspaceObj { friend class VMStructs; @@ -320,6 +321,9 @@ public: int size() const { return _constMethod_size;} void set_constMethod_size(int size) { _constMethod_size = size; } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif // code size int code_size() const { return _code_size; } diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index d4fa72032df..09c870a74ea 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -30,6 +30,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "interpreter/linkResolver.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/constantPool.hpp" @@ -1946,6 +1947,20 @@ void ConstantPool::print_value_on(outputStream* st) const { } } +#if INCLUDE_SERVICES +// Size Statistics +void ConstantPool::collect_statistics(KlassSizeStats *sz) const { + sz->_cp_all_bytes += (sz->_cp_bytes = sz->count(this)); + sz->_cp_all_bytes += (sz->_cp_tags_bytes = sz->count_array(tags())); + sz->_cp_all_bytes += (sz->_cp_cache_bytes = sz->count(cache())); + sz->_cp_all_bytes += (sz->_cp_operands_bytes = sz->count_array(operands())); + sz->_cp_all_bytes += (sz->_cp_refmap_bytes = sz->count_array(reference_map())); + + sz->_ro_bytes += sz->_cp_operands_bytes + sz->_cp_tags_bytes + + sz->_cp_refmap_bytes; + sz->_rw_bytes += sz->_cp_bytes + sz->_cp_cache_bytes; +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index ea4b13f0f9d..0d1f18878ff 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -80,6 +80,7 @@ class CPSlot VALUE_OBJ_CLASS_SPEC { } }; +class KlassSizeStats; class ConstantPool : public Metadata { friend class VMStructs; friend class BytecodeInterpreter; // Directly extracts an oop in the pool for fast instanceof/checkcast @@ -684,9 +685,13 @@ class ConstantPool : public Metadata { return 0 <= index && index < length(); } + // Sizing (in words) static int header_size() { return sizeof(ConstantPool)/HeapWordSize; } static int size(int length) { return align_object_size(header_size() + length); } int size() const { return size(length()); } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif friend class ClassFileParser; friend class SystemDictionary; diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index b0b7038e35b..c79378658e6 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -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 @@ -34,6 +34,7 @@ #include "interpreter/rewriter.hpp" #include "jvmtifiles/jvmti.h" #include "memory/genOopClosures.inline.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/fieldStreams.hpp" @@ -2960,6 +2961,52 @@ const char* InstanceKlass::internal_name() const { return external_name(); } +#if INCLUDE_SERVICES +// Size Statistics +void InstanceKlass::collect_statistics(KlassSizeStats *sz) const { + Klass::collect_statistics(sz); + + sz->_inst_size = HeapWordSize * size_helper(); + sz->_vtab_bytes = HeapWordSize * align_object_offset(vtable_length()); + sz->_itab_bytes = HeapWordSize * align_object_offset(itable_length()); + sz->_nonstatic_oopmap_bytes = HeapWordSize * + ((is_interface() || is_anonymous()) ? + align_object_offset(nonstatic_oop_map_size()) : + nonstatic_oop_map_size()); + + int n = 0; + n += (sz->_methods_array_bytes = sz->count_array(methods())); + n += (sz->_method_ordering_bytes = sz->count_array(method_ordering())); + n += (sz->_local_interfaces_bytes = sz->count_array(local_interfaces())); + n += (sz->_transitive_interfaces_bytes = sz->count_array(transitive_interfaces())); + n += (sz->_signers_bytes = sz->count_array(signers())); + n += (sz->_fields_bytes = sz->count_array(fields())); + n += (sz->_inner_classes_bytes = sz->count_array(inner_classes())); + sz->_ro_bytes += n; + + const ConstantPool* cp = constants(); + if (cp) { + cp->collect_statistics(sz); + } + + const Annotations* anno = annotations(); + if (anno) { + anno->collect_statistics(sz); + } + + const Array* methods_array = methods(); + if (methods()) { + for (int i = 0; i < methods_array->length(); i++) { + Method* method = methods_array->at(i); + if (method) { + sz->_method_count ++; + method->collect_statistics(sz); + } + } + } +} +#endif // INCLUDE_SERVICES + // Verification class VerifyFieldClosure: public OopClosure { diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 97b3dd23313..ba45aa4b039 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -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 @@ -826,6 +826,9 @@ class InstanceKlass: public Klass { is_interface(), is_anonymous()); } +#if INCLUDE_SERVICES + virtual void collect_statistics(KlassSizeStats *sz) const; +#endif static int vtable_start_offset() { return header_size(); } static int vtable_length_offset() { return offset_of(InstanceKlass, _vtable_len) / HeapWordSize; } diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 21bfb6bda69..4b33e36bf87 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -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 @@ -29,6 +29,7 @@ #include "classfile/vmSymbols.hpp" #include "gc_implementation/shared/markSweep.inline.hpp" #include "gc_interface/collectedHeap.inline.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" @@ -624,6 +625,17 @@ void Klass::oop_print_value_on(oop obj, outputStream* st) { obj->print_address_on(st); } +#if INCLUDE_SERVICES +// Size Statistics +void Klass::collect_statistics(KlassSizeStats *sz) const { + sz->_klass_bytes = sz->count(this); + sz->_mirror_bytes = sz->count(java_mirror()); + sz->_secondary_supers_bytes = sz->count_array(secondary_supers()); + + sz->_ro_bytes += sz->_secondary_supers_bytes; + sz->_rw_bytes += sz->_klass_bytes + sz->_mirror_bytes; +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index be5d0c5293d..ac4e84221cd 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -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 @@ -91,6 +91,7 @@ template class GrowableArray; class ClassLoaderData; class klassVtable; class ParCompactionManager; +class KlassSizeStats; class Klass : public Metadata { friend class VMStructs; @@ -477,6 +478,9 @@ class Klass : public Metadata { // Size of klass in word size. virtual int size() const = 0; +#if INCLUDE_SERVICES + virtual void collect_statistics(KlassSizeStats *sz) const; +#endif // Returns the Java name for a class (Resource allocated) // For arrays, this returns the name of the element with a leading '['. diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 88645cb15e7..c2e7993c065 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -34,6 +34,7 @@ #include "interpreter/oopMapCache.hpp" #include "memory/gcLocker.hpp" #include "memory/generation.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/constMethod.hpp" @@ -1954,6 +1955,22 @@ void Method::print_value_on(outputStream* st) const { if (WizardMode && code() != NULL) st->print(" ((nmethod*)%p)", code()); } +#if INCLUDE_SERVICES +// Size Statistics +void Method::collect_statistics(KlassSizeStats *sz) const { + int mysize = sz->count(this); + sz->_method_bytes += mysize; + sz->_method_all_bytes += mysize; + sz->_rw_bytes += mysize; + + if (constMethod()) { + constMethod()->collect_statistics(sz); + } + if (method_data()) { + method_data()->collect_statistics(sz); + } +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 72a4faf11d7..1b16435696e 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -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 @@ -101,6 +101,7 @@ class LocalVariableTableElement; class AdapterHandlerEntry; class MethodData; class ConstMethod; +class KlassSizeStats; class Method : public Metadata { friend class VMStructs; @@ -593,6 +594,9 @@ class Method : public Metadata { static int header_size() { return sizeof(Method)/HeapWordSize; } static int size(bool is_native); int size() const { return method_size(); } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif // interpreter support static ByteSize const_offset() { return byte_offset_of(Method, _constMethod ); } diff --git a/hotspot/src/share/vm/oops/methodData.cpp b/hotspot/src/share/vm/oops/methodData.cpp index 71d9649c268..c7a200f9e47 100644 --- a/hotspot/src/share/vm/oops/methodData.cpp +++ b/hotspot/src/share/vm/oops/methodData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -27,6 +27,7 @@ #include "interpreter/bytecode.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/linkResolver.hpp" +#include "memory/heapInspection.hpp" #include "oops/methodData.hpp" #include "prims/jvmtiRedefineClasses.hpp" #include "runtime/compilationPolicy.hpp" @@ -859,6 +860,15 @@ void MethodData::print_data_on(outputStream* st) const { } #endif +#if INCLUDE_SERVICES +// Size Statistics +void MethodData::collect_statistics(KlassSizeStats *sz) const { + int n = sz->count(this); + sz->_method_data_bytes += n; + sz->_method_all_bytes += n; + sz->_rw_bytes += n; +} +#endif // INCLUDE_SERVICES // Verification diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp index 133278878ef..1ad58cbb207 100644 --- a/hotspot/src/share/vm/oops/methodData.hpp +++ b/hotspot/src/share/vm/oops/methodData.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -32,6 +32,7 @@ #include "runtime/orderAccess.hpp" class BytecodeStream; +class KlassSizeStats; // The MethodData object collects counts and other profile information // during zeroth-tier (interpretive) and first-tier execution. @@ -1289,6 +1290,9 @@ public: // My size int size_in_bytes() const { return _size; } int size() const { return align_object_size(align_size_up(_size, BytesPerWord)/BytesPerWord); } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif int creation_mileage() const { return _creation_mileage; } void set_creation_mileage(int x) { _creation_mileage = x; } diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index 52a098a2613..6bdc059f35b 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -43,12 +43,12 @@ void DCmdRegistrant::register_dcmds(){ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); -#if INCLUDE_SERVICES // Heap dumping supported +#if INCLUDE_SERVICES // Heap dumping/inspection supported DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); -#endif // INCLUDE_SERVICES DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); +#endif // INCLUDE_SERVICES DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); - //Enhanced JMX Agent Support DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true,false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true,false)); @@ -252,7 +252,7 @@ void RunFinalizationDCmd::execute(TRAPS) { vmSymbols::void_method_signature(), CHECK); } -#if INCLUDE_SERVICES // Heap dumping supported +#if INCLUDE_SERVICES // Heap dumping/inspection supported HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), _filename("filename","Name of the dump file", "STRING",true), @@ -292,7 +292,6 @@ int HeapDumpDCmd::num_arguments() { return 0; } } -#endif // INCLUDE_SERVICES ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), @@ -319,6 +318,65 @@ int ClassHistogramDCmd::num_arguments() { } } +#define DEFAULT_COLUMNS "InstBytes,KlassBytes,CpAll,annotations,MethodCount,Bytecodes,MethodAll,ROAll,RWAll,Total" +ClassStatsDCmd::ClassStatsDCmd(outputStream* output, bool heap) : + DCmdWithParser(output, heap), + _csv("-csv", "Print in CSV (comma-separated values) format for spreadsheets", + "BOOLEAN", false, "false"), + _all("-all", "Show all columns", + "BOOLEAN", false, "false"), + _help("-help", "Show meaning of all the columns", + "BOOLEAN", false, "false"), + _columns("columns", "Comma-separated list of all the columns to show. " + "If not specified, the following columns are shown: " DEFAULT_COLUMNS, + "STRING", false) { + _dcmdparser.add_dcmd_option(&_all); + _dcmdparser.add_dcmd_option(&_csv); + _dcmdparser.add_dcmd_option(&_help); + _dcmdparser.add_dcmd_argument(&_columns); +} + +void ClassStatsDCmd::execute(TRAPS) { + if (!UnlockDiagnosticVMOptions) { + output()->print_cr("GC.class_stats command requires -XX:+UnlockDiagnosticVMOptions"); + return; + } + + VM_GC_HeapInspection heapop(output(), + true, /* request_full_gc */ + true /* need_prologue */); + heapop.set_csv_format(_csv.value()); + heapop.set_print_help(_help.value()); + heapop.set_print_class_stats(true); + if (_all.value()) { + if (_columns.has_value()) { + output()->print_cr("Cannot specify -all and individual columns at the same time"); + return; + } else { + heapop.set_columns(NULL); + } + } else { + if (_columns.has_value()) { + heapop.set_columns(_columns.value()); + } else { + heapop.set_columns(DEFAULT_COLUMNS); + } + } + VMThread::execute(&heapop); +} + +int ClassStatsDCmd::num_arguments() { + ResourceMark rm; + ClassStatsDCmd* dcmd = new ClassStatsDCmd(NULL, false); + if (dcmd != NULL) { + DCmdMark mark(dcmd); + return dcmd->_dcmdparser.num_arguments(); + } else { + return 0; + } +} +#endif // INCLUDE_SERVICES + ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), _locks("-l", "print java.util.concurrent locks", "BOOLEAN", false, "false") { diff --git a/hotspot/src/share/vm/services/diagnosticCommand.hpp b/hotspot/src/share/vm/services/diagnosticCommand.hpp index 99d75a92f33..10b7214f17a 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.hpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -178,7 +178,7 @@ public: }; #endif // INCLUDE_SERVICES -// See also: inspeactheap in attachListener.cpp +// See also: inspectheap in attachListener.cpp class ClassHistogramDCmd : public DCmdWithParser { protected: DCmdArgument _all; @@ -197,6 +197,27 @@ public: virtual void execute(TRAPS); }; +class ClassStatsDCmd : public DCmdWithParser { +protected: + DCmdArgument _all; + DCmdArgument _csv; + DCmdArgument _help; + DCmdArgument _columns; +public: + ClassStatsDCmd(outputStream* output, bool heap); + static const char* name() { + return "GC.class_stats"; + } + static const char* description() { + return "Provide statistics about Java class meta data. Requires -XX:+UnlockDiagnosticVMOptions."; + } + static const char* impact() { + return "High: Depends on Java heap size and content."; + } + static int num_arguments(); + virtual void execute(TRAPS); +}; + // See also: thread_dump in attachListener.cpp class ThreadDumpDCmd : public DCmdWithParser { protected: From a25db953cc4116d5161b994e1379573ca4de6675 Mon Sep 17 00:00:00 2001 From: Igor Ignatyev Date: Fri, 1 Feb 2013 02:50:23 -0800 Subject: [PATCH 011/158] 8006410: allocating without ResourceMark when CompileCommand was specified Reviewed-by: kvn, vlivanov --- hotspot/src/share/vm/ci/ciEnv.cpp | 2 +- hotspot/src/share/vm/ci/ciInstanceKlass.cpp | 3 +++ hotspot/src/share/vm/ci/ciMethod.cpp | 1 + hotspot/src/share/vm/ci/ciMethodData.cpp | 1 + hotspot/src/share/vm/oops/symbol.cpp | 1 + 5 files changed, 7 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index bb51f88c7b9..de0bd082555 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -1168,7 +1168,7 @@ void ciEnv::dump_replay_data() { void ciEnv::dump_replay_data(outputStream* out) { ASSERT_IN_VM; - + ResourceMark rm; #if INCLUDE_JVMTI out->print_cr("JvmtiExport can_access_local_variables %d", _jvmti_can_access_local_variables); out->print_cr("JvmtiExport can_hotswap_or_post_breakpoint %d", _jvmti_can_hotswap_or_post_breakpoint); diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp index de5e973bfbf..d74e3693ae1 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp @@ -580,6 +580,7 @@ class StaticFinalFieldPrinter : public FieldClosure { } void do_field(fieldDescriptor* fd) { if (fd->is_final() && !fd->has_initial_value()) { + ResourceMark rm; oop mirror = fd->field_holder()->java_mirror(); _out->print("staticfield %s %s %s ", _holder, fd->name()->as_quoted_ascii(), fd->signature()->as_quoted_ascii()); switch (fd->field_type()) { @@ -643,6 +644,8 @@ class StaticFinalFieldPrinter : public FieldClosure { void ciInstanceKlass::dump_replay_data(outputStream* out) { ASSERT_IN_VM; + ResourceMark rm; + InstanceKlass* ik = get_instanceKlass(); ConstantPool* cp = ik->constants(); diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index 8ad9ecb1199..e5c5e72de9b 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -1178,6 +1178,7 @@ ciMethodBlocks *ciMethod::get_method_blocks() { void ciMethod::dump_replay_data(outputStream* st) { ASSERT_IN_VM; + ResourceMark rm; Method* method = get_Method(); Klass* holder = method->method_holder(); st->print_cr("ciMethod %s %s %s %d %d %d %d %d", diff --git a/hotspot/src/share/vm/ci/ciMethodData.cpp b/hotspot/src/share/vm/ci/ciMethodData.cpp index ee5490be877..c30c6c36437 100644 --- a/hotspot/src/share/vm/ci/ciMethodData.cpp +++ b/hotspot/src/share/vm/ci/ciMethodData.cpp @@ -374,6 +374,7 @@ void ciMethodData::print_impl(outputStream* st) { void ciMethodData::dump_replay_data(outputStream* out) { ASSERT_IN_VM; + ResourceMark rm; MethodData* mdo = get_MethodData(); Method* method = mdo->method(); Klass* holder = method->method_holder(); diff --git a/hotspot/src/share/vm/oops/symbol.cpp b/hotspot/src/share/vm/oops/symbol.cpp index f2253dbcce0..54601899287 100644 --- a/hotspot/src/share/vm/oops/symbol.cpp +++ b/hotspot/src/share/vm/oops/symbol.cpp @@ -152,6 +152,7 @@ char* Symbol::as_C_string_flexible_buffer(Thread* t, } void Symbol::print_symbol_on(outputStream* st) const { + ResourceMark rm; st = st ? st : tty; st->print("%s", as_quoted_ascii()); } From 1a9e6be809a6b6c5f9149b99f43b1c7b56617690 Mon Sep 17 00:00:00 2001 From: Igor Ignatyev Date: Fri, 1 Feb 2013 03:02:01 -0800 Subject: [PATCH 012/158] 8005439: no message about inline method if it specifed by CompileCommand Reviewed-by: kvn, vlivanov --- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 9 ++-- hotspot/src/share/vm/opto/bytecodeInfo.cpp | 52 ++++++++++++--------- hotspot/src/share/vm/opto/parse.hpp | 3 +- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index cbaf83b8fea..9491607adfa 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -3667,11 +3667,12 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode } // now perform tests that are based on flag settings - if (callee->force_inline() || callee->should_inline()) { - // ignore heuristic controls on inlining - if (callee->force_inline()) - print_inlining(callee, "force inline by annotation"); + if (callee->force_inline()) { + print_inlining(callee, "force inline by annotation"); + } else if (callee->should_inline()) { + print_inlining(callee, "force inline by CompileOracle"); } else { + // use heuristic controls on inlining if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("inlining too deep"); if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep"); if (callee->code_size_for_inlining() > max_inline_size() ) INLINE_BAILOUT("callee is too large"); diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index 5b80bd75c4b..3da308c27b2 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -420,14 +420,24 @@ const char* InlineTree::check_can_parse(ciMethod* callee) { } //------------------------------print_inlining--------------------------------- -// Really, the failure_msg can be a success message also. -void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const char* failure_msg) const { - C->print_inlining(callee_method, inline_level(), caller_bci, failure_msg ? failure_msg : "inline"); - if (callee_method == NULL) tty->print(" callee not monotonic or profiled"); - if (Verbose && callee_method) { - const InlineTree *top = this; - while( top->caller_tree() != NULL ) { top = top->caller_tree(); } - //tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count()); +void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, + const char* msg, bool success) const { + assert(msg != NULL, "just checking"); + if (C->log() != NULL) { + if (success) { + C->log()->inline_success(msg); + } else { + C->log()->inline_fail(msg); + } + } + if (PrintInlining) { + C->print_inlining(callee_method, inline_level(), caller_bci, msg); + if (callee_method == NULL) tty->print(" callee not monotonic or profiled"); + if (Verbose && callee_method) { + const InlineTree *top = this; + while( top->caller_tree() != NULL ) { top = top->caller_tree(); } + //tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count()); + } } } @@ -451,23 +461,23 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, // Do some initial checks. if (!pass_initial_checks(caller_method, caller_bci, callee_method)) { - if (PrintInlining) print_inlining(callee_method, caller_bci, "failed initial checks"); + print_inlining(callee_method, caller_bci, "failed initial checks", + false /* !success */); return NULL; } // Do some parse checks. failure_msg = check_can_parse(callee_method); if (failure_msg != NULL) { - if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); + print_inlining(callee_method, caller_bci, failure_msg, + false /* !success */); return NULL; } // Check if inlining policy says no. WarmCallInfo wci = *(initial_wci); - failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci, should_delay); - if (failure_msg != NULL && C->log() != NULL) { - C->log()->inline_fail(failure_msg); - } + failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, + &wci, should_delay); #ifndef PRODUCT if (UseOldInlining && InlineWarmCalls @@ -487,7 +497,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, wci = *(WarmCallInfo::always_hot()); else wci = *(WarmCallInfo::always_cold()); - } + } if (!InlineWarmCalls) { if (!wci.is_cold() && !wci.is_hot()) { // Do not inline the warm calls. @@ -496,11 +506,10 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, } if (!wci.is_cold()) { - // In -UseOldInlining, the failure_msg may also be a success message. - if (failure_msg == NULL) failure_msg = "inline (hot)"; - // Inline! - if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); + print_inlining(callee_method, caller_bci, + failure_msg ? failure_msg : "inline (hot)", + true /* success */); if (UseOldInlining) build_inline_tree_for_callee(callee_method, jvms, caller_bci); if (InlineWarmCalls && !wci.is_hot()) @@ -509,8 +518,9 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, } // Do not inline - if (failure_msg == NULL) failure_msg = "too cold to inline"; - if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); + print_inlining(callee_method, caller_bci, + failure_msg ? failure_msg : "too cold to inline", + false /* !success */ ); return NULL; } diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp index c880832a446..2cf487f8ad6 100644 --- a/hotspot/src/share/vm/opto/parse.hpp +++ b/hotspot/src/share/vm/opto/parse.hpp @@ -73,7 +73,8 @@ protected: const char* try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result, bool& should_delay); const char* should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const; const char* should_not_inline(ciMethod* callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const; - void print_inlining(ciMethod *callee_method, int caller_bci, const char *failure_msg) const; + void print_inlining(ciMethod* callee_method, int caller_bci, + const char* msg, bool success) const; InlineTree *caller_tree() const { return _caller_tree; } InlineTree* callee_at(int bci, ciMethod* m) const; From 6c80586b400c46f570cb248e4e5b67f095498cb6 Mon Sep 17 00:00:00 2001 From: Morris Meyer Date: Fri, 25 Jan 2013 16:31:47 -0800 Subject: [PATCH 013/158] 8005811: Turn off TierdCompilation in JDK8 trunk for all platforms Disable tiered compilation in jdk8 because of CodeCache and performance anomalies Reviewed-by: kvn, twisti --- hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp | 2 +- hotspot/src/cpu/x86/vm/c2_globals_x86.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp index 0dcdea0567b..c642e915fe1 100644 --- a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp @@ -42,7 +42,7 @@ define_pd_global(bool, ProfileInterpreter, false); #else define_pd_global(bool, ProfileInterpreter, true); #endif // CC_INTERP -define_pd_global(bool, TieredCompilation, trueInTiered); +define_pd_global(bool, TieredCompilation, false); define_pd_global(intx, CompileThreshold, 10000); define_pd_global(intx, BackEdgeThreshold, 140000); diff --git a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp index 5ad08b0f158..f63b8c46d58 100644 --- a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp @@ -44,7 +44,7 @@ define_pd_global(bool, ProfileInterpreter, false); #else define_pd_global(bool, ProfileInterpreter, true); #endif // CC_INTERP -define_pd_global(bool, TieredCompilation, trueInTiered); +define_pd_global(bool, TieredCompilation, false); define_pd_global(intx, CompileThreshold, 10000); define_pd_global(intx, BackEdgeThreshold, 100000); From 89b8658977324cd452469532b19a324e30531936 Mon Sep 17 00:00:00 2001 From: David Chase Date: Fri, 25 Jan 2013 16:09:14 -0800 Subject: [PATCH 014/158] 8006500: compiler/8004741/Test8004741.java fails intermediately Rewrote the test to be more reliable, add test for invalid size exception Reviewed-by: kvn --- .../test/compiler/8004741/Test8004741.java | 162 ++++++++++++++---- 1 file changed, 126 insertions(+), 36 deletions(-) diff --git a/hotspot/test/compiler/8004741/Test8004741.java b/hotspot/test/compiler/8004741/Test8004741.java index 95e63b9c0c1..baacc34763d 100644 --- a/hotspot/test/compiler/8004741/Test8004741.java +++ b/hotspot/test/compiler/8004741/Test8004741.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -25,70 +25,160 @@ * @test Test8004741.java * @bug 8004741 * @summary Missing compiled exception handle table entry for multidimensional array allocation + * @run main/othervm -Xmx64m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+StressCompiledExceptionHandlers -XX:+SafepointALot -XX:GuaranteedSafepointInterval=100 Test8004741 * @run main/othervm -Xmx64m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+StressCompiledExceptionHandlers Test8004741 - * */ import java.util.*; public class Test8004741 extends Thread { + static int passed = 0; + + /** + * Loop forever allocating 2-d arrays. + * Catches and rethrows all exceptions; in the case of ThreadDeath, increments passed. + * Note that passed is incremented here because this is the exception handler with + * the smallest scope; we only want to declare success in the case where it is highly + * likely that the test condition + * (exception in 2-d array alloc interrupted by ThreadDeath) + * actually occurs. + */ static int[][] test(int a, int b) throws Exception { - int[][] ar = null; + int[][] ar; try { ar = new int[a][b]; - } catch (Error e) { - System.out.println("test got Error"); - passed = true; - throw(e); - } catch (Exception e) { - System.out.println("test got Exception"); + } catch (ThreadDeath e) { + System.out.println("test got ThreadDeath"); + passed++; throw(e); } return ar; } - static boolean passed = false; + /* Cookbook wait-notify to track progress of test thread. */ + Object progressLock = new Object(); + private static final int NOT_STARTED = 0; + private static final int RUNNING = 1; + private static final int STOPPING = 2; - public void run() { - System.out.println("test started"); - try { - while(true) { - test(2,20000); + int progressState = NOT_STARTED; + + void toState(int state) { + synchronized (progressLock) { + progressState = state; + progressLock.notify(); + } + } + + void waitFor(int state) { + synchronized (progressLock) { + while (progressState < state) { + try { + progressLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + System.out.println("unexpected InterruptedException"); + fail(); } - } catch (ThreadDeath e) { - System.out.println("test got ThreadDeath"); - passed = true; - } catch (Error e) { - e.printStackTrace(); - System.out.println("test got Error"); - } catch (Exception e) { - e.printStackTrace(); - System.out.println("test got Exception"); } + if (progressState > state) { + System.out.println("unexpected test state change, expected " + + state + " but saw " + progressState); + fail(); + } + } + } + + /** + * Loops running test until some sort of an exception or error, + * expects to see ThreadDeath. + */ + public void run() { + try { + // Print before state change, so that other thread is most likely + // to see this thread executing calls to test() in a loop. + System.out.println("thread running"); + toState(RUNNING); + while (true) { + // (2,2) (2,10) (2,100) were observed to tickle the bug; + test(2, 100); + } + } catch (ThreadDeath e) { + // nothing to say, passing was incremented by the test. + } catch (Throwable e) { + e.printStackTrace(); + System.out.println("unexpected Throwable " + e); + fail(); + } + toState(STOPPING); + } + + /** + * Runs a single trial of the test in a thread. + * No single trial is definitive, since the ThreadDeath + * exception might not land in the tested region of code. + */ + public static void threadTest() throws InterruptedException { + Test8004741 t = new Test8004741(); + t.start(); + t.waitFor(RUNNING); + Thread.sleep(100); + System.out.println("stopping thread"); + t.stop(); + t.waitFor(STOPPING); + t.join(); } public static void main(String[] args) throws Exception { + // Warm up "test" + // t will never be started. for (int n = 0; n < 11000; n++) { - test(2, 20); + test(2, 100); } - // First test exception catch - Test8004741 t = new Test8004741(); + // Will this sleep help ensure that the compiler is run? + Thread.sleep(500); + passed = 0; - passed = false; - t.start(); - Thread.sleep(1000); - t.stop(); + try { + test(-1, 100); + System.out.println("Missing NegativeArraySizeException #1"); + fail(); + } catch ( java.lang.NegativeArraySizeException e ) { + System.out.println("Saw expected NegativeArraySizeException #1"); + } - Thread.sleep(5000); - t.join(); - if (passed) { + try { + test(100, -1); + fail(); + System.out.println("Missing NegativeArraySizeException #2"); + fail(); + } catch ( java.lang.NegativeArraySizeException e ) { + System.out.println("Saw expected NegativeArraySizeException #2"); + } + + /* Test repetitions. If the test succeeds-mostly, it succeeds, + * as long as it does not crash (the outcome if the exception range + * table entry for the array allocation is missing). + */ + int N = 12; + for (int n = 0; n < N; n++) { + threadTest(); + } + + if (passed > N/2) { + System.out.println("Saw " + passed + " out of " + N + " possible ThreadDeath hits"); System.out.println("PASSED"); } else { - System.out.println("FAILED"); - System.exit(97); + System.out.println("Too few ThreadDeath hits; expected at least " + N/2 + + " but saw only " + passed); + fail(); } } + static void fail() { + System.out.println("FAILED"); + System.exit(97); + } }; From 7d8f623180613a6473b64d6db146f1ac4b19cc20 Mon Sep 17 00:00:00 2001 From: Morris Meyer Date: Fri, 25 Jan 2013 16:50:33 -0800 Subject: [PATCH 015/158] 6518907: cleanup IA64 specific code in Hotspot Removed unused IA64 specific code Reviewed-by: twisti, kvn, dholmes --- .../agent/src/os/linux/LinuxDebuggerLocal.c | 12 +- hotspot/agent/src/os/linux/libproc.h | 8 - .../agent/src/os/win32/windbg/sawindbg.cpp | 92 +------- hotspot/src/os/linux/vm/os_linux.cpp | 12 +- hotspot/src/os/windows/vm/os_windows.cpp | 200 ++++++++++++------ .../vm/interpreter/bytecodeInterpreter.cpp | 4 +- .../src/share/vm/opto/generateOptoStub.cpp | 17 +- hotspot/src/share/vm/runtime/os.cpp | 30 ++- .../src/share/vm/runtime/sharedRuntime.cpp | 4 - hotspot/src/share/vm/runtime/synchronizer.cpp | 2 +- hotspot/src/share/vm/runtime/vframeArray.cpp | 2 - 11 files changed, 171 insertions(+), 212 deletions(-) diff --git a/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c b/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c index 5b49294e975..1d3c3bbd027 100644 --- a/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c +++ b/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c @@ -280,7 +280,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo return (err == PS_OK)? array : 0; } -#if defined(i386) || defined(ia64) || defined(amd64) || defined(sparc) || defined(sparcv9) +#if defined(i386) || defined(amd64) || defined(sparc) || defined(sparcv9) JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0 (JNIEnv *env, jobject this_obj, jint lwp_id) { @@ -299,9 +299,6 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo #ifdef i386 #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG #endif -#ifdef ia64 -#define NPRGREG IA64_REG_COUNT -#endif #ifdef amd64 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG #endif @@ -336,13 +333,6 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo #endif /* i386 */ -#if ia64 - regs = (*env)->GetLongArrayElements(env, array, &isCopy); - for (i = 0; i < NPRGREG; i++ ) { - regs[i] = 0xDEADDEAD; - } -#endif /* ia64 */ - #ifdef amd64 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg diff --git a/hotspot/agent/src/os/linux/libproc.h b/hotspot/agent/src/os/linux/libproc.h index 5f583631c08..4cde0c19d76 100644 --- a/hotspot/agent/src/os/linux/libproc.h +++ b/hotspot/agent/src/os/linux/libproc.h @@ -79,14 +79,6 @@ combination of ptrace and /proc calls. *************************************************************************************/ -#ifdef ia64 -struct user_regs_struct { -/* copied from user.h which doesn't define this in a struct */ - -#define IA64_REG_COUNT (EF_SIZE/8+32) /* integer and fp regs */ -unsigned long regs[IA64_REG_COUNT]; /* integer and fp regs */ -}; -#endif #if defined(sparc) || defined(sparcv9) #define user_regs_struct pt_regs diff --git a/hotspot/agent/src/os/win32/windbg/sawindbg.cpp b/hotspot/agent/src/os/win32/windbg/sawindbg.cpp index c0a1e66965e..2ee4a2a02f1 100644 --- a/hotspot/agent/src/os/win32/windbg/sawindbg.cpp +++ b/hotspot/agent/src/os/win32/windbg/sawindbg.cpp @@ -27,10 +27,7 @@ #include "sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal.h" -#ifdef _M_IA64 - #include "sun_jvm_hotspot_debugger_ia64_IA64ThreadContext.h" - #define NPRGREG sun_jvm_hotspot_debugger_ia64_IA64ThreadContext_NPRGREG -#elif _M_IX86 +#ifdef _M_IX86 #include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h" #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG #elif _M_AMD64 @@ -491,92 +488,7 @@ static bool addThreads(JNIEnv* env, jobject obj) { memset(&context, 0, sizeof(CONTEXT)); #undef REG_INDEX -#ifdef _M_IA64 - #define REG_INDEX(x) sun_jvm_hotspot_debugger_ia64_IA64ThreadContext_##x - - context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG; - ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT)); - - ptrRegs[REG_INDEX(GR0)] = 0; // always 0 - ptrRegs[REG_INDEX(GR1)] = context.IntGp; // r1 - ptrRegs[REG_INDEX(GR2)] = context.IntT0; // r2-r3 - ptrRegs[REG_INDEX(GR3)] = context.IntT1; - ptrRegs[REG_INDEX(GR4)] = context.IntS0; // r4-r7 - ptrRegs[REG_INDEX(GR5)] = context.IntS1; - ptrRegs[REG_INDEX(GR6)] = context.IntS2; - ptrRegs[REG_INDEX(GR7)] = context.IntS3; - ptrRegs[REG_INDEX(GR8)] = context.IntV0; // r8 - ptrRegs[REG_INDEX(GR9)] = context.IntT2; // r9-r11 - ptrRegs[REG_INDEX(GR10)] = context.IntT3; - ptrRegs[REG_INDEX(GR11)] = context.IntT4; - ptrRegs[REG_INDEX(GR12)] = context.IntSp; // r12 stack pointer - ptrRegs[REG_INDEX(GR13)] = context.IntTeb; // r13 teb - ptrRegs[REG_INDEX(GR14)] = context.IntT5; // r14-r31 - ptrRegs[REG_INDEX(GR15)] = context.IntT6; - ptrRegs[REG_INDEX(GR16)] = context.IntT7; - ptrRegs[REG_INDEX(GR17)] = context.IntT8; - ptrRegs[REG_INDEX(GR18)] = context.IntT9; - ptrRegs[REG_INDEX(GR19)] = context.IntT10; - ptrRegs[REG_INDEX(GR20)] = context.IntT11; - ptrRegs[REG_INDEX(GR21)] = context.IntT12; - ptrRegs[REG_INDEX(GR22)] = context.IntT13; - ptrRegs[REG_INDEX(GR23)] = context.IntT14; - ptrRegs[REG_INDEX(GR24)] = context.IntT15; - ptrRegs[REG_INDEX(GR25)] = context.IntT16; - ptrRegs[REG_INDEX(GR26)] = context.IntT17; - ptrRegs[REG_INDEX(GR27)] = context.IntT18; - ptrRegs[REG_INDEX(GR28)] = context.IntT19; - ptrRegs[REG_INDEX(GR29)] = context.IntT20; - ptrRegs[REG_INDEX(GR30)] = context.IntT21; - ptrRegs[REG_INDEX(GR31)] = context.IntT22; - - ptrRegs[REG_INDEX(INT_NATS)] = context.IntNats; - ptrRegs[REG_INDEX(PREDS)] = context.Preds; - - ptrRegs[REG_INDEX(BR_RP)] = context.BrRp; - ptrRegs[REG_INDEX(BR1)] = context.BrS0; // b1-b5 - ptrRegs[REG_INDEX(BR2)] = context.BrS1; - ptrRegs[REG_INDEX(BR3)] = context.BrS2; - ptrRegs[REG_INDEX(BR4)] = context.BrS3; - ptrRegs[REG_INDEX(BR5)] = context.BrS4; - ptrRegs[REG_INDEX(BR6)] = context.BrT0; // b6-b7 - ptrRegs[REG_INDEX(BR7)] = context.BrT1; - - ptrRegs[REG_INDEX(AP_UNAT)] = context.ApUNAT; - ptrRegs[REG_INDEX(AP_LC)] = context.ApLC; - ptrRegs[REG_INDEX(AP_EC)] = context.ApEC; - ptrRegs[REG_INDEX(AP_CCV)] = context.ApCCV; - ptrRegs[REG_INDEX(AP_DCR)] = context.ApDCR; - - ptrRegs[REG_INDEX(RS_PFS)] = context.RsPFS; - ptrRegs[REG_INDEX(RS_BSP)] = context.RsBSP; - ptrRegs[REG_INDEX(RS_BSPSTORE)] = context.RsBSPSTORE; - ptrRegs[REG_INDEX(RS_RSC)] = context.RsRSC; - ptrRegs[REG_INDEX(RS_RNAT)] = context.RsRNAT; - - ptrRegs[REG_INDEX(ST_IPSR)] = context.StIPSR; - ptrRegs[REG_INDEX(ST_IIP)] = context.StIIP; - ptrRegs[REG_INDEX(ST_IFS)] = context.StIFS; - - ptrRegs[REG_INDEX(DB_I0)] = context.DbI0; - ptrRegs[REG_INDEX(DB_I1)] = context.DbI1; - ptrRegs[REG_INDEX(DB_I2)] = context.DbI2; - ptrRegs[REG_INDEX(DB_I3)] = context.DbI3; - ptrRegs[REG_INDEX(DB_I4)] = context.DbI4; - ptrRegs[REG_INDEX(DB_I5)] = context.DbI5; - ptrRegs[REG_INDEX(DB_I6)] = context.DbI6; - ptrRegs[REG_INDEX(DB_I7)] = context.DbI7; - - ptrRegs[REG_INDEX(DB_D0)] = context.DbD0; - ptrRegs[REG_INDEX(DB_D1)] = context.DbD1; - ptrRegs[REG_INDEX(DB_D2)] = context.DbD2; - ptrRegs[REG_INDEX(DB_D3)] = context.DbD3; - ptrRegs[REG_INDEX(DB_D4)] = context.DbD4; - ptrRegs[REG_INDEX(DB_D5)] = context.DbD5; - ptrRegs[REG_INDEX(DB_D6)] = context.DbD6; - ptrRegs[REG_INDEX(DB_D7)] = context.DbD7; - -#elif _M_IX86 +#ifdef _M_IX86 #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 8ff3c786b8b..537b48cdbc9 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -1155,13 +1155,9 @@ void os::Linux::capture_initial_stack(size_t max_size) { // for initial thread if its stack size exceeds 6M. Cap it at 2M, // in case other parts in glibc still assumes 2M max stack size. // FIXME: alt signal stack is gone, maybe we can relax this constraint? -#ifndef IA64 - if (stack_size > 2 * K * K) stack_size = 2 * K * K; -#else // Problem still exists RH7.2 (IA64 anyway) but 2MB is a little small - if (stack_size > 4 * K * K) stack_size = 4 * K * K; -#endif - + if (stack_size > 2 * K * K IA64_ONLY(*2)) + stack_size = 2 * K * K IA64_ONLY(*2); // Try to figure out where the stack base (top) is. This is harder. // // When an application is started, glibc saves the initial stack pointer in @@ -4367,16 +4363,12 @@ int os::Linux::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mute if (is_NPTL()) { return pthread_cond_timedwait(_cond, _mutex, _abstime); } else { -#ifndef IA64 // 6292965: LinuxThreads pthread_cond_timedwait() resets FPU control // word back to default 64bit precision if condvar is signaled. Java // wants 53bit precision. Save and restore current value. int fpu = get_fpu_control_word(); -#endif // IA64 int status = pthread_cond_timedwait(_cond, _mutex, _abstime); -#ifndef IA64 set_fpu_control_word(fpu); -#endif // IA64 return status; } } diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 98b3077d1fa..eb16478ab8b 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -349,6 +349,33 @@ address os::current_stack_base() { #ifdef _M_IA64 // IA64 has memory and register stacks + // + // This is the stack layout you get on NT/IA64 if you specify 1MB stack limit + // at thread creation (1MB backing store growing upwards, 1MB memory stack + // growing downwards, 2MB summed up) + // + // ... + // ------- top of stack (high address) ----- + // | + // | 1MB + // | Backing Store (Register Stack) + // | + // | / \ + // | | + // | | + // | | + // ------------------------ stack base ----- + // | 1MB + // | Memory Stack + // | + // | | + // | | + // | | + // | \ / + // | + // ----- bottom of stack (low address) ----- + // ... + stack_size = stack_size / 2; #endif return stack_bottom + stack_size; @@ -2005,17 +2032,34 @@ LONG Handle_Exception(struct _EXCEPTION_POINTERS* exceptionInfo, address handler JavaThread* thread = JavaThread::current(); // Save pc in thread #ifdef _M_IA64 - thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->StIIP); + // Do not blow up if no thread info available. + if (thread) { + // Saving PRECISE pc (with slot information) in thread. + uint64_t precise_pc = (uint64_t) exceptionInfo->ExceptionRecord->ExceptionAddress; + // Convert precise PC into "Unix" format + precise_pc = (precise_pc & 0xFFFFFFFFFFFFFFF0) | ((precise_pc & 0xF) >> 2); + thread->set_saved_exception_pc((address)precise_pc); + } // Set pc to handler exceptionInfo->ContextRecord->StIIP = (DWORD64)handler; + // Clear out psr.ri (= Restart Instruction) in order to continue + // at the beginning of the target bundle. + exceptionInfo->ContextRecord->StIPSR &= 0xFFFFF9FFFFFFFFFF; + assert(((DWORD64)handler & 0xF) == 0, "Target address must point to the beginning of a bundle!"); #elif _M_AMD64 - thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->Rip); + // Do not blow up if no thread info available. + if (thread) { + thread->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Rip); + } // Set pc to handler exceptionInfo->ContextRecord->Rip = (DWORD64)handler; #else - thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->Eip); + // Do not blow up if no thread info available. + if (thread) { + thread->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Eip); + } // Set pc to handler - exceptionInfo->ContextRecord->Eip = (LONG)handler; + exceptionInfo->ContextRecord->Eip = (DWORD)(DWORD_PTR)handler; #endif // Continue the execution @@ -2040,6 +2084,14 @@ extern "C" void events(); // included or copied here. #define EXCEPTION_INFO_EXEC_VIOLATION 0x08 +// Handle NAT Bit consumption on IA64. +#ifdef _M_IA64 +#define EXCEPTION_REG_NAT_CONSUMPTION STATUS_REG_NAT_CONSUMPTION +#endif + +// Windows Vista/2008 heap corruption check +#define EXCEPTION_HEAP_CORRUPTION 0xC0000374 + #define def_excpt(val) #val, val struct siglabel { @@ -2082,6 +2134,10 @@ struct siglabel exceptlabels[] = { def_excpt(EXCEPTION_GUARD_PAGE), def_excpt(EXCEPTION_INVALID_HANDLE), def_excpt(EXCEPTION_UNCAUGHT_CXX_EXCEPTION), + def_excpt(EXCEPTION_HEAP_CORRUPTION), +#ifdef _M_IA64 + def_excpt(EXCEPTION_REG_NAT_CONSUMPTION), +#endif NULL, 0 }; @@ -2206,7 +2262,14 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { if (InterceptOSException) return EXCEPTION_CONTINUE_SEARCH; DWORD exception_code = exceptionInfo->ExceptionRecord->ExceptionCode; #ifdef _M_IA64 - address pc = (address) exceptionInfo->ContextRecord->StIIP; + // On Itanium, we need the "precise pc", which has the slot number coded + // into the least 4 bits: 0000=slot0, 0100=slot1, 1000=slot2 (Windows format). + address pc = (address) exceptionInfo->ExceptionRecord->ExceptionAddress; + // Convert the pc to "Unix format", which has the slot number coded + // into the least 2 bits: 0000=slot0, 0001=slot1, 0010=slot2 + // This is needed for IA64 because "relocation" / "implicit null check" / "poll instruction" + // information is saved in the Unix format. + address pc_unix_format = (address) ((((uint64_t)pc) & 0xFFFFFFFFFFFFFFF0) | ((((uint64_t)pc) & 0xF) >> 2)); #elif _M_AMD64 address pc = (address) exceptionInfo->ContextRecord->Rip; #else @@ -2321,29 +2384,40 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { if (exception_code == EXCEPTION_STACK_OVERFLOW) { if (os::uses_stack_guard_pages()) { #ifdef _M_IA64 - // - // If it's a legal stack address continue, Windows will map it in. - // + // Use guard page for register stack. PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; address addr = (address) exceptionRecord->ExceptionInformation[1]; - if (addr > thread->stack_yellow_zone_base() && addr < thread->stack_base() ) - return EXCEPTION_CONTINUE_EXECUTION; + // Check for a register stack overflow on Itanium + if (thread->addr_inside_register_stack_red_zone(addr)) { + // Fatal red zone violation happens if the Java program + // catches a StackOverflow error and does so much processing + // that it runs beyond the unprotected yellow guard zone. As + // a result, we are out of here. + fatal("ERROR: Unrecoverable stack overflow happened. JVM will exit."); + } else if(thread->addr_inside_register_stack(addr)) { + // Disable the yellow zone which sets the state that + // we've got a stack overflow problem. + if (thread->stack_yellow_zone_enabled()) { + thread->disable_stack_yellow_zone(); + } + // Give us some room to process the exception. + thread->disable_register_stack_guard(); + // Tracing with +Verbose. + if (Verbose) { + tty->print_cr("SOF Compiled Register Stack overflow at " INTPTR_FORMAT " (SIGSEGV)", pc); + tty->print_cr("Register Stack access at " INTPTR_FORMAT, addr); + tty->print_cr("Register Stack base " INTPTR_FORMAT, thread->register_stack_base()); + tty->print_cr("Register Stack [" INTPTR_FORMAT "," INTPTR_FORMAT "]", + thread->register_stack_base(), + thread->register_stack_base() + thread->stack_size()); + } - // The register save area is the same size as the memory stack - // and starts at the page just above the start of the memory stack. - // If we get a fault in this area, we've run out of register - // stack. If we are in java, try throwing a stack overflow exception. - if (addr > thread->stack_base() && - addr <= (thread->stack_base()+thread->stack_size()) ) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), - "Register stack overflow, addr:%p, stack_base:%p\n", - addr, thread->stack_base() ); - tty->print_raw_cr(buf); - // If not in java code, return and hope for the best. - return in_java ? Handle_Exception(exceptionInfo, - SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW)) - : EXCEPTION_CONTINUE_EXECUTION; + // Reguard the permanent register stack red zone just to be sure. + // We saw Windows silently disabling this without telling us. + thread->enable_register_stack_red_zone(); + + return Handle_Exception(exceptionInfo, + SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW)); } #endif if (thread->stack_yellow_zone_enabled()) { @@ -2418,50 +2492,33 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { { // Null pointer exception. #ifdef _M_IA64 - // We catch register stack overflows in compiled code by doing - // an explicit compare and executing a st8(G0, G0) if the - // BSP enters into our guard area. We test for the overflow - // condition and fall into the normal null pointer exception - // code if BSP hasn't overflowed. - if ( in_java ) { - if(thread->register_stack_overflow()) { - assert((address)exceptionInfo->ContextRecord->IntS3 == - thread->register_stack_limit(), - "GR7 doesn't contain register_stack_limit"); - // Disable the yellow zone which sets the state that - // we've got a stack overflow problem. - if (thread->stack_yellow_zone_enabled()) { - thread->disable_stack_yellow_zone(); + // Process implicit null checks in compiled code. Note: Implicit null checks + // can happen even if "ImplicitNullChecks" is disabled, e.g. in vtable stubs. + if (CodeCache::contains((void*) pc_unix_format) && !MacroAssembler::needs_explicit_null_check((intptr_t) addr)) { + CodeBlob *cb = CodeCache::find_blob_unsafe(pc_unix_format); + // Handle implicit null check in UEP method entry + if (cb && (cb->is_frame_complete_at(pc) || + (cb->is_nmethod() && ((nmethod *)cb)->inlinecache_check_contains(pc)))) { + if (Verbose) { + intptr_t *bundle_start = (intptr_t*) ((intptr_t) pc_unix_format & 0xFFFFFFFFFFFFFFF0); + tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", pc_unix_format); + tty->print_cr(" to addr " INTPTR_FORMAT, addr); + tty->print_cr(" bundle is " INTPTR_FORMAT " (high), " INTPTR_FORMAT " (low)", + *(bundle_start + 1), *bundle_start); } - // Give us some room to process the exception - thread->disable_register_stack_guard(); - // Update GR7 with the new limit so we can continue running - // compiled code. - exceptionInfo->ContextRecord->IntS3 = - (ULONGLONG)thread->register_stack_limit(); return Handle_Exception(exceptionInfo, - SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW)); - } else { - // - // Check for implicit null - // We only expect null pointers in the stubs (vtable) - // the rest are checked explicitly now. - // - if (((uintptr_t)addr) < os::vm_page_size() ) { - // an access to the first page of VM--assume it is a null pointer - address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); - if (stub != NULL) return Handle_Exception(exceptionInfo, stub); - } + SharedRuntime::continuation_for_implicit_exception(thread, pc_unix_format, SharedRuntime::IMPLICIT_NULL)); } - } // in_java + } - // IA64 doesn't use implicit null checking yet. So we shouldn't - // get here. - tty->print_raw_cr("Access violation, possible null pointer exception"); + // Implicit null checks were processed above. Hence, we should not reach + // here in the usual case => die! + if (Verbose) tty->print_raw_cr("Access violation, possible null pointer exception"); report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord, exceptionInfo->ContextRecord); return EXCEPTION_CONTINUE_SEARCH; -#else /* !IA64 */ + +#else // !IA64 // Windows 98 reports faulting addresses incorrectly if (!MacroAssembler::needs_explicit_null_check((intptr_t)addr) || @@ -2493,7 +2550,24 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord, exceptionInfo->ContextRecord); return EXCEPTION_CONTINUE_SEARCH; - } + } // /EXCEPTION_ACCESS_VIOLATION + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#if defined _M_IA64 + else if ((exception_code == EXCEPTION_ILLEGAL_INSTRUCTION || + exception_code == EXCEPTION_ILLEGAL_INSTRUCTION_2)) { + M37 handle_wrong_method_break(0, NativeJump::HANDLE_WRONG_METHOD, PR0); + + // Compiled method patched to be non entrant? Following conditions must apply: + // 1. must be first instruction in bundle + // 2. must be a break instruction with appropriate code + if((((uint64_t) pc & 0x0F) == 0) && + (((IPF_Bundle*) pc)->get_slot0() == handle_wrong_method_break.bits())) { + return Handle_Exception(exceptionInfo, + (address)SharedRuntime::get_handle_wrong_method_stub()); + } + } // /EXCEPTION_ILLEGAL_INSTRUCTION +#endif + if (in_java) { switch (exception_code) { diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 0d139fdf71c..55ef63ee9d0 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -3099,9 +3099,9 @@ BytecodeInterpreter::print() { tty->print_cr("&native_fresult: " INTPTR_FORMAT, (uintptr_t) &this->_native_fresult); tty->print_cr("native_lresult: " INTPTR_FORMAT, (uintptr_t) this->_native_lresult); #endif -#if defined(IA64) && !defined(ZERO) +#if !defined(ZERO) tty->print_cr("last_Java_fp: " INTPTR_FORMAT, (uintptr_t) this->_last_Java_fp); -#endif // IA64 && !ZERO +#endif // !ZERO tty->print_cr("self_link: " INTPTR_FORMAT, (uintptr_t) this->_self_link); } diff --git a/hotspot/src/share/vm/opto/generateOptoStub.cpp b/hotspot/src/share/vm/opto/generateOptoStub.cpp index 56fc759f2d2..c5ebd5ad524 100644 --- a/hotspot/src/share/vm/opto/generateOptoStub.cpp +++ b/hotspot/src/share/vm/opto/generateOptoStub.cpp @@ -88,12 +88,12 @@ void GraphKit::gen_stub(address C_function, thread, in_bytes(JavaThread::frame_anchor_offset()) + in_bytes(JavaFrameAnchor::last_Java_pc_offset())); -#if defined(SPARC) || defined(IA64) +#if defined(SPARC) Node* adr_flags = basic_plus_adr(top(), thread, in_bytes(JavaThread::frame_anchor_offset()) + in_bytes(JavaFrameAnchor::flags_offset())); -#endif /* defined(SPARC) || defined(IA64) */ +#endif /* defined(SPARC) */ // Drop in the last_Java_sp. last_Java_fp is not touched. @@ -102,10 +102,8 @@ void GraphKit::gen_stub(address C_function, // users will look at the other fields. // Node *adr_sp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_sp_offset())); -#ifndef IA64 Node *last_sp = basic_plus_adr(top(), frameptr(), (intptr_t) STACK_BIAS); store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias); -#endif // Set _thread_in_native // The order of stores into TLS is critical! Setting _thread_in_native MUST @@ -210,19 +208,12 @@ void GraphKit::gen_stub(address C_function, //----------------------------- // Clear last_Java_sp -#ifdef IA64 - if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease); -#endif - store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias); -#ifdef IA64 - if (os::is_MP() && UseMembar) insert_mem_bar(new MemBarVolatileNode()); -#endif // def IA64 // Clear last_Java_pc and (optionally)_flags store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias); -#if defined(SPARC) || defined(IA64) +#if defined(SPARC) store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias); -#endif /* defined(SPARC) || defined(IA64) */ +#endif /* defined(SPARC) */ #ifdef IA64 Node* adr_last_Java_fp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_fp_offset())); if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease); diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 649ce4fcc5c..b4090680395 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -985,15 +985,28 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) { // if C stack is walkable beyond current frame. The check for fp() is not // necessary on Sparc, but it's harmless. bool os::is_first_C_frame(frame* fr) { -#ifdef IA64 - // In order to walk native frames on Itanium, we need to access the unwind - // table, which is inside ELF. We don't want to parse ELF after fatal error, - // so return true for IA64. If we need to support C stack walking on IA64, - // this function needs to be moved to CPU specific files, as fp() on IA64 - // is register stack, which grows towards higher memory address. +#if defined(IA64) && !defined(_WIN32) + // On IA64 we have to check if the callers bsp is still valid + // (i.e. within the register stack bounds). + // Notice: this only works for threads created by the VM and only if + // we walk the current stack!!! If we want to be able to walk + // arbitrary other threads, we'll have to somehow store the thread + // object in the frame. + Thread *thread = Thread::current(); + if ((address)fr->fp() <= + thread->register_stack_base() HPUX_ONLY(+ 0x0) LINUX_ONLY(+ 0x50)) { + // This check is a little hacky, because on Linux the first C + // frame's ('start_thread') register stack frame starts at + // "register_stack_base + 0x48" while on HPUX, the first C frame's + // ('__pthread_bound_body') register stack frame seems to really + // start at "register_stack_base". + return true; + } else { + return false; + } +#elif defined(IA64) && defined(_WIN32) return true; -#endif - +#else // Load up sp, fp, sender sp and sender fp, check for reasonable values. // Check usp first, because if that's bad the other accessors may fault // on some architectures. Ditto ufp second, etc. @@ -1023,6 +1036,7 @@ bool os::is_first_C_frame(frame* fr) { if (old_fp - ufp > 64 * K) return true; return false; +#endif } #ifdef ASSERT diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 7d2b816fe63..53234bc7820 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -2816,10 +2816,6 @@ VMRegPair *SharedRuntime::find_callee_arguments(Symbol* sig, bool has_receiver, JRT_LEAF(intptr_t*, SharedRuntime::OSR_migration_begin( JavaThread *thread) ) -#ifdef IA64 - ShouldNotReachHere(); // NYI -#endif /* IA64 */ - // // This code is dependent on the memory layout of the interpreter local // array and the monitors. On all of our platforms the layout is identical diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp index 667066e7f17..bdf416275dc 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.cpp +++ b/hotspot/src/share/vm/runtime/synchronizer.cpp @@ -53,7 +53,7 @@ # include "os_bsd.inline.hpp" #endif -#if defined(__GNUC__) && !defined(IA64) +#if defined(__GNUC__) // Need to inhibit inlining for older versions of GCC to avoid build-time failures #define ATTR __attribute__((noinline)) #else diff --git a/hotspot/src/share/vm/runtime/vframeArray.cpp b/hotspot/src/share/vm/runtime/vframeArray.cpp index 2c9aa0f3adb..d00e9f00954 100644 --- a/hotspot/src/share/vm/runtime/vframeArray.cpp +++ b/hotspot/src/share/vm/runtime/vframeArray.cpp @@ -233,8 +233,6 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters, // Force early return from top frame after deoptimization #ifndef CC_INTERP pc = Interpreter::remove_activation_early_entry(state->earlyret_tos()); -#else - // TBD: Need to implement ForceEarlyReturn for CC_INTERP (ia64) #endif } else { // Possibly override the previous pc computation of the top (youngest) frame From b5148d30e2e132556aecdc3d07353274aca9af66 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Sun, 27 Jan 2013 19:38:44 +0000 Subject: [PATCH 016/158] 8006944: javac, combo tests should print out the number of threads used Reviewed-by: mcimadamore --- .../lib/JavacTestingAbstractThreadedTest.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java b/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java index edb2aac3111..34029854351 100644 --- a/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java +++ b/langtools/test/tools/javac/lib/JavacTestingAbstractThreadedTest.java @@ -41,14 +41,20 @@ import javax.tools.ToolProvider; * * If the property is not set the class will use a heuristic to determine the * maximum number of threads that can be fired to execute a given test. + * + * This code will have to be revisited if jprt starts using concurrency for + * for running jtreg tests. */ public abstract class JavacTestingAbstractThreadedTest { + protected static AtomicInteger numberOfThreads = new AtomicInteger(); + protected static int getThreadPoolSize() { Integer testConc = Integer.getInteger("test.concurrency"); if (testConc != null) return testConc; int cores = Runtime.getRuntime().availableProcessors(); - return Math.max(2, Math.min(8, cores / 2)); + numberOfThreads.set(Math.max(2, Math.min(8, cores / 2))); + return numberOfThreads.get(); } protected static void checkAfterExec() throws InterruptedException { @@ -82,11 +88,18 @@ public abstract class JavacTestingAbstractThreadedTest { } else if (printCheckCount) { outWriter.println("Total check executed: " + checkCount.get()); } + /* + * This output is for supporting debugging. It does not mean that a given + * test had executed that number of threads concurrently. The value printed + * here is the maximum possible amount. + */ closePrinters(); if (printAll) { System.out.println(errSWriter.toString()); System.out.println(outSWriter.toString()); } + System.out.println("Total number of threads in thread pool: " + + numberOfThreads.get()); } protected static void closePrinters() { From 2447f369f6765d8281c827b72c13acd0f98689b7 Mon Sep 17 00:00:00 2001 From: Jesper Wilhelmsson Date: Mon, 28 Jan 2013 15:41:45 +0100 Subject: [PATCH 017/158] 6348447: Specifying -XX:OldSize crashes 64-bit VMs Heap size will be set to allow for OldSize to fit. Also reviewed by vitalyd@gmail.com Reviewed-by: ehelin, jmasa --- .../src/share/vm/memory/collectorPolicy.cpp | 27 ++++++++++++++----- .../src/share/vm/memory/collectorPolicy.hpp | 4 +-- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/memory/collectorPolicy.cpp b/hotspot/src/share/vm/memory/collectorPolicy.cpp index b13d9761120..9f83af62260 100644 --- a/hotspot/src/share/vm/memory/collectorPolicy.cpp +++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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,18 @@ void TwoGenerationCollectorPolicy::initialize_flags() { if (NewSize + OldSize > MaxHeapSize) { MaxHeapSize = NewSize + OldSize; } + + if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(NewSize)) { + // NewRatio will be used later to set the young generation size so we use + // it to calculate how big the heap should be based on the requested OldSize + // and NewRatio. + assert(NewRatio > 0, "NewRatio should have been set up earlier"); + size_t calculated_heapsize = (OldSize / NewRatio) * (NewRatio + 1); + + calculated_heapsize = align_size_up(calculated_heapsize, max_alignment()); + MaxHeapSize = calculated_heapsize; + InitialHeapSize = calculated_heapsize; + } MaxHeapSize = align_size_up(MaxHeapSize, max_alignment()); always_do_update_barrier = UseConcMarkSweepGC; @@ -384,14 +396,15 @@ void GenCollectorPolicy::initialize_size_info() { // keeping it simple also seems a worthwhile goal. bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr, - size_t heap_size, - size_t min_gen0_size) { + const size_t heap_size, + const size_t min_gen1_size) { bool result = false; + if ((*gen1_size_ptr + *gen0_size_ptr) > heap_size) { - if (((*gen0_size_ptr + OldSize) > heap_size) && - (heap_size - min_gen0_size) >= min_alignment()) { - // Adjust gen0 down to accomodate OldSize - *gen0_size_ptr = heap_size - min_gen0_size; + if ((heap_size < (*gen0_size_ptr + min_gen1_size)) && + (heap_size >= min_gen1_size + min_alignment())) { + // Adjust gen0 down to accommodate min_gen1_size + *gen0_size_ptr = heap_size - min_gen1_size; *gen0_size_ptr = MAX2((uintx)align_size_down(*gen0_size_ptr, min_alignment()), min_alignment()); diff --git a/hotspot/src/share/vm/memory/collectorPolicy.hpp b/hotspot/src/share/vm/memory/collectorPolicy.hpp index a079f71b95b..6403f5e3bb7 100644 --- a/hotspot/src/share/vm/memory/collectorPolicy.hpp +++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -321,7 +321,7 @@ class TwoGenerationCollectorPolicy : public GenCollectorPolicy { // Returns true is gen0 sizes were adjusted bool adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr, - size_t heap_size, size_t min_gen1_size); + const size_t heap_size, const size_t min_gen1_size); }; class MarkSweepPolicy : public TwoGenerationCollectorPolicy { From cb255a0269e7fa78d5ba4d98f8512596f2d8b3b7 Mon Sep 17 00:00:00 2001 From: Bharadwaj Yadavelli Date: Mon, 28 Jan 2013 10:55:30 -0500 Subject: [PATCH 018/158] 8004967: Default method cause VerifyError: Illegal use of nonvirtual Recognize VM generated method in old verifier Reviewed-by: acorn, coleenp --- hotspot/make/bsd/makefiles/mapfile-vers-debug | 1 + hotspot/make/bsd/makefiles/mapfile-vers-product | 1 + hotspot/make/linux/makefiles/mapfile-vers-debug | 1 + hotspot/make/linux/makefiles/mapfile-vers-product | 1 + hotspot/make/solaris/makefiles/mapfile-vers | 1 + hotspot/src/share/vm/prims/jvm.cpp | 9 +++++++++ hotspot/src/share/vm/prims/jvm.h | 7 +++++++ 7 files changed, 21 insertions(+) diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-debug b/hotspot/make/bsd/makefiles/mapfile-vers-debug index ef827302c54..24144fe9b70 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-debug +++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug @@ -188,6 +188,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-product b/hotspot/make/bsd/makefiles/mapfile-vers-product index 0d2b04ca774..c165c16e2d8 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-product +++ b/hotspot/make/bsd/makefiles/mapfile-vers-product @@ -188,6 +188,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-debug b/hotspot/make/linux/makefiles/mapfile-vers-debug index ae4e2f9bcc3..27238f5720a 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-debug +++ b/hotspot/make/linux/makefiles/mapfile-vers-debug @@ -184,6 +184,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-product b/hotspot/make/linux/makefiles/mapfile-vers-product index 9a3028d2a09..04531fa15aa 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-product +++ b/hotspot/make/linux/makefiles/mapfile-vers-product @@ -184,6 +184,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff --git a/hotspot/make/solaris/makefiles/mapfile-vers b/hotspot/make/solaris/makefiles/mapfile-vers index bf21253062e..d58807b046d 100644 --- a/hotspot/make/solaris/makefiles/mapfile-vers +++ b/hotspot/make/solaris/makefiles/mapfile-vers @@ -184,6 +184,7 @@ SUNWprivate_1.1 { JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index e1167924c49..7fffe0020c2 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -2302,6 +2302,15 @@ JVM_QUICK_ENTRY(jboolean, JVM_IsConstructorIx(JNIEnv *env, jclass cls, int metho JVM_END +JVM_QUICK_ENTRY(jboolean, JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cls, int method_index)) + JVMWrapper("JVM_IsVMGeneratedMethodIx"); + ResourceMark rm(THREAD); + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); + k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); + Method* method = InstanceKlass::cast(k)->methods()->at(method_index); + return method->is_overpass(); +JVM_END + JVM_ENTRY(const char*, JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cls, jint method_index)) JVMWrapper("JVM_GetMethodIxIxUTF"); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index c081f872afa..dea46d126eb 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -859,6 +859,13 @@ JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cb, int index); JNIEXPORT jboolean JNICALL JVM_IsConstructorIx(JNIEnv *env, jclass cb, int index); +/* + * Is the given method generated by the VM. + * The method is identified by method_index. + */ +JNIEXPORT jboolean JNICALL +JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cb, int index); + /* * Returns the name of a given method in UTF format. * The result remains valid until JVM_ReleaseUTF is called. From b29b4794613a2aca125c2a6e9f8ed1d0f01a4ce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Borggr=C3=A9n-Franck?= Date: Tue, 29 Jan 2013 10:32:49 +0100 Subject: [PATCH 019/158] 8004698: Implement Core Reflection for Type Annotations Reviewed-by: darcy --- jdk/src/share/classes/java/lang/Class.java | 56 ++ jdk/src/share/classes/java/lang/System.java | 9 +- .../java/lang/reflect/AnnotatedArrayType.java | 43 ++ .../reflect/AnnotatedParameterizedType.java | 42 ++ .../java/lang/reflect/AnnotatedType.java | 44 ++ .../lang/reflect/AnnotatedTypeVariable.java | 43 ++ .../lang/reflect/AnnotatedWildcardType.java | 49 ++ .../java/lang/reflect/Constructor.java | 12 + .../classes/java/lang/reflect/Executable.java | 87 +++- .../classes/java/lang/reflect/Field.java | 21 +- .../classes/java/lang/reflect/Method.java | 12 + .../java/lang/reflect/ReflectAccess.java | 6 +- .../java/lang/reflect/TypeVariable.java | 14 +- .../classes/sun/misc/JavaLangAccess.java | 15 +- .../sun/reflect/LangReflectAccess.java | 5 +- .../sun/reflect/ReflectionFactory.java | 9 +- .../annotation/AnnotatedTypeFactory.java | 320 ++++++++++++ .../reflect/annotation/AnnotationParser.java | 4 +- .../reflect/annotation/TypeAnnotation.java | 227 ++++++++ .../annotation/TypeAnnotationParser.java | 491 ++++++++++++++++++ .../reflectiveObjects/TypeVariableImpl.java | 67 ++- jdk/src/share/javavm/export/jvm.h | 6 + jdk/src/share/native/java/lang/Class.c | 5 +- .../annotation/TypeAnnotationReflection.java | 428 +++++++++++++++ .../lang/annotation/TypeParamAnnotation.java | 120 +++++ 25 files changed, 2106 insertions(+), 29 deletions(-) create mode 100644 jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java create mode 100644 jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java create mode 100644 jdk/src/share/classes/java/lang/reflect/AnnotatedType.java create mode 100644 jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java create mode 100644 jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java create mode 100644 jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java create mode 100644 jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java create mode 100644 jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java create mode 100644 jdk/test/java/lang/annotation/TypeAnnotationReflection.java create mode 100644 jdk/test/java/lang/annotation/TypeParamAnnotation.java diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index 094f0cf26d6..87f78530899 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -29,12 +29,14 @@ import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Member; import java.lang.reflect.Field; +import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.AnnotatedType; import java.lang.ref.SoftReference; import java.io.InputStream; import java.io.ObjectStreamField; @@ -2325,6 +2327,11 @@ public final // Annotations handling private native byte[] getRawAnnotations(); + // Since 1.8 + native byte[] getRawTypeAnnotations(); + static byte[] getExecutableTypeAnnotationBytes(Executable ex) { + return getReflectionFactory().getExecutableTypeAnnotationBytes(ex); + } native ConstantPool getConstantPool(); @@ -3196,4 +3203,53 @@ public final * Maintained by the ClassValue class. */ transient ClassValue.ClassValueMap classValueMap; + + /** + * Returns an AnnotatedType object that represents the use of a type to specify + * the superclass of the entity represented by this Class. (The use of type + * Foo to specify the superclass in '... extends Foo' is distinct from the + * declaration of type Foo.) + * + * If this Class represents a class type whose declaration does not explicitly + * indicate an annotated superclass, the return value is null. + * + * If this Class represents either the Object class, an interface type, an + * array type, a primitive type, or void, the return value is null. + * + * @since 1.8 + */ + public AnnotatedType getAnnotatedSuperclass() { + return TypeAnnotationParser.buildAnnotatedSuperclass(getRawTypeAnnotations(), getConstantPool(), this); +} + + /** + * Returns an array of AnnotatedType objects that represent the use of types to + * specify superinterfaces of the entity represented by this Class. (The use + * of type Foo to specify a superinterface in '... implements Foo' is + * distinct from the declaration of type Foo.) + * + * If this Class represents a class, the return value is an array + * containing objects representing the uses of interface types to specify + * interfaces implemented by the class. The order of the objects in the + * array corresponds to the order of the interface types used in the + * 'implements' clause of the declaration of this Class. + * + * If this Class represents an interface, the return value is an array + * containing objects representing the uses of interface types to specify + * interfaces directly extended by the interface. The order of the objects in + * the array corresponds to the order of the interface types used in the + * 'extends' clause of the declaration of this Class. + * + * If this Class represents a class or interface whose declaration does not + * explicitly indicate any annotated superinterfaces, the return value is an + * array of length 0. + * + * If this Class represents either the Object class, an array type, a + * primitive type, or void, the return value is an array of length 0. + * + * @since 1.8 + */ + public AnnotatedType[] getAnnotatedInterfaces() { + return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this); + } } diff --git a/jdk/src/share/classes/java/lang/System.java b/jdk/src/share/classes/java/lang/System.java index a6206e60391..d901e992b9a 100644 --- a/jdk/src/share/classes/java/lang/System.java +++ b/jdk/src/share/classes/java/lang/System.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, 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 @@ -26,6 +26,7 @@ package java.lang; import java.io.*; import java.lang.annotation.Annotation; +import java.lang.reflect.Executable; import java.util.Properties; import java.util.PropertyPermission; import java.util.StringTokenizer; @@ -1199,6 +1200,12 @@ public final class System { public A getDirectDeclaredAnnotation(Class klass, Class anno) { return klass.getDirectDeclaredAnnotation(anno); } + public byte[] getRawClassTypeAnnotations(Class klass) { + return klass.getRawTypeAnnotations(); + } + public byte[] getRawExecutableTypeAnnotations(Executable executable) { + return Class.getExecutableTypeAnnotationBytes(executable); + } public > E[] getEnumConstantsShared(Class klass) { return klass.getEnumConstantsShared(); diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java new file mode 100644 index 00000000000..e84a3360fdd --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedArrayType.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012, 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 + * 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.lang.reflect; + + +/** + * AnnotatedArrayType represents the use of an array type, whose component + * type may itself represent the annotated use of a type. + * + * @since 1.8 + */ +public interface AnnotatedArrayType extends AnnotatedType { + + /** + * Returns the annotated generic component type of this array type. + * + * @return the annotated generic component type of this array type + */ + AnnotatedType getAnnotatedGenericComponentType(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java new file mode 100644 index 00000000000..4fa089e318c --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedParameterizedType.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012, 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 + * 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.lang.reflect; + +/** + * AnnotatedParameterizedType represents the use of a parameterized type, + * whose type arguments may themselves represent annotated uses of types. + * + * @since 1.8 + */ +public interface AnnotatedParameterizedType extends AnnotatedType { + + /** + * Returns the annotated actual type arguments of this parameterized type. + * + * @return the annotated actual type arguments of this parameterized type + */ + AnnotatedType[] getAnnotatedActualTypeArguments(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java new file mode 100644 index 00000000000..d1ee79f14f4 --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedType.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, 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 + * 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.lang.reflect; + +/** + * AnnotatedType represents the annotated use of a type in the program + * currently running in this VM. The use may be of any type in the Java + * programming language, including an array type, a parameterized type, a type + * variable, or a wildcard type. + * + * @since 1.8 + */ +public interface AnnotatedType extends AnnotatedElement { + + /** + * Returns the underlying type that this annotated type represents. + * + * @return the type this annotated type represents + */ + public Type getType(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java new file mode 100644 index 00000000000..3580a14442f --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedTypeVariable.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012, 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 + * 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.lang.reflect; + +/** + * AnnotatedTypeVariable represents the use of a type variable, whose + * declaration may have bounds which themselves represent annotated uses of + * types. + * + * @since 1.8 + */ +public interface AnnotatedTypeVariable extends AnnotatedType { + + /** + * Returns the annotated bounds of this type variable. + * + * @return the annotated bounds of this type variable + */ + AnnotatedType[] getAnnotatedBounds(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java new file mode 100644 index 00000000000..c357eb9d0bc --- /dev/null +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedWildcardType.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012, 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 + * 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.lang.reflect; + +/** + * AnnotatedWildcardType represents the use of a wildcard type argument, whose + * upper or lower bounds may themselves represent annotated uses of types. + * + * @since 1.8 + */ +public interface AnnotatedWildcardType extends AnnotatedType { + + /** + * Returns the annotated lower bounds of this wildcard type. + * + * @return the annotated lower bounds of this wildcard type + */ + AnnotatedType[] getAnnotatedLowerBounds(); + + /** + * Returns the annotated upper bounds of this wildcard type. + * + * @return the annotated upper bounds of this wildcard type + */ + AnnotatedType[] getAnnotatedUpperBounds(); +} diff --git a/jdk/src/share/classes/java/lang/reflect/Constructor.java b/jdk/src/share/classes/java/lang/reflect/Constructor.java index 1973e820950..bbfd1d5ab9d 100644 --- a/jdk/src/share/classes/java/lang/reflect/Constructor.java +++ b/jdk/src/share/classes/java/lang/reflect/Constructor.java @@ -154,6 +154,10 @@ public final class Constructor extends Executable { byte[] getAnnotationBytes() { return annotations; } + @Override + byte[] getTypeAnnotationBytes() { + return typeAnnotations; + } /** * {@inheritDoc} @@ -523,4 +527,12 @@ public final class Constructor extends Executable { } } } + + /** + * {@inheritDoc} + * @since 1.8 + */ + public AnnotatedType getAnnotatedReturnType() { + return getAnnotatedReturnType0(getDeclaringClass()); + } } diff --git a/jdk/src/share/classes/java/lang/reflect/Executable.java b/jdk/src/share/classes/java/lang/reflect/Executable.java index f2befd2dcdd..b9ed7310a4d 100644 --- a/jdk/src/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -31,6 +31,8 @@ import java.util.Map; import java.util.Objects; import sun.reflect.annotation.AnnotationParser; import sun.reflect.annotation.AnnotationSupport; +import sun.reflect.annotation.TypeAnnotationParser; +import sun.reflect.annotation.TypeAnnotation; import sun.reflect.generics.repository.ConstructorRepository; /** @@ -50,6 +52,7 @@ public abstract class Executable extends AccessibleObject * Accessor method to allow code sharing */ abstract byte[] getAnnotationBytes(); + abstract byte[] getTypeAnnotationBytes(); /** * Does the Executable have generic information. @@ -470,4 +473,86 @@ public abstract class Executable extends AccessibleObject return declaredAnnotations; } + + /* Helper for subclasses of Executable. + * + * Returns an AnnotatedType object that represents the use of a type to + * specify the return type of the method/constructor represented by this + * Executable. + * + * @since 1.8 + */ + AnnotatedType getAnnotatedReturnType0(Type returnType) { + return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + returnType, + TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN_TYPE); + } + + /** + * Returns an AnnotatedType object that represents the use of a type to + * specify the receiver type of the method/constructor represented by this + * Executable. The receiver type of a method/constructor is available only + * if the method/constructor declares a formal parameter called 'this'. + * + * Returns null if this Executable represents a constructor or instance + * method that either declares no formal parameter called 'this', or + * declares a formal parameter called 'this' with no annotations on its + * type. + * + * Returns null if this Executable represents a static method. + * + * @since 1.8 + */ + public AnnotatedType getAnnotatedReceiverType() { + return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getDeclaringClass(), + TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER_TYPE); + } + + /** + * Returns an array of AnnotatedType objects that represent the use of + * types to specify formal parameter types of the method/constructor + * represented by this Executable. The order of the objects in the array + * corresponds to the order of the formal parameter types in the + * declaration of the method/constructor. + * + * Returns an array of length 0 if the method/constructor declares no + * parameters. + * + * @since 1.8 + */ + public AnnotatedType[] getAnnotatedParameterTypes() { + throw new UnsupportedOperationException("Not yet"); + } + + /** + * Returns an array of AnnotatedType objects that represent the use of + * types to specify the declared exceptions of the method/constructor + * represented by this Executable. The order of the objects in the array + * corresponds to the order of the exception types in the declaration of + * the method/constructor. + * + * Returns an array of length 0 if the method/constructor declares no + * exceptions. + * + * @since 1.8 + */ + public AnnotatedType[] getAnnotatedExceptionTypes() { + return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes(), + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getGenericExceptionTypes(), + TypeAnnotation.TypeAnnotationTarget.THROWS); + } + } diff --git a/jdk/src/share/classes/java/lang/reflect/Field.java b/jdk/src/share/classes/java/lang/reflect/Field.java index e5471459586..d2502efb4dd 100644 --- a/jdk/src/share/classes/java/lang/reflect/Field.java +++ b/jdk/src/share/classes/java/lang/reflect/Field.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, 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 @@ -36,7 +36,8 @@ import java.util.Map; import java.util.Objects; import sun.reflect.annotation.AnnotationParser; import sun.reflect.annotation.AnnotationSupport; - +import sun.reflect.annotation.TypeAnnotation; +import sun.reflect.annotation.TypeAnnotationParser; /** * A {@code Field} provides information about, and dynamic access to, a @@ -1053,4 +1054,20 @@ class Field extends AccessibleObject implements Member { } return declaredAnnotations; } + + /** + * Returns an AnnotatedType object that represents the use of a type to specify + * the declared type of the field represented by this Field. + * + * @since 1.8 + */ + public AnnotatedType getAnnotatedType() { + return TypeAnnotationParser.buildAnnotatedType(typeAnnotations, + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + this, + getDeclaringClass(), + getGenericType(), + TypeAnnotation.TypeAnnotationTarget.FIELD_TYPE); +} } diff --git a/jdk/src/share/classes/java/lang/reflect/Method.java b/jdk/src/share/classes/java/lang/reflect/Method.java index a7beb011400..1507c77194a 100644 --- a/jdk/src/share/classes/java/lang/reflect/Method.java +++ b/jdk/src/share/classes/java/lang/reflect/Method.java @@ -165,6 +165,10 @@ public final class Method extends Executable { byte[] getAnnotationBytes() { return annotations; } + @Override + byte[] getTypeAnnotationBytes() { + return typeAnnotations; + } /** * {@inheritDoc} @@ -621,6 +625,14 @@ public final class Method extends Executable { return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations); } + /** + * {@inheritDoc} + * @since 1.8 + */ + public AnnotatedType getAnnotatedReturnType() { + return getAnnotatedReturnType0(getGenericReturnType()); + } + @Override void handleParameterNumberMismatch(int resultLength, int numParameters) { throw new AnnotationFormatError("Parameter annotations don't match number of parameters"); diff --git a/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java b/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java index 80311d240e6..c3ac1557b85 100644 --- a/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java +++ b/jdk/src/share/classes/java/lang/reflect/ReflectAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -128,6 +128,10 @@ class ReflectAccess implements sun.reflect.LangReflectAccess { return c.getRawParameterAnnotations(); } + public byte[] getExecutableTypeAnnotationBytes(Executable ex) { + return ex.getTypeAnnotationBytes(); + } + // // Copying routines, needed to quickly fabricate new Field, // Method, and Constructor objects from templates diff --git a/jdk/src/share/classes/java/lang/reflect/TypeVariable.java b/jdk/src/share/classes/java/lang/reflect/TypeVariable.java index b0ff7880cda..42027e0041c 100644 --- a/jdk/src/share/classes/java/lang/reflect/TypeVariable.java +++ b/jdk/src/share/classes/java/lang/reflect/TypeVariable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -86,4 +86,16 @@ public interface TypeVariable extends Type, Annota * @return the name of this type variable, as it appears in the source code */ String getName(); + + /** + * Returns an array of AnnotatedType objects that represent the use of + * types to denote the upper bounds of the type parameter represented by + * this TypeVariable. The order of the objects in the array corresponds to + * the order of the bounds in the declaration of the type parameter. + * + * Returns an array of length 0 if the type parameter declares no bounds. + * + * @since 1.8 + */ + AnnotatedType[] getAnnotatedBounds(); } diff --git a/jdk/src/share/classes/sun/misc/JavaLangAccess.java b/jdk/src/share/classes/sun/misc/JavaLangAccess.java index 9506194c707..1624d67f4a9 100644 --- a/jdk/src/share/classes/sun/misc/JavaLangAccess.java +++ b/jdk/src/share/classes/sun/misc/JavaLangAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -26,6 +26,7 @@ package sun.misc; import java.lang.annotation.Annotation; +import java.lang.reflect.Executable; import sun.reflect.ConstantPool; import sun.reflect.annotation.AnnotationType; import sun.nio.ch.Interruptible; @@ -46,6 +47,18 @@ public interface JavaLangAccess { */ AnnotationType getAnnotationType(Class klass); + /** + * Get the array of bytes that is the class-file representation + * of this Class' type annotations. + */ + byte[] getRawClassTypeAnnotations(Class klass); + + /** + * Get the array of bytes that is the class-file representation + * of this Executable's type annotations. + */ + byte[] getRawExecutableTypeAnnotations(Executable executable); + /** * Returns the elements of an enum class or null if the * Class object does not represent an enum type; diff --git a/jdk/src/share/classes/sun/reflect/LangReflectAccess.java b/jdk/src/share/classes/sun/reflect/LangReflectAccess.java index fba1d318086..3c3b2757410 100644 --- a/jdk/src/share/classes/sun/reflect/LangReflectAccess.java +++ b/jdk/src/share/classes/sun/reflect/LangReflectAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -81,6 +81,9 @@ public interface LangReflectAccess { public void setConstructorAccessor(Constructor c, ConstructorAccessor accessor); + /** Gets the byte[] that encodes TypeAnnotations on an Executable. */ + public byte[] getExecutableTypeAnnotationBytes(Executable ex); + /** Gets the "slot" field from a Constructor (used for serialization) */ public int getConstructorSlot(Constructor c); diff --git a/jdk/src/share/classes/sun/reflect/ReflectionFactory.java b/jdk/src/share/classes/sun/reflect/ReflectionFactory.java index ea5323b8b9a..de97dfc7001 100644 --- a/jdk/src/share/classes/sun/reflect/ReflectionFactory.java +++ b/jdk/src/share/classes/sun/reflect/ReflectionFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -26,6 +26,7 @@ package sun.reflect; import java.lang.reflect.Field; +import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; @@ -314,6 +315,12 @@ public class ReflectionFactory { return langReflectAccess().copyConstructor(arg); } + /** Gets the byte[] that encodes TypeAnnotations on an executable. + */ + public byte[] getExecutableTypeAnnotationBytes(Executable ex) { + return langReflectAccess().getExecutableTypeAnnotationBytes(ex); + } + //-------------------------------------------------------------------------- // // Routines used by serialization diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java new file mode 100644 index 00000000000..afb4c4865e7 --- /dev/null +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java @@ -0,0 +1,320 @@ +/* + * Copyright (c) 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 + * 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.reflect.annotation; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static sun.reflect.annotation.TypeAnnotation.*; + +public class AnnotatedTypeFactory { + /** + * Create an AnnotatedType. + * + * @param type the type this AnnotatedType corresponds to + * @param currentLoc the location this AnnotatedType corresponds to + * @param actualTypeAnnos the type annotations this AnnotatedType has + * @param allOnSameTarget all type annotation on the same TypeAnnotationTarget + * as the AnnotatedType being built + * @param decl the declaration having the type use this AnnotatedType + * corresponds to + */ + public static AnnotatedType buildAnnotatedType(Type type, + LocationInfo currentLoc, + TypeAnnotation[] actualTypeAnnos, + TypeAnnotation[] allOnSameTarget, + AnnotatedElement decl) { + if (type == null) { + return EMPTY_ANNOTATED_TYPE; + } + if (isArray(type)) + return new AnnotatedArrayTypeImpl(type, + currentLoc, + actualTypeAnnos, + allOnSameTarget, + decl); + if (type instanceof Class) { + return new AnnotatedTypeBaseImpl(type, + addNesting(type, currentLoc), + actualTypeAnnos, + allOnSameTarget, + decl); + } else if (type instanceof TypeVariable) { + return new AnnotatedTypeVariableImpl((TypeVariable)type, + currentLoc, + actualTypeAnnos, + allOnSameTarget, + decl); + } else if (type instanceof ParameterizedType) { + return new AnnotatedParameterizedTypeImpl((ParameterizedType)type, + addNesting(type, currentLoc), + actualTypeAnnos, + allOnSameTarget, + decl); + } else if (type instanceof WildcardType) { + return new AnnotatedWildcardTypeImpl((WildcardType) type, + currentLoc, + actualTypeAnnos, + allOnSameTarget, + decl); + } + throw new AssertionError("Unknown instance of Type: " + type + "\nThis should not happen."); + } + + private static LocationInfo addNesting(Type type, LocationInfo addTo) { + if (isArray(type)) + return addTo; + if (type instanceof Class) { + Class clz = (Class)type; + if (clz.getEnclosingClass() == null) + return addTo; + return addNesting(clz.getEnclosingClass(), addTo.pushInner()); + } else if (type instanceof ParameterizedType) { + ParameterizedType t = (ParameterizedType)type; + if (t.getOwnerType() == null) + return addTo; + return addNesting(t.getOwnerType(), addTo.pushInner()); + } + return addTo; + } + + private static boolean isArray(Type t) { + if (t instanceof Class) { + Class c = (Class)t; + if (c.isArray()) + return true; + } else if (t instanceof GenericArrayType) { + return true; + } + return false; + } + + static final AnnotatedType EMPTY_ANNOTATED_TYPE = new AnnotatedTypeBaseImpl(null, LocationInfo.BASE_LOCATION, + new TypeAnnotation[0], new TypeAnnotation[0], null); + + private static class AnnotatedTypeBaseImpl implements AnnotatedType { + private final Type type; + private final AnnotatedElement decl; + private final LocationInfo location; + private final TypeAnnotation[] allOnSameTargetTypeAnnotations; + private final Map, Annotation> annotations; + + AnnotatedTypeBaseImpl(Type type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + this.type = type; + this.decl = decl; + this.location = location; + this.allOnSameTargetTypeAnnotations = allOnSameTargetTypeAnnotations; + this.annotations = TypeAnnotationParser.mapTypeAnnotations(location.filter(actualTypeAnnotations)); + } + + // AnnotatedElement + @Override + public final boolean isAnnotationPresent(Class annotation) { + return annotations.get(annotation) != null; + } + + @Override + public final Annotation[] getAnnotations() { + return getDeclaredAnnotations(); + } + + @Override + public final T getAnnotation(Class annotation) { + return getDeclaredAnnotation(annotation); + } + + @Override + public final T[] getAnnotations(Class annotation) { + return getDeclaredAnnotations(annotation); + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return annotations.values().toArray(new Annotation[0]); + } + + @Override + @SuppressWarnings("unchecked") + public T getDeclaredAnnotation(Class annotation) { + return (T)annotations.get(annotation); + } + + @Override + public T[] getDeclaredAnnotations(Class annotation) { + return AnnotationSupport.getMultipleAnnotations(annotations, annotation); + } + + // AnnotatedType + @Override + public Type getType() { + return type; + } + + // Implementation details + LocationInfo getLocation() { + return location; + } + TypeAnnotation[] getTypeAnnotations() { + return allOnSameTargetTypeAnnotations; + } + AnnotatedElement getDecl() { + return decl; + } + } + + private static class AnnotatedArrayTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedArrayType { + AnnotatedArrayTypeImpl(Type type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); + } + + @Override + public AnnotatedType getAnnotatedGenericComponentType() { + return AnnotatedTypeFactory.buildAnnotatedType(getComponentType(), + getLocation().pushArray(), + getTypeAnnotations(), + getTypeAnnotations(), + getDecl()); + } + + private Type getComponentType() { + Type t = getType(); + if (t instanceof Class) { + Class c = (Class)t; + return c.getComponentType(); + } + return ((GenericArrayType)t).getGenericComponentType(); + } + } + + private static class AnnotatedTypeVariableImpl extends AnnotatedTypeBaseImpl implements AnnotatedTypeVariable { + AnnotatedTypeVariableImpl(TypeVariable type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); + } + + @Override + public AnnotatedType[] getAnnotatedBounds() { + return getTypeVariable().getAnnotatedBounds(); + } + + private TypeVariable getTypeVariable() { + return (TypeVariable)getType(); + } + } + + private static class AnnotatedParameterizedTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedParameterizedType { + AnnotatedParameterizedTypeImpl(ParameterizedType type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); + } + + @Override + public AnnotatedType[] getAnnotatedActualTypeArguments() { + Type[] arguments = getParameterizedType().getActualTypeArguments(); + AnnotatedType[] res = new AnnotatedType[arguments.length]; + Arrays.fill(res, EMPTY_ANNOTATED_TYPE); + int initialCapacity = getTypeAnnotations().length; + for (int i = 0; i < res.length; i++) { + List l = new ArrayList<>(initialCapacity); + LocationInfo newLoc = getLocation().pushTypeArg((byte)i); + for (TypeAnnotation t : getTypeAnnotations()) + if (t.getLocationInfo().isSameLocationInfo(newLoc)) + l.add(t); + res[i] = buildAnnotatedType(arguments[i], + newLoc, + l.toArray(new TypeAnnotation[0]), + getTypeAnnotations(), + getDecl()); + } + return res; + } + + private ParameterizedType getParameterizedType() { + return (ParameterizedType)getType(); + } + } + + private static class AnnotatedWildcardTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedWildcardType { + private final boolean hasUpperBounds; + AnnotatedWildcardTypeImpl(WildcardType type, LocationInfo location, + TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, + AnnotatedElement decl) { + super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); + hasUpperBounds = (type.getLowerBounds().length == 0); + } + + @Override + public AnnotatedType[] getAnnotatedUpperBounds() { + if (!hasUpperBounds()) + return new AnnotatedType[0]; + return getAnnotatedBounds(getWildcardType().getUpperBounds()); + } + + @Override + public AnnotatedType[] getAnnotatedLowerBounds() { + if (hasUpperBounds) + return new AnnotatedType[0]; + return getAnnotatedBounds(getWildcardType().getLowerBounds()); + } + + private AnnotatedType[] getAnnotatedBounds(Type[] bounds) { + AnnotatedType[] res = new AnnotatedType[bounds.length]; + Arrays.fill(res, EMPTY_ANNOTATED_TYPE); + LocationInfo newLoc = getLocation().pushWildcard(); + int initialCapacity = getTypeAnnotations().length; + for (int i = 0; i < res.length; i++) { + List l = new ArrayList<>(initialCapacity); + for (TypeAnnotation t : getTypeAnnotations()) + if (t.getLocationInfo().isSameLocationInfo(newLoc)) + l.add(t); + res[i] = buildAnnotatedType(bounds[i], + newLoc, + l.toArray(new TypeAnnotation[0]), + getTypeAnnotations(), + getDecl()); + } + return res; + } + + private WildcardType getWildcardType() { + return (WildcardType)getType(); + } + + private boolean hasUpperBounds() { + return hasUpperBounds; + } + } +} diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java index 6f26ec368b7..a980a9126ef 100644 --- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -188,7 +188,7 @@ public class AnnotationParser { * available at runtime */ @SuppressWarnings("unchecked") - private static Annotation parseAnnotation(ByteBuffer buf, + static Annotation parseAnnotation(ByteBuffer buf, ConstantPool constPool, Class container, boolean exceptionOnMissingAnnotationClass) { diff --git a/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java new file mode 100644 index 00000000000..c5399725e8b --- /dev/null +++ b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotation.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 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 + * 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.reflect.annotation; + +import java.lang.annotation.Annotation; +import java.lang.annotation.AnnotationFormatError; +import java.lang.reflect.AnnotatedElement; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +/** + * A TypeAnnotation contains all the information needed to transform type + * annotations on declarations in the class file to actual Annotations in + * AnnotatedType instances. + * + * TypeAnnotaions contain a base Annotation, location info (which lets you + * distinguish between '@A Inner.@B Outer' in for example nested types), + * target info and the declaration the TypeAnnotaiton was parsed from. + */ +public class TypeAnnotation { + private final TypeAnnotationTargetInfo targetInfo; + private final LocationInfo loc; + private final Annotation annotation; + private final AnnotatedElement baseDeclaration; + + public TypeAnnotation(TypeAnnotationTargetInfo targetInfo, + LocationInfo loc, + Annotation annotation, + AnnotatedElement baseDeclaration) { + this.targetInfo = targetInfo; + this.loc = loc; + this.annotation = annotation; + this.baseDeclaration = baseDeclaration; + } + + public TypeAnnotationTargetInfo getTargetInfo() { + return targetInfo; + } + public Annotation getAnnotation() { + return annotation; + } + public AnnotatedElement getBaseDeclaration() { + return baseDeclaration; + } + public LocationInfo getLocationInfo() { + return loc; + } + + public static List filter(TypeAnnotation[] typeAnnotations, + TypeAnnotationTarget predicate) { + ArrayList typeAnnos = new ArrayList<>(typeAnnotations.length); + for (TypeAnnotation t : typeAnnotations) + if (t.getTargetInfo().getTarget() == predicate) + typeAnnos.add(t); + typeAnnos.trimToSize(); + return typeAnnos; + } + + public static enum TypeAnnotationTarget { + CLASS_TYPE_PARAMETER, + METHOD_TYPE_PARAMETER, + CLASS_EXTENDS, + CLASS_IMPLEMENTS, + CLASS_PARAMETER_BOUND, + METHOD_PARAMETER_BOUND, + METHOD_RETURN_TYPE, + METHOD_RECEIVER_TYPE, + FIELD_TYPE, + THROWS; + } + public static class TypeAnnotationTargetInfo { + private final TypeAnnotationTarget target; + private final int count; + private final int secondaryIndex; + private static final int UNUSED_INDEX = -2; // this is not a valid index in the 308 spec + + public TypeAnnotationTargetInfo(TypeAnnotationTarget target) { + this(target, UNUSED_INDEX, UNUSED_INDEX); + } + + public TypeAnnotationTargetInfo(TypeAnnotationTarget target, + int count) { + this(target, count, UNUSED_INDEX); + } + + public TypeAnnotationTargetInfo(TypeAnnotationTarget target, + int count, + int secondaryIndex) { + this.target = target; + this.count = count; + this.secondaryIndex = secondaryIndex; + } + + public TypeAnnotationTarget getTarget() { + return target; + } + public int getCount() { + return count; + } + public int getSecondaryIndex() { + return secondaryIndex; + } + + @Override + public String toString() { + return "" + target + ": " + count + ", " + secondaryIndex; + } + } + + public static class LocationInfo { + private final int depth; + private final Location[] locations; + + private LocationInfo() { + this(0, new Location[0]); + } + private LocationInfo(int depth, Location[] locations) { + this.depth = depth; + this.locations = locations; + } + + public static final LocationInfo BASE_LOCATION = new LocationInfo(); + + public static LocationInfo parseLocationInfo(ByteBuffer buf) { + int depth = buf.get(); + if (depth == 0) + return BASE_LOCATION; + Location[] locations = new Location[depth]; + for (int i = 0; i < depth; i++) { + byte tag = buf.get(); + byte index = buf.get(); + if (!(tag == 0 || tag == 1 | tag == 2 || tag == 3)) + throw new AnnotationFormatError("Bad Location encoding in Type Annotation"); + if (tag != 3 && index != 0) + throw new AnnotationFormatError("Bad Location encoding in Type Annotation"); + locations[i] = new Location(tag, index); + } + return new LocationInfo(depth, locations); + } + + public LocationInfo pushArray() { + return pushLocation((byte)0, (byte)0); + } + + public LocationInfo pushInner() { + return pushLocation((byte)1, (byte)0); + } + + public LocationInfo pushWildcard() { + return pushLocation((byte) 2, (byte) 0); + } + + public LocationInfo pushTypeArg(byte index) { + return pushLocation((byte) 3, index); + } + + public LocationInfo pushLocation(byte tag, byte index) { + int newDepth = this.depth + 1; + Location[] res = new Location[newDepth]; + System.arraycopy(this.locations, 0, res, 0, depth); + res[newDepth - 1] = new Location(tag, index); + return new LocationInfo(newDepth, res); + } + + public TypeAnnotation[] filter(TypeAnnotation[] ta) { + ArrayList l = new ArrayList<>(ta.length); + for (TypeAnnotation t : ta) { + if (isSameLocationInfo(t.getLocationInfo())) + l.add(t); + } + return l.toArray(new TypeAnnotation[0]); + } + + boolean isSameLocationInfo(LocationInfo other) { + if (depth != other.depth) + return false; + for (int i = 0; i < depth; i++) + if (!locations[i].isSameLocation(other.locations[i])) + return false; + return true; + } + + public static class Location { + public final byte tag; + public final byte index; + + boolean isSameLocation(Location other) { + return tag == other.tag && index == other.index; + } + + public Location(byte tag, byte index) { + this.tag = tag; + this.index = index; + } + } + } + + @Override + public String toString() { + return annotation.toString() + " with Targetnfo: " + + targetInfo.toString() + " on base declaration: " + + baseDeclaration.toString(); + } +} diff --git a/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java new file mode 100644 index 00000000000..12abe28b4d5 --- /dev/null +++ b/jdk/src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java @@ -0,0 +1,491 @@ +/* + * Copyright (c) 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 + * 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.reflect.annotation; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.nio.ByteBuffer; +import java.nio.BufferUnderflowException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import sun.misc.JavaLangAccess; +import sun.reflect.ConstantPool; +import static sun.reflect.annotation.TypeAnnotation.*; + +/** + * TypeAnnotationParser implements the logic needed to parse + * TypeAnnotations from an array of bytes. + */ +public class TypeAnnotationParser { + private static final TypeAnnotation[] EMPTY_TYPE_ANNOTATION_ARRAY = new TypeAnnotation[0]; + + /** + * Build an AnnotatedType from the parameters supplied. + * + * This method and {@code buildAnnotatedTypes} are probably + * the entry points you are looking for. + * + * @param rawAnnotations the byte[] encoding of all type annotations on this declaration + * @param cp the ConstantPool needed to parse the embedded Annotation + * @param decl the dclaration this type annotation is on + * @param container the Class this type annotation is on (may be the same as decl) + * @param type the type the AnnotatedType corresponds to + * @param filter the type annotation targets included in this AnnotatedType + */ + public static AnnotatedType buildAnnotatedType(byte[] rawAnnotations, + ConstantPool cp, + AnnotatedElement decl, + Class container, + Type type, + TypeAnnotationTarget filter) { + TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations, + cp, + decl, + container); + List l = new ArrayList<>(tas.length); + for (TypeAnnotation t : tas) { + TypeAnnotationTargetInfo ti = t.getTargetInfo(); + if (ti.getTarget() == filter) + l.add(t); + } + TypeAnnotation[] typeAnnotations = l.toArray(new TypeAnnotation[0]); + return AnnotatedTypeFactory.buildAnnotatedType(type, + LocationInfo.BASE_LOCATION, + typeAnnotations, + typeAnnotations, + decl); + } + + /** + * Build an array of AnnotatedTypes from the parameters supplied. + * + * This method and {@code buildAnnotatedType} are probably + * the entry points you are looking for. + * + * @param rawAnnotations the byte[] encoding of all type annotations on this declaration + * @param cp the ConstantPool needed to parse the embedded Annotation + * @param decl the declaration this type annotation is on + * @param container the Class this type annotation is on (may be the same as decl) + * @param types the Types the AnnotatedTypes corresponds to + * @param filter the type annotation targets that included in this AnnotatedType + */ + public static AnnotatedType[] buildAnnotatedTypes(byte[] rawAnnotations, + ConstantPool cp, + AnnotatedElement decl, + Class container, + Type[] types, + TypeAnnotationTarget filter) { + int size = types.length; + AnnotatedType[] result = new AnnotatedType[size]; + Arrays.fill(result, AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE); + @SuppressWarnings("rawtypes") + ArrayList[] l = new ArrayList[size]; // array of ArrayList + + TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations, + cp, + decl, + container); + for (TypeAnnotation t : tas) { + TypeAnnotationTargetInfo ti = t.getTargetInfo(); + if (ti.getTarget() == filter) { + int pos = ti.getCount(); + if (l[pos] == null) { + ArrayList tmp = new ArrayList<>(tas.length); + l[pos] = tmp; + } + @SuppressWarnings("unchecked") + ArrayList tmp = l[pos]; + tmp.add(t); + } + } + for (int i = 0; i < size; i++) { + @SuppressWarnings("unchecked") + ArrayList list = l[i]; + if (list != null) { + TypeAnnotation[] typeAnnotations = list.toArray(new TypeAnnotation[0]); + result[i] = AnnotatedTypeFactory.buildAnnotatedType(types[i], + LocationInfo.BASE_LOCATION, + typeAnnotations, + typeAnnotations, + decl); + } + } + return result; + } + + // Class helpers + + /** + * Build an AnnotatedType for the class decl's supertype. + * + * @param rawAnnotations the byte[] encoding of all type annotations on this declaration + * @param cp the ConstantPool needed to parse the embedded Annotation + * @param decl the Class which annotated supertype is being built + */ + public static AnnotatedType buildAnnotatedSuperclass(byte[] rawAnnotations, + ConstantPool cp, + Class decl) { + Type supertype = decl.getGenericSuperclass(); + if (supertype == null) + return AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE; + return buildAnnotatedType(rawAnnotations, + cp, + decl, + decl, + supertype, + TypeAnnotationTarget.CLASS_EXTENDS); + } + + /** + * Build an array of AnnotatedTypes for the class decl's implemented + * interfaces. + * + * @param rawAnnotations the byte[] encoding of all type annotations on this declaration + * @param cp the ConstantPool needed to parse the embedded Annotation + * @param decl the Class whose annotated implemented interfaces is being built + */ + public static AnnotatedType[] buildAnnotatedInterfaces(byte[] rawAnnotations, + ConstantPool cp, + Class decl) { + return buildAnnotatedTypes(rawAnnotations, + cp, + decl, + decl, + decl.getGenericInterfaces(), + TypeAnnotationTarget.CLASS_IMPLEMENTS); + } + + // TypeVariable helpers + + /** + * Parse regular annotations on a TypeVariable declared on genericDecl. + * + * Regular Annotations on TypeVariables are stored in the type + * annotation byte[] in the class file. + * + * @param genericsDecl the declaration declaring the type variable + * @param typeVarIndex the 0-based index of this type variable in the declaration + */ + public static Annotation[] parseTypeVariableAnnotations(D genericDecl, + int typeVarIndex) { + AnnotatedElement decl; + TypeAnnotationTarget predicate; + if (genericDecl instanceof Class) { + decl = (Class)genericDecl; + predicate = TypeAnnotationTarget.CLASS_TYPE_PARAMETER; + } else if (genericDecl instanceof Executable) { + decl = (Executable)genericDecl; + predicate = TypeAnnotationTarget.METHOD_TYPE_PARAMETER; + } else { + throw new AssertionError("Unknown GenericDeclaration " + genericDecl + "\nthis should not happen."); + } + List typeVarAnnos = TypeAnnotation.filter(parseAllTypeAnnotations(decl), + predicate); + List res = new ArrayList<>(typeVarAnnos.size()); + for (TypeAnnotation t : typeVarAnnos) + if (t.getTargetInfo().getCount() == typeVarIndex) + res.add(t.getAnnotation()); + return res.toArray(new Annotation[0]); + } + + /** + * Build an array of AnnotatedTypes for the declaration decl's bounds. + * + * @param bounds the bounds corresponding to the annotated bounds + * @param decl the declaration whose annotated bounds is being built + * @param typeVarIndex the index of this type variable on the decl + */ + public static AnnotatedType[] parseAnnotatedBounds(Type[] bounds, + D decl, + int typeVarIndex) { + return parseAnnotatedBounds(bounds, decl, typeVarIndex, LocationInfo.BASE_LOCATION); + } + //helper for above + static AnnotatedType[] parseAnnotatedBounds(Type[] bounds, + D decl, + int typeVarIndex, + LocationInfo loc) { + List candidates = fetchBounds(decl); + if (bounds != null) { + int startIndex = 0; + AnnotatedType[] res = new AnnotatedType[bounds.length]; + Arrays.fill(res, AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE); + + // Adjust bounds index + // + // Figure out if the type annotations for this bound starts with 0 + // or 1. The spec says within a bound the 0:th type annotation will + // always be on an bound of a Class type (not Interface type). So + // if the programmer starts with an Interface type for the first + // (and following) bound(s) the implicit Object bound is considered + // the first (that is 0:th) bound and type annotations start on + // index 1. + if (bounds.length > 0) { + Type b0 = bounds[0]; + if (!(b0 instanceof Class)) { + startIndex = 1; + } else { + Class c = (Class)b0; + if (c.isInterface()) { + startIndex = 1; + } + } + } + + for (int i = 0; i < bounds.length; i++) { + List l = new ArrayList<>(candidates.size()); + for (TypeAnnotation t : candidates) { + TypeAnnotationTargetInfo tInfo = t.getTargetInfo(); + if (tInfo.getSecondaryIndex() == i + startIndex && + tInfo.getCount() == typeVarIndex) { + l.add(t); + } + res[i] = AnnotatedTypeFactory.buildAnnotatedType(bounds[i], + loc, + l.toArray(new TypeAnnotation[0]), + candidates.toArray(new TypeAnnotation[0]), + (AnnotatedElement)decl); + } + } + return res; + } + return new AnnotatedType[0]; + } + private static List fetchBounds(D decl) { + AnnotatedElement boundsDecl; + TypeAnnotationTarget target; + if (decl instanceof Class) { + target = TypeAnnotationTarget.CLASS_PARAMETER_BOUND; + boundsDecl = (Class)decl; + } else { + target = TypeAnnotationTarget.METHOD_PARAMETER_BOUND; + boundsDecl = (Executable)decl; + } + return TypeAnnotation.filter(TypeAnnotationParser.parseAllTypeAnnotations(boundsDecl), target); + } + + /* + * Parse all type annotations on the declaration supplied. This is needed + * when you go from for example an annotated return type on a method that + * is a type variable declared on the class. In this case you need to + * 'jump' to the decl of the class and parse all type annotations there to + * find the ones that are applicable to the type variable. + */ + static TypeAnnotation[] parseAllTypeAnnotations(AnnotatedElement decl) { + Class container; + byte[] rawBytes; + JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess(); + if (decl instanceof Class) { + container = (Class)decl; + rawBytes = javaLangAccess.getRawClassTypeAnnotations(container); + } else if (decl instanceof Executable) { + container = ((Executable)decl).getDeclaringClass(); + rawBytes = javaLangAccess.getRawExecutableTypeAnnotations((Executable)decl); + } else { + // Should not reach here. Assert? + return EMPTY_TYPE_ANNOTATION_ARRAY; + } + return parseTypeAnnotations(rawBytes, javaLangAccess.getConstantPool(container), + decl, container); + } + + /* Parse type annotations encoded as an array of bytes */ + private static TypeAnnotation[] parseTypeAnnotations(byte[] rawAnnotations, + ConstantPool cp, + AnnotatedElement baseDecl, + Class container) { + if (rawAnnotations == null) + return EMPTY_TYPE_ANNOTATION_ARRAY; + + ByteBuffer buf = ByteBuffer.wrap(rawAnnotations); + int annotationCount = buf.getShort() & 0xFFFF; + List typeAnnotations = new ArrayList<>(annotationCount); + + // Parse each TypeAnnotation + for (int i = 0; i < annotationCount; i++) { + TypeAnnotation ta = parseTypeAnnotation(buf, cp, baseDecl, container); + if (ta != null) + typeAnnotations.add(ta); + } + + return typeAnnotations.toArray(EMPTY_TYPE_ANNOTATION_ARRAY); + } + + + // Helper + static Map, Annotation> mapTypeAnnotations(TypeAnnotation[] typeAnnos) { + Map, Annotation> result = + new LinkedHashMap<>(); + for (TypeAnnotation t : typeAnnos) { + Annotation a = t.getAnnotation(); + Class klass = a.annotationType(); + AnnotationType type = AnnotationType.getInstance(klass); + if (type.retention() == RetentionPolicy.RUNTIME) + if (result.put(klass, a) != null) + throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a); + } + return result; + } + + // Position codes + // Regular type parameter annotations + private static final byte CLASS_TYPE_PARAMETER = 0x00; + private static final byte METHOD_TYPE_PARAMETER = 0x01; + // Type Annotations outside method bodies + private static final byte CLASS_EXTENDS = 0x10; + private static final byte CLASS_TYPE_PARAMETER_BOUND = 0x11; + private static final byte METHOD_TYPE_PARAMETER_BOUND = 0x12; + private static final byte FIELD = 0x13; + private static final byte METHOD_RETURN = 0x14; + private static final byte METHOD_RECEIVER = 0x15; + private static final byte METHOD_FORMAL_PARAMETER = 0x16; + private static final byte THROWS = 0x17; + // Type Annotations inside method bodies + private static final byte LOCAL_VARIABLE = (byte)0x40; + private static final byte RESOURCE_VARIABLE = (byte)0x41; + private static final byte EXCEPTION_PARAMETER = (byte)0x42; + private static final byte CAST = (byte)0x43; + private static final byte INSTANCEOF = (byte)0x44; + private static final byte NEW = (byte)0x45; + private static final byte CONSTRUCTOR_REFERENCE_RECEIVER = (byte)0x46; + private static final byte METHOD_REFERENCE_RECEIVER = (byte)0x47; + private static final byte LAMBDA_FORMAL_PARAMETER = (byte)0x48; + private static final byte METHOD_REFERENCE = (byte)0x49; + private static final byte METHOD_REFERENCE_TYPE_ARGUMENT = (byte)0x50; + + private static TypeAnnotation parseTypeAnnotation(ByteBuffer buf, + ConstantPool cp, + AnnotatedElement baseDecl, + Class container) { + TypeAnnotationTargetInfo ti = parseTargetInfo(buf); + LocationInfo locationInfo = LocationInfo.parseLocationInfo(buf); + Annotation a = AnnotationParser.parseAnnotation(buf, cp, container, false); + if (ti == null) // Inside a method for example + return null; + return new TypeAnnotation(ti, locationInfo, a, baseDecl); + } + + private static TypeAnnotationTargetInfo parseTargetInfo(ByteBuffer buf) { + byte posCode = buf.get(); + switch(posCode) { + case CLASS_TYPE_PARAMETER: + case METHOD_TYPE_PARAMETER: { + byte index = buf.get(); + TypeAnnotationTargetInfo res; + if (posCode == CLASS_TYPE_PARAMETER) + res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_TYPE_PARAMETER, + index); + else + res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_TYPE_PARAMETER, + index); + return res; + } // unreachable break; + case CLASS_EXTENDS: { + short index = buf.getShort(); + if (index == -1) { + return new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_EXTENDS); + } else if (index >= 0) { + TypeAnnotationTargetInfo res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_IMPLEMENTS, + index); + return res; + }} break; + case CLASS_TYPE_PARAMETER_BOUND: + return parse2ByteTarget(TypeAnnotationTarget.CLASS_PARAMETER_BOUND, buf); + case METHOD_TYPE_PARAMETER_BOUND: + return parse2ByteTarget(TypeAnnotationTarget.METHOD_PARAMETER_BOUND, buf); + case FIELD: + return new TypeAnnotationTargetInfo(TypeAnnotationTarget.FIELD_TYPE); + case METHOD_RETURN: + return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RETURN_TYPE); + case METHOD_RECEIVER: + return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RECEIVER_TYPE); + case METHOD_FORMAL_PARAMETER: { + // Todo + byte index = buf.get(); + } break; + case THROWS: + return parseShortTarget(TypeAnnotationTarget.THROWS, buf); + + /* + * The ones below are inside method bodies, we don't care about them for core reflection + * other than adjusting for them in the byte stream. + */ + case LOCAL_VARIABLE: + case RESOURCE_VARIABLE: + short length = buf.getShort(); + for (int i = 0; i < length; ++i) { + short offset = buf.getShort(); + short varLength = buf.getShort(); + short index = buf.getShort(); + } + break; + case EXCEPTION_PARAMETER: { + byte index = buf.get(); + } break; + case CAST: + case INSTANCEOF: + case NEW: { + short offset = buf.getShort(); + } break; + case CONSTRUCTOR_REFERENCE_RECEIVER: + case METHOD_REFERENCE_RECEIVER: { + short offset = buf.getShort(); + byte index = buf.get(); + } break; + case LAMBDA_FORMAL_PARAMETER: { + byte index = buf.get(); + } break; + case METHOD_REFERENCE: + // This one isn't in the spec yet + break; + case METHOD_REFERENCE_TYPE_ARGUMENT: { + short offset = buf.getShort(); + byte index = buf.get(); + } break; + + default: + // will throw error below + break; + } + throw new AnnotationFormatError("Could not parse bytes for type annotations"); + } + + private static TypeAnnotationTargetInfo parseShortTarget(TypeAnnotationTarget target, ByteBuffer buf) { + short index = buf.getShort(); + return new TypeAnnotationTargetInfo(target, index); + } + private static TypeAnnotationTargetInfo parse2ByteTarget(TypeAnnotationTarget target, ByteBuffer buf) { + byte count = buf.get(); + byte secondaryIndex = buf.get(); + return new TypeAnnotationTargetInfo(target, + count, + secondaryIndex); + } +} diff --git a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java index 021b84891f1..4bc3356278b 100644 --- a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java +++ b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -25,13 +25,18 @@ package sun.reflect.generics.reflectiveObjects; -import java.lang.annotation.Annotation; +import java.lang.annotation.*; +import java.lang.reflect.AnnotatedType; import java.lang.reflect.Array; import java.lang.reflect.GenericDeclaration; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Objects; - +import sun.reflect.annotation.AnnotationSupport; +import sun.reflect.annotation.TypeAnnotationParser; +import sun.reflect.annotation.AnnotationType; import sun.reflect.generics.factory.GenericsFactory; import sun.reflect.generics.tree.FieldTypeSignature; import sun.reflect.generics.visitor.Reifier; @@ -182,45 +187,75 @@ public class TypeVariableImpl return genericDeclaration.hashCode() ^ name.hashCode(); } - // Currently vacuous implementations of AnnotatedElement methods. + // Implementations of AnnotatedElement methods. public boolean isAnnotationPresent(Class annotationClass) { Objects.requireNonNull(annotationClass); return false; } + @SuppressWarnings("unchecked") public T getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - return null; + // T is an Annotation type, the return value of get will be an annotation + return (T)mapAnnotations(getAnnotations()).get(annotationClass); } public T getDeclaredAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - return null; + return getAnnotation(annotationClass); } - @SuppressWarnings("unchecked") public T[] getAnnotations(Class annotationClass) { Objects.requireNonNull(annotationClass); - // safe because annotationClass is the class for T - return (T[])Array.newInstance(annotationClass, 0); + return AnnotationSupport.getMultipleAnnotations(mapAnnotations(getAnnotations()), annotationClass); } - @SuppressWarnings("unchecked") public T[] getDeclaredAnnotations(Class annotationClass) { Objects.requireNonNull(annotationClass); - // safe because annotationClass is the class for T - return (T[])Array.newInstance(annotationClass, 0); + return getAnnotations(annotationClass); } public Annotation[] getAnnotations() { - // Since zero-length, don't need defensive clone - return EMPTY_ANNOTATION_ARRAY; + int myIndex = typeVarIndex(); + if (myIndex < 0) + throw new AssertionError("Index must be non-negative."); + return TypeAnnotationParser.parseTypeVariableAnnotations(getGenericDeclaration(), myIndex); } public Annotation[] getDeclaredAnnotations() { - // Since zero-length, don't need defensive clone - return EMPTY_ANNOTATION_ARRAY; + return getAnnotations(); + } + + public AnnotatedType[] getAnnotatedBounds() { + return TypeAnnotationParser.parseAnnotatedBounds(getBounds(), + getGenericDeclaration(), + typeVarIndex()); } private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; + + // Helpers for annotation methods + private int typeVarIndex() { + TypeVariable[] tVars = getGenericDeclaration().getTypeParameters(); + int i = -1; + for (TypeVariable v : tVars) { + i++; + if (equals(v)) + return i; + } + return -1; + } + + private static Map, Annotation> mapAnnotations(Annotation[] annos) { + Map, Annotation> result = + new LinkedHashMap<>(); + for (Annotation a : annos) { + Class klass = a.annotationType(); + AnnotationType type = AnnotationType.getInstance(klass); + if (type.retention() == RetentionPolicy.RUNTIME) + if (result.put(klass, a) != null) + throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a); + } + return result; + } } diff --git a/jdk/src/share/javavm/export/jvm.h b/jdk/src/share/javavm/export/jvm.h index 28885cfb14d..56a8abb03cc 100644 --- a/jdk/src/share/javavm/export/jvm.h +++ b/jdk/src/share/javavm/export/jvm.h @@ -465,6 +465,12 @@ JVM_GetClassSignature(JNIEnv *env, jclass cls); JNIEXPORT jbyteArray JNICALL JVM_GetClassAnnotations(JNIEnv *env, jclass cls); +/* Type use annotations support (JDK 1.8) */ + +JNIEXPORT jbyteArray JNICALL +JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls); + + /* * New (JDK 1.4) reflection implementation */ diff --git a/jdk/src/share/native/java/lang/Class.c b/jdk/src/share/native/java/lang/Class.c index 3e595e726af..20d03060101 100644 --- a/jdk/src/share/native/java/lang/Class.c +++ b/jdk/src/share/native/java/lang/Class.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2010, 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 @@ -75,7 +75,8 @@ static JNINativeMethod methods[] = { {"getRawAnnotations", "()" BA, (void *)&JVM_GetClassAnnotations}, {"getConstantPool", "()" CPL, (void *)&JVM_GetClassConstantPool}, {"desiredAssertionStatus0","("CLS")Z",(void *)&JVM_DesiredAssertionStatus}, - {"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo} + {"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo}, + {"getRawTypeAnnotations", "()" BA, (void *)&JVM_GetClassTypeAnnotations}, }; #undef OBJ diff --git a/jdk/test/java/lang/annotation/TypeAnnotationReflection.java b/jdk/test/java/lang/annotation/TypeAnnotationReflection.java new file mode 100644 index 00000000000..b3aad9726a9 --- /dev/null +++ b/jdk/test/java/lang/annotation/TypeAnnotationReflection.java @@ -0,0 +1,428 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @bug 8004698 + * @summary Unit test for type annotations + */ + +import java.util.*; +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.io.Serializable; + +public class TypeAnnotationReflection { + public static void main(String[] args) throws Exception { + testSuper(); + testInterfaces(); + testReturnType(); + testNested(); + testArray(); + testRunException(); + testClassTypeVarBounds(); + testMethodTypeVarBounds(); + testFields(); + testClassTypeVar(); + testMethodTypeVar(); + testParameterizedType(); + testNestedParameterizedType(); + testWildcardType(); + } + + private static void check(boolean b) { + if (!b) + throw new RuntimeException(); + } + + private static void testSuper() throws Exception { + check(Object.class.getAnnotatedSuperclass().getAnnotations().length == 0); + check(Class.class.getAnnotatedSuperclass().getAnnotations().length == 0); + + AnnotatedType a; + a = TestClassArray.class.getAnnotatedSuperclass(); + Annotation[] annos = a.getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("extends")); + check(((TypeAnno2)annos[1]).value().equals("extends2")); + } + + private static void testInterfaces() throws Exception { + AnnotatedType[] as; + as = TestClassArray.class.getAnnotatedInterfaces(); + check(as.length == 3); + check(as[1].getAnnotations().length == 0); + + Annotation[] annos; + annos = as[0].getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("implements serializable")); + check(((TypeAnno2)annos[1]).value().equals("implements2 serializable")); + + annos = as[2].getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("implements cloneable")); + check(((TypeAnno2)annos[1]).value().equals("implements2 cloneable")); + } + + private static void testReturnType() throws Exception { + Method m = TestClassArray.class.getDeclaredMethod("foo", (Class[])null); + Annotation[] annos = m.getAnnotatedReturnType().getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("return1")); + } + + private static void testNested() throws Exception { + Method m = TestClassNested.class.getDeclaredMethod("foo", (Class[])null); + Annotation[] annos = m.getAnnotatedReturnType().getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("array")); + + AnnotatedType t = m.getAnnotatedReturnType(); + t = ((AnnotatedArrayType)t).getAnnotatedGenericComponentType(); + annos = t.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("Inner")); + } + + private static void testArray() throws Exception { + Method m = TestClassArray.class.getDeclaredMethod("foo", (Class[])null); + AnnotatedArrayType t = (AnnotatedArrayType) m.getAnnotatedReturnType(); + Annotation[] annos = t.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("return1")); + + t = (AnnotatedArrayType)t.getAnnotatedGenericComponentType(); + annos = t.getAnnotations(); + check(annos.length == 0); + + t = (AnnotatedArrayType)t.getAnnotatedGenericComponentType(); + annos = t.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("return3")); + + AnnotatedType tt = t.getAnnotatedGenericComponentType(); + check(!(tt instanceof AnnotatedArrayType)); + annos = tt.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("return4")); + } + + private static void testRunException() throws Exception { + Method m = TestClassException.class.getDeclaredMethod("foo", (Class[])null); + AnnotatedType[] ts = m.getAnnotatedExceptionTypes(); + check(ts.length == 3); + + AnnotatedType t; + Annotation[] annos; + t = ts[0]; + annos = t.getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("RE")); + check(((TypeAnno2)annos[1]).value().equals("RE2")); + + t = ts[1]; + annos = t.getAnnotations(); + check(annos.length == 0); + + t = ts[2]; + annos = t.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("AIOOBE")); + } + + private static void testClassTypeVarBounds() throws Exception { + Method m = TestClassTypeVarAndField.class.getDeclaredMethod("foo", (Class[])null); + AnnotatedType ret = m.getAnnotatedReturnType(); + Annotation[] annos = ret.getAnnotations(); + check(annos.length == 2); + + AnnotatedType[] annotatedBounds = ((AnnotatedTypeVariable)ret).getAnnotatedBounds(); + check(annotatedBounds.length == 2); + + annos = annotatedBounds[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("Object1")); + + annos = annotatedBounds[1].getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("Runnable1")); + check(((TypeAnno2)annos[1]).value().equals("Runnable2")); + } + + private static void testMethodTypeVarBounds() throws Exception { + Method m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo2", (Class[])null); + AnnotatedType ret2 = m2.getAnnotatedReturnType(); + AnnotatedType[] annotatedBounds2 = ((AnnotatedTypeVariable)ret2).getAnnotatedBounds(); + check(annotatedBounds2.length == 1); + + Annotation[] annos = annotatedBounds2[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("M Runnable")); + } + + private static void testFields() throws Exception { + Field f1 = TestClassTypeVarAndField.class.getDeclaredField("field1"); + AnnotatedType at; + Annotation[] annos; + + at = f1.getAnnotatedType(); + annos = at.getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("T1 field")); + check(((TypeAnno2)annos[1]).value().equals("T2 field")); + + Field f2 = TestClassTypeVarAndField.class.getDeclaredField("field2"); + at = f2.getAnnotatedType(); + annos = at.getAnnotations(); + check(annos.length == 0); + + Field f3 = TestClassTypeVarAndField.class.getDeclaredField("field3"); + at = f3.getAnnotatedType(); + annos = at.getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("Object field")); + } + + private static void testClassTypeVar() throws Exception { + TypeVariable[] typeVars = TestClassTypeVarAndField.class.getTypeParameters(); + Annotation[] annos; + check(typeVars.length == 2); + + // First TypeVar + AnnotatedType[] annotatedBounds = typeVars[0].getAnnotatedBounds(); + check(annotatedBounds.length == 2); + + annos = annotatedBounds[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("Object1")); + + annos = annotatedBounds[1].getAnnotations(); + check(annos.length == 2); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(annos[1].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno)annos[0]).value().equals("Runnable1")); + check(((TypeAnno2)annos[1]).value().equals("Runnable2")); + + // second TypeVar regular anno + Annotation[] regularAnnos = typeVars[1].getAnnotations(); + check(regularAnnos.length == 1); + check(typeVars[1].getAnnotation(TypeAnno.class).value().equals("EE")); + + // second TypeVar + annotatedBounds = typeVars[1].getAnnotatedBounds(); + check(annotatedBounds.length == 1); + + annos = annotatedBounds[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno2.class)); + check(((TypeAnno2)annos[0]).value().equals("EEBound")); + } + + private static void testMethodTypeVar() throws Exception { + Method m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo2", (Class[])null); + TypeVariable[] t = m2.getTypeParameters(); + check(t.length == 1); + Annotation[] annos = t[0].getAnnotations(); + check(annos.length == 0); + + AnnotatedType[] annotatedBounds2 = t[0].getAnnotatedBounds(); + check(annotatedBounds2.length == 1); + + annos = annotatedBounds2[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("M Runnable")); + + // Second method + m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo3", (Class[])null); + t = m2.getTypeParameters(); + check(t.length == 1); + annos = t[0].getAnnotations(); + check(annos.length == 1); + check(annos[0].annotationType().equals(TypeAnno.class)); + check(((TypeAnno)annos[0]).value().equals("K")); + + annotatedBounds2 = t[0].getAnnotatedBounds(); + check(annotatedBounds2.length == 1); + + annos = annotatedBounds2[0].getAnnotations(); + check(annos.length == 0); + } + + private static void testParameterizedType() { + // Base + AnnotatedType[] as; + as = TestParameterizedType.class.getAnnotatedInterfaces(); + check(as.length == 1); + check(as[0].getAnnotations().length == 1); + check(as[0].getAnnotation(TypeAnno.class).value().equals("M")); + + Annotation[] annos; + as = ((AnnotatedParameterizedType)as[0]).getAnnotatedActualTypeArguments(); + check(as.length == 2); + annos = as[0].getAnnotations(); + check(annos.length == 1); + check(as[0].getAnnotation(TypeAnno.class).value().equals("S")); + check(as[0].getAnnotation(TypeAnno2.class) == null); + + annos = as[1].getAnnotations(); + check(annos.length == 2); + check(((TypeAnno)annos[0]).value().equals("I")); + check(as[1].getAnnotation(TypeAnno2.class).value().equals("I2")); + } + + private static void testNestedParameterizedType() throws Exception { + Method m = TestParameterizedType.class.getDeclaredMethod("foo2", (Class[])null); + AnnotatedType ret = m.getAnnotatedReturnType(); + Annotation[] annos; + annos = ret.getAnnotations(); + check(annos.length == 1); + check(((TypeAnno)annos[0]).value().equals("I")); + + AnnotatedType[] args = ((AnnotatedParameterizedType)ret).getAnnotatedActualTypeArguments(); + check(args.length == 1); + annos = args[0].getAnnotations(); + check(annos.length == 2); + check(((TypeAnno)annos[0]).value().equals("I1")); + check(args[0].getAnnotation(TypeAnno2.class).value().equals("I2")); + } + + private static void testWildcardType() throws Exception { + Method m = TestWildcardType.class.getDeclaredMethod("foo", (Class[])null); + AnnotatedType ret = m.getAnnotatedReturnType(); + AnnotatedType[] t; + t = ((AnnotatedParameterizedType)ret).getAnnotatedActualTypeArguments(); + check(t.length == 1); + ret = t[0]; + + Field f = TestWildcardType.class.getDeclaredField("f1"); + AnnotatedWildcardType w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f + .getAnnotatedType()).getAnnotatedActualTypeArguments()[0]; + t = w.getAnnotatedLowerBounds(); + check(t.length == 0); + t = w.getAnnotatedUpperBounds(); + check(t.length == 1); + Annotation[] annos; + annos = t[0].getAnnotations(); + check(annos.length == 1); + check(((TypeAnno)annos[0]).value().equals("2")); + + f = TestWildcardType.class.getDeclaredField("f2"); + w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f + .getAnnotatedType()).getAnnotatedActualTypeArguments()[0]; + t = w.getAnnotatedUpperBounds(); + check(t.length == 0); + t = w.getAnnotatedLowerBounds(); + check(t.length == 1); + } +} + +abstract class TestWildcardType { + public List foo() { return null;} + public Class<@TypeAnno("1") ? extends @TypeAnno("2") Annotation> f1; + public Class<@TypeAnno("3") ? super @TypeAnno("4") Annotation> f2; +} + +abstract class TestParameterizedType implements @TypeAnno("M") Map<@TypeAnno("S")String, @TypeAnno("I") @TypeAnno2("I2")Integer> { + public ParameterizedOuter.ParameterizedInner foo() {return null;} + public @TypeAnno("O") ParameterizedOuter<@TypeAnno("S1") @TypeAnno2("S2") String>. + @TypeAnno("I") ParameterizedInner<@TypeAnno("I1") @TypeAnno2("I2")Integer> foo2() { + return null; + } +} + +class ParameterizedOuter { + class ParameterizedInner {} +} + +abstract class TestClassArray extends @TypeAnno("extends") @TypeAnno2("extends2") Object + implements @TypeAnno("implements serializable") @TypeAnno2("implements2 serializable") Serializable, + Readable, + @TypeAnno("implements cloneable") @TypeAnno2("implements2 cloneable") Cloneable { + public @TypeAnno("return4") Object @TypeAnno("return1") [][] @TypeAnno("return3")[] foo() { return null; } +} + +abstract class TestClassNested { + public @TypeAnno("Outer") Outer.@TypeAnno("Inner")Inner @TypeAnno("array")[] foo() { return null; } +} + +class Outer { + class Inner { + } +} + +abstract class TestClassException { + public Object foo() throws @TypeAnno("RE") @TypeAnno2("RE2") RuntimeException, + NullPointerException, + @TypeAnno("AIOOBE") ArrayIndexOutOfBoundsException { + return null; + } +} + +abstract class TestClassTypeVarAndField { + @TypeAnno("T1 field") @TypeAnno2("T2 field") T field1; + T field2; + @TypeAnno("Object field") Object field3; + + public @TypeAnno("t1") @TypeAnno2("t2") T foo(){ return null; } + public M foo2() {return null;} + public <@TypeAnno("K") K extends Cloneable> K foo3() {return null;} +} + +@Target(ElementType.TYPE_USE) +@Retention(RetentionPolicy.RUNTIME) +@interface TypeAnno { + String value(); +} + +@Target(ElementType.TYPE_USE) +@Retention(RetentionPolicy.RUNTIME) +@interface TypeAnno2 { + String value(); +} diff --git a/jdk/test/java/lang/annotation/TypeParamAnnotation.java b/jdk/test/java/lang/annotation/TypeParamAnnotation.java new file mode 100644 index 00000000000..50457ec46b1 --- /dev/null +++ b/jdk/test/java/lang/annotation/TypeParamAnnotation.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @bug 8004698 + * @summary Unit test for annotations on TypeVariables + */ + +import java.util.*; +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.io.Serializable; + +public class TypeParamAnnotation { + public static void main(String[] args) throws Exception { + testOnClass(); + testOnMethod(); + testGetAnno(); + testGetAnnos(); + } + + private static void check(boolean b) { + if (!b) + throw new RuntimeException(); + } + + private static void testOnClass() { + TypeVariable[] ts = TypeParam.class.getTypeParameters(); + check(ts.length == 3); + + Annotation[] as; + + as = ts[0].getAnnotations(); + check(as.length == 2); + check(((ParamAnno)as[0]).value().equals("t")); + check(((ParamAnno2)as[1]).value() == 1); + + as = ts[1].getAnnotations(); + check(as.length == 0); + + as = ts[2].getAnnotations(); + check(as.length == 2); + check(((ParamAnno)as[0]).value().equals("v")); + check(((ParamAnno2)as[1]).value() == 2); + } + private static void testOnMethod() throws Exception { + TypeVariable[] ts = TypeParam.class.getDeclaredMethod("foo").getTypeParameters(); + check(ts.length == 3); + + Annotation[] as; + + as = ts[0].getAnnotations(); + check(as.length == 2); + check(((ParamAnno)as[0]).value().equals("x")); + check(((ParamAnno2)as[1]).value() == 3); + + as = ts[1].getAnnotations(); + check(as.length == 0); + + as = ts[2].getAnnotations(); + check(as.length == 2); + check(((ParamAnno)as[0]).value().equals("z")); + check(((ParamAnno2)as[1]).value() == 4); + } + + private static void testGetAnno() { + TypeVariable[] ts = TypeParam.class.getTypeParameters(); + ParamAnno a; + a = ts[0].getAnnotation(ParamAnno.class); + check(a.value().equals("t")); + } + private static void testGetAnnos() throws Exception { + TypeVariable[] ts = TypeParam.class.getDeclaredMethod("foo").getTypeParameters(); + ParamAnno2[] as; + as = ts[0].getAnnotations(ParamAnno2.class); + check(as.length == 1); + check(as[0].value() == 3); + } +} + +class TypeParam <@ParamAnno("t") @ParamAnno2(1) T, + U, + @ParamAnno("v") @ParamAnno2(2) V extends Runnable> { + public <@ParamAnno("x") @ParamAnno2(3) X, + Y, + @ParamAnno("z") @ParamAnno2(4) Z extends Cloneable> void foo() {} +} + +@Target(ElementType.TYPE_PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@interface ParamAnno { + String value(); +} + +@Target(ElementType.TYPE_PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@interface ParamAnno2 { + int value(); +} From e8860a177b428810f30ffcfe911a22bb717239f5 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Tue, 29 Jan 2013 10:51:33 +0100 Subject: [PATCH 020/158] 8004710: NPG: jmap could throw sun.jvm.hotspot.types.WrongTypeException after PermGen removal When calculating live object regions, make sure that the alignment reserve, at the end of a TLAB, is excluded. Reviewed-by: jmasa, brutisso --- .../sun/jvm/hotspot/oops/ObjectHeap.java | 2 +- .../runtime/ThreadLocalAllocBuffer.java | 20 ++++++++++++++++--- .../classes/sun/jvm/hotspot/runtime/VM.java | 9 +++++++++ hotspot/src/share/vm/runtime/vmStructs.cpp | 1 + 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java index 59923078d3d..f944188f4d1 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java @@ -467,7 +467,7 @@ public class ObjectHeap { liveRegions.add(tlab.start()); liveRegions.add(tlab.start()); liveRegions.add(tlab.top()); - liveRegions.add(tlab.end()); + liveRegions.add(tlab.hardEnd()); } } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java index 381b53deded..738dc94fa91 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java @@ -27,6 +27,7 @@ package sun.jvm.hotspot.runtime; import java.io.*; import java.util.*; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.types.*; /**

ThreadLocalAllocBuffer: a descriptor for thread-local storage @@ -62,9 +63,22 @@ public class ThreadLocalAllocBuffer extends VMObject { super(addr); } - public Address start() { return startField.getValue(addr); } - public Address end() { return endField.getValue(addr); } - public Address top() { return topField.getValue(addr); } + public Address start() { return startField.getValue(addr); } + public Address end() { return endField.getValue(addr); } + public Address top() { return topField.getValue(addr); } + public Address hardEnd() { return end().addOffsetTo(alignmentReserve()); } + + private long alignmentReserve() { + return Oop.alignObjectSize(endReserve()); + } + + private long endReserve() { + long minFillerArraySize = Array.baseOffsetInBytes(BasicType.T_INT); + long reserveForAllocationPrefetch = VM.getVM().getReserveForAllocationPrefetch(); + long heapWordSize = VM.getVM().getHeapWordSize(); + + return Math.max(minFillerArraySize, reserveForAllocationPrefetch * heapWordSize); + } /** Support for iteration over heap -- not sure how this will interact with GC in reflective system, but necessary for the diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java index 5531980b1f8..80464a10bb0 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -114,6 +114,7 @@ public class VM { private int invalidOSREntryBCI; private ReversePtrs revPtrs; private VMRegImpl vmregImpl; + private int reserveForAllocationPrefetch; // System.getProperties from debuggee VM private Properties sysProps; @@ -293,6 +294,10 @@ public class VM { vmRelease = CStringUtilities.getString(releaseAddr); Address vmInternalInfoAddr = vmVersion.getAddressField("_s_internal_vm_info_string").getValue(); vmInternalInfo = CStringUtilities.getString(vmInternalInfoAddr); + + CIntegerType intType = (CIntegerType) db.lookupType("int"); + CIntegerField reserveForAllocationPrefetchField = vmVersion.getCIntegerField("_reserve_for_allocation_prefetch"); + reserveForAllocationPrefetch = (int)reserveForAllocationPrefetchField.getCInteger(intType); } catch (Exception exp) { throw new RuntimeException("can't determine target's VM version : " + exp.getMessage()); } @@ -778,6 +783,10 @@ public class VM { return vmInternalInfo; } + public int getReserveForAllocationPrefetch() { + return reserveForAllocationPrefetch; + } + public boolean isSharingEnabled() { if (sharingEnabled == null) { Flag flag = getCommandLineFlag("UseSharedSpaces"); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 70e5d2b9281..1a30f7554e7 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -1161,6 +1161,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; static_field(Abstract_VM_Version, _vm_major_version, int) \ static_field(Abstract_VM_Version, _vm_minor_version, int) \ static_field(Abstract_VM_Version, _vm_build_number, int) \ + static_field(Abstract_VM_Version, _reserve_for_allocation_prefetch, int) \ \ static_field(JDK_Version, _current, JDK_Version) \ nonstatic_field(JDK_Version, _partially_initialized, bool) \ From ebc0ebf54d6e83f2b609ec0bccf9dcfd89ab28b0 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 30 Jan 2013 09:40:54 -0800 Subject: [PATCH 021/158] 8007096: DocLint parsing problems with some comments Reviewed-by: mcimadamore --- .../tools/javac/parser/DocCommentParser.java | 86 +++++++------------ .../tools/javac/parser/JavadocTokenizer.java | 4 +- .../tools/doclint/EndWithIdentifierTest.java | 32 +++++++ .../tools/doclint/EndWithIdentifierTest.out | 20 +++++ .../doclint/UnfinishedInlineTagTest.java | 17 ++++ .../tools/doclint/UnfinishedInlineTagTest.out | 5 ++ 6 files changed, 108 insertions(+), 56 deletions(-) create mode 100644 langtools/test/tools/doclint/EndWithIdentifierTest.java create mode 100644 langtools/test/tools/doclint/EndWithIdentifierTest.out create mode 100644 langtools/test/tools/doclint/UnfinishedInlineTagTest.java create mode 100644 langtools/test/tools/doclint/UnfinishedInlineTagTest.out diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java index 989e42d066e..bbc4d81d5c7 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -279,13 +279,7 @@ public class DocCommentParser { try { nextChar(); if (isIdentifierStart(ch)) { - int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; - - Name name = names.fromChars(buf, namePos, nameLen); + Name name = readIdentifier(); TagParser tp = tagParsers.get(name); if (tp == null) { List content = blockContent(); @@ -334,14 +328,9 @@ public class DocCommentParser { try { nextChar(); if (isIdentifierStart(ch)) { - int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; + Name name = readIdentifier(); skipWhitespace(); - Name name = names.fromChars(buf, namePos, nameLen); TagParser tp = tagParsers.get(name); if (tp == null) { DCTree text = inlineText(); @@ -575,10 +564,8 @@ public class DocCommentParser { int pos = bp; if (isJavaIdentifierStart(ch)) { - nextChar(); - while (isJavaIdentifierPart(ch)) - nextChar(); - return m.at(pos).Identifier(names.fromChars(buf, pos, bp - pos)); + Name name = readJavaIdentifier(); + return m.at(pos).Identifier(name); } throw new ParseException("dc.identifier.expected"); @@ -703,39 +690,36 @@ public class DocCommentParser { protected DCTree entity() { int p = bp; nextChar(); - int namep = bp; + Name name = null; boolean checkSemi = false; if (ch == '#') { + int namep = bp; nextChar(); if (isDecimalDigit(ch)) { nextChar(); while (isDecimalDigit(ch)) nextChar(); - checkSemi = true; + name = names.fromChars(buf, namep, bp - namep); } else if (ch == 'x' || ch == 'X') { nextChar(); if (isHexDigit(ch)) { nextChar(); while (isHexDigit(ch)) nextChar(); - checkSemi = true; + name = names.fromChars(buf, namep, bp - namep); } } } else if (isIdentifierStart(ch)) { - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - checkSemi = true; + name = readIdentifier(); } - if (checkSemi && ch == ';') { + if (name == null) + return erroneous("dc.bad.entity", p); + else { + if (ch != ';') + return erroneous("dc.missing.semicolon", p); nextChar(); - return m.at(p).Entity(names.fromChars(buf, namep, bp - namep - 1)); - } else { - String code = checkSemi - ? "dc.missing.semicolon" - : "dc.bad.entity"; - return erroneous(code, p); + return m.at(p).Entity(name); } } @@ -747,11 +731,7 @@ public class DocCommentParser { int p = bp; nextChar(); if (isIdentifierStart(ch)) { - int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; + Name name = readIdentifier(); List attrs = htmlAttrs(); if (attrs != null) { boolean selfClosing = false; @@ -761,22 +741,16 @@ public class DocCommentParser { } if (ch == '>') { nextChar(); - Name name = names.fromChars(buf, namePos, nameLen); return m.at(p).StartElement(name, attrs, selfClosing); } } } else if (ch == '/') { nextChar(); if (isIdentifierStart(ch)) { - int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; + Name name = readIdentifier(); skipWhitespace(); if (ch == '>') { nextChar(); - Name name = names.fromChars(buf, namePos, nameLen); return m.at(p).EndElement(name); } } @@ -822,10 +796,7 @@ public class DocCommentParser { loop: while (isIdentifierStart(ch)) { int namePos = bp; - nextChar(); - while (isIdentifierPart(ch)) - nextChar(); - int nameLen = bp - namePos; + Name name = readIdentifier(); skipWhitespace(); List value = null; ValueKind vkind = ValueKind.EMPTY; @@ -862,7 +833,6 @@ public class DocCommentParser { skipWhitespace(); value = v.toList(); } - Name name = names.fromChars(buf, namePos, nameLen); DCAttribute attr = m.at(namePos).Attribute(name, vkind, value); attrs.add(attr); } @@ -897,7 +867,7 @@ public class DocCommentParser { protected DCErroneous erroneous(String code, int pos) { int i = bp - 1; loop: - while (i > 0) { + while (i > pos) { switch (buf[i]) { case '\f': case '\n': case '\r': newline = true; @@ -926,16 +896,24 @@ public class DocCommentParser { return Character.isUnicodeIdentifierStart(ch); } - protected boolean isIdentifierPart(char ch) { - return Character.isUnicodeIdentifierPart(ch); + protected Name readIdentifier() { + int start = bp; + nextChar(); + while (bp < buflen && Character.isUnicodeIdentifierPart(ch)) + nextChar(); + return names.fromChars(buf, start, bp - start); } protected boolean isJavaIdentifierStart(char ch) { return Character.isJavaIdentifierStart(ch); } - protected boolean isJavaIdentifierPart(char ch) { - return Character.isJavaIdentifierPart(ch); + protected Name readJavaIdentifier() { + int start = bp; + nextChar(); + while (bp < buflen && Character.isJavaIdentifierPart(ch)) + nextChar(); + return names.fromChars(buf, start, bp - start); } protected boolean isDecimalDigit(char ch) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java index d52a62ef704..847a42b17c8 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -236,7 +236,7 @@ public class JavadocTokenizer extends JavaTokenizer { // relative to the best match found in the array. if (pos == Position.NOPOS) return Position.NOPOS; - if (pos < 0 || pos >= docComment.length()) + if (pos < 0 || pos > docComment.length()) throw new StringIndexOutOfBoundsException(String.valueOf(pos)); if (docPosns == null) return Position.NOPOS; diff --git a/langtools/test/tools/doclint/EndWithIdentifierTest.java b/langtools/test/tools/doclint/EndWithIdentifierTest.java new file mode 100644 index 00000000000..afd20a3353c --- /dev/null +++ b/langtools/test/tools/doclint/EndWithIdentifierTest.java @@ -0,0 +1,32 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8007096 + * @summary DocLint parsing problems with some comments + * @build DocLintTester + * @run main DocLintTester -Xmsgs:-html EndWithIdentifierTest.java + * @run main DocLintTester -Xmsgs -ref EndWithIdentifierTest.out EndWithIdentifierTest.java + * @author jlahoda + */ + +/**@deprecated*/ +public class EndWithIdentifierTest { + + /**{@link*/ + private void unfinishedInlineTagName() {} + + /**@see List*/ + private void endsWithIdentifier() {} + + /**&*/ + private void entityName() {} + + /** Date: Wed, 30 Jan 2013 09:47:12 -0800 Subject: [PATCH 022/158] 8007034: debug printer for javac internals Reviewed-by: mcimadamore --- langtools/test/tools/javac/lib/DPrinter.java | 1326 ++++++++++++++++++ 1 file changed, 1326 insertions(+) create mode 100644 langtools/test/tools/javac/lib/DPrinter.java diff --git a/langtools/test/tools/javac/lib/DPrinter.java b/langtools/test/tools/javac/lib/DPrinter.java new file mode 100644 index 00000000000..e05b9a8ad16 --- /dev/null +++ b/langtools/test/tools/javac/lib/DPrinter.java @@ -0,0 +1,1326 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import javax.lang.model.element.Name; +import javax.lang.model.element.TypeElement; +import javax.tools.FileObject; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.source.util.Trees; +import com.sun.tools.javac.api.JavacTrees; +import com.sun.tools.javac.code.Annotations; +import com.sun.tools.javac.code.Attribute; +import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Kinds; +import com.sun.tools.javac.code.Printer; +import com.sun.tools.javac.code.Scope; +import com.sun.tools.javac.code.Scope.CompoundScope; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.code.Type.*; +import com.sun.tools.javac.code.TypeTag; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.tree.Pretty; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Assert; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Log; + + +/** + * Debug printer for javac internals, for when toString() just isn't enough. + * + *

+ * The printer provides an API to generate structured views of javac objects, + * such as AST nodes, symbol, types and annotations. Various aspects of the + * output can be configured, such as whether to show nulls, empty lists, or + * a compressed representation of the source code. Visitors are used to walk + * object hierarchies, and can be replaced with custom visitors if the default + * visitors are not flexible enough. + * + *

+ * In general, nodes are printed with an initial line identifying the node + * followed by indented lines for the child nodes. Currently, graphs are + * represented by printing a spanning subtree. + * + *

+ * The printer can be accessed via a simple command-line utility, + * which makes it easy to see the internal representation of source code, + * such as simple test programs, during the compilation pipeline. + * + *

An annotation A is directly present on an element E if the + * RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations attribute + * associated with E either: + *

+ * + *

An annotation A is present on an element E if either: + *

    + *
  • A is directly present on E; or + *
  • There are no annotations of A's type which are directly present + * on E, and E is a class, and A's type is inheritable (JLS 9.6.3.3), and A is + * present on the superclass of E + *
+ * *

If an annotation returned by a method in this interface contains * (directly or indirectly) a {@link Class}-valued member referring to * a class that is not accessible in this VM, attempting to read the class @@ -50,7 +68,7 @@ import java.lang.annotation.Annotation; * containing annotation type of T will result in an * InvalidContainerAnnotationError. * - *

Finally, Attempting to read a member whose definition has evolved + *

Finally, attempting to read a member whose definition has evolved * incompatibly will result in a {@link * java.lang.annotation.AnnotationTypeMismatchException} or an * {@link java.lang.annotation.IncompleteAnnotationException}. @@ -70,6 +88,9 @@ public interface AnnotatedElement { * is present on this element, else false. This method * is designed primarily for convenient access to marker annotations. * + *

The truth value returned by this method is equivalent to: + * {@code getAnnotation(annotationClass) != null} + * * @param annotationClass the Class object corresponding to the * annotation type * @return true if an annotation for the specified annotation @@ -110,12 +131,15 @@ public interface AnnotatedElement { T[] getAnnotations(Class annotationClass); /** - * Returns all annotations present on this element. (Returns an array - * of length zero if this element has no annotations.) The caller of - * this method is free to modify the returned array; it will have no - * effect on the arrays returned to other callers. + * Returns annotations that are present on this element. * - * @return all annotations present on this element + * If there are no annotations present on this element, the return + * value is an array of length 0. + * + * The caller of this method is free to modify the returned array; it will + * have no effect on the arrays returned to other callers. + * + * @return annotations present on this element * @since 1.5 */ Annotation[] getAnnotations(); @@ -157,14 +181,16 @@ public interface AnnotatedElement { T[] getDeclaredAnnotations(Class annotationClass); /** - * Returns all annotations that are directly present on this - * element. This method ignores inherited annotations. (Returns - * an array of length zero if no annotations are directly present - * on this element.) The caller of this method is free to modify - * the returned array; it will have no effect on the arrays - * returned to other callers. + * Returns annotations that are directly present on this element. + * This method ignores inherited annotations. * - * @return All annotations directly present on this element + * If there are no annotations directly present on this element, + * the return value is an array of length 0. + * + * The caller of this method is free to modify the returned array; it will + * have no effect on the arrays returned to other callers. + * + * @return annotations directly present on this element * @since 1.5 */ Annotation[] getDeclaredAnnotations(); diff --git a/jdk/src/share/classes/java/lang/reflect/Executable.java b/jdk/src/share/classes/java/lang/reflect/Executable.java index b9ed7310a4d..ad1a5808632 100644 --- a/jdk/src/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java @@ -26,7 +26,6 @@ package java.lang.reflect; import java.lang.annotation.*; -import java.util.Collections; import java.util.Map; import java.util.Objects; import sun.reflect.annotation.AnnotationParser; @@ -438,8 +437,7 @@ public abstract class Executable extends AccessibleObject */ public T getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - - return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass); + return annotationClass.cast(declaredAnnotations().get(annotationClass)); } /** @@ -457,7 +455,7 @@ public abstract class Executable extends AccessibleObject * {@inheritDoc} */ public Annotation[] getDeclaredAnnotations() { - return AnnotationSupport.unpackToArray(declaredAnnotations()); + return AnnotationParser.toArray(declaredAnnotations()); } private transient Map, Annotation> declaredAnnotations; diff --git a/jdk/src/share/classes/java/lang/reflect/Field.java b/jdk/src/share/classes/java/lang/reflect/Field.java index d2502efb4dd..df38832eb15 100644 --- a/jdk/src/share/classes/java/lang/reflect/Field.java +++ b/jdk/src/share/classes/java/lang/reflect/Field.java @@ -1021,8 +1021,7 @@ class Field extends AccessibleObject implements Member { */ public T getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - - return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass); + return annotationClass.cast(declaredAnnotations().get(annotationClass)); } /** @@ -1040,7 +1039,7 @@ class Field extends AccessibleObject implements Member { * {@inheritDoc} */ public Annotation[] getDeclaredAnnotations() { - return AnnotationSupport.unpackToArray(declaredAnnotations()); + return AnnotationParser.toArray(declaredAnnotations()); } private transient Map, Annotation> declaredAnnotations; diff --git a/jdk/src/share/classes/java/lang/reflect/Parameter.java b/jdk/src/share/classes/java/lang/reflect/Parameter.java index 6eed6926be0..4fda579c5fc 100644 --- a/jdk/src/share/classes/java/lang/reflect/Parameter.java +++ b/jdk/src/share/classes/java/lang/reflect/Parameter.java @@ -233,8 +233,7 @@ public final class Parameter implements AnnotatedElement { */ public T getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - - return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass); + return annotationClass.cast(declaredAnnotations().get(annotationClass)); } /** diff --git a/jdk/src/share/classes/sun/misc/JavaLangAccess.java b/jdk/src/share/classes/sun/misc/JavaLangAccess.java index 1624d67f4a9..db8d8213179 100644 --- a/jdk/src/share/classes/sun/misc/JavaLangAccess.java +++ b/jdk/src/share/classes/sun/misc/JavaLangAccess.java @@ -97,9 +97,4 @@ public interface JavaLangAccess { * Returns the ith StackTraceElement for the given throwable. */ StackTraceElement getStackTraceElement(Throwable t, int i); - - /** - * Returns a directly present annotation. - */ - public A getDirectDeclaredAnnotation(Class klass, Class anno); } diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java index 3046792b161..5ca88f90202 100644 --- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -27,63 +27,29 @@ package sun.reflect.annotation; import java.lang.annotation.*; import java.lang.reflect.*; -import java.util.Arrays; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Objects; -import sun.reflect.Reflection; -import sun.misc.JavaLangAccess; public final class AnnotationSupport { - private static final JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess(); - - /** - * Finds and returns _one_ annotation of the type indicated by - * {@code annotationClass} from the {@code Map} {@code - * annotationMap}. Looks into containers of the {@code - * annotationClass} (as specified by an the {@code - * annotationClass} type being meta-annotated with an {@code - * ContainedBy} annotation). - * - * @param annotationMap the {@code Map} used to store annotations and indexed by their type - * @param annotationClass the type of annotation to search for - * - * @return in instance of {@code annotationClass} or {@code null} if none were found - */ - public static A getOneAnnotation(final Map, Annotation> annotationMap, - final Class annotationClass) { - @SuppressWarnings("unchecked") - final A candidate = (A)annotationMap.get(annotationClass); - if (candidate != null) { - return candidate; - } - - final Class containerClass = getContainer(annotationClass); - if (containerClass != null) { - return unpackOne(annotationMap.get(containerClass), annotationClass); - } - - return null; // found none - } - /** * Finds and returns all annotation of the type indicated by * {@code annotationClass} from the {@code Map} {@code * annotationMap}. Looks into containers of the {@code * annotationClass} (as specified by an the {@code * annotationClass} type being meta-annotated with an {@code - * ContainedBy} annotation). + * Repeatable} annotation). * * @param annotationMap the {@code Map} used to store annotations indexed by their type * @param annotationClass the type of annotation to search for * * @return an array of instances of {@code annotationClass} or an empty array if none were found */ - public static A[] getMultipleAnnotations(final Map, Annotation> annotationMap, - final Class annotationClass) { - final ArrayList res = new ArrayList(); + public static A[] getMultipleAnnotations( + final Map, Annotation> annotationMap, + final Class annotationClass) { + final List res = new ArrayList(); @SuppressWarnings("unchecked") final A candidate = (A)annotationMap.get(annotationClass); @@ -101,49 +67,10 @@ public final class AnnotationSupport { return res.isEmpty() ? emptyTemplateArray : res.toArray(emptyTemplateArray); } - /** - * Unpacks the {@code annotationMap} parameter into an array of - * {@code Annotation}s. This method will unpack all repeating - * annotations containers (once). An annotation type is marked as a - * container by meta-annotating it the with the {@code - * ContainerFor} annotation. - * - * @param annotationMap the {@code Map} from where the annotations are unpacked - * - * @return an array of Annotation - */ - public static Annotation[] unpackToArray(Map, Annotation> annotationMap) { - List res = new ArrayList<>(); - for (Map.Entry, Annotation> e : annotationMap.entrySet()) { - Class annotationClass = e.getKey(); - Annotation annotationInstance = e.getValue(); - Class containee = getContainee(e.getKey()); - boolean isContainer = javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class) != null; - - if (isContainer) { - res.addAll(unpackAll(annotationInstance, containee)); - } else { - res.add(annotationInstance); - } - } - - return res.isEmpty() - ? AnnotationParser.getEmptyAnnotationArray() - : res.toArray(AnnotationParser.getEmptyAnnotationArray()); - } - /** Helper to get the container, or null if none, of an annotation. */ private static Class getContainer(Class annotationClass) { - ContainedBy containerAnnotation = - javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainedBy.class); - return (containerAnnotation == null) ? null : containerAnnotation.value(); - } - - /** Helper to get the containee, or null if this isn't a container, of a possible container annotation. */ - private static Class getContainee(Class annotationClass) { - ContainerFor containerAnnotation = - javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class); - return (containerAnnotation == null) ? null : containerAnnotation.value(); + Repeatable containingAnnotation = annotationClass.getDeclaredAnnotation(Repeatable.class); + return (containingAnnotation == null) ? null : containingAnnotation.value(); } /** Reflectively look up and get the returned array from the the @@ -156,14 +83,15 @@ public final class AnnotationSupport { // value element. Get the AnnotationType, get the "value" element // and invoke it to get the contents. - Class containerClass = containerInstance.annotationType(); - AnnotationType annoType = javaLangAccess.getAnnotationType(containerClass); + Class containerClass = containerInstance.annotationType(); + AnnotationType annoType = AnnotationType.getInstance(containerClass); if (annoType == null) throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations"); Method m = annoType.members().get("value"); if (m == null) - throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations"); + throw new InvalidContainerAnnotationError(containerInstance + + " is an invalid container for repeating annotations"); m.setAccessible(true); @SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException @@ -175,32 +103,11 @@ public final class AnnotationSupport { IllegalArgumentException | // parameters doesn't match InvocationTargetException | // the value method threw an exception ClassCastException e) { // well, a cast failed ... - throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations", - e, - containerInstance, - null); - } - } - - /* Sanity check type of and return the first annotation instance - * of type {@code annotationClass} from {@code - * containerInstance}. - */ - private static A unpackOne(Annotation containerInstance, Class annotationClass) { - if (containerInstance == null) { - return null; - } - - try { - return annotationClass.cast(getValueArray(containerInstance)[0]); - } catch (ArrayIndexOutOfBoundsException | // empty array - ClassCastException | // well, a cast failed ... - NullPointerException e) { // can this NP? for good meassure - throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s", - containerInstance, annotationClass), - e, - containerInstance, - annotationClass); + throw new InvalidContainerAnnotationError( + containerInstance + " is an invalid container for repeating annotations", + e, + containerInstance, + null); } } @@ -208,24 +115,26 @@ public final class AnnotationSupport { * instances of type {@code annotationClass} from {@code * containerInstance}. */ - private static List unpackAll(Annotation containerInstance, Class annotationClass) { + private static List unpackAll(Annotation containerInstance, + Class annotationClass) { if (containerInstance == null) { return Collections.emptyList(); // container not present } try { A[] a = getValueArray(containerInstance); - ArrayList l = new ArrayList<>(a.length); + List l = new ArrayList<>(a.length); for (int i = 0; i < a.length; i++) l.add(annotationClass.cast(a[i])); return l; } catch (ClassCastException | NullPointerException e) { - throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s", - containerInstance, annotationClass), - e, - containerInstance, - annotationClass); + throw new InvalidContainerAnnotationError( + String.format("%s is an invalid container for repeating annotations of type: %s", + containerInstance, annotationClass), + e, + containerInstance, + annotationClass); } } } diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java b/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java index 0d9cb59d1c4..10e3d746261 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 7154390 + * @bug 7154390 8005712 * @summary Unit test for repeated annotation reflection * * @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java @@ -58,7 +58,7 @@ public class RepeatedUnitTest { checkMultiplier(Me1.class.getField("foo"), 1); // METHOD - checkMultiplier(Me1.class.getDeclaredMethod("mee", null), 100); + checkMultiplier(Me1.class.getDeclaredMethod("mee", (Class[])null), 100); // INNER CLASS checkMultiplier(Me1.MiniMee.class, 1000); @@ -84,8 +84,7 @@ public class RepeatedUnitTest { static void packageRepeated(AnnotatedElement e) { Containee c = e.getAnnotation(Containee.class); - check(c.value() == 1); - + check(c == null); check(2 == countAnnotation(e, Containee.class)); c = e.getAnnotations(Containee.class)[0]; @@ -93,7 +92,7 @@ public class RepeatedUnitTest { c = e.getAnnotations(Containee.class)[1]; check(c.value() == 2); - check(2 == containsAnnotationOfType(e.getAnnotations(), Containee.class)); + check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class)); } static void packageContainer(AnnotatedElement e) { @@ -161,14 +160,26 @@ public class RepeatedUnitTest { } static void checkMultiplier(AnnotatedElement e, int m) { + // Basic sanity of non-repeating getAnnotation(Class) check(e.getAnnotation(NonRepeated.class).value() == 5 * m); + // Check count of annotations returned from getAnnotations(Class) check(4 == countAnnotation(e, Containee.class)); check(1 == countAnnotation(e, Container.class)); check(1 == countAnnotation(e, NonRepeated.class)); + // Check contents of array returned from getAnnotations(Class) check(e.getAnnotations(Containee.class)[2].value() == 3 * m); check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m); + + // Check getAnnotation(Class) + check(e.getAnnotation(Containee.class) == null); + check(e.getAnnotation(Container.class) != null); + + // Check count of annotations returned from getAnnotations() + check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class)); + check(1 == containsAnnotationOfType(e.getAnnotations(), Container.class)); + check(1 == containsAnnotationOfType(e.getAnnotations(), NonRepeated.class)); } static void check(Boolean b) { diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java index c977b2e5c2d..cca790696d6 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -26,7 +26,6 @@ package subpackage; import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(Container.class) @Repeatable(Container.class) public @interface Containee { int value(); diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java index e8e2f05ab55..f4d370b7add 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -26,7 +26,6 @@ package subpackage; import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@ContainerFor(Containee.class) public @interface Container { Containee[] value(); } diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java index 080d12ce3f5..37f44932a86 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -27,7 +27,6 @@ import java.lang.annotation.*; @Inherited @Retention(RetentionPolicy.RUNTIME) -@ContainedBy(InheritedContainer.class) @Repeatable(InheritedContainer.class) public @interface InheritedContainee { int value(); diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java index a66af4f6ed8..bff3082520e 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -27,7 +27,6 @@ import java.lang.annotation.*; @Inherited @Retention(RetentionPolicy.RUNTIME) -@ContainerFor(InheritedContainee.class) public @interface InheritedContainer { InheritedContainee[] value(); } From 9f5b40123d77bd6327c01f5aa16734d88107d7db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Thu, 31 Jan 2013 14:00:09 +0100 Subject: [PATCH 024/158] 8006872: Stop creating four jars with identical content in the new build system Reviewed-by: erikj --- common/autoconf/spec.gmk.in | 6 ++++++ common/makefiles/JavaCompilation.gmk | 12 ++++++------ common/makefiles/javadoc/Javadoc.gmk | 9 +++------ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 5fde9e7cf16..ad882958d9d 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -434,6 +434,12 @@ NATIVE2ASCII=@FIXPATH@ $(BOOT_JDK)/bin/native2ascii JARSIGNER=@FIXPATH@ $(BOOT_JDK)/bin/jarsigner +# You run the new javac using the boot jdk with $(BOOT_JDK)/bin/java $(NEW_JAVAC) ... +BOOTSTRAP_JAVAC_JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar +BOOTSTRAP_JAVAC_ARGS:="-Xbootclasspath/p:$(BOOTSTRAP_JAVAC_JAR)" -cp $(BOOTSTRAP_JAVAC_JAR) +NEW_JAVAC = $(BOOTSTRAP_JAVAC_ARGS) com.sun.tools.javac.Main +NEW_JAVADOC = $(BOOTSTRAP_JAVAC_ARGS) com.sun.tools.javadoc.Main + # Base flags for RC # Guarding this against resetting value. Legacy make files include spec multiple # times. diff --git a/common/makefiles/JavaCompilation.gmk b/common/makefiles/JavaCompilation.gmk index 59adc339779..22c199ad5b5 100644 --- a/common/makefiles/JavaCompilation.gmk +++ b/common/makefiles/JavaCompilation.gmk @@ -42,8 +42,8 @@ endif FALSE_FIND_PATTERN:=-name FILE_NAME_THAT_DOESNT_EXIST define SetupJavaCompiler - # param 1 is for example BOOT_JAVAC or NEW_JAVAC - # This is the name later used to decide which java compiler to use. + # param 1 is for example GENERATE_OLD_BYTECODE or GENERATE_NEW_JDKBYTECODE + # This is the name of the compiler setup. # param 2-9 are named args. # JVM:=The jvm used to run the javac/javah command # JAVAC:=The javac jar and bootstrap classpath changes, or just bin/javac if JVM is left out @@ -487,10 +487,10 @@ define SetupJavaCompilation # Using sjavac to compile. $1 := $$($1_ALL_COPY_TARGETS) $$($1_ALL_COPY_CLEAN_TARGETS) $$($1_BIN)/javac_state - # Create SJAVAC variable, - # expects $1_JAVAC to be "bootclasspathprepend -jar ...javac.jar" - # and it is rewritten into "bootclasspathprepend com.sun.tools.sjavac.Main" - $1_SJAVAC:=$$(word 1,$$($1_JAVAC)) -cp $$(word 3,$$($1_JAVAC)) com.sun.tools.sjavac.Main + # Create SJAVAC variable form JAVAC variable. Expects $1_JAVAC to be + # "bootclasspathprepend -cp .../javac.jar com.sun.tools.javac.Main" + # and javac is simply replaced with sjavac. + $1_SJAVAC:=$$(subst com.sun.tools.javac.Main,com.sun.tools.sjavac.Main,$$($1_JAVAC)) # Set the $1_REMOTE to spawn a background javac server. $1_REMOTE:=--server:portfile=$$($1_SJAVAC_PORTFILE),id=$1,sjavac=$$(subst $$(SPACE),%20,$$(subst $$(COMMA),%2C,$$(strip $$($1_SERVER_JVM) $$($1_SJAVAC)))) diff --git a/common/makefiles/javadoc/Javadoc.gmk b/common/makefiles/javadoc/Javadoc.gmk index 6b88a06d748..1d798120708 100644 --- a/common/makefiles/javadoc/Javadoc.gmk +++ b/common/makefiles/javadoc/Javadoc.gmk @@ -46,14 +46,11 @@ HOTSPOT_DOCS_IMPORT_PATH=$(HOTSPOT_OUTPUTDIR)/docs BUILD_NUMBER=$(JDK_BUILD_NUMBER) -BOOT_JAVA_CMD=$(JAVA) - -JAVADOC_JAR = $(LANGTOOLS_DIST)/bootstrap/lib/javadoc.jar -JAVADOC_CMD = $(BOOT_JAVA_CMD) \ +JAVADOC_CMD = $(JAVA) \ -Xmx1024m \ -Djava.awt.headless=true \ - "-Xbootclasspath/p:$(JAVADOC_JAR)" \ - -jar $(JAVADOC_JAR) -bootclasspath $(JDK_OUTPUTDIR)/classes + $(NEW_JAVADOC) \ + -bootclasspath $(JDK_OUTPUTDIR)/classes # Copyright year for beginning of Java and some of the apis # (Needed when creating the javadocs) From 45c58805e70180974a0b159732a876b8ac836e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Thu, 31 Jan 2013 14:01:45 +0100 Subject: [PATCH 025/158] 8006872: Stop creating four jars with identical content in the new build system Reviewed-by: erikj --- langtools/makefiles/BuildLangtools.gmk | 27 ++++---------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/langtools/makefiles/BuildLangtools.gmk b/langtools/makefiles/BuildLangtools.gmk index 833c8654442..cd96a601e00 100644 --- a/langtools/makefiles/BuildLangtools.gmk +++ b/langtools/makefiles/BuildLangtools.gmk @@ -112,23 +112,7 @@ ifeq ($(PROPS_ARE_CREATED),yes) $(eval $(call SetupArchive,ARCHIVE_BOOTSTRAP_JAVAC,$(BUILD_BOOTSTRAP_LANGTOOLS),\ SRCS:=$(LANGTOOLS_OUTPUTDIR)/btclasses/bootstrap,\ JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar,\ - JARMAIN:=com.sun.tools.javac.Main)) - - $(eval $(call SetupArchive,ARCHIVE_BOOTSTRAP_JAVAH,$(BUILD_BOOTSTRAP_LANGTOOLS),\ - SRCS:=$(LANGTOOLS_OUTPUTDIR)/btclasses/bootstrap,\ - JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javah.jar,\ - JARMAIN:=com.sun.tools.javah.Main)) - - $(eval $(call SetupArchive,ARCHIVE_BOOTSTRAP_JAVAP,$(BUILD_BOOTSTRAP_LANGTOOLS),\ - SRCS:=$(LANGTOOLS_OUTPUTDIR)/btclasses/bootstrap,\ - JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javap.jar,\ - JARMAIN:=com.sun.tools.javap.Main)) - - $(eval $(call SetupArchive,ARCHIVE_BOOTSTRAP_JAVADOC,$(BUILD_BOOTSTRAP_LANGTOOLS),\ - SRCS:=$(LANGTOOLS_OUTPUTDIR)/btclasses/bootstrap,\ - JAR:=$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javadoc.jar,\ - SUFFIXES:=.class $(RESOURCE_SUFFIXES),\ - JARMAIN:=com.sun.tools.javadoc.Main)) + SUFFIXES:=.class $(RESOURCE_SUFFIXES))) # GenStubs is used to bootstrap any dependencies from javac to the new JDK that is not # yet built. It is currently not needed but might be again in the future. The following @@ -176,7 +160,8 @@ ifeq ($(PROPS_ARE_CREATED),yes) $(eval $(call SetupJavaCompiler,GENERATE_NEWBYTECODE,\ JVM:=$(JAVA),\ JAVAC:="-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar" \ - -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar,\ + -cp $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar \ + com.sun.tools.javac.Main,\ FLAGS:=-XDignore.symbol.file=true -Xlint:all$(COMMA)-deprecation -Werror,\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) @@ -201,11 +186,7 @@ ifeq ($(PROPS_ARE_CREATED),yes) all: $(LANGTOOLS_OUTPUTDIR)/dist/lib/classes.jar \ $(LANGTOOLS_OUTPUTDIR)/dist/lib/src.zip \ - $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar \ - $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javah.jar \ - $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javap.jar \ - $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javadoc.jar - + $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar endif endif From 676769c08f6fec8a41af06ef97d445ffc3fbeb60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Thu, 31 Jan 2013 14:02:29 +0100 Subject: [PATCH 026/158] 8006872: Stop creating four jars with identical content in the new build system Reviewed-by: erikj --- corba/makefiles/BuildCorba.gmk | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/corba/makefiles/BuildCorba.gmk b/corba/makefiles/BuildCorba.gmk index 246c5b9bcec..b177ff2d212 100644 --- a/corba/makefiles/BuildCorba.gmk +++ b/corba/makefiles/BuildCorba.gmk @@ -35,8 +35,6 @@ include MakeBase.gmk include JavaCompilation.gmk include IdlCompilation.gmk -JAVAC_JARS ?= "-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar" \ - -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar # The Corba sources are old and generates a LOT of warnings. # Disable these using Xlint, until someone cares to fix them. DISABLE_CORBA_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-serial,-fallthrough,-cast,-rawtypes,-static,-dep-ann @@ -46,7 +44,7 @@ DISABLE_CORBA_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-serial,-fallthrough, # Thus we force the target bytecode to the boot jdk bytecode. $(eval $(call SetupJavaCompiler,GENERATE_OLDBYTECODE,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=$(BOOT_JDK_SOURCETARGET) -bootclasspath $(BOOT_RTJAR) $(DISABLE_CORBA_WARNINGS),\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) @@ -56,7 +54,7 @@ $(eval $(call SetupJavaCompiler,GENERATE_OLDBYTECODE,\ # cannot necessarily be run with the boot jdk. $(eval $(call SetupJavaCompiler,GENERATE_NEWBYTECODE,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-cp $(BOOT_TOOLSJAR) -XDignore.symbol.file=true $(DISABLE_CORBA_WARNINGS),\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) From ba0917c5314c3318ad49b1d753a3544629824265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Thu, 31 Jan 2013 14:02:44 +0100 Subject: [PATCH 027/158] 8006872: Stop creating four jars with identical content in the new build system Reviewed-by: erikj --- jaxp/makefiles/BuildJaxp.gmk | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/jaxp/makefiles/BuildJaxp.gmk b/jaxp/makefiles/BuildJaxp.gmk index e28cdf890c3..749046481a3 100644 --- a/jaxp/makefiles/BuildJaxp.gmk +++ b/jaxp/makefiles/BuildJaxp.gmk @@ -30,8 +30,6 @@ default: all include MakeBase.gmk include JavaCompilation.gmk -JAVAC_JARS ?= "-Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar" \ - -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar DISABLE_JAXP_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-serial,-dep-ann,-static,-fallthrough # The generate new bytecode uses the new compiler for to generate bytecode @@ -39,7 +37,7 @@ DISABLE_JAXP_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-seria # cannot necessarily be run with the boot jdk. $(eval $(call SetupJavaCompiler,GENERATE_NEWBYTECODE_DEBUG,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-XDignore.symbol.file=true $(DISABLE_JAXP_WARNINGS) -g,\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) From c2b707c559442da77fff44e86b1849eb1032e715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Thu, 31 Jan 2013 14:02:58 +0100 Subject: [PATCH 028/158] 8006872: Stop creating four jars with identical content in the new build system Reviewed-by: erikj --- jaxws/makefiles/BuildJaxws.gmk | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/jaxws/makefiles/BuildJaxws.gmk b/jaxws/makefiles/BuildJaxws.gmk index c1b092d64bc..348cba90780 100644 --- a/jaxws/makefiles/BuildJaxws.gmk +++ b/jaxws/makefiles/BuildJaxws.gmk @@ -30,8 +30,6 @@ include $(SPEC) include MakeBase.gmk include JavaCompilation.gmk -JAVAC_JARS ?= -Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar \ - -jar $(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar DISABLE_JAXWS_WARNINGS:=-Xlint:all,-varargs,-rawtypes,-deprecation,-unchecked,-serial,-dep-ann,-cast,-fallthrough,-static # The generate new bytecode uses the new compiler for to generate bytecode @@ -39,7 +37,7 @@ DISABLE_JAXWS_WARNINGS:=-Xlint:all,-varargs,-rawtypes,-deprecation,-unchecked,-s # cannot necessarily be run with the boot jdk. $(eval $(call SetupJavaCompiler,GENERATE_NEWBYTECODE_DEBUG,\ JVM:=$(JAVA),\ - JAVAC:=$(JAVAC_JARS),\ + JAVAC:=$(NEW_JAVAC),\ FLAGS:=-XDignore.symbol.file=true $(DISABLE_JAXWS_WARNINGS) -g,\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) From d843dec3b7d68c94b4d46ce4eb9909889cac6060 Mon Sep 17 00:00:00 2001 From: Leonid Romanov Date: Thu, 31 Jan 2013 18:25:59 +0400 Subject: [PATCH 029/158] 8007006: [macosx] Closing subwindow loses main window menus Reviewed-by: anthony --- jdk/src/macosx/native/sun/awt/AWTWindow.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/src/macosx/native/sun/awt/AWTWindow.m b/jdk/src/macosx/native/sun/awt/AWTWindow.m index 3af7c6c736f..bac24ff8d52 100644 --- a/jdk/src/macosx/native/sun/awt/AWTWindow.m +++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m @@ -813,9 +813,9 @@ JNF_COCOA_ENTER(env); if ([nsWindow isKeyWindow]) [window.javaMenuBar deactivate]; window.javaMenuBar = menuBar; - // if ([self isKeyWindow]) { - [CMenuBar activate:window.javaMenuBar modallyDisabled:NO]; - // } + if ([nsWindow isKeyWindow]) { + [CMenuBar activate:window.javaMenuBar modallyDisabled:NO]; + } }]; JNF_COCOA_EXIT(env); From 018fbffe544031d8eac44ac6088f11cf7bbb4dad Mon Sep 17 00:00:00 2001 From: Pete Brunet Date: Thu, 31 Jan 2013 18:51:17 +0400 Subject: [PATCH 030/158] 7179482: Component.accessibleContext and JComponent.accessibleContext refactoring Reviewed-by: art, anthony, alexsch --- jdk/src/share/classes/java/awt/Component.java | 24 +++++++---- jdk/src/share/classes/java/awt/Container.java | 24 ++++++++++- .../share/classes/javax/swing/JComponent.java | 43 ++++++++----------- 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/jdk/src/share/classes/java/awt/Component.java b/jdk/src/share/classes/java/awt/Component.java index 42e422d3e93..3bfb115c15e 100644 --- a/jdk/src/share/classes/java/awt/Component.java +++ b/jdk/src/share/classes/java/awt/Component.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2011, 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 @@ -8994,7 +8994,10 @@ public abstract class Component implements ImageObserver, MenuContainer, * to the individual objects which extend Component. */ - AccessibleContext accessibleContext = null; + /** + * The {@code AccessibleContext} associated with this {@code Component}. + */ + protected AccessibleContext accessibleContext = null; /** * Gets the AccessibleContext associated @@ -9034,6 +9037,13 @@ public abstract class Component implements ImageObserver, MenuContainer, protected AccessibleAWTComponent() { } + /** + * Number of PropertyChangeListener objects registered. It's used + * to add/remove ComponentListener and FocusListener to track + * target Component's state. + */ + private volatile transient int propertyListenersCount = 0; + protected ComponentListener accessibleAWTComponentHandler = null; protected FocusListener accessibleAWTFocusHandler = null; @@ -9098,10 +9108,12 @@ public abstract class Component implements ImageObserver, MenuContainer, public void addPropertyChangeListener(PropertyChangeListener listener) { if (accessibleAWTComponentHandler == null) { accessibleAWTComponentHandler = new AccessibleAWTComponentHandler(); - Component.this.addComponentListener(accessibleAWTComponentHandler); } if (accessibleAWTFocusHandler == null) { accessibleAWTFocusHandler = new AccessibleAWTFocusHandler(); + } + if (propertyListenersCount++ == 0) { + Component.this.addComponentListener(accessibleAWTComponentHandler); Component.this.addFocusListener(accessibleAWTFocusHandler); } super.addPropertyChangeListener(listener); @@ -9115,13 +9127,9 @@ public abstract class Component implements ImageObserver, MenuContainer, * @param listener The PropertyChangeListener to be removed */ public void removePropertyChangeListener(PropertyChangeListener listener) { - if (accessibleAWTComponentHandler != null) { + if (--propertyListenersCount == 0) { Component.this.removeComponentListener(accessibleAWTComponentHandler); - accessibleAWTComponentHandler = null; - } - if (accessibleAWTFocusHandler != null) { Component.this.removeFocusListener(accessibleAWTFocusHandler); - accessibleAWTFocusHandler = null; } super.removePropertyChangeListener(listener); } diff --git a/jdk/src/share/classes/java/awt/Container.java b/jdk/src/share/classes/java/awt/Container.java index 78af6b10c62..1118852f0e9 100644 --- a/jdk/src/share/classes/java/awt/Container.java +++ b/jdk/src/share/classes/java/awt/Container.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2010, 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 @@ -3824,6 +3824,12 @@ public class Container extends Component { return Container.this.getAccessibleAt(p); } + /** + * Number of PropertyChangeListener objects registered. It's used + * to add/remove ContainerListener to track target Container's state. + */ + private volatile transient int propertyListenersCount = 0; + protected ContainerListener accessibleContainerHandler = null; /** @@ -3859,11 +3865,27 @@ public class Container extends Component { public void addPropertyChangeListener(PropertyChangeListener listener) { if (accessibleContainerHandler == null) { accessibleContainerHandler = new AccessibleContainerHandler(); + } + if (propertyListenersCount++ == 0) { Container.this.addContainerListener(accessibleContainerHandler); } super.addPropertyChangeListener(listener); } + /** + * Remove a PropertyChangeListener from the listener list. + * This removes a PropertyChangeListener that was registered + * for all properties. + * + * @param listener the PropertyChangeListener to be removed + */ + public void removePropertyChangeListener(PropertyChangeListener listener) { + if (--propertyListenersCount == 0) { + Container.this.removeContainerListener(accessibleContainerHandler); + } + super.removePropertyChangeListener(listener); + } + } // inner class AccessibleAWTContainer /** diff --git a/jdk/src/share/classes/javax/swing/JComponent.java b/jdk/src/share/classes/javax/swing/JComponent.java index dbf4b3c3343..dac623a37bd 100644 --- a/jdk/src/share/classes/javax/swing/JComponent.java +++ b/jdk/src/share/classes/javax/swing/JComponent.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 @@ -3643,26 +3643,6 @@ public abstract class JComponent extends Container implements Serializable, } } - /** - * The AccessibleContext associated with this - * JComponent. - */ - protected AccessibleContext accessibleContext = null; - - /** - * Returns the AccessibleContext associated with this - * JComponent. The method implemented by this base - * class returns null. Classes that extend JComponent - * should implement this method to return the - * AccessibleContext associated with the subclass. - * - * @return the AccessibleContext of this - * JComponent - */ - public AccessibleContext getAccessibleContext() { - return accessibleContext; - } - /** * Inner class of JComponent used to provide default support for * accessibility. This class is not meant to be used directly by @@ -3689,7 +3669,18 @@ public abstract class JComponent extends Container implements Serializable, super(); } - protected ContainerListener accessibleContainerHandler = null; + /** + * Number of PropertyChangeListener objects registered. It's used + * to add/remove ContainerListener and FocusListener to track + * target JComponent's state + */ + private volatile transient int propertyListenersCount = 0; + + /** + * This field duplicates the one in java.awt.Component.AccessibleAWTComponent, + * so it has been deprecated. + */ + @Deprecated protected FocusListener accessibleFocusHandler = null; /** @@ -3747,10 +3738,12 @@ public abstract class JComponent extends Container implements Serializable, public void addPropertyChangeListener(PropertyChangeListener listener) { if (accessibleFocusHandler == null) { accessibleFocusHandler = new AccessibleFocusHandler(); - JComponent.this.addFocusListener(accessibleFocusHandler); } if (accessibleContainerHandler == null) { accessibleContainerHandler = new AccessibleContainerHandler(); + } + if (propertyListenersCount++ == 0) { + JComponent.this.addFocusListener(accessibleFocusHandler); JComponent.this.addContainerListener(accessibleContainerHandler); } super.addPropertyChangeListener(listener); @@ -3764,9 +3757,9 @@ public abstract class JComponent extends Container implements Serializable, * @param listener the PropertyChangeListener to be removed */ public void removePropertyChangeListener(PropertyChangeListener listener) { - if (accessibleFocusHandler != null) { + if (--propertyListenersCount == 0) { JComponent.this.removeFocusListener(accessibleFocusHandler); - accessibleFocusHandler = null; + JComponent.this.removeContainerListener(accessibleContainerHandler); } super.removePropertyChangeListener(listener); } From 7d2ccf3a21a3676fbb357b52354047ced5607a73 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Thu, 31 Jan 2013 10:45:09 -0800 Subject: [PATCH 031/158] 8005875: G1: Kitchensink fails with ParallelGCThreads=0 Check that the concurrent marking worker gang exists in ConcurrentMark::print_worker_threads_on(). Changes were also reviewed by Vitaly Davidovich . Reviewed-by: brutisso --- .../gc_implementation/g1/concurrentMark.cpp | 8 +++-- .../gc_implementation/g1/concurrentMark.hpp | 29 ++++++++++++------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 50821ac0cfb..b77cd155e74 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -1190,7 +1190,7 @@ void ConcurrentMark::scanRootRegions() { uint active_workers = MAX2(1U, parallel_marking_threads()); CMRootRegionScanTask task(this); - if (parallel_marking_threads() > 0) { + if (use_parallel_marking_threads()) { _parallel_workers->set_active_workers((int) active_workers); _parallel_workers->run_task(&task); } else { @@ -1226,7 +1226,7 @@ void ConcurrentMark::markFromRoots() { set_phase(active_workers, true /* concurrent */); CMConcurrentMarkingTask markingTask(this, cmThread()); - if (parallel_marking_threads() > 0) { + if (use_parallel_marking_threads()) { _parallel_workers->set_active_workers((int)active_workers); // Don't set _n_par_threads because it affects MT in proceess_strong_roots() // and the decisions on that MT processing is made elsewhere. @@ -3242,7 +3242,9 @@ void ConcurrentMark::print_summary_info() { } void ConcurrentMark::print_worker_threads_on(outputStream* st) const { - _parallel_workers->print_worker_threads_on(st); + if (use_parallel_marking_threads()) { + _parallel_workers->print_worker_threads_on(st); + } } // We take a break if someone is trying to stop the world. diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index 34c5601e050..6701e9f4171 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -499,17 +499,26 @@ protected: } // accessor methods - uint parallel_marking_threads() { return _parallel_marking_threads; } - uint max_parallel_marking_threads() { return _max_parallel_marking_threads;} - double sleep_factor() { return _sleep_factor; } - double marking_task_overhead() { return _marking_task_overhead;} - double cleanup_sleep_factor() { return _cleanup_sleep_factor; } - double cleanup_task_overhead() { return _cleanup_task_overhead;} + uint parallel_marking_threads() const { return _parallel_marking_threads; } + uint max_parallel_marking_threads() const { return _max_parallel_marking_threads;} + double sleep_factor() { return _sleep_factor; } + double marking_task_overhead() { return _marking_task_overhead;} + double cleanup_sleep_factor() { return _cleanup_sleep_factor; } + double cleanup_task_overhead() { return _cleanup_task_overhead;} - HeapWord* finger() { return _finger; } - bool concurrent() { return _concurrent; } - uint active_tasks() { return _active_tasks; } - ParallelTaskTerminator* terminator() { return &_terminator; } + bool use_parallel_marking_threads() const { + assert(parallel_marking_threads() <= + max_parallel_marking_threads(), "sanity"); + assert((_parallel_workers == NULL && parallel_marking_threads() == 0) || + parallel_marking_threads() > 0, + "parallel workers not set up correctly"); + return _parallel_workers != NULL; + } + + HeapWord* finger() { return _finger; } + bool concurrent() { return _concurrent; } + uint active_tasks() { return _active_tasks; } + ParallelTaskTerminator* terminator() { return &_terminator; } // It claims the next available region to be scanned by a marking // task/thread. It might return NULL if the next region is empty or From b3fa7187ae4430440189921e23c59e849c56b93c Mon Sep 17 00:00:00 2001 From: David Buck Date: Thu, 31 Jan 2013 10:55:15 -0800 Subject: [PATCH 032/158] 7042126: (alt-rt) HashMap.clone implementation should be re-examined Test case for cr7042126. Issue only found in OracleJDK, but test case is valid for OpenJDK as well Reviewed-by: mduigou --- .../java/util/HashMap/HashMapCloneLeak.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 jdk/test/java/util/HashMap/HashMapCloneLeak.java diff --git a/jdk/test/java/util/HashMap/HashMapCloneLeak.java b/jdk/test/java/util/HashMap/HashMapCloneLeak.java new file mode 100644 index 00000000000..2a5fcaa4f1c --- /dev/null +++ b/jdk/test/java/util/HashMap/HashMapCloneLeak.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/** + * @test + * @bug 7042126 + * @summary Verify that we do not leak contents when we clone a HashMap + * @author david.buck@oracle.com + * @run main/othervm HashMapCloneLeak + * @run main/othervm -XX:+AggressiveOpts HashMapCloneLeak + */ + +import java.util.HashMap; +import java.lang.ref.WeakReference; + +public class HashMapCloneLeak { + + static WeakReference wr = null; + + // helper method to keep testObject and map out of main method's scope + private static HashMap makeMap() { + HashMap map = new HashMap(); + Object testObject = new Object(); + wr = new WeakReference(testObject); + map.put(42, testObject); + return map; + } + + public static void main(String[] args) throws Exception { + HashMap hm = makeMap(); + hm = (HashMap)hm.clone(); + hm.clear(); + // There should no longer be a strong reference to testObject + // the WeakReference should be nulled out by GC. If not, + // we will hang here until timed out by the test harness. + Object[] chain = null; + while (wr.get() != null) { + try { + Object[] allocate = new Object[1000000]; + allocate[0] = chain; + chain = allocate; + } catch (OutOfMemoryError oome) { + chain = null; + } + System.gc(); + Thread.sleep(100); + } + } + +} From 907f0724ce28cc7a6753f1f103b9e8d30f2d5893 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Thu, 31 Jan 2013 11:09:36 -0800 Subject: [PATCH 033/158] 8005394: Base64.Decoder/Encoder.wrap(XStream) don't throw NPE for null args passed To check null for dec/enc.wrap methods Reviewed-by: alanb --- jdk/src/share/classes/java/util/Base64.java | 2 ++ jdk/test/java/util/Base64/TestBase64.java | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/util/Base64.java b/jdk/src/share/classes/java/util/Base64.java index f5ff211f8d4..7a01c05e653 100644 --- a/jdk/src/share/classes/java/util/Base64.java +++ b/jdk/src/share/classes/java/util/Base64.java @@ -413,6 +413,7 @@ public class Base64 { * specified Base64 encoded format */ public OutputStream wrap(OutputStream os) { + Objects.requireNonNull(os); return new EncOutputStream(os, isURL ? toBase64URL : toBase64, newline, linemax); } @@ -866,6 +867,7 @@ public class Base64 { * byte stream */ public InputStream wrap(InputStream is) { + Objects.requireNonNull(is); return new DecInputStream(is, isURL ? fromBase64URL : fromBase64, isMIME); } diff --git a/jdk/test/java/util/Base64/TestBase64.java b/jdk/test/java/util/Base64/TestBase64.java index 6b37772d7f6..645f570b0f3 100644 --- a/jdk/test/java/util/Base64/TestBase64.java +++ b/jdk/test/java/util/Base64/TestBase64.java @@ -22,7 +22,7 @@ */ /** - * @test 4235519 8004212 + * @test 4235519 8004212 8005394 * @summary tests java.util.Base64 */ @@ -295,6 +295,7 @@ public class TestBase64 { checkNull(new Runnable() { public void run() { enc.encode(bb_null); }}); checkNull(new Runnable() { public void run() { enc.encode(bb_null, ByteBuffer.allocate(10), 0); }}); checkNull(new Runnable() { public void run() { enc.encode(ByteBuffer.allocate(10), bb_null, 0); }}); + checkNull(new Runnable() { public void run() { enc.wrap(null); }}); } private static void testNull(final Base64.Decoder dec) { @@ -305,6 +306,7 @@ public class TestBase64 { checkNull(new Runnable() { public void run() { dec.decode(bb_null); }}); checkNull(new Runnable() { public void run() { dec.decode(bb_null, ByteBuffer.allocate(10)); }}); checkNull(new Runnable() { public void run() { dec.decode(ByteBuffer.allocate(10), bb_null); }}); + checkNull(new Runnable() { public void run() { dec.wrap(null); }}); } private static interface Testable { From 9101ca61f5fb2707a4caf94dec32bbb0c7f4728e Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 31 Jan 2013 12:13:21 -0800 Subject: [PATCH 034/158] 8005832: Remove java.lang.annotation.{ContainedBy, ContainerFor} annotation types Reviewed-by: mduigou --- .../java/lang/annotation/ContainedBy.java | 71 ------------------ .../java/lang/annotation/ContainerFor.java | 73 ------------------- .../InvalidContainerAnnotationError.java | 9 +-- 3 files changed, 4 insertions(+), 149 deletions(-) delete mode 100644 jdk/src/share/classes/java/lang/annotation/ContainedBy.java delete mode 100644 jdk/src/share/classes/java/lang/annotation/ContainerFor.java diff --git a/jdk/src/share/classes/java/lang/annotation/ContainedBy.java b/jdk/src/share/classes/java/lang/annotation/ContainedBy.java deleted file mode 100644 index 4f032863791..00000000000 --- a/jdk/src/share/classes/java/lang/annotation/ContainedBy.java +++ /dev/null @@ -1,71 +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.lang.annotation; - -/** - * The annotation type {@code java.lang.annotation.ContainedBy} is - * used to indicate that the annotation type whose declaration it - * (meta-)annotates is repeatable. The value of - * {@code @ContainedBy} indicates the containing annotation - * type for the repeatable annotation type. - * - *

The pair of annotation types {@code @ContainedBy} and - * {@link java.lang.annotation.ContainerFor @ContainerFor} are used to - * indicate that annotation types are repeatable. Specifically: - * - *

    - *
  • The annotation type {@code @ContainedBy} is used on the - * declaration of a repeatable annotation type (JLS 9.6) to indicate - * its containing annotation type. - * - *
  • The annotation type {@code @ContainerFor} is used on the - * declaration of a containing annotation type (JLS 9.6) to indicate - * the repeatable annotation type for which it serves as the - * containing annotation type. - *
- * - *

- * An inconsistent pair of {@code @ContainedBy} and - * {@code @ContainerFor} annotations on a repeatable annotation type - * and its containing annotation type (JLS 9.6) will lead to - * compile-time errors and runtime exceptions when using reflection to - * read annotations of a repeatable type. - * - * @see java.lang.annotation.ContainerFor - * @since 1.8 - * @jls 9.6 Annotation Types - * @jls 9.7 Annotations - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.ANNOTATION_TYPE) -public @interface ContainedBy { - /** - * Indicates the containing annotation type for the - * repeatable annotation type. - */ - Class value(); -} diff --git a/jdk/src/share/classes/java/lang/annotation/ContainerFor.java b/jdk/src/share/classes/java/lang/annotation/ContainerFor.java deleted file mode 100644 index 62f3446e021..00000000000 --- a/jdk/src/share/classes/java/lang/annotation/ContainerFor.java +++ /dev/null @@ -1,73 +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.lang.annotation; - -/** - * The annotation type {@code java.lang.annotation.ContainerFor} is - * used to indicate that the annotation type whose declaration it - * (meta-)annotates is a containing annotation type. The - * value of {@code @ContainerFor} indicates the repeatable - * annotation type for the containing annotation type. - * - *

The pair of annotation types {@link - * java.lang.annotation.ContainedBy @ContainedBy} and - * {@code @ContainerFor} are used to indicate that annotation types - * are repeatable. Specifically: - * - *

    - *
  • The annotation type {@code @ContainedBy} is used on the - * declaration of a repeatable annotation type (JLS 9.6) to indicate - * its containing annotation type. - * - *
  • The annotation type {@code @ContainerFor} is used on the - * declaration of a containing annotation type (JLS 9.6) to indicate - * the repeatable annotation type for which it serves as the - * containing annotation type. - *
- * - *

- * An inconsistent pair of {@code @ContainedBy} and - * {@code @ContainerFor} annotations on a repeatable annotation type - * and its containing annotation type (JLS 9.6) will lead to - * compile-time errors and runtime exceptions when using reflection to - * read annotations of a repeatable type. - * - * @see java.lang.annotation.ContainedBy - * @since 1.8 - * @jls 9.6 Annotation Types - * @jls 9.7 Annotations - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.ANNOTATION_TYPE) -public @interface ContainerFor { - - /** - * Indicates the repeatable annotation type for the containing - * annotation type. - */ - Class value(); -} diff --git a/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java b/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java index b24e3034179..37d00a98b40 100644 --- a/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java +++ b/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -27,10 +27,9 @@ package java.lang.annotation; import java.util.Objects; /** - * Thrown to indicate that an annotation type whose declaration is - * (meta-)annotated with a {@link ContainerFor} annotation is not, in - * fact, the containing annotation type of the type named by {@link - * ContainerFor}. + * Thrown to indicate that an annotation type expected to act as a + * container for another annotation type by virture of an @Repeatable + * annotation, does not act as a container. * * @see java.lang.reflect.AnnotatedElement * @since 1.8 From 4484857b5058b889f8c226a518c6f0f2b22aa099 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 31 Jan 2013 12:16:03 -0800 Subject: [PATCH 035/158] 8007313: Remove use of {ContainerFor/ContainedBy} from langtools Reviewed-by: jjg --- .../classfile/CombinationsTargetTest1.java | 9 +++------ .../classfile/CombinationsTargetTest2.java | 9 +++------ .../newlocations/RepeatingTypeAnnotations.java | 1 - .../typeAnnotations/referenceinfos/Driver.java | 6 +++--- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java index 0041dd35f61..dfab97807c2 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java @@ -174,22 +174,20 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper { String sourceBase = new String("@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainedBy( AC.class )\n" + + "@Repeatable( AC.class )\n" + "@interface A { }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainerFor(A.class)\n" + "@interface AC { A[] value(); }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainedBy( BC.class )\n" + + "@Repeatable( BC.class )\n" + "@interface B { }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainerFor(B.class)\n" + "@interface BC { B[] value(); } \n\n" + "@Retention("+retentn+")\n" + @@ -198,12 +196,11 @@ public class CombinationsTargetTest1 extends ClassfileTestHelper { "@Retention("+retentn+")\n" + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + - "@ContainedBy(DC.class)\n" + + "@Repeatable(DC.class)\n" + "@interface D { }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + - "@ContainerFor(D.class) \n" + "@interface DC { D[] value(); }\n\n"); // Test case sources with sample generated source. diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java index a0308a38975..77fb9a8aa1e 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java @@ -171,32 +171,29 @@ public class CombinationsTargetTest2 extends ClassfileTestHelper { String sourceBase = new String("@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainedBy( AC.class )\n" + + "@Repeatable( AC.class )\n" + "@interface A { }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainerFor(A.class)\n" + "@interface AC { A[] value(); }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainedBy( BC.class )\n" + + "@Repeatable( BC.class )\n" + "@interface B { }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,_OTHER_})\n" + - "@ContainerFor(B.class)\n" + "@interface BC { B[] value(); } \n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + - "@ContainedBy(DC.class)\n" + + "@Repeatable(DC.class)\n" + "@interface D { }\n\n" + "@Retention("+retentn+")\n" + "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" + - "@ContainerFor(D.class) \n" + "@interface DC { D[] value(); }\n\n"); // Test case sources with sample generated source diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.java index db227cb56f6..3aecc7a9219 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/RepeatingTypeAnnotations.java @@ -120,7 +120,6 @@ class MyList { } @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTA { } -@ContainerFor(RTA.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTAs { RTA[] value(); diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java index 5986fa95de8..052d11a77a2 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -241,8 +241,8 @@ public class Driver { sb.append("\n@Repeatable(RTAs.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTA {}"); sb.append("\n@Repeatable(RTBs.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTB {}"); - sb.append("\n@ContainerFor(RTA.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTAs { RTA[] value(); }"); - sb.append("\n@ContainerFor(RTB.class) @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTBs { RTB[] value(); }"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTAs { RTA[] value(); }"); + sb.append("\n@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface RTBs { RTB[] value(); }"); sb.append("\n@Target(value={ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.CONSTRUCTOR,ElementType.LOCAL_VARIABLE})"); sb.append("\n@interface Decl {}"); From 757d9cdeb9c5cac2cf99a8a29f53ef68448964c4 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 31 Jan 2013 12:23:04 -0800 Subject: [PATCH 036/158] 8007115: Refactor regression tests for java.lang.reflect.Parameter Reviewed-by: emc --- .../reflect/Parameter/WithoutParameters.java | 249 +++++++++--------- 1 file changed, 119 insertions(+), 130 deletions(-) diff --git a/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java b/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java index 39be21471aa..50254fd9d6b 100644 --- a/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java +++ b/jdk/test/java/lang/reflect/Parameter/WithoutParameters.java @@ -23,163 +23,152 @@ /* * @test + * @bug 8004729 * @summary javac should generate method parameters correctly. */ import java.lang.*; import java.lang.reflect.*; +import java.lang.annotation.*; import java.util.List; +import java.util.Objects; + +import static java.lang.annotation.ElementType.*; public class WithoutParameters { + int errors = 0; - private static final Class[] qux_types = { - int.class, - Foo.class, - List.class, - List.class, - List.class, - String[].class - }; + private WithoutParameters() {} public static void main(String argv[]) throws Exception { - int error = 0; - Method[] methods = Foo.class.getMethods(); - for(Method m : methods) { - System.err.println("Inspecting method " + m); - Parameter[] parameters = m.getParameters(); - if(parameters == null) - throw new Exception("getParameters should never be null"); - for(int i = 0; i < parameters.length; i++) { - Parameter p = parameters[i]; - if(!p.getDeclaringExecutable().equals(m)) { - System.err.println(p + ".getDeclaringExecutable != " + m); - error++; - } - if(null == p.getType()) { - System.err.println(p + ".getType() == null"); - error++; - } - if(null == p.getParameterizedType()) { - System.err.println(p + ".getParameterizedType == null"); - error++; - } - } - if(m.getName().equals("qux")) { - if(6 != parameters.length) { - System.err.println("Wrong number of parameters for qux"); - error++; - } - for(int i = 0; i < parameters.length; i++) { - Parameter p = parameters[i]; - // The getType family work with or without - // parameter attributes compiled in. - if(!parameters[i].getType().equals(qux_types[i])) { - System.err.println("Wrong parameter type for " + parameters[0] + ": expected " + qux_types[i] + ", but got " + parameters[i].getType()); - error++; - } - } - if(!parameters[0].getParameterizedType().equals(int.class)) { - System.err.println("getParameterizedType for quux is wrong"); - error++; - } - if(!parameters[1].getParameterizedType().equals(Foo.class)) { - System.err.println("getParameterizedType for quux is wrong"); - error++; - } - if(!(parameters[2].getParameterizedType() instanceof - ParameterizedType)) { - System.err.println("getParameterizedType for l is wrong"); - error++; - } else { - ParameterizedType pt = - (ParameterizedType) parameters[2].getParameterizedType(); - if(!pt.getRawType().equals(List.class)) { - System.err.println("Raw type for l is wrong"); - error++; - } - if(1 != pt.getActualTypeArguments().length) { - System.err.println("Number of type parameters for l is wrong"); - error++; - } - if(!(pt.getActualTypeArguments()[0] instanceof WildcardType)) { - System.err.println("Type parameter for l is wrong"); - error++; - } - } - if(!(parameters[3].getParameterizedType() instanceof - ParameterizedType)) { - System.err.println("getParameterizedType for l2 is wrong"); - error++; - } else { - ParameterizedType pt = - (ParameterizedType) parameters[3].getParameterizedType(); - if(!pt.getRawType().equals(List.class)) { - System.err.println("Raw type for l2 is wrong"); - error++; - } - if(1 != pt.getActualTypeArguments().length) { - System.err.println("Number of type parameters for l2 is wrong"); - error++; - } - if(!(pt.getActualTypeArguments()[0].equals(Foo.class))) { - System.err.println("Type parameter for l2 is wrong"); - error++; - } - } - if(!(parameters[4].getParameterizedType() instanceof - ParameterizedType)) { - System.err.println("getParameterizedType for l3 is wrong"); - error++; - } else { - ParameterizedType pt = - (ParameterizedType) parameters[4].getParameterizedType(); - if(!pt.getRawType().equals(List.class)) { - System.err.println("Raw type for l3 is wrong"); - error++; - } - if(1 != pt.getActualTypeArguments().length) { - System.err.println("Number of type parameters for l3 is wrong"); - error++; - } - if(!(pt.getActualTypeArguments()[0] instanceof WildcardType)) { - System.err.println("Type parameter for l3 is wrong"); - error++; - } else { - WildcardType wt = (WildcardType) - pt.getActualTypeArguments()[0]; - if(!wt.getUpperBounds()[0].equals(Foo.class)) { - System.err.println("Upper bounds on type parameter fol l3 is wrong"); - error++; - } - } - } - if(!parameters[5].isVarArgs()) { - System.err.println("isVarArg for rest is wrong"); - error++; - } - if(!(parameters[5].getParameterizedType().equals(String[].class))) { - System.err.println("getParameterizedType for rest is wrong"); - error++; - } + WithoutParameters wp = new WithoutParameters(); + wp.runTests(Foo.class.getMethods()); + wp.runTests(Foo.Inner.class.getConstructors()); + wp.checkForErrors(); + } + void runTests(Method[] methods) throws Exception { + for(Method m : methods) {runTest(m);} + } + + void runTests(Constructor[] constructors) throws Exception { + for(Constructor c : constructors) {runTest(c);} + } + + void runTest(Executable e) throws Exception { + System.err.println("Inspecting executable " + e); + Parameter[] parameters = e.getParameters(); + Objects.requireNonNull(parameters, "getParameters should never be null"); + + ExpectedParameterInfo epi = e.getAnnotation(ExpectedParameterInfo.class); + if (epi != null) { + abortIfTrue(epi.parameterCount() != e.getParameterCount(), "Bad parameter count for "+ e); + abortIfTrue(epi.isVarArgs() != e.isVarArgs(),"Bad varargs value for "+ e); + } + abortIfTrue(e.getParameterCount() != parameters.length, "Mismatched of parameter counts."); + + for(int i = 0; i < parameters.length; i++) { + Parameter p = parameters[i]; + errorIfTrue(!p.getDeclaringExecutable().equals(e), p + ".getDeclaringExecutable != " + e); + Objects.requireNonNull(p.getType(), "getType() should not be null"); + Objects.requireNonNull(p.getParameterizedType(), "getParameterizedType() should not be null"); + + if (epi != null) { + Class expectedParameterType = epi.parameterTypes()[i]; + errorIfTrue(!p.getType().equals(expectedParameterType), + "Wrong parameter type for " + p + ": expected " + expectedParameterType + + ", but got " + p.getType()); + + ParameterizedInfo[] expectedParameterizedTypes = epi.parameterizedTypes(); + if (expectedParameterizedTypes.length > 0) { + Type parameterizedType = p.getParameterizedType(); + Class expectedParameterziedTypeType = expectedParameterizedTypes[i].value(); + errorIfTrue(!expectedParameterziedTypeType.isAssignableFrom(parameterizedType.getClass()), + "Wrong class of parameteried type of " + p + ": expected " + expectedParameterziedTypeType + + ", but got " + parameterizedType.getClass()); + + if (expectedParameterziedTypeType.equals(Class.class)) { + errorIfTrue(!parameterizedType.equals(expectedParameterType), + "Wrong parameteried type for " + p + ": expected " + expectedParameterType + + ", but got " + parameterizedType); + } else { + if (expectedParameterziedTypeType.equals(ParameterizedType.class)) { + ParameterizedType ptype = (ParameterizedType)parameterizedType; + errorIfTrue(!ptype.getRawType().equals(expectedParameterType), + "Wrong raw type for " + p + ": expected " + expectedParameterType + + ", but got " + ptype.getRawType()); + } + + // Check string representation + String expectedStringOfType = epi.parameterizedTypes()[i].string(); + errorIfTrue(!expectedStringOfType.equals(parameterizedType.toString()), + "Bad type string" + p + ": expected " + expectedStringOfType + + ", but got " + parameterizedType.toString()); + } + } } } - if(0 != error) - throw new Exception("Failed " + error + " tests"); + } + + private void checkForErrors() { + if (errors > 0) + throw new RuntimeException("Failed " + errors + " tests"); + } + + private void errorIfTrue(boolean predicate, String errMessage) { + if (predicate) { + errors++; + System.err.println(errMessage); + } + } + + private void abortIfTrue(boolean predicate, String errMessage) { + if (predicate) { + throw new RuntimeException(errMessage); + } + } + + @Retention(RetentionPolicy.RUNTIME) + @Target({METHOD, CONSTRUCTOR}) + @interface ExpectedParameterInfo { + int parameterCount() default 0; + Class[] parameterTypes() default {}; + ParameterizedInfo[] parameterizedTypes() default {}; + boolean isVarArgs() default false; + } + + @Target({}) + @interface ParameterizedInfo { + Class value() default Class.class; + String string() default ""; } public class Foo { int thing; + @ExpectedParameterInfo(parameterCount = 6, + parameterTypes = + {int.class, Foo.class, + List.class, List.class, + List.class, String[].class}, + parameterizedTypes = + {@ParameterizedInfo(Class.class), + @ParameterizedInfo(Class.class), + @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List"), + @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List"), + @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List"), + @ParameterizedInfo(Class.class)}, + isVarArgs = true) public void qux(int quux, Foo quuux, List l, List l2, List l3, String... rest) {} public class Inner { int thang; + @ExpectedParameterInfo(parameterCount = 2, + parameterTypes = {Foo.class, int.class}) public Inner(int theng) { thang = theng + thing; } } } - } From 320ce960ce44832016963f7356269e3ae6b63677 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Thu, 31 Jan 2013 13:13:14 -0800 Subject: [PATCH 037/158] 8007298: Base64.getMimeDecoder().decode() throws IAE for a single non-base64 character 8006526: Base64.Decoder.decode(String) spec contains a copy-paste mistake To ignore single non-base64 char in mime decoding Reviewed-by: alanb --- jdk/src/share/classes/java/util/Base64.java | 7 +++++-- jdk/test/java/util/Base64/TestBase64.java | 18 +++++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/java/util/Base64.java b/jdk/src/share/classes/java/util/Base64.java index 7a01c05e653..471b4e28620 100644 --- a/jdk/src/share/classes/java/util/Base64.java +++ b/jdk/src/share/classes/java/util/Base64.java @@ -696,7 +696,7 @@ public class Base64 { * using the {@link Base64} encoding scheme. * *

An invocation of this method has exactly the same effect as invoking - * {@code return decode(src.getBytes(StandardCharsets.ISO_8859_1))} + * {@code decode(src.getBytes(StandardCharsets.ISO_8859_1))} * * @param src * the string to decode @@ -1014,9 +1014,12 @@ public class Base64 { int len = sl - sp; if (len == 0) return 0; - if (len < 2) + if (len < 2) { + if (isMIME && base64[0] == -1) + return 0; throw new IllegalArgumentException( "Input byte[] should at least have 2 bytes for base64 bytes"); + } if (src[sl - 1] == '=') { paddings++; if (src[sl - 2] == '=') diff --git a/jdk/test/java/util/Base64/TestBase64.java b/jdk/test/java/util/Base64/TestBase64.java index 645f570b0f3..0a8eea6e4aa 100644 --- a/jdk/test/java/util/Base64/TestBase64.java +++ b/jdk/test/java/util/Base64/TestBase64.java @@ -22,7 +22,7 @@ */ /** - * @test 4235519 8004212 8005394 + * @test 4235519 8004212 8005394 8007298 * @summary tests java.util.Base64 */ @@ -109,6 +109,9 @@ public class TestBase64 { // test return value from decode(ByteBuffer, ByteBuffer) testDecBufRet(); + + // test single-non-base64 character for mime decoding + testSingleNonBase64MimeDec(); } private static sun.misc.BASE64Encoder sunmisc = new sun.misc.BASE64Encoder(); @@ -356,6 +359,19 @@ public class TestBase64 { } catch (IllegalArgumentException iae) {} } + // single-non-base64-char should be ignored for mime decoding, but + // iae for basic decoding + private static void testSingleNonBase64MimeDec() throws Throwable { + for (String nonBase64 : new String[] {"#", "(", "!", "\\", "-", "_"}) { + if (Base64.getMimeDecoder().decode(nonBase64).length != 0) { + throw new RuntimeException("non-base64 char is not ignored"); + } + try { + Base64.getDecoder().decode(nonBase64); + throw new RuntimeException("No IAE for single non-base64 char"); + } catch (IllegalArgumentException iae) {} + } + } private static void testDecBufRet() throws Throwable { Random rnd = new java.util.Random(); From 665fca9d60704d2dad7b0611f4b73adabd0e659a Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Thu, 31 Jan 2013 13:27:04 -0800 Subject: [PATCH 038/158] 8006709: Add minimal support of MacOSX platform for NetBeans Projects Adds support for MacOSX platform and architecture detection. Other minor updates (-source/target 1.8) Reviewed-by: ohair --- .../architectures/arch-x86_64.properties | 32 +++++++++++++++++++ .../architectures/name-Macosx.properties | 32 +++++++++++++++++++ jdk/make/netbeans/common/java-data-native.ent | 4 +-- .../netbeans/common/java-data-no-native.ent | 4 +-- jdk/make/netbeans/common/make.xml | 7 +++- jdk/make/netbeans/common/shared.xml | 7 ++-- 6 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 jdk/make/netbeans/common/architectures/arch-x86_64.properties create mode 100644 jdk/make/netbeans/common/architectures/name-Macosx.properties diff --git a/jdk/make/netbeans/common/architectures/arch-x86_64.properties b/jdk/make/netbeans/common/architectures/arch-x86_64.properties new file mode 100644 index 00000000000..eac11240e57 --- /dev/null +++ b/jdk/make/netbeans/common/architectures/arch-x86_64.properties @@ -0,0 +1,32 @@ +# +# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# - Neither the name of Oracle nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +arch=x86_64 diff --git a/jdk/make/netbeans/common/architectures/name-Macosx.properties b/jdk/make/netbeans/common/architectures/name-Macosx.properties new file mode 100644 index 00000000000..05744c7f05c --- /dev/null +++ b/jdk/make/netbeans/common/architectures/name-Macosx.properties @@ -0,0 +1,32 @@ +# +# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# - Neither the name of Oracle nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +platform=macosx diff --git a/jdk/make/netbeans/common/java-data-native.ent b/jdk/make/netbeans/common/java-data-native.ent index a801e821db6..8db2a86d618 100644 --- a/jdk/make/netbeans/common/java-data-native.ent +++ b/jdk/make/netbeans/common/java-data-native.ent @@ -39,11 +39,11 @@ ${bootstrap.jdk}/jre/lib/rt.jar ${root}/build/${platform}-${arch}/classes ${root}/build/${platform}-${arch}/docs/api - 1.7 + 1.8 ${root}/test - 1.7 + 1.8 diff --git a/jdk/make/netbeans/common/java-data-no-native.ent b/jdk/make/netbeans/common/java-data-no-native.ent index a204f3a6f17..240ec4aadc9 100644 --- a/jdk/make/netbeans/common/java-data-no-native.ent +++ b/jdk/make/netbeans/common/java-data-no-native.ent @@ -37,11 +37,11 @@ ${bootstrap.jdk}/jre/lib/rt.jar ${root}/build/${platform}-${arch}/classes ${root}/build/${platform}-${arch}/docs/api - 1.7 + 1.8 ${root}/test - 1.7 + 1.8 diff --git a/jdk/make/netbeans/common/make.xml b/jdk/make/netbeans/common/make.xml index a61f04f07db..ee1a47a4fe1 100644 --- a/jdk/make/netbeans/common/make.xml +++ b/jdk/make/netbeans/common/make.xml @@ -33,7 +33,7 @@ - + @@ -42,6 +42,11 @@ + + + + + diff --git a/jdk/make/netbeans/common/shared.xml b/jdk/make/netbeans/common/shared.xml index 7c2b8095f79..ba104445273 100644 --- a/jdk/make/netbeans/common/shared.xml +++ b/jdk/make/netbeans/common/shared.xml @@ -85,6 +85,9 @@ + + + @@ -126,10 +129,6 @@ - - - - From 6b6febce981413881bccfd238c456a0bdbd63352 Mon Sep 17 00:00:00 2001 From: Tim Bell Date: Thu, 31 Jan 2013 13:31:30 -0800 Subject: [PATCH 039/158] 8006933: Need to use nawk on Solaris to avoid awk limitations Reviewed-by: erikj, dholmes, dsamersoff --- common/makefiles/IdlCompilation.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/makefiles/IdlCompilation.gmk b/common/makefiles/IdlCompilation.gmk index 6dc5fee2999..2eb77dd3beb 100644 --- a/common/makefiles/IdlCompilation.gmk +++ b/common/makefiles/IdlCompilation.gmk @@ -71,7 +71,7 @@ define add_idl_package $4 $(RM) -f $$(addprefix $3/$$($4_TMPDIR)/,$6) $(CP) -rp $3/$$($4_TMPDIR)/* $3 - ($(CD) $3/$$($4_TMPDIR); find . -type f | sed 's!\./!$3/!g' | awk '{ print $$$$1 ": $4" }' > $5) + ($(CD) $3/$$($4_TMPDIR) && $(FIND) . -type f | $(SED) 's!\./!$3/!g' | $(NAWK) '{ print $$$$1 ": $4" }' > $5) $(RM) -rf $3/$$($4_TMPDIR) endef From f7f0768c22be02b8e88f44c7b023bbe079f083a4 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Thu, 31 Jan 2013 14:29:19 -0800 Subject: [PATCH 040/158] 6355704: (fmt) %f formatting of BigDecimals is incorrect Reviewed-by: darcy --- jdk/test/java/util/Formatter/Basic-X.java.template | 9 +++++++++ jdk/test/java/util/Formatter/BasicBigDecimal.java | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/jdk/test/java/util/Formatter/Basic-X.java.template b/jdk/test/java/util/Formatter/Basic-X.java.template index 55b24097f6e..831c49212f0 100644 --- a/jdk/test/java/util/Formatter/Basic-X.java.template +++ b/jdk/test/java/util/Formatter/Basic-X.java.template @@ -1103,6 +1103,15 @@ public class Basic$Type$ extends Basic { test("%.5f", "1.99999", val); test("%.6f", "1.999990", val); + val = new BigDecimal(0.9996); + test("%.0f", "1", val); + test("%.1f", "1.0", val); + test("%.2f", "1.00", val); + test("%.3f", "1.000", val); + test("%.4f", "0.9996", val); + test("%.5f", "0.99960", val); + test("%.6f", "0.999600", val); + #end[BigDecimal] #if[float] diff --git a/jdk/test/java/util/Formatter/BasicBigDecimal.java b/jdk/test/java/util/Formatter/BasicBigDecimal.java index afc446ae4b0..6f36201aa34 100644 --- a/jdk/test/java/util/Formatter/BasicBigDecimal.java +++ b/jdk/test/java/util/Formatter/BasicBigDecimal.java @@ -1102,6 +1102,15 @@ public class BasicBigDecimal extends Basic { test("%.4f", "2.0000", val); test("%.5f", "1.99999", val); test("%.6f", "1.999990", val); + + val = new BigDecimal(0.9996); + test("%.0f", "1", val); + test("%.1f", "1.0", val); + test("%.2f", "1.00", val); + test("%.3f", "1.000", val); + test("%.4f", "0.9996", val); + test("%.5f", "0.99960", val); + test("%.6f", "0.999600", val); From 0c6cb9cdc2f088b887efdf3599213f39208f191c Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Fri, 1 Feb 2013 07:39:41 +0800 Subject: [PATCH 041/158] 8006564: Test sun/security/util/Oid/S11N.sh fails with timeout on Linux 32-bit Reviewed-by: alanb --- jdk/test/sun/security/util/Oid/S11N.java | 246 ++++++++++++++++++ jdk/test/sun/security/util/Oid/S11N.sh | 188 ------------- .../sun/security/util/Oid/SerialTest.java | 66 ----- 3 files changed, 246 insertions(+), 254 deletions(-) create mode 100644 jdk/test/sun/security/util/Oid/S11N.java delete mode 100644 jdk/test/sun/security/util/Oid/S11N.sh delete mode 100644 jdk/test/sun/security/util/Oid/SerialTest.java diff --git a/jdk/test/sun/security/util/Oid/S11N.java b/jdk/test/sun/security/util/Oid/S11N.java new file mode 100644 index 00000000000..a5595d10112 --- /dev/null +++ b/jdk/test/sun/security/util/Oid/S11N.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @bug 4811968 6908628 8006564 + * @run main S11N check + * @summary Serialization compatibility with old versions (and fixes) + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.HashMap; +import java.util.Map; +import sun.misc.BASE64Encoder; +import sun.security.util.ObjectIdentifier; + +public class S11N { + static String[] SMALL= { + "0.0", + "1.1", + "2.2", + "1.2.3456", + "1.2.2147483647.4", + "1.2.268435456.4", + }; + + static String[] HUGE = { + "2.16.764.1.3101555394.1.0.100.2.1", + "1.2.2147483648.4", + "2.3.4444444444444444444444", + "1.2.8888888888888888.33333333333333333.44444444444444", + }; + + // Do not use j.u.Base64, the test needs to run in jdk6 + static BASE64Encoder encoder = new BASE64Encoder() { + @Override + protected int bytesPerLine() { + return 48; + } + }; + + public static void main(String[] args) throws Exception { + if (args[0].equals("check")) { + int version = Integer.valueOf(System.getProperty("java.version") + .split("\\.")[1]); + System.out.println("version is " + version); + if (version >= 7) { + for (String oid: SMALL) { + // 7 -> 7 + check(out(oid), oid); + // 6 -> 7 + check(out6(oid), oid); + } + for (String oid: HUGE) { + // 7 -> 7 + check(out(oid), oid); + } + } else { + for (String oid: SMALL) { + // 6 -> 6 + check(out(oid), oid); + // 7 -> 6 + check(out7(oid), oid); + } + for (String oid: HUGE) { + // 7 -> 6 fails for HUGE oids + boolean ok = false; + try { + check(out7(oid), oid); + ok = true; + } catch (Exception e) { + System.out.println(e); + } + if (ok) { + throw new Exception(); + } + } + } + } else { + // Generates the JDK6 serialized string inside this test, call + // $JDK7/bin/java S11N dump7 + // $JDK6/bin/java S11N dump6 + // and paste the output at the end of this test. + dump(args[0], SMALL); + // For jdk6, the following line will throw an exception, ignore it + dump(args[0], HUGE); + } + } + + // Gets the serialized form for jdk6 + private static byte[] out6(String oid) throws Exception { + return new sun.misc.BASE64Decoder().decodeBuffer(dump6.get(oid)); + } + + // Gets the serialized form for jdk7 + private static byte[] out7(String oid) throws Exception { + return new sun.misc.BASE64Decoder().decodeBuffer(dump7.get(oid)); + } + + // Gets the serialized form for this java + private static byte[] out(String oid) throws Exception { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + new ObjectOutputStream(bout).writeObject(new ObjectIdentifier(oid)); + return bout.toByteArray(); + } + + // Makes sure serialized form can be deserialized + private static void check(byte[] in, String oid) throws Exception { + ObjectIdentifier o = (ObjectIdentifier) ( + new ObjectInputStream(new ByteArrayInputStream(in)).readObject()); + if (!o.toString().equals(oid)) { + throw new Exception("Read Fail " + o + ", not " + oid); + } + } + + // dump serialized form to java code style text + private static void dump(String title, String[] oids) throws Exception { + for (String oid: oids) { + String[] base64 = encoder.encodeBuffer(out(oid)).split("\n"); + System.out.println(" " + title + ".put(\"" + oid + "\","); + for (int i = 0; i dump7 = new HashMap(); + private static Map dump6 = new HashMap(); + + static { + ////////////// PASTE BEGIN ////////////// + dump7.put("0.0", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAACAAAAAAAAAAB1cgACW0Ks8xf4BghU4AIAAHhwAAAAAQB4"); + dump7.put("1.1", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAACAAAAAQAAAAF1cgACW0Ks8xf4BghU4AIAAHhwAAAAASl4"); + dump7.put("2.2", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAAnVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAACAAAAAgAAAAJ1cgACW0Ks8xf4BghU4AIAAHhwAAAAAVJ4"); + dump7.put("1.2.3456", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAAA3VyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAADAAAAAQAAAAIAAA2AdXIAAltCrPMX+AYIVOACAAB4cAAAAAMqmwB4"); + dump7.put("1.2.2147483647.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAABHVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAAEAAAAAQAAAAJ/////AAAABHVyAAJbQqzzF/gGCFTgAgAAeHAAAAAHKof///9/" + + "BHg="); + dump7.put("1.2.268435456.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhwAAAABHVyAAJbSU26YCZ26rKlAgAAeHAA" + + "AAAEAAAAAQAAAAIQAAAAAAAABHVyAAJbQqzzF/gGCFTgAgAAeHAAAAAHKoGAgIAA" + + "BHg="); + dump7.put("2.16.764.1.3101555394.1.0.100.2.1", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + + "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + + "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAADmCFfAGLxvf1QgEAZAIB" + + "eA=="); + dump7.put("1.2.2147483648.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + + "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + + "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAAByqIgICAAAR4"); + dump7.put("2.3.4444444444444444444444", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + + "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + + "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAADFOD4e+HpNG968eOHHg="); + dump7.put("1.2.8888888888888888.33333333333333333.44444444444444", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4DAANJAAxjb21wb25lbnRMZW5MAApjb21wb25lbnRzdAASTGphdmEvbGFuZy9P" + + "YmplY3Q7WwAIZW5jb2Rpbmd0AAJbQnhw/////3NyAD5zdW4uc2VjdXJpdHkudXRp" + + "bC5PYmplY3RJZGVudGlmaWVyJEh1Z2VPaWROb3RTdXBwb3J0ZWRCeU9sZEpESwAA" + + "AAAAAAABAgAAeHB1cgACW0Ks8xf4BghU4AIAAHhwAAAAGCqP5Yzbxa6cOLubj9ek" + + "japVio3AusuOHHg="); + + dump6.put("0.0", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" + + "W0lNumAmduqypQIAAHhwAAAAAgAAAAAAAAAA"); + dump6.put("1.1", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" + + "W0lNumAmduqypQIAAHhwAAAAAgAAAAEAAAAB"); + dump6.put("2.2", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAJ1cgAC" + + "W0lNumAmduqypQIAAHhwAAAAAgAAAAIAAAAC"); + dump6.put("1.2.3456", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAN1cgAC" + + "W0lNumAmduqypQIAAHhwAAAAAwAAAAEAAAACAAANgA=="); + dump6.put("1.2.2147483647.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAR1cgAC" + + "W0lNumAmduqypQIAAHhwAAAABAAAAAEAAAACf////wAAAAQ="); + dump6.put("1.2.268435456.4", + "rO0ABXNyACJzdW4uc2VjdXJpdHkudXRpbC5PYmplY3RJZGVudGlmaWVyeLIO7GQX" + + "fy4CAAJJAAxjb21wb25lbnRMZW5bAApjb21wb25lbnRzdAACW0l4cAAAAAR1cgAC" + + "W0lNumAmduqypQIAAHhwAAAABAAAAAEAAAACEAAAAAAAAAQ="); + ////////////// PASTE END ////////////// + } +} diff --git a/jdk/test/sun/security/util/Oid/S11N.sh b/jdk/test/sun/security/util/Oid/S11N.sh deleted file mode 100644 index a19af17be5f..00000000000 --- a/jdk/test/sun/security/util/Oid/S11N.sh +++ /dev/null @@ -1,188 +0,0 @@ -# -# Copyright (c) 2004, 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. -# -# 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. -# -# @test -# @bug 4811968 6908628 -# @summary Serialization compatibility with old versions (and fix) -# @author Weijun Wang -# -# set a few environment variables so that the shell-script can run stand-alone -# in the source directory - -if [ "${TESTSRC}" = "" ] ; then - TESTSRC="." -fi -if [ "${TESTCLASSES}" = "" ] ; then - TESTCLASSES="." -fi -if [ "${TESTJAVA}" = "" ] ; then - echo "TESTJAVA not set. Test cannot execute." - echo "FAILED!!!" - exit 1 -fi -if [ "${COMPILEJAVA}" = "" ]; then - COMPILEJAVA="${TESTJAVA}" -fi - -# set platform-dependent variables -PF="" - -OS=`uname -s` -case "$OS" in - SunOS ) - FS="/" - ARCH=`isainfo` - case "$ARCH" in - sparc* ) - PF="solaris-sparc" - ;; - i[3-6]86 ) - PF="solaris-i586" - ;; - amd64* ) - PF="solaris-amd64" - ;; - * ) - echo "Unsupported System: Solaris ${ARCH}" - exit 0; - ;; - esac - ;; - Linux ) - ARCH=`uname -m` - FS="/" - case "$ARCH" in - i[3-6]86 ) - PF="linux-i586" - ;; - amd64* | x86_64 ) - PF="linux-amd64" - ;; - * ) - echo "Unsupported System: Linux ${ARCH}" - exit 0; - ;; - esac - ;; - Windows* ) - FS="\\" - PF="windows-i586" - - # 'uname -m' does not give us enough information - - # should rely on $PROCESSOR_IDENTIFIER (as is done in Defs-windows.gmk), - # but JTREG does not pass this env variable when executing a shell script. - # - # execute test program - rely on it to exit if platform unsupported - - ;; - * ) - echo "Unsupported System: ${OS}" - exit 0; - ;; -esac - -echo "===================================================" -echo "Try to set ALT_JAVA_RE_JDK if you see timeout error" -echo "===================================================" - -# the test code - -${COMPILEJAVA}${FS}bin${FS}javac -target 1.4 -source 1.4 \ - -d . ${TESTSRC}${FS}SerialTest.java || exit 10 - -# You can set ALT_JAVA_RE_JDK to another location that contains the -# binaries for older JDK releases. You can set it to a non-existent -# directory to skip the interop tests between different versions. - -if [ "$ALT_JAVA_RE_JDK" = "" ]; then - JAVA_RE_JDK=/java/re/j2se -else - JAVA_RE_JDK=$ALT_JAVA_RE_JDK -fi - -OLDJAVA=" - $JAVA_RE_JDK/1.6.0/latest/binaries/${PF} - $JAVA_RE_JDK/1.5.0/latest/binaries/${PF} - $JAVA_RE_JDK/1.4.2/latest/binaries/${PF} -" - -SMALL=" - 0.0 - 1.1 - 2.2 - 1.2.3456 - 1.2.2147483647.4 - 1.2.268435456.4 -" - -HUGE=" - 2.16.764.1.3101555394.1.0.100.2.1 - 1.2.2147483648.4 - 2.3.4444444444444444444444 - 1.2.888888888888888888.111111111111111.2222222222222.33333333333333333.44444444444444 -" - -for oid in ${SMALL}; do - echo ${oid} - # new -> - ${TESTJAVA}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial || exit 1 - # -> new - ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 2 - for oldj in ${OLDJAVA}; do - if [ -d ${oldj} ]; then - echo ${oldj} - # -> old - ${oldj}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 3 - # old -> - ${oldj}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial.old || exit 4 - # -> new - ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial.old || exit 5 - fi - done -done - -for oid in ${HUGE}; do - echo ${oid} - # new -> - ${TESTJAVA}${FS}bin${FS}java SerialTest out ${oid} > tmp.oid.serial || exit 1 - # -> new - ${TESTJAVA}${FS}bin${FS}java SerialTest in ${oid} < tmp.oid.serial || exit 2 - for oldj in ${OLDJAVA}; do - if [ -d ${oldj} ]; then - echo ${oldj} - # -> old - ${oldj}${FS}bin${FS}java SerialTest badin < tmp.oid.serial || exit 3 - fi - done -done - -rm -f tmp.oid.serial -rm -f tmp.oid.serial.old -rm -f SerialTest.class - -for oldj in ${OLDJAVA}; do - if [ ! -d ${oldj} ]; then - echo WARNING: ${oldj} is missing. Test incomplete! > /dev/stderr - fi -done - -exit 0 diff --git a/jdk/test/sun/security/util/Oid/SerialTest.java b/jdk/test/sun/security/util/Oid/SerialTest.java deleted file mode 100644 index ba127441cad..00000000000 --- a/jdk/test/sun/security/util/Oid/SerialTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2004, 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. - * - * 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. - */ - -/* - * read S11.sh - */ -import java.io.*; -import sun.security.util.*; - -/** - * Test OID serialization between versions - * - * java SerialTest out oid // write a OID into System.out - * java SerialTest in oid // read from System.in and compare it with oid - * java SerialTest badin // make sure *cannot* read from System.in - */ -class SerialTest { - public static void main(String[] args) throws Exception { - if (args[0].equals("out")) - out(args[1]); - else if (args[0].equals("in")) - in(args[1]); - else - badin(); - } - - static void in(String oid) throws Exception { - ObjectIdentifier o = (ObjectIdentifier) (new ObjectInputStream(System.in).readObject()); - if (!o.toString().equals(oid)) - throw new Exception("Read Fail " + o + ", not " + oid); - } - - static void badin() throws Exception { - boolean pass = true; - try { - new ObjectInputStream(System.in).readObject(); - } catch (Exception e) { - pass = false; - } - if (pass) throw new Exception("Should fail but not"); - } - - static void out(String oid) throws Exception { - new ObjectOutputStream(System.out).writeObject(new ObjectIdentifier(oid)); - } -} From f9329eb66f344eda820d8d4034bdbbe9af68f982 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 31 Jan 2013 17:04:19 -0800 Subject: [PATCH 042/158] Added tag jdk8-b75 for changeset a86f171d15a1 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 53096d3923b..4b6644480b7 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -196,3 +196,4 @@ cdb401a60cea6ad5ef3f498725ed1decf8dda1ea jdk8-b68 c1be681d80a1f1c848dc671d664fccb19e046a12 jdk8-b72 93b9664f97eeb6f89397a8842318ebacaac9feb9 jdk8-b73 b43aa5bd8ca5c8121336495382d35ecfa7a71536 jdk8-b74 +2a713921952cbd77a1e699626976cb6cdfe3e57e jdk8-b75 From 7ecc657cee4e28a89e4a06334dae901dd8cc9533 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 31 Jan 2013 17:04:24 -0800 Subject: [PATCH 043/158] Added tag jdk8-b75 for changeset 5aa96ebbc95e --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index c01bb26f197..294902d0bc8 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -196,3 +196,4 @@ d54dc53e223ed9ce7d5f4d2cd02ad9d5def3c2db jdk8-b59 cb40427f47145b01b7e53c3e02b38ff7625efbda jdk8-b72 191afde59e7be0e1a1d76d06f2a32ff17444f0ec jdk8-b73 2132845cf5f717ff5c240a2431c0c0e03e66e3a5 jdk8-b74 +d4e68ce17795601017ac2f952baad7272942c36e jdk8-b75 From 545ef0e5fe5a1ac74e95c5beeb8218c89a94c57f Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 31 Jan 2013 17:04:28 -0800 Subject: [PATCH 044/158] Added tag jdk8-b75 for changeset 3b129a5ff9fd --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index d46eb646def..494b1c8a523 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -311,3 +311,4 @@ d5cb5830f570d1304ea4b196dde672a291b55f29 jdk8-b72 70c89bd6b895a10d25ca70e08093c09ff2005fda hs25-b16 1a3e54283c54aaa8b3437813e8507fbdc966e5b6 jdk8-b74 b4391649e91ea8d37f66317a03d6d2573a93d10d hs25-b17 +6778d0b1659323a506ca47600ca29a9d9f8b383d jdk8-b75 From 34d99c6b392a2598cf8fc1d3b8f115fe00f8e0fc Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 31 Jan 2013 17:04:37 -0800 Subject: [PATCH 045/158] Added tag jdk8-b75 for changeset 504959da18bb --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 25b3727d9e6..172530e8a1a 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -196,3 +196,4 @@ b854e70084214e9dcf1b37373f6e4b1a68760e03 jdk8-b68 bdf2af722a6b54fca47d8c51d17a1b8f41dd7a3e jdk8-b72 84946404d1e1de003ed2bf218ef8d48906a90e37 jdk8-b73 2087e24a4357eceb6432e94918e75fdc706a27d6 jdk8-b74 +ff0b73a6b3f6cea644d37d56d746a37743419fa7 jdk8-b75 From 7c22c50e9e69743403dcea82aecf0ea05744b7c6 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 31 Jan 2013 17:04:40 -0800 Subject: [PATCH 046/158] Added tag jdk8-b75 for changeset bef9d985cc1c --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 1ae97b3df38..5811938d611 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -196,3 +196,4 @@ f577a39c9fb3d5820248c13c2cc74a192a9313e0 jdk8-b71 d9707230294d54e695e745a90de6112909100f12 jdk8-b72 c606f644a5d9118c14b5822738bf23c300f14f24 jdk8-b73 12db3c5a3393b03eeb09ff26f418c4420c21aaab jdk8-b74 +966bf9f3c41a59ff5d86ff4275291c52f329f984 jdk8-b75 From 79896f3eafe913fff55222f58f107cc90cd36017 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 31 Jan 2013 17:04:47 -0800 Subject: [PATCH 047/158] Added tag jdk8-b75 for changeset cfe93cb07f19 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index dbc8d128f1f..ac37d19a025 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -196,3 +196,4 @@ a996b57e554198f4592a5f3c30f2f9f4075e545d jdk8-b70 32a57e645e012a1f0665c075969ca598e0dbb948 jdk8-b72 733885f57e14cc27f5a5ff0dffe641d2fa3c704a jdk8-b73 57d5d954462831ac353a1f40d3bb05ddb4620952 jdk8-b74 +4a67fdb752b7d6329d9be9c28d3f9d6cf7eb9a3c jdk8-b75 From 2ccecb9e10d1375305ccf142352c47907c3b640c Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 31 Jan 2013 17:04:55 -0800 Subject: [PATCH 048/158] Added tag jdk8-b75 for changeset dbafd8b0d8a2 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index f4fbd85e67d..b29a3af53a1 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -196,3 +196,4 @@ d7360bf35ee1f40ff78c2e83a22b5446ee464346 jdk8-b69 6f0986ed9b7e11d6eb06618f27e20b18f19fb797 jdk8-b72 8d0baee36c7184d55c80354b45704c37d6b7ac79 jdk8-b73 56c97aff46bb577b8668874154c24115a7e8a3e8 jdk8-b74 +c2e11e2ec4a3682513e566849e5562f31ded8c65 jdk8-b75 From b543c19bac8cece7e4ad6b4f82077fd255dae76b Mon Sep 17 00:00:00 2001 From: Yumin Qi Date: Thu, 31 Jan 2013 17:43:01 -0800 Subject: [PATCH 049/158] 8000973: SA on windows thread inspection is broken After bug 7161732, On Windows SA could not find correct address of thread_id of OSThread since _thread_id moved to end of the class . The presupposition of the address is following thread handle no longer stands. Fix by adding thread_id field to OSThread and getting the address directly from OSThread. Reviewed-by: nloodin, sspitsyn --- .../windbg/amd64/WindbgAMD64Thread.java | 18 ++++-------------- .../debugger/windbg/x86/WindbgX86Thread.java | 18 ++++-------------- .../sun/jvm/hotspot/runtime/OSThread.java | 9 ++++++++- .../Win32AMD64JavaThreadPDAccess.java | 14 +++++++------- .../win32_x86/Win32X86JavaThreadPDAccess.java | 14 +++++++------- 5 files changed, 30 insertions(+), 43 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java index bf30dd0a5bf..ec5aea35e8c 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -34,21 +34,11 @@ class WindbgAMD64Thread implements ThreadProxy { private boolean gotID; private long id; - /** The address argument must be the address of the HANDLE of the - desired thread in the target process. */ + // The address argument must be the address of the OSThread::_thread_id WindbgAMD64Thread(WindbgDebugger debugger, Address addr) { this.debugger = debugger; - // FIXME: size of data fetched here should be configurable. - // However, making it so would produce a dependency on the "types" - // package from the debugger package, which is not desired. - - // another hack here is that we use sys thread id instead of handle. - // windbg can't get details based on handles it seems. - // I assume that osThread_win32 thread struct has _thread_id (which - // sys thread id) just after handle field. - - this.sysId = (int) addr.addOffsetTo(debugger.getAddressSize()).getCIntegerAt(0, 4, true); - gotID = false; + this.sysId = (long)addr.getCIntegerAt(0, 4, true); + gotID = false; } WindbgAMD64Thread(WindbgDebugger debugger, long sysId) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java index 84d19e03bc0..e5417972b13 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -34,21 +34,11 @@ class WindbgX86Thread implements ThreadProxy { private boolean gotID; private long id; - /** The address argument must be the address of the HANDLE of the - desired thread in the target process. */ + // The address argument must be the address of OSThread::_thread_id WindbgX86Thread(WindbgDebugger debugger, Address addr) { this.debugger = debugger; - // FIXME: size of data fetched here should be configurable. - // However, making it so would produce a dependency on the "types" - // package from the debugger package, which is not desired. - - // another hack here is that we use sys thread id instead of handle. - // windbg can't get details based on handles it seems. - // I assume that osThread_win32 thread struct has _thread_id (which - // sys thread id) just after handle field. - - this.sysId = (int) addr.addOffsetTo(debugger.getAddressSize()).getCIntegerAt(0, 4, true); - gotID = false; + this.sysId = (long)addr.getCIntegerAt(0, 4, true); + gotID = false; } WindbgX86Thread(WindbgDebugger debugger, long sysId) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java index cdcbf113871..fb17c53d329 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -32,6 +32,7 @@ import sun.jvm.hotspot.types.*; // to the sys_thread_t structure of the classic JVM implementation. public class OSThread extends VMObject { private static JIntField interruptedField; + private static JIntField threadIdField; static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -43,6 +44,7 @@ public class OSThread extends VMObject { private static synchronized void initialize(TypeDataBase db) { Type type = db.lookupType("OSThread"); interruptedField = type.getJIntField("_interrupted"); + threadIdField = type.getJIntField("_thread_id"); } public OSThread(Address addr) { @@ -52,4 +54,9 @@ public class OSThread extends VMObject { public boolean interrupted() { return ((int)interruptedField.getValue(addr)) != 0; } + + public int threadId() { + return (int)threadIdField.getValue(addr); + } + } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java index e18dd4f8053..86255a48f6e 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -43,7 +43,7 @@ public class Win32AMD64JavaThreadPDAccess implements JavaThreadPDAccess { private static AddressField osThreadField; // Field from OSThread - private static Field osThreadThreadHandleField; + private static Field osThreadThreadIdField; // This is currently unneeded but is being kept in case we change // the currentFrameGuess algorithm @@ -64,7 +64,7 @@ public class Win32AMD64JavaThreadPDAccess implements JavaThreadPDAccess { osThreadField = type.getAddressField("_osthread"); type = db.lookupType("OSThread"); - osThreadThreadHandleField = type.getField("_thread_handle"); + osThreadThreadIdField = type.getField("_thread_id"); } public Address getLastJavaFP(Address addr) { @@ -128,10 +128,10 @@ public class Win32AMD64JavaThreadPDAccess implements JavaThreadPDAccess { // Fetch the OSThread (for now and for simplicity, not making a // separate "OSThread" class in this package) Address osThreadAddr = osThreadField.getValue(addr); - // Get the address of the HANDLE within the OSThread - Address threadHandleAddr = - osThreadAddr.addOffsetTo(osThreadThreadHandleField.getOffset()); + // Get the address of the thread_id within the OSThread + Address threadIdAddr = + osThreadAddr.addOffsetTo(osThreadThreadIdField.getOffset()); JVMDebugger debugger = VM.getVM().getDebugger(); - return debugger.getThreadForIdentifierAddress(threadHandleAddr); + return debugger.getThreadForIdentifierAddress(threadIdAddr); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java index dff6615a008..435e4762335 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -42,7 +42,7 @@ public class Win32X86JavaThreadPDAccess implements JavaThreadPDAccess { private static AddressField osThreadField; // Field from OSThread - private static Field osThreadThreadHandleField; + private static Field osThreadThreadIdField; // This is currently unneeded but is being kept in case we change // the currentFrameGuess algorithm @@ -63,7 +63,7 @@ public class Win32X86JavaThreadPDAccess implements JavaThreadPDAccess { osThreadField = type.getAddressField("_osthread"); type = db.lookupType("OSThread"); - osThreadThreadHandleField = type.getField("_thread_handle"); + osThreadThreadIdField = type.getField("_thread_id"); } public Address getLastJavaFP(Address addr) { @@ -127,10 +127,10 @@ public class Win32X86JavaThreadPDAccess implements JavaThreadPDAccess { // Fetch the OSThread (for now and for simplicity, not making a // separate "OSThread" class in this package) Address osThreadAddr = osThreadField.getValue(addr); - // Get the address of the HANDLE within the OSThread - Address threadHandleAddr = - osThreadAddr.addOffsetTo(osThreadThreadHandleField.getOffset()); + // Get the address of the thread_id within the OSThread + Address threadIdAddr = + osThreadAddr.addOffsetTo(osThreadThreadIdField.getOffset()); JVMDebugger debugger = VM.getVM().getDebugger(); - return debugger.getThreadForIdentifierAddress(threadHandleAddr); + return debugger.getThreadForIdentifierAddress(threadIdAddr); } } From 71b457cb970e0bb791bf79a9f2707f453f861eab Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 31 Jan 2013 18:58:17 -0800 Subject: [PATCH 050/158] 8007351: Malformed copyright statements in typeAnnotations test directory Reviewed-by: jjg --- .../typeAnnotations/TargetTypes.java | 2 +- .../typeAnnotations/TypeProcOnly.java | 2 +- .../api/AnnotatedArrayOrder.java | 2 +- .../typeAnnotations/api/ArrayCreationTree.java | 2 +- .../api/ArrayPositionConsistency.java | 2 +- .../classfile/ClassfileTestHelper.java | 2 +- .../classfile/CombinationsTargetTest1.java | 2 +- .../classfile/CombinationsTargetTest2.java | 2 +- .../classfile/NewTypeArguments.java | 2 +- .../classfile/NoTargetAnnotations.java | 2 +- .../typeAnnotations/classfile/TypeCasts.java | 2 +- .../typeAnnotations/classfile/Wildcards.java | 2 +- .../failures/target/DotClass.java | 18 +++++++++--------- .../typeAnnotations/newlocations/Varargs.java | 7 +++---- .../packageanno/PackageProcessor.java | 2 +- .../packageanno/mypackage/Anno.java | 2 +- .../packageanno/mypackage/MyClass.java | 2 +- .../packageanno/mypackage/package-info.java | 2 +- .../referenceinfos/ClassExtends.java | 2 +- .../referenceinfos/ClassTypeParam.java | 2 +- .../referenceinfos/Constructors.java | 2 +- .../typeAnnotations/referenceinfos/Driver.java | 2 +- .../referenceinfos/ExceptionParameters.java | 2 +- .../typeAnnotations/referenceinfos/Fields.java | 2 +- .../referenceinfos/FromSpecification.java | 2 +- .../referenceinfos/MethodParameters.java | 2 +- .../referenceinfos/MethodReceivers.java | 2 +- .../referenceinfos/MethodReturns.java | 2 +- .../referenceinfos/MethodThrows.java | 2 +- .../referenceinfos/MethodTypeParam.java | 2 +- .../referenceinfos/MultiCatch.java | 2 +- .../referenceinfos/NestedTypes.java | 2 +- .../referenceinfos/NewObjects.java | 2 +- .../referenceinfos/ReferenceInfoUtil.java | 2 +- .../RepeatingTypeAnnotations.java | 2 +- .../referenceinfos/TypeCasts.java | 2 +- .../referenceinfos/TypeTests.java | 2 +- 37 files changed, 47 insertions(+), 48 deletions(-) diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java b/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java index f808a8d4cda..8ffa7e5b53c 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java b/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java index 73d28971ee0..31ec31adceb 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/api/AnnotatedArrayOrder.java b/langtools/test/tools/javac/annotations/typeAnnotations/api/AnnotatedArrayOrder.java index 947b46536cc..68f11f5e64c 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/api/AnnotatedArrayOrder.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/api/AnnotatedArrayOrder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayCreationTree.java b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayCreationTree.java index 55f81eb7cf6..952f37c2b92 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayCreationTree.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayCreationTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayPositionConsistency.java b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayPositionConsistency.java index 7d00ef3aa19..1b73d918a03 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayPositionConsistency.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/api/ArrayPositionConsistency.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java index a06407e0144..b02621639aa 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java index dfab97807c2..ed3c094685c 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java index 77fb9a8aa1e..e3414db9f98 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NewTypeArguments.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NewTypeArguments.java index 84b9a85b3ae..f39857cada1 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NewTypeArguments.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NewTypeArguments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NoTargetAnnotations.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NoTargetAnnotations.java index 6458d54234b..a5dc098811b 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NoTargetAnnotations.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/NoTargetAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeCasts.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeCasts.java index 18f8e3b36bd..5529fa5a664 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeCasts.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/TypeCasts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/classfile/Wildcards.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/Wildcards.java index d4621047ac5..e0301520d74 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/Wildcards.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/Wildcards.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.java b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.java index 9aaa99e7e99..6363da0a301 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/target/DotClass.java @@ -1,13 +1,5 @@ -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.ElementType.TYPE_PARAMETER; -import static java.lang.annotation.ElementType.TYPE_USE; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -36,6 +28,14 @@ import java.lang.annotation.Target; * @compile/fail/ref=DotClass.out -XDrawDiagnostics DotClass.java */ +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.ElementType.TYPE_PARAMETER; +import static java.lang.annotation.ElementType.TYPE_USE; + @Target({TYPE_USE, TYPE_PARAMETER, TYPE}) @Retention(RetentionPolicy.RUNTIME) @interface A {} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Varargs.java b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Varargs.java index d28c108a6c6..e0c3082ebb6 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Varargs.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/newlocations/Varargs.java @@ -1,6 +1,5 @@ - /* - * Copyright (c) 2008 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -22,8 +21,6 @@ * questions. */ -import java.lang.annotation.*; - /* * @test * @summary test acceptance of varargs annotations @@ -31,6 +28,8 @@ import java.lang.annotation.*; * @compile Varargs.java */ +import java.lang.annotation.*; + @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER}) @interface A {} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java index 4f0d56522f9..02e20ad3b19 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java index 25f05341fbc..901cb6c9850 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java index e955ffc825e..98f9e433880 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/package-info.java b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/package-info.java index f80bd8afa53..bcd7fb672e8 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/package-info.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java index 5fd9751879a..4d5f2db0a12 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassExtends.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassTypeParam.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassTypeParam.java index 0d82706984f..2fca8089824 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassTypeParam.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ClassTypeParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java index 2ad8b31badc..bbdcba3f319 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java index 052d11a77a2..042b7b0b1db 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Driver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java index 70ca77aa560..a7c2818cf5d 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ExceptionParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java index d352fa79b23..91bc6496a98 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/FromSpecification.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/FromSpecification.java index e8e111d8c30..c3006390219 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/FromSpecification.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/FromSpecification.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java index cfe36ed9ae2..c23636c2f82 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReceivers.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReceivers.java index c834d0cef56..dc19f8d12fd 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReceivers.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReceivers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReturns.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReturns.java index 07fc9f23742..b6946817666 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReturns.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodReturns.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodThrows.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodThrows.java index 155e4bbfb71..457ca5b0a10 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodThrows.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodThrows.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodTypeParam.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodTypeParam.java index 4b7b521904f..5798eaa9b49 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodTypeParam.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MethodTypeParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MultiCatch.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MultiCatch.java index d62d52ff158..69694e453be 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MultiCatch.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/MultiCatch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java index 476e23f05ce..e98df7bd0c2 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NewObjects.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NewObjects.java index b56dbb74d23..fb3e3f55eeb 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NewObjects.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/NewObjects.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java index 0a94ee07de3..33ae4edaabf 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ReferenceInfoUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/RepeatingTypeAnnotations.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/RepeatingTypeAnnotations.java index 2755b4871c7..22982ae4d27 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/RepeatingTypeAnnotations.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/RepeatingTypeAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * 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 diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java index c77dcdc5857..84e5e01b358 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeCasts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeTests.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeTests.java index 5aa07b88db6..3b319197afe 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeTests.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/TypeTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 From 64ef3bfccc0e26860369c1a3c2af293846c1f5f3 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 31 Jan 2013 19:19:40 -0800 Subject: [PATCH 051/158] 8007329: minor issues in impl class hierarchry for DCTree.* classes Reviewed-by: darcy --- .../share/classes/com/sun/tools/javac/tree/DCTree.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java b/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java index e49cabe0838..c2ca23caf4b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/DCTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -119,7 +119,7 @@ public abstract class DCTree implements DocTree { } - public static abstract class DCBlockTag extends DCTree implements InlineTagTree { + public static abstract class DCBlockTag extends DCTree implements BlockTagTree { public String getTagName() { return getKind().tagName; } @@ -169,7 +169,7 @@ public abstract class DCTree implements DocTree { } } - public static class DCAuthor extends DCInlineTag implements AuthorTree { + public static class DCAuthor extends DCBlockTag implements AuthorTree { public final List name; DCAuthor(List name) { @@ -640,7 +640,7 @@ public abstract class DCTree implements DocTree { } } - public static class DCSince extends DCInlineTag implements SinceTree { + public static class DCSince extends DCBlockTag implements SinceTree { public final List body; DCSince(List body) { From 9bf4d2f978334791faf107a406870e1316b18cb2 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Thu, 31 Jan 2013 19:31:37 -0800 Subject: [PATCH 052/158] 8004353: Generated html is wrong for overview.html; content has incorrect css footer class Reviewed-by: jjg --- .../tools/doclets/formats/html/PackageIndexWriter.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java index 77d2bae2fe4..c5df5f3413a 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.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 @@ -196,10 +196,7 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter { protected void addOverviewComment(Content htmltree) { if (root.inlineTags().length > 0) { htmltree.addContent(getMarkerAnchor("overview_description")); - HtmlTree div = new HtmlTree(HtmlTag.DIV); - div.addStyle(HtmlStyle.subTitle); - addInlineComment(root, div); - htmltree.addContent(div); + addInlineComment(root, htmltree); } } @@ -211,7 +208,7 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter { */ protected void addOverview(Content body) throws IOException { HtmlTree div = new HtmlTree(HtmlTag.DIV); - div.addStyle(HtmlStyle.footer); + div.addStyle(HtmlStyle.contentContainer); addOverviewComment(div); addTagsInfo(root, div); body.addContent(div); From 823c749bd14cd3e956ad34d8f29ac43cdaacecef Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Thu, 31 Jan 2013 20:07:18 -0800 Subject: [PATCH 053/158] 8006542: JSR 292: the VM_RedefineClasses::append_entry() must support invokedynamic entry kinds Need a support for invokedynamic entry kinds when new and old constant pools are merged. Reviewed-by: coleenp, twisti --- .../share/vm/prims/jvmtiRedefineClasses.cpp | 236 ++++++++---------- .../share/vm/prims/jvmtiRedefineClasses.hpp | 5 +- 2 files changed, 110 insertions(+), 131 deletions(-) diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index 97799b9ad30..a09fa16ed0c 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -278,76 +278,23 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, case JVM_CONSTANT_NameAndType: { int name_ref_i = scratch_cp->name_ref_index_at(scratch_i); - int new_name_ref_i = 0; - bool match = (name_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(name_ref_i, *merge_cp_p, name_ref_i, - THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match - - int found_i = scratch_cp->find_matching_entry(name_ref_i, *merge_cp_p, - THREAD); - if (found_i != 0) { - guarantee(found_i != name_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_name_ref_i = found_i; - map_index(scratch_cp, name_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, name_ref_i, merge_cp_p, merge_cp_length_p, - THREAD); - // The above call to append_entry() can only append one entry - // so the post call query of *merge_cp_length_p is only for - // the sake of consistency. - new_name_ref_i = *merge_cp_length_p - 1; - } - } + int new_name_ref_i = find_or_append_indirect_entry(scratch_cp, name_ref_i, merge_cp_p, + merge_cp_length_p, THREAD); int signature_ref_i = scratch_cp->signature_ref_index_at(scratch_i); - int new_signature_ref_i = 0; - match = (signature_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(signature_ref_i, *merge_cp_p, - signature_ref_i, THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match - - int found_i = scratch_cp->find_matching_entry(signature_ref_i, - *merge_cp_p, THREAD); - if (found_i != 0) { - guarantee(found_i != signature_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_signature_ref_i = found_i; - map_index(scratch_cp, signature_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, signature_ref_i, merge_cp_p, - merge_cp_length_p, THREAD); - // The above call to append_entry() can only append one entry - // so the post call query of *merge_cp_length_p is only for - // the sake of consistency. - new_signature_ref_i = *merge_cp_length_p - 1; - } - } + int new_signature_ref_i = find_or_append_indirect_entry(scratch_cp, signature_ref_i, + merge_cp_p, merge_cp_length_p, + THREAD); // If the referenced entries already exist in *merge_cp_p, then // both new_name_ref_i and new_signature_ref_i will both be 0. // In that case, all we are appending is the current entry. - if (new_name_ref_i == 0) { - new_name_ref_i = name_ref_i; - } else { + if (new_name_ref_i != name_ref_i) { RC_TRACE(0x00080000, ("NameAndType entry@%d name_ref_index change: %d to %d", *merge_cp_length_p, name_ref_i, new_name_ref_i)); } - if (new_signature_ref_i == 0) { - new_signature_ref_i = signature_ref_i; - } else { + if (new_signature_ref_i != signature_ref_i) { RC_TRACE(0x00080000, ("NameAndType entry@%d signature_ref_index change: %d to %d", *merge_cp_length_p, signature_ref_i, new_signature_ref_i)); @@ -369,76 +316,12 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, case JVM_CONSTANT_Methodref: { int klass_ref_i = scratch_cp->uncached_klass_ref_index_at(scratch_i); - int new_klass_ref_i = 0; - bool match = (klass_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(klass_ref_i, *merge_cp_p, klass_ref_i, - THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match + int new_klass_ref_i = find_or_append_indirect_entry(scratch_cp, klass_ref_i, + merge_cp_p, merge_cp_length_p, THREAD); - int found_i = scratch_cp->find_matching_entry(klass_ref_i, *merge_cp_p, - THREAD); - if (found_i != 0) { - guarantee(found_i != klass_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_klass_ref_i = found_i; - map_index(scratch_cp, klass_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, klass_ref_i, merge_cp_p, merge_cp_length_p, - THREAD); - // The above call to append_entry() can only append one entry - // so the post call query of *merge_cp_length_p is only for - // the sake of consistency. Without the optimization where we - // use JVM_CONSTANT_UnresolvedClass, then up to two entries - // could be appended. - new_klass_ref_i = *merge_cp_length_p - 1; - } - } - - int name_and_type_ref_i = - scratch_cp->uncached_name_and_type_ref_index_at(scratch_i); - int new_name_and_type_ref_i = 0; - match = (name_and_type_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(name_and_type_ref_i, *merge_cp_p, - name_and_type_ref_i, THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match - - int found_i = scratch_cp->find_matching_entry(name_and_type_ref_i, - *merge_cp_p, THREAD); - if (found_i != 0) { - guarantee(found_i != name_and_type_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_name_and_type_ref_i = found_i; - map_index(scratch_cp, name_and_type_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, name_and_type_ref_i, merge_cp_p, - merge_cp_length_p, THREAD); - // The above call to append_entry() can append more than - // one entry so the post call query of *merge_cp_length_p - // is required in order to get the right index for the - // JVM_CONSTANT_NameAndType entry. - new_name_and_type_ref_i = *merge_cp_length_p - 1; - } - } - - // If the referenced entries already exist in *merge_cp_p, then - // both new_klass_ref_i and new_name_and_type_ref_i will both be - // 0. In that case, all we are appending is the current entry. - if (new_klass_ref_i == 0) { - new_klass_ref_i = klass_ref_i; - } - if (new_name_and_type_ref_i == 0) { - new_name_and_type_ref_i = name_and_type_ref_i; - } + int name_and_type_ref_i = scratch_cp->uncached_name_and_type_ref_index_at(scratch_i); + int new_name_and_type_ref_i = find_or_append_indirect_entry(scratch_cp, name_and_type_ref_i, + merge_cp_p, merge_cp_length_p, THREAD); const char *entry_name; switch (scratch_cp->tag_at(scratch_i).value()) { @@ -481,6 +364,72 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, (*merge_cp_length_p)++; } break; + // this is an indirect CP entry so it needs special handling + case JVM_CONSTANT_MethodType: + { + int ref_i = scratch_cp->method_type_index_at(scratch_i); + int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p, + merge_cp_length_p, THREAD); + if (new_ref_i != ref_i) { + RC_TRACE(0x00080000, + ("MethodType entry@%d ref_index change: %d to %d", + *merge_cp_length_p, ref_i, new_ref_i)); + } + (*merge_cp_p)->method_type_index_at_put(*merge_cp_length_p, new_ref_i); + if (scratch_i != *merge_cp_length_p) { + // The new entry in *merge_cp_p is at a different index than + // the new entry in scratch_cp so we need to map the index values. + map_index(scratch_cp, scratch_i, *merge_cp_length_p); + } + (*merge_cp_length_p)++; + } break; + + // this is an indirect CP entry so it needs special handling + case JVM_CONSTANT_MethodHandle: + { + int ref_kind = scratch_cp->method_handle_ref_kind_at(scratch_i); + int ref_i = scratch_cp->method_handle_index_at(scratch_i); + int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p, + merge_cp_length_p, THREAD); + if (new_ref_i != ref_i) { + RC_TRACE(0x00080000, + ("MethodHandle entry@%d ref_index change: %d to %d", + *merge_cp_length_p, ref_i, new_ref_i)); + } + (*merge_cp_p)->method_handle_index_at_put(*merge_cp_length_p, ref_kind, new_ref_i); + if (scratch_i != *merge_cp_length_p) { + // The new entry in *merge_cp_p is at a different index than + // the new entry in scratch_cp so we need to map the index values. + map_index(scratch_cp, scratch_i, *merge_cp_length_p); + } + (*merge_cp_length_p)++; + } break; + + // this is an indirect CP entry so it needs special handling + case JVM_CONSTANT_InvokeDynamic: + { + // TBD: cross-checks and possible extra appends into CP and bsm operands + // are needed as well. This issue is tracked by a separate bug 8007037. + int bss_idx = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i); + + int ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i); + int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p, + merge_cp_length_p, THREAD); + if (new_ref_i != ref_i) { + RC_TRACE(0x00080000, + ("InvokeDynamic entry@%d name_and_type ref_index change: %d to %d", + *merge_cp_length_p, ref_i, new_ref_i)); + } + + (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, bss_idx, new_ref_i); + if (scratch_i != *merge_cp_length_p) { + // The new entry in *merge_cp_p is at a different index than + // the new entry in scratch_cp so we need to map the index values. + map_index(scratch_cp, scratch_i, *merge_cp_length_p); + } + (*merge_cp_length_p)++; + } break; + // At this stage, Class or UnresolvedClass could be here, but not // ClassIndex case JVM_CONSTANT_ClassIndex: // fall through @@ -507,6 +456,35 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp, } // end append_entry() +int VM_RedefineClasses::find_or_append_indirect_entry(constantPoolHandle scratch_cp, + int ref_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) { + + int new_ref_i = ref_i; + bool match = (ref_i < *merge_cp_length_p) && + scratch_cp->compare_entry_to(ref_i, *merge_cp_p, ref_i, THREAD); + + if (!match) { + // forward reference in *merge_cp_p or not a direct match + int found_i = scratch_cp->find_matching_entry(ref_i, *merge_cp_p, THREAD); + if (found_i != 0) { + guarantee(found_i != ref_i, "compare_entry_to() and find_matching_entry() do not agree"); + // Found a matching entry somewhere else in *merge_cp_p so just need a mapping entry. + new_ref_i = found_i; + map_index(scratch_cp, ref_i, found_i); + } else { + // no match found so we have to append this entry to *merge_cp_p + append_entry(scratch_cp, ref_i, merge_cp_p, merge_cp_length_p, THREAD); + // The above call to append_entry() can only append one entry + // so the post call query of *merge_cp_length_p is only for + // the sake of consistency. + new_ref_i = *merge_cp_length_p - 1; + } + } + + return new_ref_i; +} // end find_or_append_indirect_entry() + + void VM_RedefineClasses::swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class, TRAPS) { AnnotationArray* save; diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp index 23839670d98..d348ed2c759 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp @@ -421,10 +421,11 @@ class VM_RedefineClasses: public VM_Operation { // and in all direct and indirect subclasses. void increment_class_counter(InstanceKlass *ik, TRAPS); - // Support for constant pool merging (these routines are in alpha - // order): + // Support for constant pool merging (these routines are in alpha order): void append_entry(constantPoolHandle scratch_cp, int scratch_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS); + int find_or_append_indirect_entry(constantPoolHandle scratch_cp, int scratch_i, + constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS); int find_new_index(int old_index); bool is_unresolved_class_mismatch(constantPoolHandle cp1, int index1, constantPoolHandle cp2, int index2); From da8ccb93758007d70384beff761b60c69dfc0414 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Thu, 31 Jan 2013 20:09:16 -0800 Subject: [PATCH 054/158] 8006546: JSR 292: typos in the ConstantPool::copy_cp_impl() Simple typos that need to be fixed Reviewed-by: coleenp, twisti --- hotspot/src/share/vm/oops/constantPool.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index b65d9bc7f35..1c21420c29a 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -1129,7 +1129,7 @@ void ConstantPool::copy_operands(constantPoolHandle from_cp, (len = old_off) * sizeof(u2)); fillp += len; // first part of src - Copy::conjoint_memory_atomic(to_cp->operands()->adr_at(0), + Copy::conjoint_memory_atomic(from_cp->operands()->adr_at(0), new_operands->adr_at(fillp), (len = from_off) * sizeof(u2)); fillp += len; @@ -1139,7 +1139,7 @@ void ConstantPool::copy_operands(constantPoolHandle from_cp, (len = old_len - old_off) * sizeof(u2)); fillp += len; // second part of src - Copy::conjoint_memory_atomic(to_cp->operands()->adr_at(from_off), + Copy::conjoint_memory_atomic(from_cp->operands()->adr_at(from_off), new_operands->adr_at(fillp), (len = from_len - from_off) * sizeof(u2)); fillp += len; From 932c29e08e8a352e7c6a745c1b768a85536ef9f1 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Thu, 31 Jan 2013 20:11:14 -0800 Subject: [PATCH 055/158] 8006731: JSR 292: the VM_RedefineClasses::rewrite_cp_refs_in_method() must support invokedynamic The invokedynamic bytecode ref to a CP entry needs to be checked and fixed as well. Reviewed-by: coleenp, twisti --- hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index a09fa16ed0c..ce1ec56ef65 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -1542,6 +1542,7 @@ void VM_RedefineClasses::rewrite_cp_refs_in_method(methodHandle method, case Bytecodes::_getfield : // fall through case Bytecodes::_getstatic : // fall through case Bytecodes::_instanceof : // fall through + case Bytecodes::_invokedynamic : // fall through case Bytecodes::_invokeinterface: // fall through case Bytecodes::_invokespecial : // fall through case Bytecodes::_invokestatic : // fall through From d0830009e80631e78a3a776954143194bab97530 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Fri, 1 Feb 2013 06:51:37 +0000 Subject: [PATCH 056/158] 8006395: Race in async socket close on Linux Reviewed-by: alanb, dsamersoff --- jdk/src/solaris/native/java/net/linux_close.c | 21 +++-- jdk/test/java/net/Socket/asyncClose/Race.java | 77 +++++++++++++++++++ 2 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 jdk/test/java/net/Socket/asyncClose/Race.java diff --git a/jdk/src/solaris/native/java/net/linux_close.c b/jdk/src/solaris/native/java/net/linux_close.c index 5665e85e09c..51f9cb2ee70 100644 --- a/jdk/src/solaris/native/java/net/linux_close.c +++ b/jdk/src/solaris/native/java/net/linux_close.c @@ -191,17 +191,6 @@ static int closefd(int fd1, int fd2) { pthread_mutex_lock(&(fdEntry->lock)); { - /* - * Send a wakeup signal to all threads blocked on this - * file descriptor. - */ - threadEntry_t *curr = fdEntry->threads; - while (curr != NULL) { - curr->intr = 1; - pthread_kill( curr->thr, sigWakeup ); - curr = curr->next; - } - /* * And close/dup the file descriptor * (restart if interrupted by signal) @@ -214,6 +203,16 @@ static int closefd(int fd1, int fd2) { } } while (rv == -1 && errno == EINTR); + /* + * Send a wakeup signal to all threads blocked on this + * file descriptor. + */ + threadEntry_t *curr = fdEntry->threads; + while (curr != NULL) { + curr->intr = 1; + pthread_kill( curr->thr, sigWakeup ); + curr = curr->next; + } } /* diff --git a/jdk/test/java/net/Socket/asyncClose/Race.java b/jdk/test/java/net/Socket/asyncClose/Race.java new file mode 100644 index 00000000000..f8869394b3d --- /dev/null +++ b/jdk/test/java/net/Socket/asyncClose/Race.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @bug 8006395 + * @summary Race in async socket close on Linux + */ + +import java.io.InputStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.util.concurrent.Phaser; + +// Racey test, will not always fail, but if it does then we have a problem. + +public class Race { + final static int THREADS = 100; + + public static void main(String[] args) throws Exception { + try (ServerSocket ss = new ServerSocket(0)) { + final int port = ss.getLocalPort(); + final Phaser phaser = new Phaser(THREADS + 1); + for (int i=0; i<100; i++) { + final Socket s = new Socket("localhost", port); + s.setSoLinger(false, 0); + try (Socket sa = ss.accept()) { + sa.setSoLinger(false, 0); + final InputStream is = s.getInputStream(); + Thread[] threads = new Thread[THREADS]; + for (int j=0; j Date: Fri, 1 Feb 2013 07:25:51 -0800 Subject: [PATCH 057/158] 8006536: [launcher] removes trailing slashes on arguments Reviewed-by: ksrini, akhil --- jdk/src/windows/bin/cmdtoargs.c | 13 ++++++++++++- jdk/test/tools/launcher/Arrrghs.java | 3 ++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/jdk/src/windows/bin/cmdtoargs.c b/jdk/src/windows/bin/cmdtoargs.c index 4e92d18708c..669f3683bfe 100644 --- a/jdk/src/windows/bin/cmdtoargs.c +++ b/jdk/src/windows/bin/cmdtoargs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -104,6 +104,11 @@ static char* next_arg(char* cmdline, char* arg, jboolean* wildcard) { case ' ': case '\t': + if (prev == '\\') { + for (i = 0 ; i < slashes; i++) { + *dest++ = prev; + } + } if (quotes % 2 == 1) { *dest++ = ch; } else { @@ -591,6 +596,12 @@ int main(int argc, char* argv[]) { // v->disable(); vectors[i++] = v; + v= new Vector(argv[0], "a b\\\\ d"); + v->add("a", FALSE); + v->add("b\\\\", FALSE); + v->add("d", FALSE); + vectors[i++] = v; + dotest(vectors); printf("All tests pass [%d]\n", i); doexit(0); diff --git a/jdk/test/tools/launcher/Arrrghs.java b/jdk/test/tools/launcher/Arrrghs.java index 9bf9f21b465..cf0dfbf7410 100644 --- a/jdk/test/tools/launcher/Arrrghs.java +++ b/jdk/test/tools/launcher/Arrrghs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -309,6 +309,7 @@ public class Arrrghs extends TestHelper { checkArgumentParsing("../../*", "../../*"); checkArgumentParsing("..\\..\\", "..\\..\\"); checkArgumentParsing("../../", "../../"); + checkArgumentParsing("a b\\ c", "a", "b\\", "c"); } private void initEmptyDir(File emptyDir) throws IOException { From 01ea5d17ec5f6fe542636d0fa12f16b4da9caab4 Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Fri, 1 Feb 2013 20:06:27 +0400 Subject: [PATCH 058/158] 8004801: The image of BufferedImage.TYPE_INT_ARGB is blank Reviewed-by: prr --- .../native/sun/awt/image/awt_parseImage.c | 65 ++++++++++++ jdk/src/solaris/native/sun/awt/awt_Mlib.c | 46 --------- jdk/src/solaris/native/sun/awt/awt_Mlib.h | 1 - .../windows/native/sun/windows/awt_Mlib.cpp | 46 --------- jdk/src/windows/native/sun/windows/awt_Mlib.h | 1 - .../image/LookupOp/IntImageReverseTest.java | 99 +++++++++++++++++++ 6 files changed, 164 insertions(+), 94 deletions(-) create mode 100644 jdk/test/java/awt/image/LookupOp/IntImageReverseTest.java diff --git a/jdk/src/share/native/sun/awt/image/awt_parseImage.c b/jdk/src/share/native/sun/awt/image/awt_parseImage.c index 264a02f1642..d6f6d60d356 100644 --- a/jdk/src/share/native/sun/awt/image/awt_parseImage.c +++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.c @@ -489,6 +489,71 @@ void awt_freeParsedImage(BufImageS_t *imageP, int freeImageP) { } } +static void +awt_getBIColorOrder(int type, int *colorOrder) { + switch(type) { + case java_awt_image_BufferedImage_TYPE_INT_ARGB: + case java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE: +#ifdef _LITTLE_ENDIAN + colorOrder[0] = 2; + colorOrder[1] = 1; + colorOrder[2] = 0; + colorOrder[3] = 3; +#else + colorOrder[0] = 1; + colorOrder[1] = 2; + colorOrder[2] = 3; + colorOrder[3] = 0; +#endif + break; + case java_awt_image_BufferedImage_TYPE_INT_BGR: +#ifdef _LITTLE_ENDIAN + colorOrder[0] = 0; + colorOrder[1] = 1; + colorOrder[2] = 2; +#else + colorOrder[0] = 3; + colorOrder[1] = 2; + colorOrder[2] = 1; +#endif + break; + case java_awt_image_BufferedImage_TYPE_INT_RGB: +#ifdef _LITTLE_ENDIAN + colorOrder[0] = 2; + colorOrder[1] = 1; + colorOrder[2] = 0; +#else + colorOrder[0] = 1; + colorOrder[1] = 2; + colorOrder[2] = 3; +#endif + break; + case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR: + case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE: + colorOrder[0] = 3; + colorOrder[1] = 2; + colorOrder[2] = 1; + colorOrder[3] = 0; + break; + case java_awt_image_BufferedImage_TYPE_3BYTE_BGR: + colorOrder[0] = 2; + colorOrder[1] = 1; + colorOrder[2] = 0; + break; + case java_awt_image_BufferedImage_TYPE_USHORT_565_RGB: + case java_awt_image_BufferedImage_TYPE_USHORT_555_RGB: + colorOrder[0] = 0; + colorOrder[1] = 1; + colorOrder[2] = 2; + break; + case java_awt_image_BufferedImage_TYPE_BYTE_GRAY: + case java_awt_image_BufferedImage_TYPE_USHORT_GRAY: + case java_awt_image_BufferedImage_TYPE_BYTE_BINARY: + case java_awt_image_BufferedImage_TYPE_BYTE_INDEXED: + colorOrder[0] = 0; + break; + } +} static int setHints(JNIEnv *env, BufImageS_t *imageP) { diff --git a/jdk/src/solaris/native/sun/awt/awt_Mlib.c b/jdk/src/solaris/native/sun/awt/awt_Mlib.c index fb00d4d9f12..0b7c291c811 100644 --- a/jdk/src/solaris/native/sun/awt/awt_Mlib.c +++ b/jdk/src/solaris/native/sun/awt/awt_Mlib.c @@ -145,52 +145,6 @@ mlib_stop_timer awt_setMlibStopTimer() { return stop_timer; } -void awt_getBIColorOrder(int type, int *colorOrder) { - switch(type) { - case java_awt_image_BufferedImage_TYPE_INT_ARGB: - case java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE: - colorOrder[0] = 1; - colorOrder[1] = 2; - colorOrder[2] = 3; - colorOrder[3] = 0; - break; - case java_awt_image_BufferedImage_TYPE_INT_BGR: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - break; - case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR: - case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE: - colorOrder[0] = 3; - colorOrder[1] = 2; - colorOrder[2] = 1; - colorOrder[3] = 0; - break; - case java_awt_image_BufferedImage_TYPE_3BYTE_BGR: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - break; - case java_awt_image_BufferedImage_TYPE_INT_RGB: - colorOrder[0] = 1; - colorOrder[1] = 2; - colorOrder[2] = 3; - break; - case java_awt_image_BufferedImage_TYPE_USHORT_565_RGB: - case java_awt_image_BufferedImage_TYPE_USHORT_555_RGB: - colorOrder[0] = 0; - colorOrder[1] = 1; - colorOrder[2] = 2; - break; - case java_awt_image_BufferedImage_TYPE_BYTE_GRAY: - case java_awt_image_BufferedImage_TYPE_USHORT_GRAY: - case java_awt_image_BufferedImage_TYPE_BYTE_BINARY: - case java_awt_image_BufferedImage_TYPE_BYTE_INDEXED: - colorOrder[0] = 0; - break; - } -} - /*************************************************************************** * Static Functions * ***************************************************************************/ diff --git a/jdk/src/solaris/native/sun/awt/awt_Mlib.h b/jdk/src/solaris/native/sun/awt/awt_Mlib.h index 03d65868994..cbaf38d1de6 100644 --- a/jdk/src/solaris/native/sun/awt/awt_Mlib.h +++ b/jdk/src/solaris/native/sun/awt/awt_Mlib.h @@ -33,6 +33,5 @@ typedef void (*mlib_stop_timer)(int, int); mlib_status awt_getImagingLib(JNIEnv *, mlibFnS_t *, mlibSysFnS_t *); mlib_start_timer awt_setMlibStartTimer(); mlib_stop_timer awt_setMlibStopTimer(); -void awt_getBIColorOrder(int type, int *colorOrder); #endif /* _AWT_MLIB_H */ diff --git a/jdk/src/windows/native/sun/windows/awt_Mlib.cpp b/jdk/src/windows/native/sun/windows/awt_Mlib.cpp index 022ebd0419a..308b2823e4c 100644 --- a/jdk/src/windows/native/sun/windows/awt_Mlib.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Mlib.cpp @@ -105,50 +105,4 @@ extern "C" mlib_stop_timer awt_setMlibStopTimer() { return NULL; } - - void awt_getBIColorOrder(int type, int *colorOrder) { - switch(type) { - case java_awt_image_BufferedImage_TYPE_INT_ARGB: - case java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - colorOrder[3] = 3; - break; - case java_awt_image_BufferedImage_TYPE_INT_BGR: - colorOrder[0] = 0; - colorOrder[1] = 1; - colorOrder[2] = 2; - break; - case java_awt_image_BufferedImage_TYPE_INT_RGB: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - break; - case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR: - case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE: - colorOrder[0] = 3; - colorOrder[1] = 2; - colorOrder[2] = 1; - colorOrder[3] = 0; - break; - case java_awt_image_BufferedImage_TYPE_3BYTE_BGR: - colorOrder[0] = 2; - colorOrder[1] = 1; - colorOrder[2] = 0; - break; - case java_awt_image_BufferedImage_TYPE_USHORT_565_RGB: - case java_awt_image_BufferedImage_TYPE_USHORT_555_RGB: - colorOrder[0] = 0; - colorOrder[1] = 1; - colorOrder[2] = 2; - break; - case java_awt_image_BufferedImage_TYPE_BYTE_GRAY: - case java_awt_image_BufferedImage_TYPE_USHORT_GRAY: - case java_awt_image_BufferedImage_TYPE_BYTE_BINARY: - case java_awt_image_BufferedImage_TYPE_BYTE_INDEXED: - colorOrder[0] = 0; - break; - } - } } diff --git a/jdk/src/windows/native/sun/windows/awt_Mlib.h b/jdk/src/windows/native/sun/windows/awt_Mlib.h index f9b63d900bb..9ebee32a932 100644 --- a/jdk/src/windows/native/sun/windows/awt_Mlib.h +++ b/jdk/src/windows/native/sun/windows/awt_Mlib.h @@ -38,7 +38,6 @@ JNIEXPORT mlib_status awt_getImagingLib(JNIEnv *env, mlibFnS_t *sMlibFns, mlibSysFnS_t *sMlibSysFns); JNIEXPORT mlib_start_timer awt_setMlibStartTimer(); JNIEXPORT mlib_stop_timer awt_setMlibStopTimer(); -JNIEXPORT void awt_getBIColorOrder(int type, int *colorOrder); #ifdef __cplusplus }; /* end of extern "C" */ diff --git a/jdk/test/java/awt/image/LookupOp/IntImageReverseTest.java b/jdk/test/java/awt/image/LookupOp/IntImageReverseTest.java new file mode 100644 index 00000000000..62de1683827 --- /dev/null +++ b/jdk/test/java/awt/image/LookupOp/IntImageReverseTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @bug 8004801 + * @summary Test verifies that byte lookup table with single lookup + * affects only color components in buffered images with + * integer data type, and that this operation does not distort + * colors in the destination image. + * @run main IntImageReverseTest + */ + +import java.awt.image.BufferedImage; +import java.awt.image.ByteLookupTable; +import java.awt.image.LookupOp; +import java.awt.image.LookupTable; + +public class IntImageReverseTest { + + public static void main(String[] args) { + LookupTable tbl = createReverseTable(); + LookupOp op = new LookupOp(tbl, null); + + for (ImageType t : ImageType.values()) { + System.out.print(t); + + BufferedImage src = createSourceImage(t); + + BufferedImage dst = op.filter(src, null); + + int rgb = dst.getRGB(0, 0); + + System.out.printf(" Result: 0x%X ", rgb); + + if (rgb != argbReverse) { + throw new RuntimeException("Test failed."); + } + System.out.println("Passed."); + } + } + + /** + * Reverse image color components, leave alpha unchanged. + */ + private static LookupTable createReverseTable() { + byte[] data = new byte[256]; + + for (int i = 0; i < 256; i++) { + data[i] = (byte) (255 - i); + } + + + return new ByteLookupTable(0, data); + } + + private static BufferedImage createSourceImage(ImageType type) { + BufferedImage img = new BufferedImage(1, 1, type.bi_type); + + img.setRGB(0, 0, argbTest); + + return img; + } + private static final int argbTest = 0xFFDDAA77; + private static final int argbReverse = 0xFF225588; + + private static enum ImageType { + + INT_ARGB(BufferedImage.TYPE_INT_ARGB), + INT_ARGB_PRE(BufferedImage.TYPE_INT_ARGB_PRE), + INT_RGB(BufferedImage.TYPE_INT_BGR), + INT_BGR(BufferedImage.TYPE_INT_BGR); + + private ImageType(int bi_type) { + this.bi_type = bi_type; + } + public final int bi_type; + } +} From 81e9d881ca343719c38bf10b19f6a3231bbc6b84 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 1 Feb 2013 08:33:48 -0800 Subject: [PATCH 059/158] 8007306: DPrinter: improve display of impl-class, internal tag/kind, and external tag/kind Reviewed-by: mcimadamore --- langtools/test/tools/javac/lib/DPrinter.java | 132 +++++++++---------- 1 file changed, 64 insertions(+), 68 deletions(-) diff --git a/langtools/test/tools/javac/lib/DPrinter.java b/langtools/test/tools/javac/lib/DPrinter.java index e05b9a8ad16..ea747acb26d 100644 --- a/langtools/test/tools/javac/lib/DPrinter.java +++ b/langtools/test/tools/javac/lib/DPrinter.java @@ -210,7 +210,7 @@ public class DPrinter { return; } - printString(label, ""); + printString(label, hashString(annotations)); indent(+1); if (attributes == DECL_NOT_STARTED) @@ -383,11 +383,12 @@ public class DPrinter { case FULL: indent(); out.print(label); - out.println(": " + String.format("0x%x", sym.kind) - + "--" + Kinds.kindName(sym).name() - + " " + sym.getKind() + out.println(": " + + info(sym.getClass(), + String.format("0x%x--%s", sym.kind, Kinds.kindName(sym)), + sym.getKind()) + " " + sym.name - + " " + String.format("#%x", sym.hashCode())); + + " " + hashString(sym)); indent(+1); if (showSrc) { @@ -401,7 +402,7 @@ public class DPrinter { printSymbol("owner", sym.owner, Details.SUMMARY); printType("type", sym.type, Details.SUMMARY); printType("erasure", sym.erasure_field, Details.SUMMARY); - sym.accept(symVisitor, true); + sym.accept(symVisitor, null); printAnnotations("annotations", sym.annotations, Details.SUMMARY); indent(-1); } @@ -417,7 +418,13 @@ public class DPrinter { printNull(label); } else { indent(); - out.print(label + ": " + tree.getTag()); + String ext; + try { + ext = tree.getKind().name(); + } catch (Throwable t) { + ext = "n/a"; + } + out.print(label + ": " + info(tree.getClass(), tree.getTag(), ext)); if (showPositions) { // We can always get start position, but to get end position // and/or line+offset, we would need a JCCompilationUnit @@ -456,13 +463,13 @@ public class DPrinter { case FULL: indent(); out.print(label); - out.println(": " + type.getTag() - + " " + String.format("#%x", type.hashCode())); + out.println(": " + info(type.getClass(), type.getTag(), type.getKind()) + + " " + hashString(type)); indent(+1); printSymbol("tsym", type.tsym, Details.SUMMARY); printObject("constValue", type.constValue(), Details.SUMMARY); - type.accept(typeVisitor, true); + type.accept(typeVisitor, null); indent(-1); } } @@ -472,6 +479,14 @@ public class DPrinter { return (printer != null) ? printer.visit(type, locale) : String.valueOf(type); } + protected String hashString(Object obj) { + return String.format("#%x", obj.hashCode()); + } + + protected String info(Class clazz, Object internal, Object external) { + return String.format("%s,%s,%s", clazz.getSimpleName(), internal, external); + } + private int indent = 0; protected void indent() { @@ -853,17 +868,16 @@ public class DPrinter { // - protected Symbol.Visitor symVisitor = new SymbolVisitor(); + protected Symbol.Visitor symVisitor = new SymbolVisitor(); /** * Default visitor class for Symbol objects. * Note: each visitXYZ method ends by calling the corresponding * visit method for its superclass. */ - class SymbolVisitor implements Symbol.Visitor { + class SymbolVisitor implements Symbol.Visitor { @Override - public Void visitClassSymbol(ClassSymbol sym, Boolean impl) { - if (impl) printImplClass(sym, ClassSymbol.class); + public Void visitClassSymbol(ClassSymbol sym, Void ignore) { printName("fullname", sym.fullname); printName("flatname", sym.flatname); printScope("members", sym.members_field); @@ -871,55 +885,49 @@ public class DPrinter { printFileObject("classfile", sym.classfile); // trans-local? // pool? - return visitTypeSymbol(sym, false); + return visitTypeSymbol(sym, null); } @Override - public Void visitMethodSymbol(MethodSymbol sym, Boolean impl) { - if (impl) printImplClass(sym, MethodSymbol.class); + public Void visitMethodSymbol(MethodSymbol sym, Void ignore) { // code printList("params", sym.params); printList("savedParameterNames", sym.savedParameterNames); - return visitSymbol(sym, false); + return visitSymbol(sym, null); } @Override - public Void visitPackageSymbol(PackageSymbol sym, Boolean impl) { - if (impl) printImplClass(sym, PackageSymbol.class); + public Void visitPackageSymbol(PackageSymbol sym, Void ignore) { printName("fullname", sym.fullname); printScope("members", sym.members_field); printSymbol("package-info", sym.package_info, Details.SUMMARY); - return visitTypeSymbol(sym, false); + return visitTypeSymbol(sym, null); } @Override - public Void visitOperatorSymbol(OperatorSymbol sym, Boolean impl) { - if (impl) printImplClass(sym, OperatorSymbol.class); + public Void visitOperatorSymbol(OperatorSymbol sym, Void ignore) { printInt("opcode", sym.opcode); - return visitMethodSymbol(sym, false); + return visitMethodSymbol(sym, null); } @Override - public Void visitVarSymbol(VarSymbol sym, Boolean impl) { - if (impl) printImplClass(sym, VarSymbol.class); + public Void visitVarSymbol(VarSymbol sym, Void ignore) { printInt("pos", sym.pos); printInt("adm", sym.adr); // data is a private field, and the standard accessors may // mutate it as part of lazy evaluation. Therefore, use // reflection to get the raw data. printObject("data", getField(sym, VarSymbol.class, "data"), Details.SUMMARY); - return visitSymbol(sym, false); + return visitSymbol(sym, null); } @Override - public Void visitTypeSymbol(TypeSymbol sym, Boolean impl) { - if (impl) printImplClass(sym, TypeSymbol.class); - return visitSymbol(sym, false); + public Void visitTypeSymbol(TypeSymbol sym, Void ignore) { + return visitSymbol(sym, null); } @Override - public Void visitSymbol(Symbol sym, Boolean impl) { - if (impl) printImplClass(sym, Symbol.class); + public Void visitSymbol(Symbol sym, Void ignore) { return null; } } @@ -928,71 +936,62 @@ public class DPrinter { // - protected Type.Visitor typeVisitor = new TypeVisitor(); + protected Type.Visitor typeVisitor = new TypeVisitor(); /** * Default visitor class for Type objects. * Note: each visitXYZ method ends by calling the corresponding * visit method for its superclass. */ - public class TypeVisitor implements Type.Visitor { - public Void visitAnnotatedType(AnnotatedType type, Boolean impl) { - if (impl) printImplClass(type, AnnotatedType.class); + public class TypeVisitor implements Type.Visitor { + public Void visitAnnotatedType(AnnotatedType type, Void ignore) { printList("typeAnnotations", type.typeAnnotations); printType("underlyingType", type.underlyingType, Details.FULL); - return visitType(type, false); + return visitType(type, null); } - public Void visitArrayType(ArrayType type, Boolean impl) { - if (impl) printImplClass(type, ArrayType.class); + public Void visitArrayType(ArrayType type, Void ignore) { printType("elemType", type.elemtype, Details.FULL); - return visitType(type, false); + return visitType(type, null); } - public Void visitCapturedType(CapturedType type, Boolean impl) { - if (impl) printImplClass(type, CapturedType.class); + public Void visitCapturedType(CapturedType type, Void ignore) { printType("wildcard", type.wildcard, Details.FULL); - return visitTypeVar(type, false); + return visitTypeVar(type, null); } - public Void visitClassType(ClassType type, Boolean impl) { - if (impl) printImplClass(type, ClassType.class); + public Void visitClassType(ClassType type, Void ignore) { printType("outer", type.getEnclosingType(), Details.SUMMARY); printList("typarams", type.typarams_field); printList("allparams", type.allparams_field); printType("supertype", type.supertype_field, Details.SUMMARY); printList("interfaces", type.interfaces_field); printList("allinterfaces", type.all_interfaces_field); - return visitType(type, false); + return visitType(type, null); } - public Void visitErrorType(ErrorType type, Boolean impl) { - if (impl) printImplClass(type, ErrorType.class); + public Void visitErrorType(ErrorType type, Void ignore) { printType("originalType", type.getOriginalType(), Details.FULL); - return visitClassType(type, false); + return visitClassType(type, null); } - public Void visitForAll(ForAll type, Boolean impl) { - if (impl) printImplClass(type, ForAll.class); + public Void visitForAll(ForAll type, Void ignore) { printList("tvars", type.tvars); return visitDelegatedType(type); } - public Void visitMethodType(MethodType type, Boolean impl) { - if (impl) printImplClass(type, MethodType.class); + public Void visitMethodType(MethodType type, Void ignore) { printList("argtypes", type.argtypes); printType("restype", type.restype, Details.FULL); printList("thrown", type.thrown); - return visitType(type, false); + return visitType(type, null); } - public Void visitPackageType(PackageType type, Boolean impl) { - if (impl) printImplClass(type, PackageType.class); - return visitType(type, false); + public Void visitPackageType(PackageType type, Void ignore) { + return visitType(type, null); } - public Void visitTypeVar(TypeVar type, Boolean impl) { - if (impl) printImplClass(type, TypeVar.class); + public Void visitTypeVar(TypeVar type, Void ignore) { // For TypeVars (and not subtypes), the bound should always be // null or bot. So, only print the bound for subtypes of TypeVar, // or if the bound is (erroneously) not null or bot. @@ -1001,32 +1000,29 @@ public class DPrinter { printType("bound", type.bound, Details.FULL); } printType("lower", type.lower, Details.FULL); - return visitType(type, false); + return visitType(type, null); } - public Void visitUndetVar(UndetVar type, Boolean impl) { - if (impl) printImplClass(type, UndetVar.class); + public Void visitUndetVar(UndetVar type, Void ignore) { for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values()) printList("bounds." + ib, type.getBounds(ib)); printType("inst", type.inst, Details.SUMMARY); return visitDelegatedType(type); } - public Void visitWildcardType(WildcardType type, Boolean impl) { - if (impl) printImplClass(type, WildcardType.class); + public Void visitWildcardType(WildcardType type, Void ignore) { printType("type", type.type, Details.SUMMARY); printString("kind", type.kind.name()); printType("bound", type.bound, Details.SUMMARY); - return visitType(type, false); + return visitType(type, null); } protected Void visitDelegatedType(DelegatedType type) { printType("qtype", type.qtype, Details.FULL); - return visitType(type, false); + return visitType(type, null); } - public Void visitType(Type type, Boolean impl) { - if (impl) printImplClass(type, Type.class); + public Void visitType(Type type, Void ignore) { return null; } } From 7ee6242d0c6526c637d31632e9fd4276a0acec99 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 1 Feb 2013 08:36:15 -0800 Subject: [PATCH 060/158] 8007305: DPrinter: provide better usage message Reviewed-by: mcimadamore --- langtools/test/tools/javac/lib/DPrinter.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/langtools/test/tools/javac/lib/DPrinter.java b/langtools/test/tools/javac/lib/DPrinter.java index ea747acb26d..45d1296cdda 100644 --- a/langtools/test/tools/javac/lib/DPrinter.java +++ b/langtools/test/tools/javac/lib/DPrinter.java @@ -1087,21 +1087,30 @@ public class DPrinter { */ static class Main { public static void main(String... args) throws IOException { + Main m = new Main(); PrintWriter out = new PrintWriter(System.out); try { if (args.length == 0) - usage(out); + m.usage(out); else - new Main().run(out, args); + m.run(out, args); } finally { out.flush(); } } - static void usage(PrintWriter out) { + void usage(PrintWriter out) { out.println("Usage:"); out.println(" java " + Main.class.getName() + " mode [options] [javac-options]"); - out.println("where options include:"); + out.print("where mode is one of: "); + String sep = ""; + for (Handler h: getHandlers().values()) { + out.print(sep); + out.print(h.name); + sep = ", "; + } + out.println(); + out.println("and where options include:"); out.println(" -before PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); out.println(" -after PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); out.println(" -showPositions"); From a2966dd62d93b4759585a89123d68f364ad31472 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Fri, 1 Feb 2013 14:14:54 -0500 Subject: [PATCH 061/158] 8006298: Specifying malformed JFR options (-XX:+FlightRecorderOptions) outputs non-sensical error Change error messages for malformed options so the messages are more useful. Reviewed-by: mikael, kvn, nloodin --- hotspot/src/share/vm/runtime/arguments.cpp | 29 +++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 5e6ad6e21bb..47851058cd9 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -827,7 +827,8 @@ bool Arguments::process_argument(const char* arg, return true; } - const char * const argname = *arg == '+' || *arg == '-' ? arg + 1 : arg; + bool has_plus_minus = (*arg == '+' || *arg == '-'); + const char* const argname = has_plus_minus ? arg + 1 : arg; if (is_newly_obsolete(arg, &since)) { char version[256]; since.to_string(version, sizeof(version)); @@ -838,13 +839,29 @@ bool Arguments::process_argument(const char* arg, // For locked flags, report a custom error message if available. // Otherwise, report the standard unrecognized VM option. - Flag* locked_flag = Flag::find_flag((char*)argname, strlen(argname), true); - if (locked_flag != NULL) { + size_t arg_len; + const char* equal_sign = strchr(argname, '='); + if (equal_sign == NULL) { + arg_len = strlen(argname); + } else { + arg_len = equal_sign - argname; + } + + Flag* found_flag = Flag::find_flag((char*)argname, arg_len, true); + if (found_flag != NULL) { char locked_message_buf[BUFLEN]; - locked_flag->get_locked_message(locked_message_buf, BUFLEN); + found_flag->get_locked_message(locked_message_buf, BUFLEN); if (strlen(locked_message_buf) == 0) { - jio_fprintf(defaultStream::error_stream(), - "Unrecognized VM option '%s'\n", argname); + if (found_flag->is_bool() && !has_plus_minus) { + jio_fprintf(defaultStream::error_stream(), + "Missing +/- setting for VM option '%s'\n", argname); + } else if (!found_flag->is_bool() && has_plus_minus) { + jio_fprintf(defaultStream::error_stream(), + "Unexpected +/- setting in VM option '%s'\n", argname); + } else { + jio_fprintf(defaultStream::error_stream(), + "Improperly specified VM option '%s'\n", argname); + } } else { jio_fprintf(defaultStream::error_stream(), "%s", locked_message_buf); } From 8f90cd00254e20c2b58a8fe330acf8911a6514e2 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 1 Feb 2013 12:01:03 -0800 Subject: [PATCH 062/158] 8007344: javac may not make tree end positions and/or doc comments available to processors and listeners Reviewed-by: darcy --- .../sun/tools/javac/main/JavaCompiler.java | 2 + .../test/tools/javac/api/8007344/Test.java | 227 ++++++++++++++++++ 2 files changed, 229 insertions(+) create mode 100644 langtools/test/tools/javac/api/8007344/Test.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 5bf9d276872..fc4786a2a60 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -629,6 +629,8 @@ public class JavaCompiler implements ClassReader.SourceCompleter { if (!taskListener.isEmpty()) { TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, filename); taskListener.started(e); + keepComments = true; + genEndPos = true; } Parser parser = parserFactory.newParser(content, keepComments(), genEndPos, lineDebugInfo); tree = parser.parseCompilationUnit(); diff --git a/langtools/test/tools/javac/api/8007344/Test.java b/langtools/test/tools/javac/api/8007344/Test.java new file mode 100644 index 00000000000..871faa70617 --- /dev/null +++ b/langtools/test/tools/javac/api/8007344/Test.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2010, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @bug 8007344 + * @summary javac may not make tree end positions and/or doc comments + * available to processors and listeners + * @library /tools/javac/lib + * @build JavacTestingAbstractProcessor + * @run main Test + */ + +import java.io.File; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Set; + +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +import com.sun.source.doctree.DocCommentTree; +import com.sun.source.tree.*; +import com.sun.source.util.DocTrees; +import com.sun.source.util.JavacTask; +import com.sun.source.util.SourcePositions; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.source.util.TreePath; +import com.sun.source.util.TreePathScanner; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.Pretty; +import com.sun.tools.javac.util.Position; + +/** Doc comment: Test */ +public class Test { + public static final int EXPECT_DOC_COMMENTS = 3; + + /** Doc comment: main */ + public static void main(String... args) throws Exception { + PrintWriter out = new PrintWriter(System.err); + try { + new Test(out).run(); + } finally { + out.flush(); + } + } + + PrintWriter out; + int errors; + + Test(PrintWriter out) { + this.out = out; + } + + /** Doc comment: run */ + void run() throws Exception { + File testSrc = new File(System.getProperty("test.src")); + File thisFile = new File(testSrc, getClass().getName() + ".java"); + JavacTool javac = JavacTool.create(); + StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null); + Iterable fos = fm.getJavaFileObjects(thisFile); + testAnnoProcessor(javac, fm, fos, out, EXPECT_DOC_COMMENTS); + testTaskListener(javac, fm, fos, out, EXPECT_DOC_COMMENTS); + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + void testAnnoProcessor(JavacTool javac, StandardJavaFileManager fm, + Iterable files, PrintWriter out, + int expectedDocComments) { + out.println("Test annotation processor"); + JavacTask task = javac.getTask(out, fm, null, null, null, files); + AnnoProc ap = new AnnoProc(DocTrees.instance(task)); + task.setProcessors(Arrays.asList(ap)); + task.call(); + ap.checker.checkDocComments(expectedDocComments); + } + + void testTaskListener(JavacTool javac, StandardJavaFileManager fm, + Iterable files, PrintWriter out, + int expectedDocComments) { + out.println("Test task listener"); + JavacTask task = javac.getTask(out, fm, null, null, null, files); + TaskListnr tl = new TaskListnr(DocTrees.instance(task)); + task.addTaskListener(tl); + task.call(); + tl.checker.checkDocComments(expectedDocComments); + } + + void error(String msg) { + out.println("Error: " + msg); + errors++; + } + + class AnnoProc extends JavacTestingAbstractProcessor { + Checker checker; + + AnnoProc(DocTrees trees) { + checker = new Checker(trees); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (Element e : roundEnv.getRootElements()) { + checker.scan(checker.trees.getPath(e), null); + } + return true; + } + } + + class TaskListnr implements TaskListener { + Checker checker; + + TaskListnr(DocTrees trees) { + checker = new Checker(trees); + } + + public void started(TaskEvent e) { + if (e.getKind() == TaskEvent.Kind.ANALYZE) + checker.scan(new TreePath(e.getCompilationUnit()), null); + } + + public void finished(TaskEvent e) { + } + } + + class Checker extends TreePathScanner { + DocTrees trees; + SourcePositions srcPosns; + + int docComments = 0; + + Checker(DocTrees trees) { + this.trees = trees; + srcPosns = trees.getSourcePositions(); + } + + @Override + public Void scan(Tree tree, Void ignore) { + if (tree != null) { + switch (tree.getKind()) { + // HACK: Workaround 8007350 + // Some tree nodes do not have endpos set + case ASSIGNMENT: + case BLOCK: + case IDENTIFIER: + case METHOD_INVOCATION: + break; + + default: + checkEndPos(getCurrentPath().getCompilationUnit(), tree); + } + } + return super.scan(tree, ignore); + } + + @Override + public Void visitClass(ClassTree tree, Void ignore) { + checkComment(); + return super.visitClass(tree, ignore); + } + + @Override + public Void visitMethod(MethodTree tree, Void ignore) { + checkComment(); + return super.visitMethod(tree, ignore); + } + + @Override + public Void visitVariable(VariableTree tree, Void ignore) { + checkComment(); + return super.visitVariable(tree, ignore); + } + + void checkComment() { + DocCommentTree dc = trees.getDocCommentTree(getCurrentPath()); + if (dc != null) { + out.println("comment: " + dc.toString().replaceAll("\\s+", " ")); + docComments++; + } + } + + void checkEndPos(CompilationUnitTree unit, Tree tree) { + long sp = srcPosns.getStartPosition(unit, tree); + long ep = srcPosns.getEndPosition(unit, tree); + if (sp >= 0 && ep == Position.NOPOS) { + error("endpos not set for " + tree.getKind() + + " " + Pretty.toSimpleString(((JCTree) tree)) + +", start:" + sp); + } + } + + void checkDocComments(int expected) { + if (docComments != expected) { + error("Unexpected number of doc comments received: " + + docComments + ", expected: " + expected); + } + } + + } +} From c2e77030a1e91c6047ddac4ce3ba8a6f959a9d12 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 1 Feb 2013 13:01:26 -0800 Subject: [PATCH 063/158] 8001614: Include annotation type to documented supported-ness Reviewed-by: alanb, jjg, tbell --- langtools/make/Makefile-classic | 1 + langtools/make/build.properties | 1 + .../src/share/classes/jdk/Supported.java | 53 +++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 langtools/src/share/classes/jdk/Supported.java diff --git a/langtools/make/Makefile-classic b/langtools/make/Makefile-classic index f0693b7216b..c253ee8949b 100644 --- a/langtools/make/Makefile-classic +++ b/langtools/make/Makefile-classic @@ -241,6 +241,7 @@ JAVAC_DIRS = \ javax/annotation/processing \ javax/lang/model \ javax/tools \ + jdk/ \ com/sun/source \ com/sun/tools/javac diff --git a/langtools/make/build.properties b/langtools/make/build.properties index 72ae8793c24..7fd5ffcb371 100644 --- a/langtools/make/build.properties +++ b/langtools/make/build.properties @@ -116,6 +116,7 @@ javac.includes = \ javax/annotation/processing/ \ javax/lang/model/ \ javax/tools/ \ + jdk/ \ com/sun/source/ \ com/sun/tools/javac/ \ com/sun/tools/doclint/ diff --git a/langtools/src/share/classes/jdk/Supported.java b/langtools/src/share/classes/jdk/Supported.java new file mode 100644 index 00000000000..f5bf1c54ba6 --- /dev/null +++ b/langtools/src/share/classes/jdk/Supported.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 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 + * 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 jdk; + +import java.lang.annotation.*; + +/** + * Indicates whether or not a JDK specific type or package is a + * supported part of the JDK. + * + * This annotation should only be applied to types and packages + * outside of the Java SE namespaces of {@code java.*} and + * {@code javax.*} packages. For example, certain portions of {@code + * com.sun.*} are official parts of the JDK meant to be generally + * usable while other portions of {@code com.sun.*} are not. This + * annotation type allows those portions to be easily and + * programmaticly distinguished. + * + * @since 1.8 + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.PACKAGE}) +@Supported +public @interface Supported { + /** + * Whether or not this package or type is a supported part of the JDK. + */ + boolean value() default true; +} From 854e269f2070cb04422933225eff9841837a553e Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 1 Feb 2013 21:01:44 +0000 Subject: [PATCH 064/158] 5035569: Formatter should document that %a conversion unsupported for BigDecimal args Reviewed-by: darcy --- jdk/src/share/classes/java/util/Formatter.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/util/Formatter.java b/jdk/src/share/classes/java/util/Formatter.java index f5f479588c1..03a58004918 100644 --- a/jdk/src/share/classes/java/util/Formatter.java +++ b/jdk/src/share/classes/java/util/Formatter.java @@ -351,7 +351,9 @@ import sun.misc.FormattedFloatingDecimal; * {@code 'a'}, {@code 'A'} * floating point * The result is formatted as a hexadecimal floating-point number with - * a significand and an exponent + * a significand and an exponent. This conversion is not supported + * for the {@code BigDecimal} type despite the latter's being in the + * floating point argument category. * * {@code 't'}, {@code 'T'} * date/time From d701ede8bbdc597bbf4dd9cdffbd4c1903531735 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Fri, 1 Feb 2013 13:17:04 -0800 Subject: [PATCH 065/158] 8006894: G1: Number of marking threads missing from PrintFlagsFinal output Set ConcGCThreads to the calculated number of marking threads. Reviewed-by: jmasa, ysr --- .../gc_implementation/g1/concurrentMark.cpp | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 3199cbf5a60..50821ac0cfb 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -571,19 +571,14 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) : _sleep_factor = 0.0; _marking_task_overhead = 1.0; } else { - if (ConcGCThreads > 0) { - // notice that ConcGCThreads overwrites G1MarkingOverheadPercent + if (!FLAG_IS_DEFAULT(ConcGCThreads) && ConcGCThreads > 0) { + // Note: ConcGCThreads has precedence over G1MarkingOverheadPercent // if both are set - - _parallel_marking_threads = (uint) ConcGCThreads; - _max_parallel_marking_threads = _parallel_marking_threads; _sleep_factor = 0.0; _marking_task_overhead = 1.0; } else if (G1MarkingOverheadPercent > 0) { - // we will calculate the number of parallel marking threads - // based on a target overhead with respect to the soft real-time - // goal - + // We will calculate the number of parallel marking threads based + // on a target overhead with respect to the soft real-time goal double marking_overhead = (double) G1MarkingOverheadPercent / 100.0; double overall_cm_overhead = (double) MaxGCPauseMillis * marking_overhead / @@ -596,17 +591,22 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) : double sleep_factor = (1.0 - marking_task_overhead) / marking_task_overhead; - _parallel_marking_threads = (uint) marking_thread_num; - _max_parallel_marking_threads = _parallel_marking_threads; + FLAG_SET_ERGO(uintx, ConcGCThreads, (uint) marking_thread_num); _sleep_factor = sleep_factor; _marking_task_overhead = marking_task_overhead; } else { - _parallel_marking_threads = scale_parallel_threads((uint)ParallelGCThreads); - _max_parallel_marking_threads = _parallel_marking_threads; + // Calculate the number of parallel marking threads by scaling + // the number of parallel GC threads. + uint marking_thread_num = scale_parallel_threads((uint) ParallelGCThreads); + FLAG_SET_ERGO(uintx, ConcGCThreads, marking_thread_num); _sleep_factor = 0.0; _marking_task_overhead = 1.0; } + assert(ConcGCThreads > 0, "Should have been set"); + _parallel_marking_threads = (uint) ConcGCThreads; + _max_parallel_marking_threads = _parallel_marking_threads; + if (parallel_marking_threads() > 1) { _cleanup_task_overhead = 1.0; } else { From 111ddcc8274fa81649917b2c61558baab97507c7 Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Fri, 1 Feb 2013 23:48:08 +0100 Subject: [PATCH 066/158] 8005012: Add WB APIs to better support NMT testing Add WB API functions to enable better NMT testing Reviewed-by: dholmes, zgu --- .../tools/whitebox/sun/hotspot/WhiteBox.java | 5 ++ hotspot/src/share/vm/memory/allocation.hpp | 5 +- hotspot/src/share/vm/prims/whitebox.cpp | 63 +++++++++++++++++++ hotspot/src/share/vm/services/memBaseline.cpp | 1 + hotspot/src/share/vm/services/memPtr.cpp | 2 +- hotspot/src/share/vm/services/memPtr.hpp | 10 +-- hotspot/src/share/vm/services/memRecorder.cpp | 5 +- hotspot/src/share/vm/services/memRecorder.hpp | 6 +- .../src/share/vm/services/memTrackWorker.cpp | 11 ++++ .../src/share/vm/services/memTrackWorker.hpp | 1 + hotspot/src/share/vm/services/memTracker.cpp | 50 ++++++++++++++- hotspot/src/share/vm/services/memTracker.hpp | 26 +++++++- 12 files changed, 171 insertions(+), 14 deletions(-) diff --git a/hotspot/src/share/tools/whitebox/sun/hotspot/WhiteBox.java b/hotspot/src/share/tools/whitebox/sun/hotspot/WhiteBox.java index 3a8592dec58..ecc5085896f 100644 --- a/hotspot/src/share/tools/whitebox/sun/hotspot/WhiteBox.java +++ b/hotspot/src/share/tools/whitebox/sun/hotspot/WhiteBox.java @@ -76,4 +76,9 @@ public class WhiteBox { public native long g1NumFreeRegions(); public native int g1RegionSize(); public native Object[] parseCommandLine(String commandline, DiagnosticCommand[] args); + + // NMT + public native boolean NMTAllocTest(); + public native boolean NMTFreeTestMemory(); + public native boolean NMTWaitForDataMerge(); } diff --git a/hotspot/src/share/vm/memory/allocation.hpp b/hotspot/src/share/vm/memory/allocation.hpp index 3cade72c260..e1e266ec5cf 100644 --- a/hotspot/src/share/vm/memory/allocation.hpp +++ b/hotspot/src/share/vm/memory/allocation.hpp @@ -145,9 +145,10 @@ enum MemoryType { mtChunk = 0x0B00, // chunk that holds content of arenas mtJavaHeap = 0x0C00, // Java heap mtClassShared = 0x0D00, // class data sharing - mt_number_of_types = 0x000D, // number of memory types (mtDontTrack + mtTest = 0x0E00, // Test type for verifying NMT + mt_number_of_types = 0x000E, // number of memory types (mtDontTrack // is not included as validate type) - mtDontTrack = 0x0E00, // memory we do not or cannot track + mtDontTrack = 0x0F00, // memory we do not or cannot track mt_masks = 0x7F00, // object type mask diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 6c60be19f10..c93b4a2149a 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -43,6 +43,10 @@ #include "gc_implementation/g1/heapRegionRemSet.hpp" #endif // !SERIALGC +#ifdef INCLUDE_NMT +#include "services/memTracker.hpp" +#endif // INCLUDE_NMT + bool WhiteBox::_used = false; WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj)) @@ -110,6 +114,60 @@ WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o)) WB_END #endif // !SERIALGC +#ifdef INCLUDE_NMT +// Keep track of the 3 allocations in NMTAllocTest so we can free them later +// on and verify that they're not visible anymore +static void* nmtMtTest1 = NULL, *nmtMtTest2 = NULL, *nmtMtTest3 = NULL; + +// Alloc memory using the test memory type so that we can use that to see if +// NMT picks it up correctly +WB_ENTRY(jboolean, WB_NMTAllocTest(JNIEnv* env)) + void *mem; + + if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { + return false; + } + + // Allocate 2 * 128k + 256k + 1024k and free the 1024k one to make sure we track + // everything correctly. Total should be 512k held alive. + nmtMtTest1 = os::malloc(128 * 1024, mtTest); + mem = os::malloc(1024 * 1024, mtTest); + nmtMtTest2 = os::malloc(256 * 1024, mtTest); + os::free(mem, mtTest); + nmtMtTest3 = os::malloc(128 * 1024, mtTest); + + return true; +WB_END + +// Free the memory allocated by NMTAllocTest +WB_ENTRY(jboolean, WB_NMTFreeTestMemory(JNIEnv* env)) + + if (nmtMtTest1 == NULL || nmtMtTest2 == NULL || nmtMtTest3 == NULL) { + return false; + } + + os::free(nmtMtTest1, mtTest); + nmtMtTest1 = NULL; + os::free(nmtMtTest2, mtTest); + nmtMtTest2 = NULL; + os::free(nmtMtTest3, mtTest); + nmtMtTest3 = NULL; + + return true; +WB_END + +// Block until the current generation of NMT data to be merged, used to reliably test the NMT feature +WB_ENTRY(jboolean, WB_NMTWaitForDataMerge(JNIEnv* env)) + + if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { + return false; + } + + return MemTracker::wbtest_wait_for_data_merge(); +WB_END + +#endif // INCLUDE_NMT + //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, Symbol* signature_symbol) { @@ -177,6 +235,11 @@ static JNINativeMethod methods[] = { {CC"g1NumFreeRegions", CC"()J", (void*)&WB_G1NumFreeRegions }, {CC"g1RegionSize", CC"()I", (void*)&WB_G1RegionSize }, #endif // !SERIALGC +#ifdef INCLUDE_NMT + {CC"NMTAllocTest", CC"()Z", (void*)&WB_NMTAllocTest }, + {CC"NMTFreeTestMemory", CC"()Z", (void*)&WB_NMTFreeTestMemory }, + {CC"NMTWaitForDataMerge",CC"()Z", (void*)&WB_NMTWaitForDataMerge}, +#endif // INCLUDE_NMT }; #undef CC diff --git a/hotspot/src/share/vm/services/memBaseline.cpp b/hotspot/src/share/vm/services/memBaseline.cpp index 9d9832e8601..681b4d7d9d1 100644 --- a/hotspot/src/share/vm/services/memBaseline.cpp +++ b/hotspot/src/share/vm/services/memBaseline.cpp @@ -40,6 +40,7 @@ MemType2Name MemBaseline::MemType2NameMap[NUMBER_OF_MEMORY_TYPE] = { {mtNMT, "Memory Tracking"}, {mtChunk, "Pooled Free Chunks"}, {mtClassShared,"Shared spaces for classes"}, + {mtTest, "Test"}, {mtNone, "Unknown"} // It can happen when type tagging records are lagging // behind }; diff --git a/hotspot/src/share/vm/services/memPtr.cpp b/hotspot/src/share/vm/services/memPtr.cpp index 5d0fbf5bf57..3e124e2bde2 100644 --- a/hotspot/src/share/vm/services/memPtr.cpp +++ b/hotspot/src/share/vm/services/memPtr.cpp @@ -27,8 +27,8 @@ #include "services/memTracker.hpp" volatile jint SequenceGenerator::_seq_number = 1; +volatile unsigned long SequenceGenerator::_generation = 1; NOT_PRODUCT(jint SequenceGenerator::_max_seq_number = 1;) -DEBUG_ONLY(volatile unsigned long SequenceGenerator::_generation = 0;) jint SequenceGenerator::next() { jint seq = Atomic::add(1, &_seq_number); diff --git a/hotspot/src/share/vm/services/memPtr.hpp b/hotspot/src/share/vm/services/memPtr.hpp index a27c3eb4a10..e1c852ac7ba 100644 --- a/hotspot/src/share/vm/services/memPtr.hpp +++ b/hotspot/src/share/vm/services/memPtr.hpp @@ -47,16 +47,16 @@ class SequenceGenerator : AllStatic { static void reset() { assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required"); _seq_number = 1; - DEBUG_ONLY(_generation ++;) + _generation ++; }; - DEBUG_ONLY(static unsigned long current_generation() { return (unsigned long)_generation; }) + static unsigned long current_generation() { return _generation; } NOT_PRODUCT(static jint max_seq_num() { return _max_seq_number; }) private: - static volatile jint _seq_number; - NOT_PRODUCT(static jint _max_seq_number; ) - DEBUG_ONLY(static volatile unsigned long _generation; ) + static volatile jint _seq_number; + static volatile unsigned long _generation; + NOT_PRODUCT(static jint _max_seq_number; ) }; /* diff --git a/hotspot/src/share/vm/services/memRecorder.cpp b/hotspot/src/share/vm/services/memRecorder.cpp index 93703269ede..776ad223c00 100644 --- a/hotspot/src/share/vm/services/memRecorder.cpp +++ b/hotspot/src/share/vm/services/memRecorder.cpp @@ -55,7 +55,7 @@ volatile jint MemRecorder::_instance_count = 0; MemRecorder::MemRecorder() { assert(MemTracker::is_on(), "Native memory tracking is off"); Atomic::inc(&_instance_count); - debug_only(set_generation();) + set_generation(); if (MemTracker::track_callsite()) { _pointer_records = new (std::nothrow)FixedSizeMemPointerArray { // used for linked list MemRecorder* _next; // active recorder can only record a certain generation data - debug_only(unsigned long _generation;) + unsigned long _generation; protected: _NOINLINE_ MemRecorder(); @@ -251,6 +251,8 @@ class MemRecorder : public CHeapObj { SequencedRecordIterator pointer_itr(); + // return the generation of this recorder which it belongs to + unsigned long get_generation() const { return _generation; } protected: // number of MemRecorder instance static volatile jint _instance_count; @@ -263,7 +265,7 @@ class MemRecorder : public CHeapObj { static int sort_record_fn(const void* e1, const void* e2); debug_only(void check_dup_seq(jint seq) const;) - debug_only(void set_generation();) + void set_generation(); }; #endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP diff --git a/hotspot/src/share/vm/services/memTrackWorker.cpp b/hotspot/src/share/vm/services/memTrackWorker.cpp index 19b375d4085..8c38d1a3731 100644 --- a/hotspot/src/share/vm/services/memTrackWorker.cpp +++ b/hotspot/src/share/vm/services/memTrackWorker.cpp @@ -91,6 +91,8 @@ void MemTrackWorker::run() { MemSnapshot* snapshot = MemTracker::get_snapshot(); assert(snapshot != NULL, "Worker should not be started"); MemRecorder* rec; + unsigned long processing_generation = 0; + bool worker_idle = false; while (!MemTracker::shutdown_in_progress()) { NOT_PRODUCT(_last_gen_in_use = generations_in_use();) @@ -100,6 +102,12 @@ void MemTrackWorker::run() { rec = _gen[_head].next_recorder(); } if (rec != NULL) { + if (rec->get_generation() != processing_generation || worker_idle) { + processing_generation = rec->get_generation(); + worker_idle = false; + MemTracker::set_current_processing_generation(processing_generation); + } + // merge the recorder into staging area if (!snapshot->merge(rec)) { MemTracker::shutdown(MemTracker::NMT_out_of_memory); @@ -129,6 +137,9 @@ void MemTrackWorker::run() { MemTracker::shutdown(MemTracker::NMT_out_of_memory); } } else { + // worker thread is idle + worker_idle = true; + MemTracker::report_worker_idle(); snapshot->wait(1000); ThreadCritical tc; // check if more data arrived diff --git a/hotspot/src/share/vm/services/memTrackWorker.hpp b/hotspot/src/share/vm/services/memTrackWorker.hpp index 9a2d52802e2..be80e294d58 100644 --- a/hotspot/src/share/vm/services/memTrackWorker.hpp +++ b/hotspot/src/share/vm/services/memTrackWorker.hpp @@ -107,6 +107,7 @@ class MemTrackWorker : public NamedThread { NOT_PRODUCT(int _merge_count;) NOT_PRODUCT(int _last_gen_in_use;) + // how many generations are queued inline int generations_in_use() const { return (_tail >= _head ? (_tail - _head + 1) : (MAX_GENERATIONS - (_head - _tail) + 1)); } diff --git a/hotspot/src/share/vm/services/memTracker.cpp b/hotspot/src/share/vm/services/memTracker.cpp index c8032d8fd1a..4c110d584ac 100644 --- a/hotspot/src/share/vm/services/memTracker.cpp +++ b/hotspot/src/share/vm/services/memTracker.cpp @@ -29,6 +29,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/safepoint.hpp" #include "runtime/threadCritical.hpp" +#include "runtime/vm_operations.hpp" #include "services/memPtr.hpp" #include "services/memReporter.hpp" #include "services/memTracker.hpp" @@ -65,6 +66,8 @@ volatile MemTracker::NMTStates MemTracker::_state = NMT_uninited; MemTracker::ShutdownReason MemTracker::_reason = NMT_shutdown_none; int MemTracker::_thread_count = 255; volatile jint MemTracker::_pooled_recorder_count = 0; +volatile unsigned long MemTracker::_processing_generation = 0; +volatile bool MemTracker::_worker_thread_idle = false; debug_only(intx MemTracker::_main_thread_tid = 0;) NOT_PRODUCT(volatile jint MemTracker::_pending_recorder_count = 0;) @@ -279,7 +282,7 @@ MemRecorder* MemTracker::get_new_or_pooled_instance() { } cur_head->set_next(NULL); Atomic::dec(&_pooled_recorder_count); - debug_only(cur_head->set_generation();) + cur_head->set_generation(); return cur_head; } } @@ -570,6 +573,51 @@ bool MemTracker::print_memory_usage(BaselineOutputer& out, size_t unit, bool sum return false; } +// Whitebox API for blocking until the current generation of NMT data has been merged +bool MemTracker::wbtest_wait_for_data_merge() { + // NMT can't be shutdown while we're holding _query_lock + MutexLockerEx lock(_query_lock, true); + assert(_worker_thread != NULL, "Invalid query"); + // the generation at query time, so NMT will spin till this generation is processed + unsigned long generation_at_query_time = SequenceGenerator::current_generation(); + unsigned long current_processing_generation = _processing_generation; + // if generation counter overflown + bool generation_overflown = (generation_at_query_time < current_processing_generation); + long generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation; + // spin + while (!shutdown_in_progress()) { + if (!generation_overflown) { + if (current_processing_generation > generation_at_query_time) { + return true; + } + } else { + assert(generations_to_wrap >= 0, "Sanity check"); + long current_generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation; + assert(current_generations_to_wrap >= 0, "Sanity check"); + // to overflow an unsigned long should take long time, so to_wrap check should be sufficient + if (current_generations_to_wrap > generations_to_wrap && + current_processing_generation > generation_at_query_time) { + return true; + } + } + + // if worker thread is idle, but generation is not advancing, that means + // there is not safepoint to let NMT advance generation, force one. + if (_worker_thread_idle) { + VM_ForceSafepoint vfs; + VMThread::execute(&vfs); + } + MemSnapshot* snapshot = get_snapshot(); + if (snapshot == NULL) { + return false; + } + snapshot->wait(1000); + current_processing_generation = _processing_generation; + } + // We end up here if NMT is shutting down before our data has been merged + return false; +} + // compare memory usage between current snapshot and baseline bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { MutexLockerEx lock(_query_lock, true); diff --git a/hotspot/src/share/vm/services/memTracker.hpp b/hotspot/src/share/vm/services/memTracker.hpp index 538195c0c75..764b2950543 100644 --- a/hotspot/src/share/vm/services/memTracker.hpp +++ b/hotspot/src/share/vm/services/memTracker.hpp @@ -91,9 +91,10 @@ class MemTracker : AllStatic { static bool compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only = true) { } + static bool wbtest_wait_for_data_merge() { } + static inline void sync() { } static inline void thread_exiting(JavaThread* thread) { } - }; @@ -111,6 +112,10 @@ class MemTracker : AllStatic { extern bool NMT_track_callsite; +#ifndef MAX_UNSIGNED_LONG +#define MAX_UNSIGNED_LONG (unsigned long)(-1) +#endif + #ifdef ASSERT #define DEBUG_CALLER_PC (NMT_track_callsite ? os::get_caller_pc(2) : 0) #else @@ -380,6 +385,11 @@ class MemTracker : AllStatic { static bool compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only = true); + // the version for whitebox testing support, it ensures that all memory + // activities before this method call, are reflected in the snapshot + // database. + static bool wbtest_wait_for_data_merge(); + // sync is called within global safepoint to synchronize nmt data static void sync(); @@ -432,6 +442,15 @@ class MemTracker : AllStatic { static void create_record_in_recorder(address addr, MEMFLAGS type, size_t size, address pc, JavaThread* thread); + static void set_current_processing_generation(unsigned long generation) { + _worker_thread_idle = false; + _processing_generation = generation; + } + + static void report_worker_idle() { + _worker_thread_idle = true; + } + private: // global memory snapshot static MemSnapshot* _snapshot; @@ -483,6 +502,11 @@ class MemTracker : AllStatic { static volatile enum NMTStates _state; // the reason for shutting down nmt static enum ShutdownReason _reason; + // the generation that NMT is processing + static volatile unsigned long _processing_generation; + // although NMT is still procesing current generation, but + // there is not more recorder to process, set idle state + static volatile bool _worker_thread_idle; }; #endif // !INCLUDE_NMT From 26b2bbe306ae927f698322e245e232bf96dbfabf Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Fri, 1 Feb 2013 17:21:53 -0800 Subject: [PATCH 067/158] 8007257: NPG: metaspace.cpp: Incorrect arguments in calls to err_msg Fix size checks in assert and corrected some print formats. Also reviewed by vitalyd@gmail.com. Reviewed-by: coleenp, sspitsyn --- hotspot/src/share/vm/memory/metaspace.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index f54803a190f..c629e175f09 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -1737,10 +1737,10 @@ void SpaceManager::get_initial_chunk_sizes(Metaspace::MetaspaceType type, *class_chunk_word_size = ClassSmallChunk; break; } - assert(chunk_word_size != 0 && class_chunk_word_size != 0, + assert(*chunk_word_size != 0 && *class_chunk_word_size != 0, err_msg("Initial chunks sizes bad: data " SIZE_FORMAT " class " SIZE_FORMAT, - chunk_word_size, class_chunk_word_size)); + *chunk_word_size, *class_chunk_word_size)); } size_t SpaceManager::sum_free_in_chunks_in_use() const { @@ -2040,7 +2040,7 @@ SpaceManager::~SpaceManager() { align_size_up(humongous_chunks->word_size(), HumongousChunkGranularity), err_msg("Humongous chunk size is wrong: word size " SIZE_FORMAT - " granularity " SIZE_FORMAT, + " granularity %d", humongous_chunks->word_size(), HumongousChunkGranularity)); Metachunk* next_humongous_chunks = humongous_chunks->next(); chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks); @@ -2264,7 +2264,8 @@ void SpaceManager::verify_allocation_total() { } MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); assert(allocation_total() == sum_used_in_chunks_in_use(), - err_msg("allocation total is not consistent %d vs %d", + err_msg("allocation total is not consistent " SIZE_FORMAT + " vs " SIZE_FORMAT, allocation_total(), sum_used_in_chunks_in_use())); } @@ -2578,7 +2579,8 @@ void Metaspace::global_initialize() { // argument passed in is at the top of the compressed space void Metaspace::initialize_class_space(ReservedSpace rs) { // The reserved space size may be bigger because of alignment, esp with UseLargePages - assert(rs.size() >= ClassMetaspaceSize, err_msg("%d != %d", rs.size(), ClassMetaspaceSize)); + assert(rs.size() >= ClassMetaspaceSize, + err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), ClassMetaspaceSize)); _class_space_list = new VirtualSpaceList(rs); } From 0050c5b4fbec24b46fb46c5d070a98a4e86c2174 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 1 Feb 2013 19:30:02 -0800 Subject: [PATCH 068/158] 6964528: Double.toHexString(double d) String manipulation with + in an append of StringBuilder Reviewed-by: shade --- jdk/src/share/classes/java/lang/Double.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Double.java b/jdk/src/share/classes/java/lang/Double.java index f79980f4bb8..9bdb0ca4679 100644 --- a/jdk/src/share/classes/java/lang/Double.java +++ b/jdk/src/share/classes/java/lang/Double.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, 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 @@ -289,7 +289,7 @@ public final class Double extends Number implements Comparable { return Double.toString(d); else { // Initialized to maximum size of output. - StringBuffer answer = new StringBuffer(24); + StringBuilder answer = new StringBuilder(24); if (Math.copySign(1.0, d) == -1.0) // value is negative, answer.append("-"); // so append sign info @@ -300,8 +300,7 @@ public final class Double extends Number implements Comparable { if(d == 0.0) { answer.append("0.0p0"); - } - else { + } else { boolean subnormal = (d < DoubleConsts.MIN_NORMAL); // Isolate significand bits and OR in a high-order bit @@ -324,13 +323,14 @@ public final class Double extends Number implements Comparable { "0": signif.replaceFirst("0{1,12}$", "")); + answer.append('p'); // If the value is subnormal, use the E_min exponent // value for double; otherwise, extract and report d's // exponent (the representation of a subnormal uses // E_min -1). - answer.append("p" + (subnormal ? - DoubleConsts.MIN_EXPONENT: - Math.getExponent(d) )); + answer.append(subnormal ? + DoubleConsts.MIN_EXPONENT: + Math.getExponent(d)); } return answer.toString(); } From 81a6d7fb0112e56b07f00075f5602eac0595140e Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Fri, 1 Feb 2013 22:12:52 -0800 Subject: [PATCH 069/158] 8003549: (pack200) assertion errors when processing lambda class files with IMethods Add more check for opcode, sketch provided by jrose Reviewed-by: jrose --- .../com/sun/java/util/jar/pack/Attribute.java | 23 +++-- .../sun/java/util/jar/pack/ClassReader.java | 53 +++++++--- .../sun/java/util/jar/pack/ConstantPool.java | 30 +++++- .../sun/java/util/jar/pack/Instruction.java | 14 ++- .../sun/java/util/jar/pack/PackageWriter.java | 10 ++ .../sun/java/util/jar/pack/PackerImpl.java | 14 ++- .../com/sun/java/util/jar/pack/PropMap.java | 7 +- .../com/sun/java/util/jar/pack/Utils.java | 8 +- jdk/test/ProblemList.txt | 3 - jdk/test/tools/pack200/InstructionTests.java | 99 +++++++++++++++++++ .../src/xmlkit/ClassReader.java | 17 ++++ 11 files changed, 241 insertions(+), 37 deletions(-) create mode 100644 jdk/test/tools/pack200/InstructionTests.java diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java index 9e891fc7c87..f6ff030263e 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java @@ -1287,19 +1287,24 @@ class Attribute implements Comparable { if (localRef == 0) { globalRef = null; // N.B. global null reference is -1 } else { - globalRef = holder.getCPMap()[localRef]; - if (e.refKind == CONSTANT_Signature + Entry[] cpMap = holder.getCPMap(); + globalRef = (localRef >= 0 && localRef < cpMap.length + ? cpMap[localRef] + : null); + byte tag = e.refKind; + if (globalRef != null && tag == CONSTANT_Signature && globalRef.getTag() == CONSTANT_Utf8) { // Cf. ClassReader.readSignatureRef. String typeName = globalRef.stringValue(); globalRef = ConstantPool.getSignatureEntry(typeName); - } else if (e.refKind == CONSTANT_FieldSpecific) { - assert(globalRef.getTag() >= CONSTANT_Integer); - assert(globalRef.getTag() <= CONSTANT_String || - globalRef.getTag() >= CONSTANT_MethodHandle); - assert(globalRef.getTag() <= CONSTANT_MethodType); - } else if (e.refKind < CONSTANT_GroupFirst) { - assert(e.refKind == globalRef.getTag()); + } + String got = (globalRef == null + ? "invalid CP index" + : "type=" + ConstantPool.tagName(globalRef.tag)); + if (globalRef == null || !globalRef.tagMatches(tag)) { + throw new IllegalArgumentException( + "Bad constant, expected type=" + + ConstantPool.tagName(tag) + " got " + got); } } out.putRef(bandIndex, globalRef); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java index 2ca2d0926c6..3df8706da37 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -54,6 +54,7 @@ class ClassReader { Package pkg; Class cls; long inPos; + long constantPoolLimit = -1; DataInputStream in; Map attrDefs; Map attrCommands; @@ -117,15 +118,33 @@ class ClassReader { private Entry readRef(byte tag) throws IOException { Entry e = readRef(); - assert(e != null); assert(!(e instanceof UnresolvedEntry)); - assert(e.tagMatches(tag)); + checkTag(e, tag); return e; } + /** Throw a ClassFormatException if the entry does not match the expected tag type. */ + private Entry checkTag(Entry e, byte tag) throws ClassFormatException { + if (e == null || !e.tagMatches(tag)) { + String where = (inPos == constantPoolLimit + ? " in constant pool" + : " at pos: " + inPos); + String got = (e == null + ? "null CP index" + : "type=" + ConstantPool.tagName(e.tag)); + throw new ClassFormatException("Bad constant, expected type=" + + ConstantPool.tagName(tag) + + " got "+ got + ", in File: " + cls.file.nameString + where); + } + return e; + } + private Entry checkTag(Entry e, byte tag, boolean nullOK) throws ClassFormatException { + return nullOK && e == null ? null : checkTag(e, tag); + } + private Entry readRefOrNull(byte tag) throws IOException { Entry e = readRef(); - assert(e == null || e.tagMatches(tag)); + checkTag(e, tag, true); return e; } @@ -143,8 +162,10 @@ class ClassReader { private SignatureEntry readSignatureRef() throws IOException { // The class file stores a Utf8, but we want a Signature. - Entry e = readRef(CONSTANT_Utf8); - return ConstantPool.getSignatureEntry(e.stringValue()); + Entry e = readRef(CONSTANT_Signature); + return (e != null && e.getTag() == CONSTANT_Utf8) + ? ConstantPool.getSignatureEntry(e.stringValue()) + : (SignatureEntry) e; } void read() throws IOException { @@ -279,6 +300,7 @@ class ClassReader { " at pos: " + inPos); } } + constantPoolLimit = inPos; // Fix up refs, which might be out of order. while (fptr > 0) { @@ -311,25 +333,25 @@ class ClassReader { case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: - ClassEntry mclass = (ClassEntry) cpMap[ref]; - DescriptorEntry mdescr = (DescriptorEntry) cpMap[ref2]; + ClassEntry mclass = (ClassEntry) checkTag(cpMap[ref], CONSTANT_Class); + DescriptorEntry mdescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType); cpMap[cpi] = ConstantPool.getMemberEntry((byte)tag, mclass, mdescr); break; case CONSTANT_NameandType: - Utf8Entry mname = (Utf8Entry) cpMap[ref]; - Utf8Entry mtype = (Utf8Entry) cpMap[ref2]; + Utf8Entry mname = (Utf8Entry) checkTag(cpMap[ref], CONSTANT_Utf8); + Utf8Entry mtype = (Utf8Entry) checkTag(cpMap[ref2], CONSTANT_Signature); cpMap[cpi] = ConstantPool.getDescriptorEntry(mname, mtype); break; case CONSTANT_MethodType: - cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) cpMap[ref]); + cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) checkTag(cpMap[ref], CONSTANT_Signature)); break; case CONSTANT_MethodHandle: byte refKind = (byte)(-1 ^ ref); - MemberEntry memRef = (MemberEntry) cpMap[ref2]; + MemberEntry memRef = (MemberEntry) checkTag(cpMap[ref2], CONSTANT_AnyMember); cpMap[cpi] = ConstantPool.getMethodHandleEntry(refKind, memRef); break; case CONSTANT_InvokeDynamic: - DescriptorEntry idescr = (DescriptorEntry) cpMap[ref2]; + DescriptorEntry idescr = (DescriptorEntry) checkTag(cpMap[ref2], CONSTANT_NameandType); cpMap[cpi] = new UnresolvedEntry((byte)tag, (-1 ^ ref), idescr); // Note that ref must be resolved later, using the BootstrapMethods attribute. break; @@ -541,7 +563,8 @@ class ClassReader { code.max_locals = readUnsignedShort(); code.bytes = new byte[readInt()]; in.readFully(code.bytes); - Instruction.opcodeChecker(code.bytes); + Entry[] cpMap = cls.getCPMap(); + Instruction.opcodeChecker(code.bytes, cpMap); int nh = readUnsignedShort(); code.setHandlerCount(nh); for (int i = 0; i < nh; i++) { @@ -559,7 +582,7 @@ class ClassReader { MethodHandleEntry bsmRef = (MethodHandleEntry) readRef(CONSTANT_MethodHandle); Entry[] argRefs = new Entry[readUnsignedShort()]; for (int j = 0; j < argRefs.length; j++) { - argRefs[j] = readRef(); + argRefs[j] = readRef(CONSTANT_LoadableValue); } bsms[i] = ConstantPool.getBootstrapMethodEntry(bsmRef, argRefs); } diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java index be4da54d247..ad2175f9993 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -243,8 +243,32 @@ class ConstantPool { return tag == CONSTANT_Double || tag == CONSTANT_Long; } - public final boolean tagMatches(int tag) { - return (this.tag == tag); + public final boolean tagMatches(int matchTag) { + if (tag == matchTag) + return true; + byte[] allowedTags; + switch (matchTag) { + case CONSTANT_All: + return true; + case CONSTANT_Signature: + return tag == CONSTANT_Utf8; // format check also? + case CONSTANT_LoadableValue: + allowedTags = LOADABLE_VALUE_TAGS; + break; + case CONSTANT_AnyMember: + allowedTags = ANY_MEMBER_TAGS; + break; + case CONSTANT_FieldSpecific: + allowedTags = FIELD_SPECIFIC_TAGS; + break; + default: + return false; + } + for (byte b : allowedTags) { + if (b == tag) + return true; + } + return false; } public String toString() { diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java index f488bede323..31ee22b059d 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -647,7 +647,7 @@ class Instruction { } } - public static void opcodeChecker(byte[] code) throws FormatException { + public static void opcodeChecker(byte[] code, ConstantPool.Entry[] cpMap) throws FormatException { Instruction i = at(code, 0); while (i != null) { int opcode = i.getBC(); @@ -655,6 +655,16 @@ class Instruction { String message = "illegal opcode: " + opcode + " " + i; throw new FormatException(message); } + ConstantPool.Entry e = i.getCPRef(cpMap); + if (e != null) { + byte tag = i.getCPTag(); + if (!e.tagMatches(tag)) { + String message = "illegal reference, expected type=" + + ConstantPool.tagName(tag) + ": " + + i.toString(cpMap); + throw new FormatException(message); + } + } i = i.next(); } } diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java index e6990451135..47959294fd2 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java @@ -1618,6 +1618,16 @@ class PackageWriter extends BandStructure { bc_which = null; assert(false); } + if (ref != null && bc_which.index != null && !bc_which.index.contains(ref)) { + // Crash and burn with a complaint if there are funny + // references for this bytecode instruction. + // Example: invokestatic of a CONSTANT_InterfaceMethodref. + String complaint = code.getMethod() + + " contains a bytecode " + i + + " with an unsupported constant reference; please use the pass-file option on this class."; + Utils.log.warning(complaint); + throw new IOException(complaint); + } bc_codes.putByte(vbc); bc_which.putRef(ref); // handle trailing junk diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java index c7ef4ee2013..0dc88a108c7 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -180,6 +180,15 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { } unknownAttrCommand = uaMode.intern(); } + final String classFormatCommand; + { + String fmtMode = props.getProperty(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS); + if (!(Pack200.Packer.PASS.equals(fmtMode) || + Pack200.Packer.ERROR.equals(fmtMode))) { + throw new RuntimeException("Bad option: " + Utils.CLASS_FORMAT_ERROR + " = " + fmtMode); + } + classFormatCommand = fmtMode.intern(); + } final Map attrDefs; final Map attrCommands; @@ -505,8 +514,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { } } else if (ioe instanceof ClassReader.ClassFormatException) { ClassReader.ClassFormatException ce = (ClassReader.ClassFormatException) ioe; - // %% TODO: Do we invent a new property for this or reuse %% - if (unknownAttrCommand.equals(Pack200.Packer.PASS)) { + if (classFormatCommand.equals(Pack200.Packer.PASS)) { Utils.log.info(ce.toString()); Utils.log.warning(message + " unknown class format: " + fname); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java index 6199c77b51d..24485040378 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -112,6 +112,11 @@ final class PropMap implements SortedMap { // Pass through files with unrecognized attributes by default. props.put(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS); + // Pass through files with unrecognized format by default, also + // allow system property to be set + props.put(Utils.CLASS_FORMAT_ERROR, + System.getProperty(Utils.CLASS_FORMAT_ERROR, Pack200.Packer.PASS)); + // Default effort is 5, midway between 1 and 9. props.put(Pack200.Packer.EFFORT, "5"); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java index 5edd73e21cb..ebe0960dba0 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -122,6 +122,12 @@ class Utils { */ static final String PACK_ZIP_ARCHIVE_MARKER_COMMENT = "PACK200"; + /* + * behaviour when we hit a class format error, but not necessarily + * an unknown attribute, by default it is allowed to PASS. + */ + static final String CLASS_FORMAT_ERROR = COM_PREFIX+"class.format.error"; + // Keep a TLS point to the global data and environment. // This makes it simpler to supply environmental options // to the engine code, especially the native code. diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 5e181ac7e03..7b763477192 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -321,9 +321,6 @@ sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all tools/pack200/CommandLineTests.java generic-all tools/pack200/Pack200Test.java generic-all -# 8001163 -tools/pack200/AttributeTests.java generic-all - # 7150569 tools/launcher/UnicodeTest.java macosx-all diff --git a/jdk/test/tools/pack200/InstructionTests.java b/jdk/test/tools/pack200/InstructionTests.java new file mode 100644 index 00000000000..ce92c0ed558 --- /dev/null +++ b/jdk/test/tools/pack200/InstructionTests.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ +import java.io.File; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import static java.nio.file.StandardOpenOption.*; +import java.util.regex.Pattern; + +/* + * @test + * @bug 8003549 + * @summary tests class files instruction formats introduced in JSR-335 + * @compile -XDignore.symbol.file Utils.java InstructionTests.java + * @run main InstructionTests + * @author ksrini + */ +public class InstructionTests { + public static void main(String... args) throws Exception { + testInvokeOpCodes(); + } + /* + * the following should produce invokestatic and invokespecial + * on InterfaceMethodRefs vs. MethodRefs, packer/unpacker should work + */ + static void testInvokeOpCodes() throws Exception { + List scratch = new ArrayList<>(); + final String fname = "A"; + String javaFileName = fname + Utils.JAVA_FILE_EXT; + scratch.add("interface IntIterator {"); + scratch.add(" default void forEach(){}"); + scratch.add(" static void next() {}"); + scratch.add("}"); + scratch.add("class A implements IntIterator {"); + scratch.add("public void forEach(Object o){"); + scratch.add("IntIterator.super.forEach();"); + scratch.add("IntIterator.next();"); + scratch.add("}"); + scratch.add("}"); + File cwd = new File("."); + File javaFile = new File(cwd, javaFileName); + Files.write(javaFile.toPath(), scratch, Charset.defaultCharset(), + CREATE, TRUNCATE_EXISTING); + + // make sure we have -g so that we compare LVT and LNT entries + Utils.compiler("-g", javaFile.getName()); + + // jar the file up + File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT); + Utils.jar("cvf", testjarFile.getName(), "."); + + // pack using --repack + File outjarFile = new File(cwd, "out" + Utils.JAR_FILE_EXT); + scratch.clear(); + scratch.add(Utils.getPack200Cmd()); + scratch.add("-J-ea"); + scratch.add("-J-esa"); + scratch.add("--repack"); + scratch.add(outjarFile.getName()); + scratch.add(testjarFile.getName()); + List output = Utils.runExec(scratch); + // TODO remove this when we get bc escapes working correctly + // this test anyhow would fail at that time + findString("WARNING: Passing.*" + fname + Utils.CLASS_FILE_EXT, + output); + + Utils.doCompareVerify(testjarFile, outjarFile); + } + + static boolean findString(String str, List list) { + Pattern p = Pattern.compile(str); + for (String x : list) { + if (p.matcher(x).matches()) + return true; + } + throw new RuntimeException("Error: " + str + " not found in output"); + } +} diff --git a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java b/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java index 177849872a9..db7d0465777 100644 --- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java +++ b/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java @@ -57,8 +57,10 @@ import com.sun.tools.classfile.MethodParameters_attribute; import com.sun.tools.classfile.Opcode; import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute; +import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute; +import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; import com.sun.tools.classfile.Signature_attribute; import com.sun.tools.classfile.SourceDebugExtension_attribute; import com.sun.tools.classfile.SourceFile_attribute; @@ -1214,6 +1216,21 @@ class AttributeVisitor implements Attribute.Visitor { p.add(e); return null; } + + /* + * TODO + * add these two for now to keep the compiler happy, we will implement + * these along with the JSR-308 changes. + */ + @Override + public Element visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute rvta, Element p) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Element visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute rita, Element p) { + throw new UnsupportedOperationException("Not supported yet."); + } } class StackMapVisitor implements StackMapTable_attribute.stack_map_frame.Visitor { From 8da1d4a40c9b4827e2fdb3cbe7488c5cb991c9ae Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Fri, 1 Feb 2013 22:18:18 -0800 Subject: [PATCH 070/158] 8007428: [launcher] add tools/launcher/FXLauncherTest.java to ProblemList.txt Reviewed-by: mchung --- jdk/test/ProblemList.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 7b763477192..1870b0b9219 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -324,6 +324,9 @@ tools/pack200/Pack200Test.java generic-all # 7150569 tools/launcher/UnicodeTest.java macosx-all +# 8007410 +tools/launcher/FXLauncherTest.java linux-all + ############################################################################ # jdk_jdi From 8734c66d55d0f84d42d701fe243e7f57cc621c74 Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Sat, 2 Feb 2013 16:34:10 +0100 Subject: [PATCH 071/158] 8005013: Add NMT tests Add tests for the Native Memory Tracking feature, includes regression tests for 8005936 and 8004802 Reviewed-by: zgu, coleenp --- hotspot/test/TEST.ROOT | 2 +- hotspot/test/runtime/NMT/AllocTestType.java | 72 +++++++++++ .../runtime/NMT/BaselineWithParameter.java | 54 ++++++++ .../test/runtime/NMT/CommandLineDetail.java | 45 +++++++ .../runtime/NMT/CommandLineEmptyArgument.java | 41 ++++++ .../NMT/CommandLineInvalidArgument.java | 41 ++++++ .../test/runtime/NMT/CommandLineSummary.java | 45 +++++++ .../runtime/NMT/CommandLineTurnOffNMT.java | 44 +++++++ hotspot/test/runtime/NMT/JcmdScale.java | 67 ++++++++++ .../test/runtime/NMT/JcmdWithNMTDisabled.java | 63 ++++++++++ .../test/runtime/NMT/PrintNMTStatistics.java | 66 ++++++++++ .../PrintNMTStatisticsWithNMTDisabled.java | 44 +++++++ hotspot/test/runtime/NMT/ShutdownTwice.java | 56 +++++++++ .../runtime/NMT/SummaryAfterShutdown.java | 56 +++++++++ .../test/runtime/NMT/SummarySanityCheck.java | 119 ++++++++++++++++++ 15 files changed, 814 insertions(+), 1 deletion(-) create mode 100644 hotspot/test/runtime/NMT/AllocTestType.java create mode 100644 hotspot/test/runtime/NMT/BaselineWithParameter.java create mode 100644 hotspot/test/runtime/NMT/CommandLineDetail.java create mode 100644 hotspot/test/runtime/NMT/CommandLineEmptyArgument.java create mode 100644 hotspot/test/runtime/NMT/CommandLineInvalidArgument.java create mode 100644 hotspot/test/runtime/NMT/CommandLineSummary.java create mode 100644 hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java create mode 100644 hotspot/test/runtime/NMT/JcmdScale.java create mode 100644 hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java create mode 100644 hotspot/test/runtime/NMT/PrintNMTStatistics.java create mode 100644 hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java create mode 100644 hotspot/test/runtime/NMT/ShutdownTwice.java create mode 100644 hotspot/test/runtime/NMT/SummaryAfterShutdown.java create mode 100644 hotspot/test/runtime/NMT/SummarySanityCheck.java diff --git a/hotspot/test/TEST.ROOT b/hotspot/test/TEST.ROOT index 24014f68209..629bb54ddb4 100644 --- a/hotspot/test/TEST.ROOT +++ b/hotspot/test/TEST.ROOT @@ -28,4 +28,4 @@ # DO NOT EDIT without first contacting hotspot-regtest@sun.com # The list of keywords supported in this test suite -keys=cte_test +keys=cte_test jcmd nmt regression diff --git a/hotspot/test/runtime/NMT/AllocTestType.java b/hotspot/test/runtime/NMT/AllocTestType.java new file mode 100644 index 00000000000..7644884445d --- /dev/null +++ b/hotspot/test/runtime/NMT/AllocTestType.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @summary Test consistency of NMT by leaking a few select allocations of the Test type and then verify visibility with jcmd + * @key nmt jcmd + * @library /testlibrary + * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI AllocTestType.java + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail AllocTestType + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class AllocTestType { + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + // Use WB API to alloc with the mtTest type + if (!WhiteBox.getWhiteBox().NMTAllocTest()) { + throw new Exception("Call to WB API NMTAllocTest() failed"); + } + + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + + // Run 'jcmd VM.native_memory summary' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=512KB, committed=512KB)"); + + // Free the memory allocated by NMTAllocTest + if (!WhiteBox.getWhiteBox().NMTFreeTestMemory()) { + throw new Exception("Call to WB API NMTFreeTestMemory() failed"); + } + + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + } +} diff --git a/hotspot/test/runtime/NMT/BaselineWithParameter.java b/hotspot/test/runtime/NMT/BaselineWithParameter.java new file mode 100644 index 00000000000..594bd7165ed --- /dev/null +++ b/hotspot/test/runtime/NMT/BaselineWithParameter.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @bug 8004802 + * @key nmt jcmd regression + * @summary Regression test for invoking a jcmd with baseline=false, result was that the target VM crashed + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=detail BaselineWithParameter + */ + +import com.oracle.java.testlibrary.*; + +public class BaselineWithParameter { + + public static void main(String args[]) throws Exception { + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + OutputAnalyzer output; + + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory baseline=false' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline=false"}); + pb.start(); + + // Run 'jcmd VM.native_memory summary=false' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary=false"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("No command to execute"); + + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineDetail.java b/hotspot/test/runtime/NMT/CommandLineDetail.java new file mode 100644 index 00000000000..d993316ba9c --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineDetail.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + + /* + * @test + * @key nmt + * @summary Running with NMT detail should not result in an error or warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineDetail { + + public static void main(String args[]) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:NativeMemoryTracking=detail", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java b/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java new file mode 100644 index 00000000000..956cdd26006 --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + + /* + * @test + * @key nmt + * @summary Empty argument to NMT should result in an informative error message + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineEmptyArgument { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:NativeMemoryTracking="); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]"); + output.shouldHaveExitValue(1); + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java b/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java new file mode 100644 index 00000000000..79cc2de9442 --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + + /* + * @test + * @key nmt + * @summary Invalid argument to NMT should result in an informative error message + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineInvalidArgument { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:NativeMemoryTracking=apa"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]"); + output.shouldHaveExitValue(1); + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineSummary.java b/hotspot/test/runtime/NMT/CommandLineSummary.java new file mode 100644 index 00000000000..b8415d1bde9 --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineSummary.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + + /* + * @test + * @key nmt + * @summary Running with NMT summary should not result in an error or warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineSummary { + + public static void main(String args[]) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:NativeMemoryTracking=summary", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java b/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java new file mode 100644 index 00000000000..e8d950cba0a --- /dev/null +++ b/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + + /* + * @test + * @key nmt + * @summary Turning off NMT should not result in an error or warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineTurnOffNMT { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:NativeMemoryTracking=off", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/JcmdScale.java b/hotspot/test/runtime/NMT/JcmdScale.java new file mode 100644 index 00000000000..e57d27b59a3 --- /dev/null +++ b/hotspot/test/runtime/NMT/JcmdScale.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Test the NMT scale parameter + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=summary JcmdScale + */ + +import com.oracle.java.testlibrary.*; + +public class JcmdScale { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = new ProcessBuilder(); + OutputAnalyzer output; + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=KB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("KB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=MB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("MB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=GB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("GB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=apa"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Incorrect scale value: apa"); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=GB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("GB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=apa"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Incorrect scale value: apa"); + + } +} diff --git a/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java b/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java new file mode 100644 index 00000000000..7b58a841315 --- /dev/null +++ b/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Verify that jcmd correctly reports that NMT is not enabled + * @library /testlibrary + * First run without enabling NMT + * @run main/othervm JcmdWithNMTDisabled + * Then run with explicitly disabling NMT, should not be any difference + * @run main/othervm -XX:NativeMemoryTracking=off JcmdWithNMTDisabled + */ + +import com.oracle.java.testlibrary.*; + +public class JcmdWithNMTDisabled { + static ProcessBuilder pb = new ProcessBuilder(); + static String pid; + + public static void main(String args[]) throws Exception { + // Grab my own PID + pid = Integer.toString(ProcessTools.getProcessId()); + + jcmdCommand("summary"); + jcmdCommand("detail"); + jcmdCommand("baseline"); + jcmdCommand("summary.diff"); + jcmdCommand("detail.diff"); + jcmdCommand("scale=GB"); + jcmdCommand("shutdown"); + } + + // Helper method for invoking different jcmd calls, all should fail with the same message saying NMT is not enabled + public static void jcmdCommand(String command) throws Exception { + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", command}); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT is not enabled + output.shouldContain("Native memory tracking is not enabled"); + } +} diff --git a/hotspot/test/runtime/NMT/PrintNMTStatistics.java b/hotspot/test/runtime/NMT/PrintNMTStatistics.java new file mode 100644 index 00000000000..307ab948abd --- /dev/null +++ b/hotspot/test/runtime/NMT/PrintNMTStatistics.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @key nmt regression + * @bug 8005936 + * @summary Make sure PrintNMTStatistics works on normal JVM exit + * @library /testlibrary + * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI PrintNMTStatistics.java + */ + +import com.oracle.java.testlibrary.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import sun.hotspot.WhiteBox; + +public class PrintNMTStatistics { + + public static void main(String args[]) throws Exception { + + // We start a new java process running with an argument and use WB API to ensure + // we have data for NMT on VM exit + if (args.length > 0) { + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + return; + } + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:NativeMemoryTracking=summary", + "+XX:+PrintNMTStatistics", + "PrintNMTStatistics", + "test"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Java Heap (reserved="); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java b/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java new file mode 100644 index 00000000000..1c25f284d4b --- /dev/null +++ b/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + + /* + * @test + * @key nmt + * @summary Trying to enable PrintNMTStatistics should result in a warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class PrintNMTStatisticsWithNMTDisabled { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+PrintNMTStatistics", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("warning: PrintNMTStatistics is disabled, because native memory tracking is not enabled"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/NMT/ShutdownTwice.java b/hotspot/test/runtime/NMT/ShutdownTwice.java new file mode 100644 index 00000000000..1bb327aedb1 --- /dev/null +++ b/hotspot/test/runtime/NMT/ShutdownTwice.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Run shutdown twice + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=detail ShutdownTwice + */ + +import com.oracle.java.testlibrary.*; + +public class ShutdownTwice { + + public static void main(String args[]) throws Exception { + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + OutputAnalyzer output; + + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory shutdown' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "shutdown"}); + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT is shutting down + output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown"); + + // Run shutdown again + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT has been shutdown already + output.shouldContain("Native memory tracking has been shutdown by user"); + } +} diff --git a/hotspot/test/runtime/NMT/SummaryAfterShutdown.java b/hotspot/test/runtime/NMT/SummaryAfterShutdown.java new file mode 100644 index 00000000000..96061f3f004 --- /dev/null +++ b/hotspot/test/runtime/NMT/SummaryAfterShutdown.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Verify that jcmd correctly reports that NMT is not enabled after a shutdown + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=detail SummaryAfterShutdown + */ + +import com.oracle.java.testlibrary.*; + +public class SummaryAfterShutdown { + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory shutdown' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "shutdown"}); + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT is shutting down + output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown"); + + // Run 'jcmd VM.native_memory summary' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT has been shutdown + output.shouldContain("Native memory tracking has been shutdown by user"); + } +} diff --git a/hotspot/test/runtime/NMT/SummarySanityCheck.java b/hotspot/test/runtime/NMT/SummarySanityCheck.java new file mode 100644 index 00000000000..cf81d5b35af --- /dev/null +++ b/hotspot/test/runtime/NMT/SummarySanityCheck.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @key nmt jcmd + * @summary Sanity check the output of NMT + * @library /testlibrary + * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI SummarySanityCheck.java + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+WhiteBoxAPI SummarySanityCheck + */ + +import com.oracle.java.testlibrary.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import sun.hotspot.WhiteBox; + +public class SummarySanityCheck { + + private static String jcmdout; + public static void main(String args[]) throws Exception { + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory summary scale=KB' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=KB"}); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + jcmdout = output.getOutput(); + // Split by '-' to get the 'groups' + String[] lines = jcmdout.split("\n"); + + if (lines.length == 0) { + throwTestException("Failed to parse jcmd output"); + } + + int totalCommitted = 0, totalReserved = 0; + int totalCommittedSum = 0, totalReservedSum = 0; + + // Match '- (reserved=KB, committed=KB) + Pattern mtTypePattern = Pattern.compile("-\\s+(?[\\w\\s]+)\\(reserved=(?\\d+)KB,\\scommitted=(?\\d+)KB\\)"); + // Match 'Total: reserved=KB, committed=KB' + Pattern totalMemoryPattern = Pattern.compile("Total\\:\\s\\sreserved=(?\\d+)KB,\\s\\scommitted=(?\\d+)KB"); + + for (int i = 0; i < lines.length; i++) { + if (lines[i].startsWith("Total")) { + Matcher totalMemoryMatcher = totalMemoryPattern.matcher(lines[i]); + + if (totalMemoryMatcher.matches() && totalMemoryMatcher.groupCount() == 2) { + totalCommitted = Integer.parseInt(totalMemoryMatcher.group("committed")); + totalReserved = Integer.parseInt(totalMemoryMatcher.group("reserved")); + } else { + throwTestException("Failed to match the expected groups in 'Total' memory part"); + } + } else if (lines[i].startsWith("-")) { + Matcher typeMatcher = mtTypePattern.matcher(lines[i]); + if (typeMatcher.matches()) { + int typeCommitted = Integer.parseInt(typeMatcher.group("committed")); + int typeReserved = Integer.parseInt(typeMatcher.group("reserved")); + + // Make sure reserved is always less or equals + if (typeCommitted > typeReserved) { + throwTestException("Committed (" + typeCommitted + ") was more than Reserved (" + + typeReserved + ") for mtType: " + typeMatcher.group("typename")); + } + + // Add to total and compare them in the end + totalCommittedSum += typeCommitted; + totalReservedSum += typeReserved; + } else { + throwTestException("Failed to match the group on line " + i); + } + } + } + + // See if they add up correctly, rounding is a problem so make sure we're within +/- 8KB + int committedDiff = totalCommitted - totalCommittedSum; + if (committedDiff > 8 || committedDiff < -8) { + throwTestException("Total committed (" + totalCommitted + ") did not match the summarized committed (" + totalCommittedSum + ")" ); + } + + int reservedDiff = totalReserved - totalReservedSum; + if (reservedDiff > 8 || reservedDiff < -8) { + throwTestException("Total reserved (" + totalReserved + ") did not match the summarized reserved (" + totalReservedSum + ")" ); + } + } + + private static void throwTestException(String reason) throws Exception { + throw new Exception(reason + " . Stdout is :\n" + jcmdout); + } +} From b61bb15030d4c205949f3663bc6d60e41bce3c6c Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Sat, 2 Feb 2013 17:15:13 +0000 Subject: [PATCH 072/158] 8007322: untangle ftp protocol from general networking URL tests Reviewed-by: alanb --- jdk/test/java/net/URL/Constructor.java | 260 ++++++++++++++---- jdk/test/java/net/URL/HandlerLoop.java | 2 +- jdk/test/java/net/URL/Test.java | 19 +- jdk/test/java/net/URL/URIToURLTest.java | 31 ++- jdk/test/java/net/URL/abnormal_http_urls | 43 --- jdk/test/java/net/URL/ftp_urls | 27 -- jdk/test/java/net/URL/jar_urls | 75 ----- jdk/test/java/net/URL/normal_http_urls | 83 ------ jdk/test/java/net/URL/runconstructor.sh | 67 ----- jdk/test/java/net/URL/share_file_urls | 51 ---- jdk/test/java/net/URL/win32_file_urls | 15 - .../net/URLConnection/RequestProperties.java | 129 ++++----- .../URLConnection/RequestPropertyValues.java | 30 +- jdk/test/sun/net/{www => ftp}/EncDec.doc | Bin .../sun/net/{www => ftp}/MarkResetTest.java | 0 .../sun/net/{www => ftp}/MarkResetTest.sh | 0 .../net/www/http/HttpClient/ProxyTest.java | 12 +- 17 files changed, 327 insertions(+), 517 deletions(-) delete mode 100644 jdk/test/java/net/URL/abnormal_http_urls delete mode 100644 jdk/test/java/net/URL/ftp_urls delete mode 100644 jdk/test/java/net/URL/jar_urls delete mode 100644 jdk/test/java/net/URL/normal_http_urls delete mode 100644 jdk/test/java/net/URL/runconstructor.sh delete mode 100644 jdk/test/java/net/URL/share_file_urls delete mode 100644 jdk/test/java/net/URL/win32_file_urls rename jdk/test/sun/net/{www => ftp}/EncDec.doc (100%) rename jdk/test/sun/net/{www => ftp}/MarkResetTest.java (100%) rename jdk/test/sun/net/{www => ftp}/MarkResetTest.sh (100%) diff --git a/jdk/test/java/net/URL/Constructor.java b/jdk/test/java/net/URL/Constructor.java index 2930db2fa4c..13eae40d6d4 100644 --- a/jdk/test/java/net/URL/Constructor.java +++ b/jdk/test/java/net/URL/Constructor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -21,71 +21,235 @@ * questions. */ -/* This is no longer run directly. See runconstructor.sh - * - * - * +/* + * @test + * @bug 4393671 + * @summary URL constructor URL(URL context, String spec) FAILED with specific input + */ + +/* * This program tests the URL parser in the URL constructor. It * tries to construct a variety of valid URLs with a given context * (which may be null) and a variety of specs. It then compares the * result with an expected value. - * - * It expects that a data file named "urls" be available in the - * current directory, from which it will get its testing data. The - * format of the file is: - * - * URL: null - * spec: jar:http://www.foo.com/dir1/jar.jar!/ - * expected: jar:http://www.foo.com/dir1/jar.jar!/ - * - * where URL is the context, spec is the spec and expected is the - * expected result. The first : must be followed by a space. Each test - * entry should be followed by a blank line. */ -import java.io.*; +import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; public class Constructor { public static void main(String[] args) throws Exception { - URL url = null; - String urls = "jar_urls"; - if (args.length > 0 && args[0] != null) { - urls = args[0]; - } + List entries = new ArrayList<>(); + entries.addAll(Arrays.asList(fileURLs)); + entries.addAll(Arrays.asList(jarURLs)); + entries.addAll(Arrays.asList(normalHttpURLs)); + entries.addAll(Arrays.asList(abnormalHttpURLs)); + if (hasFtp()) + entries.addAll(Arrays.asList(ftpURLs)); + URL url; - File f = new File(urls); - InputStream file = new FileInputStream(f); - BufferedReader in = new BufferedReader(new InputStreamReader(file)); - while(true) { - String context = in.readLine(); - if (context == null) { - break; - } - context = getValue(context); - String spec = getValue(in.readLine()); - String expected = getValue(in.readLine()); + for (Entry e : entries) { + if (e.context == null) + url = new URL(e.spec); + else + url = new URL(new URL(e.context), e.spec); - if (context.equals("null")) { - url = new URL(spec); - } else { - url = new URL(new URL(context), spec); - } - if (!(url.toString().equals(expected))) { - throw new RuntimeException("error for: \n\tURL:" + context + - "\n\tspec: " + spec + - "\n\texpected: " + expected + + if (!(url.toString().equals(e.expected))) { + throw new RuntimeException("error for: \n\tURL:" + e.context + + "\n\tspec: " + e.spec + + "\n\texpected: " + e.expected + "\n\tactual: " + url.toString()); } else { - System.out.println("success for: " + url + "\n"); + //debug + //System.out.println("success for: " + url); } - in.readLine(); } - in.close(); } - private static String getValue(String value) { - return value.substring(value.indexOf(':') + 2); + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } } + + static class Entry { + final String context; + final String spec; + final String expected; + Entry(String context, String spec, String expected) { + this.context = context; + this.spec =spec; + this.expected = expected; + } + } + + static Entry[] fileURLs = new Entry[] { + new Entry(null, + "file://JavaSoft/Test", + "file://JavaSoft/Test"), + new Entry(null, + "file:///JavaSoft/Test", + "file:/JavaSoft/Test"), + new Entry(null, + "file:/JavaSoft/Test", + "file:/JavaSoft/Test"), + new Entry(null, + "file:/c:/JavaSoft/Test", + "file:/c:/JavaSoft/Test"), + new Entry(null, + "file:/c:/JavaSoft/Test:something", + "file:/c:/JavaSoft/Test:something"), + new Entry(null, + "file:/c:/JavaSoft/Test#anchor", + "file:/c:/JavaSoft/Test#anchor"), + new Entry("file://JavaSoft/Test", + "Test#bar", + "file://JavaSoft/Test#bar"), + new Entry("file://codrus/c:/jdk/eng/index.html", + "pulsar.html", + "file://codrus/c:/jdk/eng/pulsar.html"), + new Entry("file:///c:/jdk/eng/index.html", + "pulsar.html", + "file:/c:/jdk/eng/pulsar.html"), + new Entry("file:///jdk/eng/index.html", + "pulsar.html", + "file:/jdk/eng/pulsar.html"), + new Entry("file://JavaSoft/Test", + "file://radartoad.com/Test#bar", + "file://radartoad.com/Test#bar"), + new Entry("file://JavaSoft/Test", + "/c:/Test#bar", + "file://JavaSoft/c:/Test#bar"), + }; + + static Entry[] jarURLs = new Entry[] { + new Entry(null, + "jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt"), + new Entry(null, + "jar:http://www.foo.com/dir1/jar.jar!/", + "jar:http://www.foo.com/dir1/jar.jar!/"), + new Entry(null, + "jar:http://www.foo.com/dir1/jar.jar!/", + "jar:http://www.foo.com/dir1/jar.jar!/"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "dir1/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/dir1/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir1/", + "entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir2/dir3/entry2.txt", + "/dir1/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/dir1/foo/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/", + "dir4/foo/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/dir4/foo/entry.txt"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/", + "/dir1/foo/entry.txt", + "jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt"), + new Entry(null, + "jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor", + "jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/foo.txt", + "#anchor", + "jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor"), + new Entry("jar:http://www.foo.com/dir1/jar.jar!/foo/bar/", + "baz/quux#anchor", + "jar:http://www.foo.com/dir1/jar.jar!/foo/bar/baz/quux#anchor"), + new Entry("jar:http://balloo.com/olle.jar!/", + "p2", + "jar:http://balloo.com/olle.jar!/p2") + }; + + static Entry[] normalHttpURLs = new Entry[] { + new Entry("http://a/b/c/d;p?q", "g", "http://a/b/c/g"), + new Entry("http://a/b/c/d;p?q", "./g", "http://a/b/c/g"), + new Entry("http://a/b/c/d;p?q", "g/", "http://a/b/c/g/"), + new Entry("http://a/b/c/d;p?q", "/g", "http://a/g"), + new Entry("http://a/b/c/d;p?q", "//g", "http://g"), + new Entry("http://a/b/c/d;p?q", "?y", "http://a/b/c/?y"), + new Entry("http://a/b/c/d;p?q", "g?y", "http://a/b/c/g?y"), + new Entry("http://a/b/c/d;p?q", "g#s", "http://a/b/c/g#s"), + new Entry("http://a/b/c/d;p?q", "g?y#s", "http://a/b/c/g?y#s"), + new Entry("http://a/b/c/d;p?q", ";x", "http://a/b/c/;x"), + new Entry("http://a/b/c/d;p?q", "g;x", "http://a/b/c/g;x"), + new Entry("http://a/b/c/d;p?q", "g;x?y#s", "http://a/b/c/g;x?y#s"), + new Entry("http://a/b/c/d;p?q", ".", "http://a/b/c/"), + new Entry("http://a/b/c/d;p?q", "./", "http://a/b/c/"), + new Entry("http://a/b/c/d;p?q", "..", "http://a/b/"), + new Entry("http://a/b/c/d;p?q", "../", "http://a/b/"), + new Entry("http://a/b/c/d;p?q", "../g", "http://a/b/g"), + new Entry("http://a/b/c/d;p?q", "../..", "http://a/"), + new Entry("http://a/b/c/d;p?q", "../../", "http://a/"), + new Entry("http://a/b/c/d;p?q", "../../g", "http://a/g"), + new Entry(null, + "http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc", + "http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc") + }; + + static Entry[] abnormalHttpURLs = new Entry[] { + new Entry("http://a/b/c/d;p?q", "../../../g", "http://a/../g"), + new Entry("http://a/b/c/d;p?q", "../../../../g", "http://a/../../g"), + new Entry("http://a/b/c/d;p?q", "/./g", "http://a/./g"), + new Entry("http://a/b/c/d;p?q", "/../g", "http://a/../g"), + new Entry("http://a/b/c/d;p?q", ".g", "http://a/b/c/.g"), + new Entry("http://a/b/c/d;p?q", "g.", "http://a/b/c/g."), + new Entry("http://a/b/c/d;p?q", "./../g", "http://a/b/g"), + new Entry("http://a/b/c/d;p?q", "./g/.", "http://a/b/c/g/"), + new Entry("http://a/b/c/d;p?q", "g/./h", "http://a/b/c/g/h"), + new Entry("http://a/b/c/d;p?q", "g;x=1/./y", "http://a/b/c/g;x=1/y"), + new Entry("http://a/b/c/d;p?q", "g;x=1/../y", "http://a/b/c/y") + }; + + static Entry[] ftpURLs = new Entry[] { + new Entry(null, + "ftp://ftp.foo.com/dir1/entry.txt", + "ftp://ftp.foo.com/dir1/entry.txt"), + new Entry(null, + "ftp://br:pwd@ftp.foo.com/dir1/jar.jar", + "ftp://br:pwd@ftp.foo.com/dir1/jar.jar"), + new Entry("ftp://ftp.foo.com/dir1/foo.txt", + "bar.txt", + "ftp://ftp.foo.com/dir1/bar.txt"), + new Entry("ftp://ftp.foo.com/dir1/jar.jar", + "/entry.txt", + "ftp://ftp.foo.com/entry.txt"), + new Entry("ftp://ftp.foo.com/dir1/jar.jar", + "dir1/entry.txt", + "ftp://ftp.foo.com/dir1/dir1/entry.txt"), + new Entry("ftp://ftp.foo.com/dir1/jar.jar", + "/dir1/entry.txt", + "ftp://ftp.foo.com/dir1/entry.txt"), + new Entry("ftp://br:pwd@ftp.foo.com/dir1/jar.jar", + "/dir1/entry.txt", + "ftp://br:pwd@ftp.foo.com/dir1/entry.txt") + }; } diff --git a/jdk/test/java/net/URL/HandlerLoop.java b/jdk/test/java/net/URL/HandlerLoop.java index 69ca4e523b5..df02891b038 100644 --- a/jdk/test/java/net/URL/HandlerLoop.java +++ b/jdk/test/java/net/URL/HandlerLoop.java @@ -36,7 +36,7 @@ public class HandlerLoop { public static void main(String args[]) throws Exception { URL.setURLStreamHandlerFactory( new HandlerFactory("sun.net.www.protocol")); - URL url = new URL("file://bogus/index.html"); + URL url = new URL("file:///bogus/index.html"); System.out.println("url = " + url); url.openConnection(); } diff --git a/jdk/test/java/net/URL/Test.java b/jdk/test/java/net/URL/Test.java index 4ea4bd7c634..1e44ffe8b03 100644 --- a/jdk/test/java/net/URL/Test.java +++ b/jdk/test/java/net/URL/Test.java @@ -310,7 +310,14 @@ public class Test { throw new RuntimeException("Test failed"); } - + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } + } // -- Tests -- @@ -319,8 +326,9 @@ public class Test { header("RFC2396: Basic examples"); - test("ftp://ftp.is.co.za/rfc/rfc1808.txt") - .s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z(); + if (hasFtp()) + test("ftp://ftp.is.co.za/rfc/rfc1808.txt") + .s("ftp").h("ftp.is.co.za").p("/rfc/rfc1808.txt").z(); test("http://www.math.uio.no/faq/compression-faq/part1.html") .s("http").h("www.math.uio.no").p("/faq/compression-faq/part1.html").z(); @@ -328,8 +336,9 @@ public class Test { test("http://www.w3.org/Addressing/") .s("http").h("www.w3.org").p("/Addressing/").z(); - test("ftp://ds.internic.net/rfc/") - .s("ftp").h("ds.internic.net").p("/rfc/").z(); + if (hasFtp()) + test("ftp://ds.internic.net/rfc/") + .s("ftp").h("ds.internic.net").p("/rfc/").z(); test("http://www.ics.uci.edu/pub/ietf/url/historical.html#WARNING") .s("http").h("www.ics.uci.edu").p("/pub/ietf/url/historical.html") diff --git a/jdk/test/java/net/URL/URIToURLTest.java b/jdk/test/java/net/URL/URIToURLTest.java index 8ae07b36b12..79273b246c5 100644 --- a/jdk/test/java/net/URL/URIToURLTest.java +++ b/jdk/test/java/net/URL/URIToURLTest.java @@ -28,20 +28,22 @@ */ import java.net.*; +import java.util.ArrayList; +import java.util.List; public class URIToURLTest { public static void main(String args[]) throws Exception { - String[] uris = { - "http://jag:cafebabe@java.sun.com:94/b/c/d?q#g", - "http://[1080:0:0:0:8:800:200C:417A]/index.html", - "http://a/b/c/d;p?q", - "ftp://ftp.is.co.za/rfc/rfc1808.txt", - "mailto:mduerst@ifi.unizh.ch", // opaque url - "http:comp.infosystems.www.servers.unix" //opaque url - }; + List uris = new ArrayList<>(); + uris.add("http://jag:cafebabe@java.sun.com:94/b/c/d?q#g"); + uris.add("http://[1080:0:0:0:8:800:200C:417A]/index.html"); + uris.add("http://a/b/c/d;p?q"); + uris.add("mailto:mduerst@ifi.unizh.ch"); + uris.add("http:comp.infosystems.www.servers.unix"); + if (hasFtp()) + uris.add("ftp://ftp.is.co.za/rfc/rfc1808.txt"); - for (int i = 0; i < uris.length; i++) { - URI uri = new URI(uris[i]); + for (String uriStr : uris) { + URI uri = new URI(uriStr); URL url = uri.toURL(); String scheme = uri.getScheme(); boolean schemeCheck = scheme == null? url.getProtocol() == null : @@ -111,4 +113,13 @@ public class URIToURLTest { url.getRef()); } } + + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } + } } diff --git a/jdk/test/java/net/URL/abnormal_http_urls b/jdk/test/java/net/URL/abnormal_http_urls deleted file mode 100644 index 1fbf57d37a5..00000000000 --- a/jdk/test/java/net/URL/abnormal_http_urls +++ /dev/null @@ -1,43 +0,0 @@ -URL: http://a/b/c/d;p?q -spec: ../../../g -expected: http://a/../g - -URL: http://a/b/c/d;p?q -spec: ../../../../g -expected: http://a/../../g - -URL: http://a/b/c/d;p?q -spec: /./g -expected: http://a/./g - -URL: http://a/b/c/d;p?q -spec: /../g -expected: http://a/../g - -URL: http://a/b/c/d;p?q -spec: .g -expected: http://a/b/c/.g - -URL: http://a/b/c/d;p?q -spec: g. -expected: http://a/b/c/g. - -URL: http://a/b/c/d;p?q -spec: ./../g -expected: http://a/b/g - -URL: http://a/b/c/d;p?q -spec: ./g/. -expected: http://a/b/c/g/ - -URL: http://a/b/c/d;p?q -spec: g/./h -expected: http://a/b/c/g/h - -URL: http://a/b/c/d;p?q -spec: g;x=1/./y -expected: http://a/b/c/g;x=1/y - -URL: http://a/b/c/d;p?q -spec: g;x=1/../y -expected: http://a/b/c/y diff --git a/jdk/test/java/net/URL/ftp_urls b/jdk/test/java/net/URL/ftp_urls deleted file mode 100644 index 1f8d6fc6fa6..00000000000 --- a/jdk/test/java/net/URL/ftp_urls +++ /dev/null @@ -1,27 +0,0 @@ -URL: null -spec: ftp://ftp.foo.com/dir1/entry.txt -expected: ftp://ftp.foo.com/dir1/entry.txt - -URL: null -spec: ftp://br:pwd@ftp.foo.com/dir1/jar.jar -expected: ftp://br:pwd@ftp.foo.com/dir1/jar.jar - -URL: ftp://ftp.foo.com/dir1/foo.txt -spec: bar.txt -expected: ftp://ftp.foo.com/dir1/bar.txt - -URL: ftp://ftp.foo.com/dir1/jar.jar -spec: /entry.txt -expected: ftp://ftp.foo.com/entry.txt - -URL: ftp://ftp.foo.com/dir1/jar.jar -spec: dir1/entry.txt -expected: ftp://ftp.foo.com/dir1/dir1/entry.txt - -URL: ftp://ftp.foo.com/dir1/jar.jar -spec: /dir1/entry.txt -expected: ftp://ftp.foo.com/dir1/entry.txt - -URL: ftp://br:pwd@ftp.foo.com/dir1/jar.jar -spec: /dir1/entry.txt -expected: ftp://br:pwd@ftp.foo.com/dir1/entry.txt diff --git a/jdk/test/java/net/URL/jar_urls b/jdk/test/java/net/URL/jar_urls deleted file mode 100644 index ebd888450fa..00000000000 --- a/jdk/test/java/net/URL/jar_urls +++ /dev/null @@ -1,75 +0,0 @@ -URL: null -spec: jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir2/entry.txt - -URL: null -spec: jar:http://www.foo.com/dir1/jar.jar!/ -expected: jar:http://www.foo.com/dir1/jar.jar!/ - -URL: null -spec: jar:http://www.foo.com/dir1/jar.jar!/ -expected: jar:http://www.foo.com/dir1/jar.jar!/ - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: dir1/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /dir1/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/dir1/ -spec: entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/dir2/dir3/entry2.txt -spec: /dir1/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /dir1/foo/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/ -spec: dir4/foo/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/dir2/dir3/dir4/foo/entry.txt - -URL: jar:http://www.foo.com/dir1/jar.jar!/ -spec: /dir1/foo/entry.txt -expected: jar:http://www.foo.com/dir1/jar.jar!/dir1/foo/entry.txt - -URL: null -spec: jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor -expected: jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor - -URL: jar:http://www.foo.com/dir1/jar.jar!/foo.txt -spec: #anchor -expected: jar:http://www.foo.com/dir1/jar.jar!/foo.txt#anchor - -URL: jar:http://www.foo.com/dir1/jar.jar!/foo/bar/ -spec: baz/quux#anchor -expected: jar:http://www.foo.com/dir1/jar.jar!/foo/bar/baz/quux#anchor - -URL: jar:http://balloo.com/olle.jar!/ -spec: p2 -expected: jar:http://balloo.com/olle.jar!/p2 diff --git a/jdk/test/java/net/URL/normal_http_urls b/jdk/test/java/net/URL/normal_http_urls deleted file mode 100644 index 52d332057dd..00000000000 --- a/jdk/test/java/net/URL/normal_http_urls +++ /dev/null @@ -1,83 +0,0 @@ -URL: http://a/b/c/d;p?q -spec: g -expected: http://a/b/c/g - -URL: http://a/b/c/d;p?q -spec: ./g -expected: http://a/b/c/g - -URL: http://a/b/c/d;p?q -spec: g/ -expected: http://a/b/c/g/ - -URL: http://a/b/c/d;p?q -spec: /g -expected: http://a/g - -URL: http://a/b/c/d;p?q -spec: //g -expected: http://g - -URL: http://a/b/c/d;p?q -spec: ?y -expected: http://a/b/c/?y - -URL: http://a/b/c/d;p?q -spec: g?y -expected: http://a/b/c/g?y - -URL: http://a/b/c/d;p?q -spec: g#s -expected: http://a/b/c/g#s - -URL: http://a/b/c/d;p?q -spec: g?y#s -expected: http://a/b/c/g?y#s - -URL: http://a/b/c/d;p?q -spec: ;x -expected: http://a/b/c/;x - -URL: http://a/b/c/d;p?q -spec: g;x -expected: http://a/b/c/g;x - -URL: http://a/b/c/d;p?q -spec: g;x?y#s -expected: http://a/b/c/g;x?y#s - -URL: http://a/b/c/d;p?q -spec: . -expected: http://a/b/c/ - -URL: http://a/b/c/d;p?q -spec: ./ -expected: http://a/b/c/ - -URL: http://a/b/c/d;p?q -spec: .. -expected: http://a/b/ - -URL: http://a/b/c/d;p?q -spec: ../ -expected: http://a/b/ - -URL: http://a/b/c/d;p?q -spec: ../g -expected: http://a/b/g - -URL: http://a/b/c/d;p?q -spec: ../.. -expected: http://a/ - -URL: http://a/b/c/d;p?q -spec: ../../ -expected: http://a/ - -URL: http://a/b/c/d;p?q -spec: ../../g -expected: http://a/g - -URL: null -spec: http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc -expected: http://www.javasoft.com/jdc/community/chat/index.html#javalive?frontpage-jdc diff --git a/jdk/test/java/net/URL/runconstructor.sh b/jdk/test/java/net/URL/runconstructor.sh deleted file mode 100644 index f64fd8509d1..00000000000 --- a/jdk/test/java/net/URL/runconstructor.sh +++ /dev/null @@ -1,67 +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. -# -# 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. -# - -# @test -# @bug 4393671 -# @summary URL constructor URL(URL context, String spec) FAILED with specific input in merlin -# -OS=`uname -s` -case "$OS" in - SunOS | Linux | Darwin ) - PS=":" - FS="/" - ;; - CYGWIN* ) - PS=";" - FS="/" - ;; - Windows* ) - PS=";" - FS="\\" - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac -${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . \ - ${TESTSRC}${FS}Constructor.java - -failures=0 - -go() { - echo '' - ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} Constructor $1 - if [ $? != 0 ]; then failures=`expr $failures + 1`; fi -} - -go ${TESTSRC}${FS}share_file_urls -go ${TESTSRC}${FS}jar_urls -go ${TESTSRC}${FS}normal_http_urls -go ${TESTSRC}${FS}ftp_urls -go ${TESTSRC}${FS}abnormal_http_urls - -if [ "$failures" != "0" ]; then - echo $failures tests failed - exit 1; -fi diff --git a/jdk/test/java/net/URL/share_file_urls b/jdk/test/java/net/URL/share_file_urls deleted file mode 100644 index 48451b45db4..00000000000 --- a/jdk/test/java/net/URL/share_file_urls +++ /dev/null @@ -1,51 +0,0 @@ -URL: null -spec: file://JavaSoft/Test -expected: file://JavaSoft/Test - -URL: null -spec: file:///JavaSoft/Test -expected: file:/JavaSoft/Test - -URL: null -spec: file:/JavaSoft/Test -expected: file:/JavaSoft/Test - -URL: null -spec: file:/c:/JavaSoft/Test -expected: file:/c:/JavaSoft/Test - -URL: null -spec: file:/c:/JavaSoft/Test:something -expected: file:/c:/JavaSoft/Test:something - -URL: null -spec: file:/c:/JavaSoft/Test#anchor -expected: file:/c:/JavaSoft/Test#anchor - -URL: null -spec: file:/JavaSoft/Test -expected: file:/JavaSoft/Test - -URL: file://JavaSoft/Test -spec: Test#bar -expected: file://JavaSoft/Test#bar - -URL: file://codrus/c:/jdk/eng/index.html -spec: pulsar.html -expected: file://codrus/c:/jdk/eng/pulsar.html - -URL: file:///c:/jdk/eng/index.html -spec: pulsar.html -expected: file:/c:/jdk/eng/pulsar.html - -URL: file:///jdk/eng/index.html -spec: pulsar.html -expected: file:/jdk/eng/pulsar.html - -URL: file://JavaSoft/Test -spec: file://radartoad.com/Test#bar -expected: file://radartoad.com/Test#bar - -URL: file://JavaSoft/Test -spec: /c:/Test#bar -expected: file://JavaSoft/c:/Test#bar \ No newline at end of file diff --git a/jdk/test/java/net/URL/win32_file_urls b/jdk/test/java/net/URL/win32_file_urls deleted file mode 100644 index 7e3981c1490..00000000000 --- a/jdk/test/java/net/URL/win32_file_urls +++ /dev/null @@ -1,15 +0,0 @@ -URL: null -spec: file://c:\JavaSoft\Test -expected: file://c:/JavaSoft/Test - -URL: null -spec: file:/c:\JavaSoft\Test -expected: file:/c:/JavaSoft/Test - -URL: null -spec: file:/c:\JavaSoft\Test:something#anchor -expected: file:/c:/JavaSoft/Test:something#anchor - -URL: file:///c:\jdk\eng\index.html -spec: pulsar.html -expected: file:/c:/jdk/eng/pulsar.html \ No newline at end of file diff --git a/jdk/test/java/net/URLConnection/RequestProperties.java b/jdk/test/java/net/URLConnection/RequestProperties.java index 74fd558ddbe..af549e22e54 100644 --- a/jdk/test/java/net/URLConnection/RequestProperties.java +++ b/jdk/test/java/net/URLConnection/RequestProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -28,90 +28,55 @@ */ import java.net.*; +import java.util.ArrayList; +import java.util.List; public class RequestProperties { - public static void main (String args[]) throws Exception { - URL url0 = new URL ("http://foo.com/bar/"); - URL url1 = new URL ("file:/etc/passwd"); - URL url2 = new URL ("ftp://foo:bar@foobar.com/etc/passwd"); - URL url3 = new URL ("jar:http://foo.com/bar.html!/foo/bar"); - URLConnection urlc0 = url0.openConnection (); - URLConnection urlc1 = url1.openConnection (); - URLConnection urlc2 = url2.openConnection (); - URLConnection urlc3 = url3.openConnection (); - int count = 0; - String s = null; - try { - urlc0.setRequestProperty (null, null); - System.out.println ("http: setRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc0.addRequestProperty (null, null); - System.out.println ("http: addRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc1.setRequestProperty (null, null); - System.out.println ("file: setRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc1.addRequestProperty (null, null); - System.out.println ("file: addRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc2.setRequestProperty (null, null); - System.out.println ("ftp: setRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc2.addRequestProperty (null, null); - System.out.println ("ftp: addRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc3.setRequestProperty (null, null); - System.out.println ("jar: setRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - try { - urlc3.addRequestProperty (null, null); - System.out.println ("jar: addRequestProperty (null,) did not throw NPE"); - } catch (NullPointerException e) { - count ++; - } - if (urlc0.getRequestProperty (null) != null) { - System.out.println ("http: getRequestProperty (null,) did not return null"); - } else { - count ++; - } - if (urlc1.getRequestProperty (null) != null) { - System.out.println ("file: getRequestProperty (null,) did not return null"); - } else { - count ++; - } - if (urlc2.getRequestProperty (null) != null) { - System.out.println ("ftp: getRequestProperty (null,) did not return null"); - } else { - count ++; - } - if (urlc2.getRequestProperty (null) != null) { - System.out.println ("jar: getRequestProperty (null,) did not return null"); - } else { - count ++; - } + static int failed; - if (count != 12) { - throw new RuntimeException ((12 -count) + " errors") ; + public static void main (String args[]) throws Exception { + List urls = new ArrayList<>(); + urls.add("http://foo.com/bar/"); + urls.add("jar:http://foo.com/bar.html!/foo/bar"); + urls.add("file:/etc/passwd"); + if (hasFtp()) + urls.add("ftp://foo:bar@foobar.com/etc/passwd"); + + for (String urlStr : urls) + test(new URL(urlStr)); + + if (failed != 0) + throw new RuntimeException(failed + " errors") ; + } + + static void test(URL url) throws Exception { + URLConnection urlc = url.openConnection(); + try { + urlc.setRequestProperty(null, null); + System.out.println(url.getProtocol() + + ": setRequestProperty(null,) did not throw NPE"); + failed++; + } catch (NullPointerException e) { /* Expected */ } + try { + urlc.addRequestProperty(null, null); + System.out.println(url.getProtocol() + + ": addRequestProperty(null,) did not throw NPE"); + failed++; + } catch (NullPointerException e) { /* Expected */ } + + if (urlc.getRequestProperty(null) != null) { + System.out.println(url.getProtocol() + + ": getRequestProperty(null,) did not return null"); + failed++; + } + } + + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; } } } diff --git a/jdk/test/java/net/URLConnection/RequestPropertyValues.java b/jdk/test/java/net/URLConnection/RequestPropertyValues.java index 77bb469e672..6874063ca1d 100644 --- a/jdk/test/java/net/URLConnection/RequestPropertyValues.java +++ b/jdk/test/java/net/URLConnection/RequestPropertyValues.java @@ -27,8 +27,11 @@ * @summary Test URLConnection Request Proterties */ +import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; +import java.util.ArrayList; +import java.util.List; /** * Part1: @@ -45,28 +48,29 @@ public class RequestPropertyValues { } public static void part1() throws Exception { - URL[] urls = { new URL("http://localhost:8088"), - new URL("file:/etc/passwd"), - new URL("ftp://foo:bar@foobar.com/etc/passwd"), - new URL("jar:http://foo.com/bar.html!/foo/bar") - }; + List urls = new ArrayList<>(); + urls.add(new URL("http://localhost:8088")); + urls.add(new URL("file:/etc/passwd")); + urls.add(new URL("jar:http://foo.com/bar.html!/foo/bar")); + if (hasFtp()) + urls.add(new URL("ftp://foo:bar@foobar.com/etc/passwd")); boolean failed = false; - for (int proto = 0; proto < urls.length; proto++) { - URLConnection uc = (URLConnection) urls[proto].openConnection(); + for (URL url : urls) { + URLConnection uc = url.openConnection(); try { uc.setRequestProperty("TestHeader", null); } catch (NullPointerException npe) { System.out.println("setRequestProperty is throwing NPE" + - " for url: " + urls[proto]); + " for url: " + url); failed = true; } try { uc.addRequestProperty("TestHeader", null); } catch (NullPointerException npe) { System.out.println("addRequestProperty is throwing NPE" + - " for url: " + urls[proto]); + " for url: " + url); failed = true; } } @@ -110,4 +114,12 @@ public class RequestPropertyValues { } } + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } + } } diff --git a/jdk/test/sun/net/www/EncDec.doc b/jdk/test/sun/net/ftp/EncDec.doc similarity index 100% rename from jdk/test/sun/net/www/EncDec.doc rename to jdk/test/sun/net/ftp/EncDec.doc diff --git a/jdk/test/sun/net/www/MarkResetTest.java b/jdk/test/sun/net/ftp/MarkResetTest.java similarity index 100% rename from jdk/test/sun/net/www/MarkResetTest.java rename to jdk/test/sun/net/ftp/MarkResetTest.java diff --git a/jdk/test/sun/net/www/MarkResetTest.sh b/jdk/test/sun/net/ftp/MarkResetTest.sh similarity index 100% rename from jdk/test/sun/net/www/MarkResetTest.sh rename to jdk/test/sun/net/ftp/MarkResetTest.sh diff --git a/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java b/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java index 18c2e1f0840..5d13a58d8cb 100644 --- a/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java +++ b/jdk/test/sun/net/www/http/HttpClient/ProxyTest.java @@ -161,8 +161,18 @@ public class ProxyTest { } } + private static boolean hasFtp() { + try { + return new java.net.URL("ftp://") != null; + } catch (java.net.MalformedURLException x) { + System.out.println("FTP not supported by this runtime."); + return false; + } + } + public static void main(String[] args) throws Exception { - ProxyTest test = new ProxyTest(); + if (hasFtp()) + new ProxyTest(); } public ProxyTest() throws Exception { From 898965f4587e4d256fb1345720a8ab719dfadbda Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Sat, 2 Feb 2013 20:13:27 +0100 Subject: [PATCH 073/158] 8000363: runtime/7158988/FieldMonitor.java fails with exception Removed unnecessary shell script in the test. Reviewed-by: coleenp, sla --- .../test/runtime/7158988/FieldMonitor.java | 4 +- .../test/runtime/7158988/TestFieldMonitor.sh | 75 ------------------- 2 files changed, 3 insertions(+), 76 deletions(-) delete mode 100644 hotspot/test/runtime/7158988/TestFieldMonitor.sh diff --git a/hotspot/test/runtime/7158988/FieldMonitor.java b/hotspot/test/runtime/7158988/FieldMonitor.java index 584d39d20ca..5421f626278 100644 --- a/hotspot/test/runtime/7158988/FieldMonitor.java +++ b/hotspot/test/runtime/7158988/FieldMonitor.java @@ -24,8 +24,10 @@ /* * @test FieldMonitor.java * @bug 7158988 + * @key regression * @summary verify jvm does not crash while debugging - * @run shell TestFieldMonitor.sh + * @run compile TestPostFieldModification.java + * @run main/othervm FieldMonitor * @author axel.siebenborn@sap.com */ import java.io.BufferedReader; diff --git a/hotspot/test/runtime/7158988/TestFieldMonitor.sh b/hotspot/test/runtime/7158988/TestFieldMonitor.sh deleted file mode 100644 index aa18c1609ba..00000000000 --- a/hotspot/test/runtime/7158988/TestFieldMonitor.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/sh - -if [ "${TESTSRC}" = "" ] -then TESTSRC=. -fi - -if [ "${TESTJAVA}" = "" ] -then - PARENT=`dirname \`which java\`` - TESTJAVA=`dirname ${PARENT}` - echo "TESTJAVA not set, selecting " ${TESTJAVA} - echo "If this is incorrect, try setting the variable manually." -fi - -if [ "${TESTCLASSES}" = "" ] -then - echo "TESTCLASSES not set. Test cannot execute. Failed." - exit 1 -fi - -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - SunOS | Linux | Darwin) - NULL=/dev/null - PS=":" - FS="/" - ;; - Windows_95 | Windows_98 | Windows_ME ) - NULL=NUL - PS=";" - FS="\\" - echo "Test skipped, only for WinNT" - exit 0 - ;; - Windows_NT ) - NULL=NUL - PS=";" - FS="\\" - ;; - CYGWIN_NT* ) - NULL=/dev/null - PS=";" - FS="/" - ;; - CYGWIN_* ) - NULL=/dev/null - PS=";" - FS="/" - echo "Test skipped, only for WinNT" - exit 0 - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac - -#CLASSPATH=.${PS}${TESTCLASSES} ; export CLASSPATH - -cp ${TESTSRC}${FS}*.java . - -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -fullversion - -${TESTJAVA}${FS}bin${FS}javac -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar *.java - -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar FieldMonitor > test.out - -grep "A fatal error has been detected" test.out > ${NULL} -if [ $? = 0 ]; then - cat test.out - STATUS=1 -fi - -exit $STATUS From e618b1556c93d5dec1c30b236a46f22f0e6f756e Mon Sep 17 00:00:00 2001 From: Ragini Prasad Date: Sat, 2 Feb 2013 12:08:43 -0800 Subject: [PATCH 074/158] 8007135: tools/launcher/VersionCheck.java failing with new tool jabswitch Reviewed-by: ksrini, mduigou --- jdk/test/tools/launcher/VersionCheck.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/test/tools/launcher/VersionCheck.java b/jdk/test/tools/launcher/VersionCheck.java index c30ef424011..11f65cb2e9a 100644 --- a/jdk/test/tools/launcher/VersionCheck.java +++ b/jdk/test/tools/launcher/VersionCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -42,6 +42,7 @@ public class VersionCheck extends TestHelper { // tools that do not accept -J-option static final String[] BLACKLIST_JOPTION = { "controlpanel", + "jabswitch", "java-rmi", "java-rmi.cgi", "java", From a9f424c887883bb9e9bd10deb93e657321313f80 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Sat, 2 Feb 2013 21:04:56 +0000 Subject: [PATCH 075/158] 8005075: Pool.Method, and Pool.Variable redundant Symbol field should be removed Reviewed-by: jjg --- .../com/sun/tools/javac/code/Symbol.java | 10 +++-- .../com/sun/tools/javac/jvm/ClassWriter.java | 6 +-- .../classes/com/sun/tools/javac/jvm/Pool.java | 44 +++++++++---------- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java index a970da60530..0bc115e1041 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java @@ -496,9 +496,9 @@ public abstract class Symbol implements Element { return l.toList(); } - public static class DelegatedSymbol extends Symbol { - protected Symbol other; - public DelegatedSymbol(Symbol other) { + public static class DelegatedSymbol extends Symbol { + protected T other; + public DelegatedSymbol(T other) { super(other.kind, other.flags_field, other.name, other.type, other.owner); this.other = other; } @@ -532,6 +532,10 @@ public abstract class Symbol implements Element { public R accept(Symbol.Visitor v, P p) { return v.visitSymbol(other, p); } + + public T getUnderlyingSymbol() { + return other; + } } /** A class for type symbols. Type variables are represented by instances diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index b48701ee37c..8c1e3204c5d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -482,10 +482,8 @@ public class ClassWriter extends ClassFile { while (i < pool.pp) { Object value = pool.pool[i]; Assert.checkNonNull(value); - if (value instanceof Method) - value = ((Method)value).m; - else if (value instanceof Variable) - value = ((Variable)value).v; + if (value instanceof Method || value instanceof Variable) + value = ((DelegatedSymbol)value).getUnderlyingSymbol(); if (value instanceof MethodSymbol) { MethodSymbol m = (MethodSymbol)value; diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java index 08a5d57d87f..553cc3ae1a1 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -140,23 +140,23 @@ public class Pool { return n == null ? -1 : n.intValue(); } - static class Method extends DelegatedSymbol { - MethodSymbol m; + static class Method extends DelegatedSymbol { UniqueType uniqueType; Method(MethodSymbol m, Types types) { super(m); - this.m = m; this.uniqueType = new UniqueType(m.type, types); } - public boolean equals(Object other) { - if (!(other instanceof Method)) return false; - MethodSymbol o = ((Method)other).m; + public boolean equals(Object any) { + if (!(any instanceof Method)) return false; + MethodSymbol o = ((Method)any).other; + MethodSymbol m = this.other; return o.name == m.name && o.owner == m.owner && - ((Method)other).uniqueType.equals(uniqueType); + ((Method)any).uniqueType.equals(uniqueType); } public int hashCode() { + MethodSymbol m = this.other; return m.name.hashCode() * 33 + m.owner.hashCode() * 9 + @@ -173,21 +173,21 @@ public class Pool { } @Override - public boolean equals(Object other) { - if (!super.equals(other)) return false; - if (!(other instanceof DynamicMethod)) return false; - DynamicMethodSymbol dm1 = (DynamicMethodSymbol)m; - DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)other).m; + public boolean equals(Object any) { + if (!super.equals(any)) return false; + if (!(any instanceof DynamicMethod)) return false; + DynamicMethodSymbol dm1 = (DynamicMethodSymbol)other; + DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)any).other; return dm1.bsm == dm2.bsm && dm1.bsmKind == dm2.bsmKind && Arrays.equals(uniqueStaticArgs, - ((DynamicMethod)other).uniqueStaticArgs); + ((DynamicMethod)any).uniqueStaticArgs); } @Override public int hashCode() { int hash = super.hashCode(); - DynamicMethodSymbol dm = (DynamicMethodSymbol)m; + DynamicMethodSymbol dm = (DynamicMethodSymbol)other; hash += dm.bsmKind * 7 + dm.bsm.hashCode() * 11; for (int i = 0; i < dm.staticArgs.length; i++) { @@ -209,23 +209,23 @@ public class Pool { } } - static class Variable extends DelegatedSymbol { - VarSymbol v; + static class Variable extends DelegatedSymbol { UniqueType uniqueType; Variable(VarSymbol v, Types types) { super(v); - this.v = v; this.uniqueType = new UniqueType(v.type, types); } - public boolean equals(Object other) { - if (!(other instanceof Variable)) return false; - VarSymbol o = ((Variable)other).v; + public boolean equals(Object any) { + if (!(any instanceof Variable)) return false; + VarSymbol o = ((Variable)any).other; + VarSymbol v = other; return o.name == v.name && o.owner == v.owner && - ((Variable)other).uniqueType.equals(uniqueType); + ((Variable)any).uniqueType.equals(uniqueType); } public int hashCode() { + VarSymbol v = other; return v.name.hashCode() * 33 + v.owner.hashCode() * 9 + From a4a897ce527e42523783f5fc46b7b1f80342d25a Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Sun, 3 Feb 2013 02:31:30 +0000 Subject: [PATCH 076/158] 7199823: javac generates inner class that can't be verified Reviewed-by: jjg, mcimadamore --- .../com/sun/tools/javac/comp/Lower.java | 49 +++++--- .../7199823/InnerClassCannotBeVerified.java | 110 ++++++++++++++++++ 2 files changed, 143 insertions(+), 16 deletions(-) create mode 100644 langtools/test/tools/javac/7199823/InnerClassCannotBeVerified.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java index bb3e913c33d..fb5202dffcb 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java @@ -570,10 +570,19 @@ public class Lower extends TreeTranslator { * @param flags The class symbol's flags * @param owner The class symbol's owner */ - ClassSymbol makeEmptyClass(long flags, ClassSymbol owner) { + JCClassDecl makeEmptyClass(long flags, ClassSymbol owner) { + return makeEmptyClass(flags, owner, null, true); + } + + JCClassDecl makeEmptyClass(long flags, ClassSymbol owner, Name flatname, + boolean addToDefs) { // Create class symbol. ClassSymbol c = reader.defineClass(names.empty, owner); - c.flatname = chk.localClassName(c); + if (flatname != null) { + c.flatname = flatname; + } else { + c.flatname = chk.localClassName(c); + } c.sourcefile = owner.sourcefile; c.completer = null; c.members_field = new Scope(c); @@ -597,9 +606,8 @@ public class Lower extends TreeTranslator { cdef.type = c.type; // Append class definition tree to owner's definitions. - odef.defs = odef.defs.prepend(cdef); - - return c; + if (addToDefs) odef.defs = odef.defs.prepend(cdef); + return cdef; } /************************************************************************** @@ -706,7 +714,7 @@ public class Lower extends TreeTranslator { * and synthethise a class (with makeEmptyClass) if one is not available. * However, there is a small possibility that an existing class will not * be generated as expected if it is inside a conditional with a constant - * expression. If that is found to be the case, create an empty class here. + * expression. If that is found to be the case, create an empty class tree here. */ private void checkAccessConstructorTags() { for (List l = accessConstrTags; l.nonEmpty(); l = l.tail) { @@ -714,14 +722,10 @@ public class Lower extends TreeTranslator { if (isTranslatedClassAvailable(c)) continue; // Create class definition tree. - JCClassDecl cdef = make.ClassDef( - make.Modifiers(STATIC | SYNTHETIC), names.empty, - List.nil(), - null, List.nil(), List.nil()); - cdef.sym = c; - cdef.type = c.type; - // add it to the list of classes to be generated - translated.append(cdef); + JCClassDecl cdec = makeEmptyClass(STATIC | SYNTHETIC, + c.outermostClass(), c.flatname, false); + swapAccessConstructorTag(c, cdec.sym); + translated.append(cdec); } } // where @@ -735,6 +739,19 @@ public class Lower extends TreeTranslator { return false; } + void swapAccessConstructorTag(ClassSymbol oldCTag, ClassSymbol newCTag) { + for (MethodSymbol methodSymbol : accessConstrs.values()) { + Assert.check(methodSymbol.type.hasTag(METHOD)); + MethodType oldMethodType = + (MethodType)methodSymbol.type; + if (oldMethodType.argtypes.head.tsym == oldCTag) + methodSymbol.type = + types.createMethodTypeWithParameters(oldMethodType, + oldMethodType.getParameterTypes().tail + .prepend(newCTag.erasure(types))); + } + } + /************************************************************************** * Access methods *************************************************************************/ @@ -1211,7 +1228,7 @@ public class Lower extends TreeTranslator { "1"); ClassSymbol ctag = chk.compiled.get(flatname); if (ctag == null) - ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass); + ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass).sym; // keep a record of all tags, to verify that all are generated as required accessConstrTags = accessConstrTags.prepend(ctag); return ctag; @@ -1778,7 +1795,7 @@ public class Lower extends TreeTranslator { if (e.sym.kind == TYP && e.sym.name == names.empty && (e.sym.flags() & INTERFACE) == 0) return (ClassSymbol) e.sym; - return makeEmptyClass(STATIC | SYNTHETIC, clazz); + return makeEmptyClass(STATIC | SYNTHETIC, clazz).sym; } /** Return symbol for "class$" method. If there is no method definition diff --git a/langtools/test/tools/javac/7199823/InnerClassCannotBeVerified.java b/langtools/test/tools/javac/7199823/InnerClassCannotBeVerified.java new file mode 100644 index 00000000000..c30927484ab --- /dev/null +++ b/langtools/test/tools/javac/7199823/InnerClassCannotBeVerified.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2012, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @bug 7199823 + * @summary javac generates inner class that can't be verified + * @run main InnerClassCannotBeVerified + */ + +import java.util.Arrays; +import javax.tools.JavaFileObject; +import java.net.URI; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; +import javax.tools.JavaCompiler; +import com.sun.source.util.JavacTask; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPoolException; +import java.io.File; +import java.io.IOException; + +public class InnerClassCannotBeVerified { + + private static final String errorMessage = + "Compile error while compiling the following source:\n"; + + public static void main(String... args) throws Exception { + new InnerClassCannotBeVerified().run(); + } + + void run() throws Exception { + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + JavaSource source = new JavaSource(); + JavacTask ct = (JavacTask)comp.getTask(null, null, null, + null, null, Arrays.asList(source)); + try { + if (!ct.call()) { + throw new AssertionError(errorMessage + + source.getCharContent(true)); + } + } catch (Throwable ex) { + throw new AssertionError(errorMessage + + source.getCharContent(true)); + } + check(); + } + + private void check() throws IOException, ConstantPoolException { + File file = new File("Test$1.class"); + ClassFile classFile = ClassFile.read(file); + boolean inheritsFromObject = + classFile.getSuperclassName().equals("java/lang/Object"); + boolean implementsNoInterface = classFile.interfaces.length == 0; + boolean noMethods = classFile.methods.length == 0; + if (!(inheritsFromObject && + implementsNoInterface && + noMethods)) { + throw new AssertionError("The inner classes reused as " + + "access constructor tag for this code must be empty"); + } + } + + class JavaSource extends SimpleJavaFileObject { + + String internalSource = + "public class Test {\n" + + " private static class Foo {}\n" + + " public static void main(String[] args){ \n" + + " new Foo();\n" + + " if(false) {\n" + + " new Runnable() {\n" + + " @Override\n" + + " public void run() {\n" + + " System.out.println();\n" + + " }\n" + + " }.run();\n" + + " }\n" + + " }\n" + + "}"; + public JavaSource() { + super(URI.create("Test.java"), JavaFileObject.Kind.SOURCE); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return internalSource; + } + } +} From 3f02516d3e67f8cd452bdd95cecb5667752abc81 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Sun, 3 Feb 2013 18:20:24 +0400 Subject: [PATCH 077/158] 6471906: java.lang.NegativeArraySizeException in tenToThe Reviewed-by: darcy --- .../share/classes/java/math/BigDecimal.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/classes/java/math/BigDecimal.java b/jdk/src/share/classes/java/math/BigDecimal.java index d95b1cb27b3..b7f6380948e 100644 --- a/jdk/src/share/classes/java/math/BigDecimal.java +++ b/jdk/src/share/classes/java/math/BigDecimal.java @@ -3537,13 +3537,25 @@ public class BigDecimal extends Number implements Comparable { else return expandBigIntegerTenPowers(n); } - // BigInteger.pow is slow, so make 10**n by constructing a - // BigInteger from a character string (still not very fast) - char tenpow[] = new char[n + 1]; - tenpow[0] = '1'; - for (int i = 1; i <= n; i++) - tenpow[i] = '0'; - return new BigInteger(tenpow,1, tenpow.length); + + if (n < 1024*524288) { + // BigInteger.pow is slow, so make 10**n by constructing a + // BigInteger from a character string (still not very fast) + // which occupies no more than 1GB (!) of memory. + char tenpow[] = new char[n + 1]; + tenpow[0] = '1'; + for (int i = 1; i <= n; i++) { + tenpow[i] = '0'; + } + return new BigInteger(tenpow, 1, tenpow.length); + } + + if ((n & 0x1) == 0x1) { + return BigInteger.TEN.multiply(bigTenToThe(n - 1)); + } else { + BigInteger tmp = bigTenToThe(n/2); + return tmp.multiply(tmp); + } } /** From eea117f3e5a46f6183ccf36fe87f5cfb3eb8fb0e Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Sun, 3 Feb 2013 21:39:58 +0400 Subject: [PATCH 078/158] 8002048: Protocol to discovery of manageable Java processes on a network Introduce a protocol to discover manageble Java instances across a network subnet, JDP Reviewed-by: sla, dfuchs --- .../share/classes/sun/management/Agent.java | 218 ++++++++---- .../sun/management/jdp/JdpBroadcaster.java | 124 +++++++ .../sun/management/jdp/JdpController.java | 196 +++++++++++ .../sun/management/jdp/JdpException.java | 40 +++ .../sun/management/jdp/JdpGenericPacket.java | 95 ++++++ .../sun/management/jdp/JdpJmxPacket.java | 196 +++++++++++ .../classes/sun/management/jdp/JdpPacket.java | 63 ++++ .../sun/management/jdp/JdpPacketReader.java | 139 ++++++++ .../sun/management/jdp/JdpPacketWriter.java | 93 +++++ .../sun/management/jdp/package-info.java | 55 +++ jdk/test/sun/management/jdp/JdpClient.java | 160 +++++++++ .../sun/management/jdp/JdpDoSomething.java | 103 ++++++ jdk/test/sun/management/jdp/JdpTest.sh | 323 ++++++++++++++++++ jdk/test/sun/management/jdp/JdpUnitTest.java | 90 +++++ 14 files changed, 1824 insertions(+), 71 deletions(-) create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpController.java create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpException.java create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpPacket.java create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java create mode 100644 jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java create mode 100644 jdk/src/share/classes/sun/management/jdp/package-info.java create mode 100644 jdk/test/sun/management/jdp/JdpClient.java create mode 100644 jdk/test/sun/management/jdp/JdpDoSomething.java create mode 100644 jdk/test/sun/management/jdp/JdpTest.sh create mode 100644 jdk/test/sun/management/jdp/JdpUnitTest.java diff --git a/jdk/src/share/classes/sun/management/Agent.java b/jdk/src/share/classes/sun/management/Agent.java index 19d2dedb5b4..feef02ad6be 100644 --- a/jdk/src/share/classes/sun/management/Agent.java +++ b/jdk/src/share/classes/sun/management/Agent.java @@ -22,7 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package sun.management; import java.io.BufferedInputStream; @@ -31,49 +30,55 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; - +import java.lang.management.ManagementFactory; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.management.ManagementFactory; - +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; import java.text.MessageFormat; - import java.util.MissingResourceException; import java.util.Properties; import java.util.ResourceBundle; import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXServiceURL; import static sun.management.AgentConfigurationError.*; import sun.management.jmxremote.ConnectorBootstrap; +import sun.management.jdp.JdpController; +import sun.management.jdp.JdpException; import sun.misc.VMSupport; /** - * This Agent is started by the VM when -Dcom.sun.management.snmp - * or -Dcom.sun.management.jmxremote is set. This class will be - * loaded by the system class loader. Also jmx framework could - * be started by jcmd + * This Agent is started by the VM when -Dcom.sun.management.snmp or + * -Dcom.sun.management.jmxremote is set. This class will be loaded by the + * system class loader. Also jmx framework could be started by jcmd */ public class Agent { // management properties + private static Properties mgmtProps; private static ResourceBundle messageRB; - private static final String CONFIG_FILE = - "com.sun.management.config.file"; + "com.sun.management.config.file"; private static final String SNMP_PORT = - "com.sun.management.snmp.port"; + "com.sun.management.snmp.port"; private static final String JMXREMOTE = - "com.sun.management.jmxremote"; + "com.sun.management.jmxremote"; private static final String JMXREMOTE_PORT = - "com.sun.management.jmxremote.port"; + "com.sun.management.jmxremote.port"; + private static final String RMI_PORT = + "com.sun.management.jmxremote.rmi.port"; private static final String ENABLE_THREAD_CONTENTION_MONITORING = - "com.sun.management.enableThreadContentionMonitoring"; + "com.sun.management.enableThreadContentionMonitoring"; private static final String LOCAL_CONNECTOR_ADDRESS_PROP = - "com.sun.management.jmxremote.localConnectorAddress"; - + "com.sun.management.jmxremote.localConnectorAddress"; private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME = - "sun.management.snmp.AdaptorBootstrap"; + "sun.management.snmp.AdaptorBootstrap"; + + private static final String JDP_DEFAULT_ADDRESS = "239.255.255.225"; + private static final int JDP_DEFAULT_PORT = 7095; // The only active agent allowed private static JMXConnectorServer jmxServer = null; @@ -81,26 +86,25 @@ public class Agent { // Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy // and return property set if args is null or empty // return empty property set - private static Properties parseString(String args){ + private static Properties parseString(String args) { Properties argProps = new Properties(); if (args != null) { - for (String option : args.split(",")) { - String s[] = option.split("=", 2); - String name = s[0].trim(); - String value = (s.length > 1) ? s[1].trim() : ""; + for (String option : args.split(",")) { + String s[] = option.split("=", 2); + String name = s[0].trim(); + String value = (s.length > 1) ? s[1].trim() : ""; - if (!name.startsWith("com.sun.management.")) { - error(INVALID_OPTION, name); - } + if (!name.startsWith("com.sun.management.")) { + error(INVALID_OPTION, name); + } - argProps.setProperty(name, value); - } + argProps.setProperty(name, value); + } } return argProps; } - // invoked by -javaagent or -Dcom.sun.management.agent.class public static void premain(String args) throws Exception { agentmain(args); @@ -115,18 +119,18 @@ public class Agent { Properties arg_props = parseString(args); // Read properties from the config file - Properties config_props = new Properties(); - String fname = arg_props.getProperty(CONFIG_FILE); - readConfiguration(fname, config_props); + Properties config_props = new Properties(); + String fname = arg_props.getProperty(CONFIG_FILE); + readConfiguration(fname, config_props); - // Arguments override config file - config_props.putAll(arg_props); - startAgent(config_props); + // Arguments override config file + config_props.putAll(arg_props); + startAgent(config_props); } // jcmd ManagementAgent.start_local entry point // Also called due to command-line via startAgent() - private static synchronized void startLocalManagementAgent(){ + private static synchronized void startLocalManagementAgent() { Properties agentProps = VMSupport.getAgentProperties(); // start local connector if not started @@ -156,7 +160,7 @@ public class Agent { throw new RuntimeException(getText(INVALID_STATE, "Agent already started")); } - Properties argProps = parseString(args); + Properties argProps = parseString(args); Properties configProps = new Properties(); // Load the management properties from the config file @@ -169,7 +173,7 @@ public class Agent { // management properties can be overridden by system properties // which take precedence Properties sysProps = System.getProperties(); - synchronized(sysProps){ + synchronized (sysProps) { configProps.putAll(sysProps); } @@ -190,21 +194,26 @@ public class Agent { // can specify this property inside config file, so enable optional // monitoring functionality if this property is set final String enableThreadContentionMonitoring = - configProps.getProperty(ENABLE_THREAD_CONTENTION_MONITORING); + configProps.getProperty(ENABLE_THREAD_CONTENTION_MONITORING); if (enableThreadContentionMonitoring != null) { ManagementFactory.getThreadMXBean(). - setThreadContentionMonitoringEnabled(true); + setThreadContentionMonitoringEnabled(true); } String jmxremotePort = configProps.getProperty(JMXREMOTE_PORT); if (jmxremotePort != null) { jmxServer = ConnectorBootstrap. - startRemoteConnectorServer(jmxremotePort, configProps); + startRemoteConnectorServer(jmxremotePort, configProps); + + startDiscoveryService(configProps); } } private static synchronized void stopRemoteManagementAgent() throws Exception { + + JdpController.stopDiscoveryService(); + if (jmxServer != null) { ConnectorBootstrap.unexportRegistry(); @@ -222,15 +231,15 @@ public class Agent { // Enable optional monitoring functionality if requested final String enableThreadContentionMonitoring = - props.getProperty(ENABLE_THREAD_CONTENTION_MONITORING); + props.getProperty(ENABLE_THREAD_CONTENTION_MONITORING); if (enableThreadContentionMonitoring != null) { ManagementFactory.getThreadMXBean(). - setThreadContentionMonitoringEnabled(true); + setThreadContentionMonitoringEnabled(true); } try { if (snmpPort != null) { - loadSnmpAgent(snmpPort, props); + loadSnmpAgent(snmpPort, props); } /* @@ -242,13 +251,14 @@ public class Agent { * of this "local" server is exported as a counter to the jstat * instrumentation buffer. */ - if (jmxremote != null || jmxremotePort != null) { + if (jmxremote != null || jmxremotePort != null) { if (jmxremotePort != null) { - jmxServer = ConnectorBootstrap. - startRemoteConnectorServer(jmxremotePort, props); + jmxServer = ConnectorBootstrap. + startRemoteConnectorServer(jmxremotePort, props); + startDiscoveryService(props); } startLocalManagementAgent(); - } + } } catch (AgentConfigurationError e) { error(e.getError(), e.getParams()); @@ -257,6 +267,73 @@ public class Agent { } } + private static void startDiscoveryService(Properties props) + throws IOException { + // Start discovery service if requested + String discoveryPort = props.getProperty("com.sun.management.jdp.port"); + String discoveryAddress = props.getProperty("com.sun.management.jdp.address"); + String discoveryShouldStart = props.getProperty("com.sun.management.jmxremote.autodiscovery"); + + // Decide whether we should start autodicovery service. + // To start autodiscovery following conditions should be met: + // autodiscovery==true OR (autodicovery==null AND jdp.port != NULL) + + boolean shouldStart = false; + if (discoveryShouldStart == null){ + shouldStart = (discoveryPort != null); + } + else{ + try{ + shouldStart = Boolean.parseBoolean(discoveryShouldStart); + } catch (NumberFormatException e) { + throw new AgentConfigurationError("Couldn't parse autodiscovery argument"); + } + } + + if (shouldStart) { + // port and address are required arguments and have no default values + InetAddress address; + try { + address = (discoveryAddress == null) ? + InetAddress.getByName(JDP_DEFAULT_ADDRESS) : InetAddress.getByName(discoveryAddress); + } catch (UnknownHostException e) { + throw new AgentConfigurationError("Unable to broadcast to requested address", e); + } + + int port = JDP_DEFAULT_PORT; + if (discoveryPort != null) { + try { + port = Integer.parseInt(discoveryPort); + } catch (NumberFormatException e) { + throw new AgentConfigurationError("Couldn't parse JDP port argument"); + } + } + + // Rebuilding service URL to broadcast it + String jmxremotePort = props.getProperty(JMXREMOTE_PORT); + String rmiPort = props.getProperty(RMI_PORT); + + JMXServiceURL url = jmxServer.getAddress(); + String hostname = url.getHost(); + + String jmxUrlStr = (rmiPort != null) + ? String.format( + "service:jmx:rmi://%s:%s/jndi/rmi://%s:%s/jmxrmi", + hostname, rmiPort, hostname, jmxremotePort) + : String.format( + "service:jmx:rmi:///jndi/rmi://%s:%s/jmxrmi", hostname, jmxremotePort); + + String instanceName = System.getProperty("com.sun.management.jdp.name"); + + try{ + JdpController.startDiscoveryService(address, port, instanceName, jmxUrlStr); + } + catch(JdpException e){ + throw new AgentConfigurationError("Couldn't start JDP service", e); + } + } + } + public static Properties loadManagementProperties() { Properties props = new Properties(); @@ -268,22 +345,22 @@ public class Agent { // management properties can be overridden by system properties // which take precedence Properties sysProps = System.getProperties(); - synchronized(sysProps){ + synchronized (sysProps) { props.putAll(sysProps); } return props; - } + } - public static synchronized Properties getManagementProperties() { + public static synchronized Properties getManagementProperties() { if (mgmtProps == null) { String configFile = System.getProperty(CONFIG_FILE); String snmpPort = System.getProperty(SNMP_PORT); String jmxremote = System.getProperty(JMXREMOTE); String jmxremotePort = System.getProperty(JMXREMOTE_PORT); - if (configFile == null && snmpPort == null && - jmxremote == null && jmxremotePort == null) { + if (configFile == null && snmpPort == null + && jmxremote == null && jmxremotePort == null) { // return if out-of-the-management option is not specified return null; } @@ -297,22 +374,23 @@ public class Agent { // invoke the following through reflection: // AdaptorBootstrap.initialize(snmpPort, props); final Class adaptorClass = - Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME,true,null); + Class.forName(SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME, true, null); final Method initializeMethod = adaptorClass.getMethod("initialize", - String.class, Properties.class); - initializeMethod.invoke(null,snmpPort,props); + String.class, Properties.class); + initializeMethod.invoke(null, snmpPort, props); } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException x) { // snmp runtime doesn't exist - initialization fails - throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,x); + throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, x); } catch (InvocationTargetException x) { final Throwable cause = x.getCause(); - if (cause instanceof RuntimeException) + if (cause instanceof RuntimeException) { throw (RuntimeException) cause; - else if (cause instanceof Error) + } else if (cause instanceof Error) { throw (Error) cause; + } // should not happen... - throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT,cause); + throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT, cause); } } @@ -353,8 +431,8 @@ public class Agent { } catch (IOException e) { error(CONFIG_FILE_CLOSE_FAILED, fname); } - } - } + } + } } public static void startAgent() throws Exception { @@ -389,9 +467,9 @@ public class Agent { // invoke the premain(String args) method Class clz = ClassLoader.getSystemClassLoader().loadClass(cname); Method premain = clz.getMethod("premain", - new Class[] { String.class }); + new Class[]{String.class}); premain.invoke(null, /* static */ - new Object[] { args }); + new Object[]{args}); } catch (ClassNotFoundException ex) { error(AGENT_CLASS_NOT_FOUND, "\"" + cname + "\""); } catch (NoSuchMethodException ex) { @@ -400,8 +478,8 @@ public class Agent { error(AGENT_CLASS_ACCESS_DENIED); } catch (Exception ex) { String msg = (ex.getCause() == null - ? ex.getMessage() - : ex.getCause().getMessage()); + ? ex.getMessage() + : ex.getCause().getMessage()); error(AGENT_CLASS_FAILED, msg); } } @@ -425,7 +503,6 @@ public class Agent { } } - public static void error(String key, String message) { String keyText = getText(key); System.err.print(getText("agent.err.error") + ": " + keyText); @@ -447,7 +524,7 @@ public class Agent { private static void initResource() { try { messageRB = - ResourceBundle.getBundle("sun.management.resources.agent"); + ResourceBundle.getBundle("sun.management.resources.agent"); } catch (MissingResourceException e) { throw new Error("Fatal: Resource for management agent is missing"); } @@ -470,10 +547,9 @@ public class Agent { } String format = messageRB.getString(key); if (format == null) { - format = "missing resource key: key = \"" + key + "\", " + - "arguments = \"{0}\", \"{1}\", \"{2}\""; + format = "missing resource key: key = \"" + key + "\", " + + "arguments = \"{0}\", \"{1}\", \"{2}\""; } return MessageFormat.format(format, (Object[]) args); } - } diff --git a/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java b/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java new file mode 100644 index 00000000000..df5f23458e5 --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java @@ -0,0 +1,124 @@ +/* + * 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. + * + * 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.management.jdp; + +import java.io.IOException; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.ProtocolFamily; +import java.net.StandardProtocolFamily; +import java.net.StandardSocketOptions; +import java.nio.ByteBuffer; +import java.nio.channels.DatagramChannel; +import java.nio.channels.UnsupportedAddressTypeException; + +/** + * JdpBroadcaster is responsible for sending pre-built JDP packet across a Net + * + *

Multicast group address, port number and ttl have to be chosen on upper + * level and passed to broadcaster constructor. Also it's possible to specify + * source address to broadcast from.

+ * + *

JdpBradcaster doesn't perform any validation on a supplied {@code port} and {@code ttl} because + * the allowed values depend on an operating system setup

+ * + */ +public final class JdpBroadcaster { + + private final InetAddress addr; + private final int port; + private final DatagramChannel channel; + + /** + * Create a new broadcaster + * + * @param address - multicast group address + * @param srcAddress - address of interface we should use to broadcast. + * @param port - udp port to use + * @param ttl - packet ttl + * @throws IOException + */ + public JdpBroadcaster(InetAddress address, InetAddress srcAddress, int port, int ttl) + throws IOException, JdpException { + this.addr = address; + this.port = port; + + ProtocolFamily family = (address instanceof Inet6Address) + ? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; + + channel = DatagramChannel.open(family); + channel.setOption(StandardSocketOptions.SO_REUSEADDR, true); + channel.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl); + + // with srcAddress equal to null, this constructor do exactly the same as + // if srcAddress is not passed + if (srcAddress != null) { + // User requests particular interface to bind to + NetworkInterface interf = NetworkInterface.getByInetAddress(srcAddress); + try { + channel.bind(new InetSocketAddress(srcAddress, 0)); + } catch (UnsupportedAddressTypeException ex) { + throw new JdpException("Unable to bind to source address"); + } + channel.setOption(StandardSocketOptions.IP_MULTICAST_IF, interf); + } + } + + /** + * Create a new broadcaster + * + * @param address - multicast group address + * @param port - udp port to use + * @param ttl - packet ttl + * @throws IOException + */ + public JdpBroadcaster(InetAddress address, int port, int ttl) + throws IOException, JdpException { + this(address, null, port, ttl); + } + + /** + * Broadcast pre-built packet + * + * @param packet - instance of JdpPacket + * @throws IOException + */ + public void sendPacket(JdpPacket packet) + throws IOException { + byte[] data = packet.getPacketData(); + // Unlike allocate/put wrap don't need a flip afterward + ByteBuffer b = ByteBuffer.wrap(data); + channel.send(b, new InetSocketAddress(addr, port)); + } + + /** + * Shutdown broadcaster and close underlying socket channel + * + * @throws IOException + */ + public void shutdown() throws IOException { + channel.close(); + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpController.java b/jdk/src/share/classes/sun/management/jdp/JdpController.java new file mode 100644 index 00000000000..d8d0ed46930 --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpController.java @@ -0,0 +1,196 @@ +/* + * 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. + * + * 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.management.jdp; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.UUID; + +/** + * JdpController is responsible to create and manage a broadcast loop + * + *

Other part of code has no access to broadcast loop and have to use + * provided static methods + * {@link #startDiscoveryService(InetAddress,int,String,String) startDiscoveryService} + * and {@link #stopDiscoveryService() stopDiscoveryService}

+ *

{@link #startDiscoveryService(InetAddress,int,String,String) startDiscoveryService} could be called multiple + * times as it stops the running service if it is necessary. Call to {@link #stopDiscoveryService() stopDiscoveryService} + * ignored if service isn't run

+ * + * + *

+ * + *

System properties below could be used to control broadcast loop behavior. + * Property below have to be set explicitly in command line. It's not possible to + * set it in management.config file. Careless changes of these properties could + * lead to security or network issues. + *

    + *
  • com.sun.management.jdp.ttl - set ttl for broadcast packet
  • + *
  • com.sun.management.jdp.pause - set broadcast interval in seconds
  • + *
  • com.sun.management.jdp.source_addr - an address of interface to use for broadcast
  • + *
+

+ *

null parameters values are filtered out on {@link JdpPacketWriter} level and + * corresponding keys are not placed to packet.

+ */ +public final class JdpController { + + private static class JDPControllerRunner implements Runnable { + + private final JdpJmxPacket packet; + private final JdpBroadcaster bcast; + private final int pause; + private volatile boolean shutdown = false; + + private JDPControllerRunner(JdpBroadcaster bcast, JdpJmxPacket packet, int pause) { + this.bcast = bcast; + this.packet = packet; + this.pause = pause; + } + + @Override + public void run() { + try { + while (!shutdown) { + bcast.sendPacket(packet); + try { + Thread.sleep(this.pause); + } catch (InterruptedException e) { + // pass + } + } + + } catch (IOException e) { + // pass; + } + + // It's not possible to re-use controller, + // nevertheless reset shutdown variable + try { + stop(); + bcast.shutdown(); + } catch (IOException ex) { + // pass - ignore IOException during shutdown + } + } + + public void stop() { + shutdown = true; + } + } + private static JDPControllerRunner controller = null; + + private JdpController(){ + // Don't allow to instantiate this class. + } + + // Utility to handle optional system properties + // Parse an integer from string or return default if provided string is null + private static int getInteger(String val, int dflt, String msg) throws JdpException { + try { + return (val == null) ? dflt : Integer.parseInt(val); + } catch (NumberFormatException ex) { + throw new JdpException(msg); + } + } + + // Parse an inet address from string or return default if provided string is null + private static InetAddress getInetAddress(String val, InetAddress dflt, String msg) throws JdpException { + try { + return (val == null) ? dflt : InetAddress.getByName(val); + } catch (UnknownHostException ex) { + throw new JdpException(msg); + } + } + + /** + * Starts discovery service + * + * @param address - multicast group address + * @param port - udp port to use + * @param instanceName - name of running JVM instance + * @param url - JMX service url + * @throws IOException + */ + public static synchronized void startDiscoveryService(InetAddress address, int port, String instanceName, String url) + throws IOException, JdpException { + + // Limit packet to local subnet by default + int ttl = getInteger( + System.getProperty("com.sun.management.jdp.ttl"), 1, + "Invalid jdp packet ttl"); + + // Broadcast once a 5 seconds by default + int pause = getInteger( + System.getProperty("com.sun.management.jdp.pause"), 5, + "Invalid jdp pause"); + + // Converting seconds to milliseconds + pause = pause * 1000; + + // Allow OS to choose broadcast source + InetAddress sourceAddress = getInetAddress( + System.getProperty("com.sun.management.jdp.source_addr"), null, + "Invalid source address provided"); + + // Generate session id + UUID id = UUID.randomUUID(); + + JdpJmxPacket packet = new JdpJmxPacket(id, url); + + // Don't broadcast whole command line for security reason. + // Strip everything after first space + String javaCommand = System.getProperty("sun.java.command"); + if (javaCommand != null) { + String[] arr = javaCommand.split(" ", 2); + packet.setMainClass(arr[0]); + } + + // Put optional explicit java instance name to packet, if user doesn't specify + // it the key is skipped. PacketWriter is responsible to skip keys having null value. + packet.setInstanceName(instanceName); + + JdpBroadcaster bcast = new JdpBroadcaster(address, sourceAddress, port, ttl); + + // Stop discovery service if it's already running + stopDiscoveryService(); + + controller = new JDPControllerRunner(bcast, packet, pause); + + Thread t = new Thread(controller, "JDP broadcaster"); + t.setDaemon(true); + t.start(); + } + + /** + * Stop running discovery service, + * it's safe to attempt to stop not started service + */ + public static synchronized void stopDiscoveryService() { + if ( controller != null ){ + controller.stop(); + controller = null; + } + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpException.java b/jdk/src/share/classes/sun/management/jdp/JdpException.java new file mode 100644 index 00000000000..03404223e94 --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpException.java @@ -0,0 +1,40 @@ +/* + * 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. + * + * 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.management.jdp; + +/** + * An Exception thrown if a JDP implementation encounters a problem. + */ +public final class JdpException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Construct a new JDP exception with a meaningful message + * + * @param msg - message + */ + public JdpException(String msg) { + super(msg); + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java b/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java new file mode 100644 index 00000000000..8e88b148265 --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java @@ -0,0 +1,95 @@ +/* + * 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. + * + * 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.management.jdp; + +/** + * JdpGenericPacket responsible to provide fields + * common for all Jdp packets + */ +public abstract class JdpGenericPacket implements JdpPacket { + + /** + * JDP protocol magic. Magic allows a reader to quickly select + * JDP packets from a bunch of broadcast packets addressed to the same port + * and broadcast group. Any packet intended to be parsed by JDP client + * has to start from this magic. + */ + private static final int MAGIC = 0xC0FFEE42; + + /** + * Current version of protocol. Any implementation of this protocol has to + * conform with the packet structure and the flow described in JEP-168 + */ + private static final short PROTOCOL_VERSION = 1; + + /** + * Default do-nothing constructor + */ + protected JdpGenericPacket(){ + // do nothing + } + + + /** + * Validate protocol header magic field + * + * @param magic - value to validate + * @throws JdpException + */ + public static void checkMagic(int magic) + throws JdpException { + if (magic != MAGIC) { + throw new JdpException("Invalid JDP magic header: " + magic); + } + } + + /** + * Validate protocol header version field + * + * @param version - value to validate + * @throws JdpException + */ + public static void checkVersion(short version) + throws JdpException { + + if (version > PROTOCOL_VERSION) { + throw new JdpException("Unsupported protocol version: " + version); + } + } + + /** + * + * @return protocol magic + */ + public static int getMagic() { + return MAGIC; + } + + /** + * + * @return current protocol version + */ + public static short getVersion() { + return PROTOCOL_VERSION; + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java b/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java new file mode 100644 index 00000000000..7d5ccc2f892 --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java @@ -0,0 +1,196 @@ +/* + * 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. + * + * 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.management.jdp; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; + +/** + * A packet to broadcasts JMX URL + * + * Fields: + * + *
    + *
  • UUID - broadcast session ID, changed every time when we start/stop + * discovery service
  • + *
  • JMX_URL - URL to connect to JMX service
  • + *
  • MAIN_CLASS - optional name of main class, filled from sun.java.command stripped for + * security reason to first space
  • + *
  • INSTANCE_NAME - optional custom name of particular instance as provided by customer
  • + *
+ */ +public final class JdpJmxPacket + extends JdpGenericPacket + implements JdpPacket { + + /** + * Session ID + */ + public final static String UUID_KEY = "DISCOVERABLE_SESSION_UUID"; + /** + * Name of main class + */ + public final static String MAIN_CLASS_KEY = "MAIN_CLASS"; + /** + * JMX service URL + */ + public final static String JMX_SERVICE_URL_KEY = "JMX_SERVICE_URL"; + /** + * Name of Java instance + */ + public final static String INSTANCE_NAME_KEY = "INSTANCE_NAME"; + + private UUID id; + private String mainClass; + private String jmxServiceUrl; + private String instanceName; + + /** + * Create new instance from user provided data. Set mandatory fields + * + * @param id - java instance id + * @param jmxServiceUrl - JMX service url + */ + public JdpJmxPacket(UUID id, String jmxServiceUrl) { + this.id = id; + this.jmxServiceUrl = jmxServiceUrl; + } + + /** + * Create new instance from network data Parse packet and set fields. + * + * @param data - raw packet data as it came from a Net + * @throws JdpException + */ + public JdpJmxPacket(byte[] data) + throws JdpException { + JdpPacketReader reader; + + reader = new JdpPacketReader(data); + Map p = reader.getDiscoveryDataAsMap(); + + String sId = p.get(UUID_KEY); + this.id = (sId == null) ? null : UUID.fromString(sId); + this.jmxServiceUrl = p.get(JMX_SERVICE_URL_KEY); + this.mainClass = p.get(MAIN_CLASS_KEY); + this.instanceName = p.get(INSTANCE_NAME_KEY); + } + + /** + * Set main class field + * + * @param mainClass - main class of running app + */ + public void setMainClass(String mainClass) { + this.mainClass = mainClass; + } + + /** + * Set instance name field + * + * @param instanceName - name of instance as provided by customer + */ + public void setInstanceName(String instanceName) { + this.instanceName = instanceName; + } + + /** + * @return id of discovery session + */ + public UUID getId() { + return id; + } + + /** + * + * @return main class field + */ + public String getMainClass() { + return mainClass; + } + + /** + * + * @return JMX service URL + */ + public String getJmxServiceUrl() { + return jmxServiceUrl; + } + + /** + * + * @return instance name + */ + public String getInstanceName() { + return instanceName; + } + + /** + * + * @return assembled packet ready to be sent across a Net + * @throws IOException + */ + @Override + public byte[] getPacketData() throws IOException { + // Assemble packet from fields to byte array + JdpPacketWriter writer; + writer = new JdpPacketWriter(); + writer.addEntry(UUID_KEY, (id == null) ? null : id.toString()); + writer.addEntry(MAIN_CLASS_KEY, mainClass); + writer.addEntry(JMX_SERVICE_URL_KEY, jmxServiceUrl); + writer.addEntry(INSTANCE_NAME_KEY, instanceName); + return writer.getPacketBytes(); + } + + /** + * + * @return packet hash code + */ + @Override + public int hashCode() { + int hash = 1; + hash = hash * 31 + id.hashCode(); + hash = hash * 31 + jmxServiceUrl.hashCode(); + return hash; + } + + /** + * Compare two packets + * + * @param o - packet to compare + * @return either packet equals or not + */ + @Override + public boolean equals(Object o) { + + if (o == null || ! (o instanceof JdpJmxPacket) ){ + return false; + } + + JdpJmxPacket p = (JdpJmxPacket) o; + return Objects.equals(id, p.getId()) && Objects.equals(jmxServiceUrl, p.getJmxServiceUrl()); + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpPacket.java b/jdk/src/share/classes/sun/management/jdp/JdpPacket.java new file mode 100644 index 00000000000..ba0ec4f97ac --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpPacket.java @@ -0,0 +1,63 @@ +/* + * 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. + * + * 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.management.jdp; + +import java.io.IOException; + +/** + * Packet to broadcast + * + *

Each packet have to contain MAGIC and PROTOCOL_VERSION in order to be + * recognized as a valid JDP packet.

+ * + *

Default implementation build packet as a set of UTF-8 encoded Key/Value pairs + * are stored as an ordered list of values, and are sent to the server + * in that order.

+ * + *

+ * Packet structure: + * + * 4 bytes JDP magic (0xC0FFE42) + * 2 bytes JDP protocol version (01) + * + * 2 bytes size of key + * x bytes key (UTF-8 encoded) + * 2 bytes size of value + * x bytes value (UTF-8 encoded) + * + * repeat as many times as necessary ... + *

+ */ +public interface JdpPacket { + + /** + * This method responsible to assemble packet and return a byte array + * ready to be sent across a Net. + * + * @return assembled packet as an array of bytes + * @throws IOException + */ + public byte[] getPacketData() throws IOException; + +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java b/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java new file mode 100644 index 00000000000..9f3957ab5ce --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java @@ -0,0 +1,139 @@ +/* + * 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. + * + * 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.management.jdp; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * JdpPacketReader responsible for reading a packet

This class gets a byte + * array as it came from a Net, validates it and breaks a part

+ */ +public final class JdpPacketReader { + + private final DataInputStream pkt; + private Map pmap = null; + + /** + * Create packet reader, extract and check magic and version + * + * @param packet - packet received from a Net + * @throws JdpException + */ + public JdpPacketReader(byte[] packet) + throws JdpException { + ByteArrayInputStream bais = new ByteArrayInputStream(packet); + pkt = new DataInputStream(bais); + + try { + int magic = pkt.readInt(); + JdpGenericPacket.checkMagic(magic); + } catch (IOException e) { + throw new JdpException("Invalid JDP packet received, bad magic"); + } + + try { + short version = pkt.readShort(); + JdpGenericPacket.checkVersion(version); + } catch (IOException e) { + throw new JdpException("Invalid JDP packet received, bad protocol version"); + } + } + + /** + * Get next entry from packet + * + * @return the entry + * @throws EOFException + * @throws JdpException + */ + public String getEntry() + throws EOFException, JdpException { + + try { + short len = pkt.readShort(); + // Artificial setting the "len" field to Short.MAX_VALUE may cause a reader to allocate + // to much memory. Prevent this possible DOS attack. + if (len < 1 && len > pkt.available()) { + throw new JdpException("Broken JDP packet. Invalid entry length field."); + } + + byte[] b = new byte[len]; + if (pkt.read(b) != len) { + throw new JdpException("Broken JDP packet. Unable to read entry."); + } + return new String(b, "UTF-8"); + + } catch (EOFException e) { + throw e; + } catch (UnsupportedEncodingException ex) { + throw new JdpException("Broken JDP packet. Unable to decode entry."); + } catch (IOException e) { + throw new JdpException("Broken JDP packet. Unable to read entry."); + } + + + } + + /** + * return packet content as a key/value map + * + * @return map containing packet entries pair of entries treated as + * key,value + * @throws IOException + * @throws JdpException + */ + public Map getDiscoveryDataAsMap() + throws JdpException { + // return cached map if possible + if (pmap != null) { + return pmap; + } + + String key = null, value = null; + + final Map tmpMap = new HashMap<>(); + try { + while (true) { + key = getEntry(); + value = getEntry(); + tmpMap.put(key, value); + } + } catch (EOFException e) { + // EOF reached on reading value, report broken packet + // otherwise ignore it. + if (value == null) { + throw new JdpException("Broken JDP packet. Key without value." + key); + } + } + + pmap = Collections.unmodifiableMap(tmpMap); + return pmap; + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java b/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java new file mode 100644 index 00000000000..7ebd002608c --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java @@ -0,0 +1,93 @@ +/* + * 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. + * + * 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.management.jdp; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * JdpPacketWriter responsible for writing a packet + *

This class assembles a set of key/value pairs to valid JDP packet, + * ready to be sent across a Net

+ */ +public final class JdpPacketWriter { + + private final ByteArrayOutputStream baos; + private final DataOutputStream pkt; + + /** + * Create a JDP packet, add mandatory magic and version headers + * + * @throws IOException + */ + public JdpPacketWriter() + throws IOException { + baos = new ByteArrayOutputStream(); + pkt = new DataOutputStream(baos); + + pkt.writeInt(JdpGenericPacket.getMagic()); + pkt.writeShort(JdpGenericPacket.getVersion()); + } + + /** + * Put string entry to packet + * + * @param entry - string to put (utf-8 encoded) + * @throws IOException + */ + public void addEntry(String entry) + throws IOException { + pkt.writeShort(entry.length()); + byte[] b = entry.getBytes("UTF-8"); + pkt.write(b); + } + + /** + * Put key/value pair to packet + * + * @param key - key to put (utf-8 encoded) + * @param val - value to put (utf-8 encoded) + * @throws IOException + */ + public void addEntry(String key, String val) + throws IOException { + /* Silently skip key if value is null. + * We don't need to distinguish between key missing + * and key has no value cases + */ + if (val != null) { + addEntry(key); + addEntry(val); + } + } + + /** + * Return assembled packet as a byte array + * + * @return packet bytes + */ + public byte[] getPacketBytes() { + return baos.toByteArray(); + } +} diff --git a/jdk/src/share/classes/sun/management/jdp/package-info.java b/jdk/src/share/classes/sun/management/jdp/package-info.java new file mode 100644 index 00000000000..e21e461214f --- /dev/null +++ b/jdk/src/share/classes/sun/management/jdp/package-info.java @@ -0,0 +1,55 @@ +/** + * Summary + * ------- + * + * Define a lightweight network protocol for discovering running and + * manageable Java processes within a network subnet. + * + * + * Description + * ----------- + * + * The protocol is lightweight multicast based, and works like a beacon, + * broadcasting the JMXService URL needed to connect to the external JMX + * agent if an application is started with appropriate parameters. + * + * The payload is structured like this: + * + * 4 bytes JDP magic (0xC0FFEE42) + * 2 bytes JDP protocol version (1) + * 2 bytes size of the next entry + * x bytes next entry (UTF-8 encoded) + * 2 bytes size of next entry + * ... Rinse and repeat... + * + * The payload will be parsed as even entries being keys, odd entries being + * values. + * + * The standard JDP packet contains four entries: + * + * - `DISCOVERABLE_SESSION_UUID` -- Unique id of the instance; this id changes every time + * the discovery protocol starts and stops + * + * - `MAIN_CLASS` -- The value of the `sun.java.command` property + * + * - `JMX_SERVICE_URL` -- The URL to connect to the JMX agent + * + * - `INSTANCE_NAME` -- The user-provided name of the running instance + * + * The protocol sends packets to 239.255.255.225:7095 by default. + * + * The protocol uses system properties to control it's behaviour: + * - `com.sun.management.jdp.port` -- override default port + * + * - `com.sun.management.jdp.address` -- override default address + * + * - `com.sun.management.jmxremote.autodiscovery` -- whether we should start autodiscovery or + * not. Autodiscovery starts if and only if following conditions are met: (autodiscovery is + * true OR (autodiscovery is not set AND jdp.port is set)) + * + * - `com.sun.management.jdp.ttl` -- set ttl for broadcast packet, default is 1 + * - `com.sun.management.jdp.pause` -- set broadcast interval in seconds default is 5 + * - `com.sun.management.jdp.source_addr` -- an address of interface to use for broadcast + */ + +package sun.management.jdp; diff --git a/jdk/test/sun/management/jdp/JdpClient.java b/jdk/test/sun/management/jdp/JdpClient.java new file mode 100644 index 00000000000..4a2348468b2 --- /dev/null +++ b/jdk/test/sun/management/jdp/JdpClient.java @@ -0,0 +1,160 @@ +/* + * 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. + * + * 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. + */ + +import java.io.IOException; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.ProtocolFamily; +import java.net.StandardProtocolFamily; +import java.net.StandardSocketOptions; +import java.nio.ByteBuffer; +import java.nio.channels.DatagramChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.util.Collections; +import java.util.Enumeration; +import sun.management.jdp.JdpException; +import sun.management.jdp.JdpJmxPacket; + +public class JdpClient { + + private static class PacketListener implements Runnable { + + private static final int BUFFER_LENGTH = 4096; + private final DatagramChannel channel; + private static int maxPacketCount = 1; + private static int maxEmptyPacketCount = 10; + + + PacketListener(DatagramChannel channel) { + this.channel = channel; + } + + @java.lang.Override + public void run() { + try { + Selector sel; + sel = Selector.open(); + channel.configureBlocking(false); + channel.register(sel, SelectionKey.OP_READ); + ByteBuffer buf = ByteBuffer.allocate(1024); + + int count = 1; + int emptyPacketsCount = 1; + + try { + while (true) { + + sel.selectedKeys().clear(); + buf.rewind(); + + sel.select(10 * 1000); + channel.receive(buf); + + if (buf.position() == 0 ){ + if (JdpDoSomething.getVerbose()){ + System.err.println("Empty packet received"); + } + if (++emptyPacketsCount > maxEmptyPacketCount){ + throw new RuntimeException("Test failed, maxEmptyPacketCount reached"); + } + + continue; + } + + buf.flip(); + byte[] dgramData = new byte[buf.remaining()]; + buf.get(dgramData); + + try { + JdpJmxPacket packet = new JdpJmxPacket(dgramData); + JdpDoSomething.printJdpPacket(packet); + if(++count > maxPacketCount){ + break; + } + } catch (JdpException e) { + e.printStackTrace(); + throw new RuntimeException("Test failed"); + } + + } + + System.out.println("OK: Test passed"); + + } finally { + sel.close(); + channel.close(); + } + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException("Test failed"); + } + } + } + + public static void main(String[] args) { + try { + String discoveryPort = System.getProperty("com.sun.management.jdp.port"); + String discoveryAddress = System.getProperty("com.sun.management.jdp.address"); + if (discoveryAddress == null || discoveryPort == null) { + System.out.println("Test failed. address and port must be specified"); + return; + } + + int port = Integer.parseInt(discoveryPort); + InetAddress address = InetAddress.getByName(discoveryAddress); + + + ProtocolFamily family = (address instanceof Inet6Address) + ? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; + + DatagramChannel channel; + + channel = DatagramChannel.open(family); + channel.setOption(StandardSocketOptions.SO_REUSEADDR, true); + channel.bind(new InetSocketAddress(port)); + + Enumeration nets = NetworkInterface.getNetworkInterfaces(); + for (NetworkInterface interf : Collections.list(nets)) { + if (interf.supportsMulticast()) { + try { + channel.join(address, interf); + } catch (IOException e) { + // Skip not configured interfaces + } + } + } + + PacketListener listener = new PacketListener(channel); + new Thread(listener, "Jdp Client").start(); + + } catch (RuntimeException e){ + System.out.println("Test failed."); + } catch (Exception e) { + e.printStackTrace(); + System.out.println("Test failed. unexpected error " + e); + } + } +} diff --git a/jdk/test/sun/management/jdp/JdpDoSomething.java b/jdk/test/sun/management/jdp/JdpDoSomething.java new file mode 100644 index 00000000000..ad9366cbaa4 --- /dev/null +++ b/jdk/test/sun/management/jdp/JdpDoSomething.java @@ -0,0 +1,103 @@ +/* + * 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. + * + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Objects; + +import sun.management.jdp.JdpJmxPacket; +import sun.management.jdp.JdpException; + +public class JdpDoSomething { + + private static final String lockFileName = "JdpDoSomething.lck"; + private static final boolean verbose=false; + + public static boolean getVerbose(){ + return verbose; + } + + public static void printJdpPacket(JdpJmxPacket p) { + if (getVerbose()) { + try { + RandomAccessFile f = new RandomAccessFile("out.dmp", "rw"); + f.write(p.getPacketData()); + f.close(); + } catch (IOException e) { + System.out.println("Can't write a dump file: " + e); + } + + System.out.println("Id: " + p.getId()); + System.out.println("Jmx: " + p.getJmxServiceUrl()); + System.out.println("Main: " + p.getMainClass()); + System.out.println("InstanceName: " + p.getInstanceName()); + + System.out.flush(); + } + } + + public static void compaireJdpPacketEx(JdpJmxPacket p1, JdpJmxPacket p2) + throws JdpException { + + if (!Objects.equals(p1, p1)) { + throw new JdpException("Packet mismatch error"); + } + + if (!Objects.equals(p1.getMainClass(), p2.getMainClass())) { + throw new JdpException("Packet mismatch error (main class)"); + } + + if (!Objects.equals(p1.getInstanceName(), p2.getInstanceName())) { + throw new JdpException("Packet mismatch error (instance name)"); + } + } + + public static void doSomething() { + try { + File lockFile = new File(lockFileName); + lockFile.createNewFile(); + + while (lockFile.exists()) { + long datetime = lockFile.lastModified(); + long epoch = System.currentTimeMillis() / 1000; + + // Don't allow test app to run more than an hour + if (epoch - datetime > 3600) { + System.err.println("Lock is too old. Aborting"); + return; + } + Thread.sleep(1); + } + + } catch (Throwable e) { + System.err.println("Something bad happens:" + e); + } + } + + public static void main(String args[]) throws Exception { + System.err.println("main enter"); + doSomething(); + System.err.println("main exit"); + } +} diff --git a/jdk/test/sun/management/jdp/JdpTest.sh b/jdk/test/sun/management/jdp/JdpTest.sh new file mode 100644 index 00000000000..2aded729953 --- /dev/null +++ b/jdk/test/sun/management/jdp/JdpTest.sh @@ -0,0 +1,323 @@ +#!/bin/sh + +# Copyright (c) 2011, 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. +# +# 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. + +# @test +# @bug 7169888 +# @build JdpUnitTest JdpClient JdpDoSomething +# @run shell JdpTest.sh --jtreg --no-compile +# @summary No word Failed expected in the test output + +_verbose=no +_jtreg=no +_compile=yes + +# temporary disable jcmd related tests +# _testsuite="01,02,03,04,05" +_testsuite="01,02,04" + +_pwd=`pwd` + +_testclasses=".classes" +_testsrc="${_pwd}" +_lockFileName="JdpDoSomething.lck" + +_logname=".classes/output.txt" +_last_pid="" + + +_compile(){ + + if [ ! -e ${_testclasses} ] + then + mkdir -p ${_testclasses} + fi + + rm -f ${_testclasses}/*.class + + # Compile testcase + ${TESTJAVA}/bin/javac -d ${_testclasses} JdpUnitTest.java \ + JdpDoSomething.java \ + JdpClient.java + + + if [ ! -e ${_testclasses}/JdpDoSomething.class -o ! -e ${_testclasses}/JdpClient.class -o ! -e ${_testclasses}/JdpUnitTest.class ] + then + echo "ERROR: Can't compile" + exit -1 + fi +} + + +_app_start(){ + + testappname=$1 + shift + + ${TESTJAVA}/bin/java -server $* -cp ${_testclasses} ${testappname} >> ${_logname} 2>&1 & + _last_pid=$! + + npid=`_get_pid` + if [ "${npid}" = "" ] + then + echo "ERROR: Test app not started" + if [ "${_jtreg}" = "yes" ] + then + exit -1 + fi + fi +} + +_get_pid(){ + ${TESTJAVA}/bin/jps | sed -n "/Jdp/s/ .*//p" +} + +_app_stop(){ + rm ${_lockFileName} + +# wait until VM is actually shuts down + while true + do + npid=`_get_pid` + if [ "${npid}" = "" ] + then + break + fi + sleep 1 + done +} + +_testme(){ + ${TESTJAVA}/bin/java \ + -cp ${_testclasses} \ + $* \ + -Dcom.sun.management.jdp.port=7095 \ + -Dcom.sun.management.jdp.address=239.255.255.225 \ + JdpClient + +} + + +_jcmd(){ + ${TESTJAVA}/bin/jcmd JdpDoSomething $* > /dev/null 2>/dev/null +} + + +_echo(){ + echo "$*" + echo "$*" >> ${_logname} +} + +# ============= TESTS ====================================== + +test_01(){ + + _echo "**** Test one ****" + + _app_start JdpUnitTest \ + -Dcom.sun.management.jdp.port=7095 \ + -Dcom.sun.management.jdp.address=239.255.255.225 \ + -Dcom.sun.management.jdp.pause=5 + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + +test_02(){ + + _echo "**** Test two ****" + + _app_start JdpDoSomething \ + -Dcom.sun.management.jdp.port=7095 \ + -Dcom.sun.management.jdp.address=239.255.255.225 \ + -Dcom.sun.management.jdp.pause=5 \ + -Dcom.sun.management.jmxremote.port=4545 \ + -Dcom.sun.management.jmxremote.authenticate=false \ + -Dcom.sun.management.jmxremote.ssl=false + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + +test_03(){ + + _echo "**** Test three ****" + + _app_start JdpDoSomething + + _jcmd ManagementAgent.start\ + jdp.port=7095 \ + jdp.address=239.255.255.225 \ + jdp.pause=5 \ + jmxremote.port=4545 \ + jmxremote.authenticate=false \ + jmxremote.ssl=false + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + +test_04(){ + + _echo "**** Test four ****" + + _app_start JdpDoSomething \ + -Dcom.sun.management.jmxremote.autodiscovery=true \ + -Dcom.sun.management.jmxremote.port=4545 \ + -Dcom.sun.management.jmxremote.authenticate=false \ + -Dcom.sun.management.jmxremote.ssl=false + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + +test_05(){ + + _echo "**** Test five ****" + + _app_start JdpDoSomething + + _jcmd ManagementAgent.start\ + jmxremote.autodiscovery=true \ + jmxremote.port=4545 \ + jmxremote.authenticate=false \ + jmxremote.ssl=false + + + res=`_testme` + + case "${res}" in + OK*) + _echo "Passed" + ;; + *) + _echo "Failed!" + ;; + esac + + _app_stop +} + + +# ============= MAIN ======================================= + +if [ "x${TESTJAVA}" = "x" ] +then + echo "TESTJAVA env have to be set" + exit +fi + +#------------------------------------------------------------------------------ +# reading parameters + +for parm in "$@" +do + case $parm in + --verbose) _verbose=yes ;; + --jtreg) _jtreg=yes ;; + --no-compile) _compile=no ;; + --testsuite=*) _testsuite=`_echo $parm | sed "s,^--.*=\(.*\),\1,"` ;; + *) + echo "Undefined parameter $parm. Try --help for help" + exit + ;; + esac +done + +if [ ${_compile} = "yes" ] +then + _compile +fi + +if [ ${_jtreg} = "yes" ] +then + _testclasses=${TESTCLASSES} + _testsrc=${TESTSRC} + _logname="output.txt" +fi + +# Make sure _tesclasses is absolute path +tt=`echo ${_testclasses} | sed -e 's,/,,'` +if [ ${tt} = ${_testclasses} ] +then + _testclasses="${_pwd}/${_testclasses}" +fi + +_policyname="${_testclasses}/policy" + +rm -f ${_logname} +rm -f ${_policyname} + +if [ -e ${_testsrc}/policy.tpl ] +then + +cat ${_testsrc}/policy.tpl | \ + sed -e "s,@_TESTCLASSES@,${_testclasses},g" -e "s,@TESTJAVA@,${TESTJAVA},g" \ + > ${_policyname} + +fi + +# Local mode tests +for i in `echo ${_testsuite} | sed -e "s/,/ /g"` +do + test_${i} +done diff --git a/jdk/test/sun/management/jdp/JdpUnitTest.java b/jdk/test/sun/management/jdp/JdpUnitTest.java new file mode 100644 index 00000000000..fed4ae216c2 --- /dev/null +++ b/jdk/test/sun/management/jdp/JdpUnitTest.java @@ -0,0 +1,90 @@ +/* + * 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. + * + * 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. + */ + +import java.io.IOException; +import java.net.InetAddress; +import java.util.UUID; + +import sun.management.jdp.JdpController; +import sun.management.jdp.JdpPacket; +import sun.management.jdp.JdpJmxPacket; +import sun.management.jdp.JdpException; + +public class JdpUnitTest { + + /** + * This test tests that complete packet is build correctly + */ + public static void PacketBuilderTest() + throws IOException, JdpException { + + /* Complete packet test */ + { + JdpJmxPacket p1 = new JdpJmxPacket(UUID.randomUUID(), "fake://unit-test"); + p1.setMainClass("FakeUnitTest"); + p1.setInstanceName("Fake"); + byte[] b = p1.getPacketData(); + + JdpJmxPacket p2 = new JdpJmxPacket(b); + JdpDoSomething.printJdpPacket(p1); + JdpDoSomething.compaireJdpPacketEx(p1, p2); + } + + /*Missed field packet test*/ + { + JdpJmxPacket p1 = new JdpJmxPacket(UUID.randomUUID(), "fake://unit-test"); + p1.setMainClass("FakeUnitTest"); + p1.setInstanceName(null); + byte[] b = p1.getPacketData(); + + JdpJmxPacket p2 = new JdpJmxPacket(b); + JdpDoSomething.printJdpPacket(p1); + JdpDoSomething.compaireJdpPacketEx(p1, p2); + } + + System.out.println("OK: Test passed"); + + } + + public static void startFakeDiscoveryService() + throws IOException, JdpException { + + String discoveryPort = System.getProperty("com.sun.management.jdp.port"); + String discoveryAddress = System.getProperty("com.sun.management.jdp.address"); + InetAddress address = InetAddress.getByName(discoveryAddress); + int port = Integer.parseInt(discoveryPort); + JdpController.startDiscoveryService(address, port, "FakeDiscovery", "fake://unit-test"); + } + + public static void main(String[] args) { + try { + PacketBuilderTest(); + startFakeDiscoveryService(); + JdpDoSomething.doSomething(); + + } catch (Throwable e) { + e.printStackTrace(); + System.out.println("Test failed. unexpected error " + e); + } + } +} From 302a583c08b64a9ea34b61290f529769698061f7 Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Sun, 3 Feb 2013 22:28:08 +0400 Subject: [PATCH 079/158] 8002048: Protocol to discovery of manageable Java processes on a network Introduce a protocol to discover manageble Java instances across a network subnet, JDP Reviewed-by: sla, dfuchs --- .../share/vm/services/diagnosticCommand.cpp | 44 +++++++++++++++++-- .../share/vm/services/diagnosticCommand.hpp | 10 +++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index 6bdc059f35b..df01ec83b19 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -464,7 +464,32 @@ JMXStartRemoteDCmd::JMXStartRemoteDCmd(outputStream *output, bool heap_allocated _jmxremote_ssl_config_file ("jmxremote.ssl.config.file", - "set com.sun.management.jmxremote.ssl_config_file", "STRING", false) + "set com.sun.management.jmxremote.ssl_config_file", "STRING", false), + +// JDP Protocol support + _jmxremote_autodiscovery + ("jmxremote.autodiscovery", + "set com.sun.management.jmxremote.autodiscovery", "STRING", false), + + _jdp_port + ("jdp.port", + "set com.sun.management.jdp.port", "INT", false), + + _jdp_address + ("jdp.address", + "set com.sun.management.jdp.address", "STRING", false), + + _jdp_source_addr + ("jdp.source_addr", + "set com.sun.management.jdp.source_addr", "STRING", false), + + _jdp_ttl + ("jdp.ttl", + "set com.sun.management.jdp.ttl", "INT", false), + + _jdp_pause + ("jdp.pause", + "set com.sun.management.jdp.pause", "INT", false) { _dcmdparser.add_dcmd_option(&_config_file); @@ -480,6 +505,12 @@ JMXStartRemoteDCmd::JMXStartRemoteDCmd(outputStream *output, bool heap_allocated _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_protocols); _dcmdparser.add_dcmd_option(&_jmxremote_ssl_need_client_auth); _dcmdparser.add_dcmd_option(&_jmxremote_ssl_config_file); + _dcmdparser.add_dcmd_option(&_jmxremote_autodiscovery); + _dcmdparser.add_dcmd_option(&_jdp_port); + _dcmdparser.add_dcmd_option(&_jdp_address); + _dcmdparser.add_dcmd_option(&_jdp_source_addr); + _dcmdparser.add_dcmd_option(&_jdp_ttl); + _dcmdparser.add_dcmd_option(&_jdp_pause); } @@ -494,7 +525,6 @@ int JMXStartRemoteDCmd::num_arguments() { } } - void JMXStartRemoteDCmd::execute(TRAPS) { ResourceMark rm(THREAD); HandleMark hm(THREAD); @@ -524,7 +554,9 @@ void JMXStartRemoteDCmd::execute(TRAPS) { // file. #define PUT_OPTION(a) \ if ( (a).is_set() ){ \ - options.print("%scom.sun.management.%s=%s", comma, (a).name(), (a).value()); \ + options.print(\ + ( *((a).type()) == 'I' ) ? "%scom.sun.management.%s=%d" : "%scom.sun.management.%s=%s",\ + comma, (a).name(), (a).value()); \ comma[0] = ','; \ } @@ -541,6 +573,12 @@ void JMXStartRemoteDCmd::execute(TRAPS) { PUT_OPTION(_jmxremote_ssl_enabled_protocols); PUT_OPTION(_jmxremote_ssl_need_client_auth); PUT_OPTION(_jmxremote_ssl_config_file); + PUT_OPTION(_jmxremote_autodiscovery); + PUT_OPTION(_jdp_port); + PUT_OPTION(_jdp_address); + PUT_OPTION(_jdp_source_addr); + PUT_OPTION(_jdp_ttl); + PUT_OPTION(_jdp_pause); #undef PUT_OPTION diff --git a/hotspot/src/share/vm/services/diagnosticCommand.hpp b/hotspot/src/share/vm/services/diagnosticCommand.hpp index 10b7214f17a..b9dec46e096 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.hpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp @@ -257,6 +257,16 @@ class JMXStartRemoteDCmd : public DCmdWithParser { DCmdArgument _jmxremote_ssl_need_client_auth; DCmdArgument _jmxremote_ssl_config_file; + // JDP support + // Keep autodiscovery char* not bool to pass true/false + // as property value to java level. + DCmdArgument _jmxremote_autodiscovery; + DCmdArgument _jdp_port; + DCmdArgument _jdp_address; + DCmdArgument _jdp_source_addr; + DCmdArgument _jdp_ttl; + DCmdArgument _jdp_pause; + public: JMXStartRemoteDCmd(outputStream *output, bool heap_allocated); From 812262d16bf42a690ddbca9e965bb5ebf5788e34 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Sun, 3 Feb 2013 16:49:16 -0500 Subject: [PATCH 080/158] 7197672: There are issues with shared data on windows On Windows, set rw protection on the CDS file just before removing it. Reviewed-by: dcubed, iklam --- hotspot/src/share/vm/memory/filemap.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index fe0958073e3..fec0957f145 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -210,13 +210,14 @@ void FileMapInfo::open_for_write() { tty->print_cr(" %s", _full_path); } - // Remove the existing file in case another process has it open. - remove(_full_path); -#ifdef _WINDOWS // if 0444 is used on Windows, then remove() will fail. - int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0744); -#else - int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444); +#ifdef _WINDOWS // On Windows, need WRITE permission to remove the file. + chmod(_full_path, _S_IREAD | _S_IWRITE); #endif + + // Use remove() to delete the existing file because, on Unix, this will + // allow processes that have it open continued access to the file. + remove(_full_path); + int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444); if (fd < 0) { fail_stop("Unable to create shared archive file %s.", _full_path); } From f13dbb00cfa1bbcd5f2ae21949c2259b14fcfbf5 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Mon, 4 Feb 2013 09:11:21 +0100 Subject: [PATCH 081/158] 8005114: VM is crashing in ciKlass*ciObjArrayKlass::element_klass() if metaspaces are full Missing test for loaded klass in c1 Reviewed-by: kvn --- hotspot/src/share/vm/c1/c1_Instruction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/c1/c1_Instruction.cpp b/hotspot/src/share/vm/c1/c1_Instruction.cpp index 628091ce315..985cb098e6f 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.cpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.cpp @@ -188,7 +188,7 @@ ciType* LoadIndexed::exact_type() const { ciType* LoadIndexed::declared_type() const { ciType* array_type = array()->declared_type(); - if (array_type == NULL) { + if (array_type == NULL || !array_type->is_loaded()) { return NULL; } assert(array_type->is_array_klass(), "what else?"); From 2708349f7ce97aedb63113748e31b749ac16ae5a Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Mon, 4 Feb 2013 10:53:38 +0100 Subject: [PATCH 082/158] 8007093: build-infra: Make should fail if spec is older than configure files Reviewed-by: tbell --- common/makefiles/Main.gmk | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/common/makefiles/Main.gmk b/common/makefiles/Main.gmk index c96747f090c..ded49ff55e4 100644 --- a/common/makefiles/Main.gmk +++ b/common/makefiles/Main.gmk @@ -75,7 +75,14 @@ ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_BITS),solaris-64) all: overlay-images endif -start-make: +# Setup a rule for SPEC file that fails if executed. This check makes sure the configuration +# is up to date after changes to configure +$(SPEC): $(wildcard $(SRC_ROOT)/common/autoconf/*) + @$(ECHO) ERROR: $(SPEC) is not up to date + @$(ECHO) Please rerun configure! + @if test "x$(IGNORE_OLD_CONFIG)" != "xtrue"; then exit 1; fi + +start-make: $(SPEC) @$(call AtMakeStart) langtools: langtools-only From fe5aed65c281040a2a304423d929ee249e04084c Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Mon, 4 Feb 2013 10:58:26 +0100 Subject: [PATCH 083/158] 8007268: build-infra: configure reports Solaris needs gcc for deploy, but logs don't indicate it's used Reviewed-by: tbell, katleman --- jdk/make/common/shared/Sanity.gmk | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/jdk/make/common/shared/Sanity.gmk b/jdk/make/common/shared/Sanity.gmk index c73a3b755d6..c4a96d73c5f 100644 --- a/jdk/make/common/shared/Sanity.gmk +++ b/jdk/make/common/shared/Sanity.gmk @@ -1486,26 +1486,6 @@ endif ###################################################### sane-gcc-compiler: ifndef OPENJDK - ifeq ($(PLATFORM), solaris) - @if [ -r $(GCC_COMPILER_PATH) ]; then \ - if [ ! "$(GCC_VER)" = $(REQUIRED_GCC_VER) ]; then \ - $(ECHO) "ERROR: The Solaris GCC compiler version must be $(REQUIRED_GCC_VER). \n" \ - " You are using the following compiler version: $(GCC_VER) \n" \ - " The compiler was obtained from the following location: \n" \ - " $(GCC_COMPILER_PATH) \n" \ - " Please change your compiler. \n" \ - "" >> $(ERROR_FILE) ; \ - fi \ - else \ - $(ECHO) "ERROR: You do not have a valid GCC_COMPILER_PATH setting. \n" \ - " Please check your access to \n" \ - " $(GCC_COMPILER_PATH) \n" \ - " and/or check your value of ALT_GCC_COMPILER_PATH. \n" \ - " This will affect you if you build the plugin target. \n" \ - "" >> $(ERROR_FILE) ; \ - fi - endif - ifeq ($(PLATFORM), linux) ifeq ($(ARCH_DATA_MODEL), 32) ifdef ALT_GCC29_COMPILER_PATH From 2b800f01d965c164badc9b4ea2286d30717ce032 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Mon, 4 Feb 2013 11:02:03 +0100 Subject: [PATCH 084/158] 8007275: build-infra: Create final-images target Reviewed-by: tbell --- common/autoconf/generated-configure.sh | 11 +++++-- common/makefiles/Jprt.gmk | 45 ++++++++++++++++++++------ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 2415b520802..d53e56ec100 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -3723,7 +3723,7 @@ fi #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1359376859 +DATE_WHEN_GENERATED=1359971740 ############################################################################### # @@ -10778,7 +10778,8 @@ if test "x$with_milestone" = xyes; then as_fn_error $? "Milestone must have a value" "$LINENO" 5 elif test "x$with_milestone" != x; then MILESTONE="$with_milestone" -else +fi +if test "x$MILESTONE" = x; then MILESTONE=internal fi @@ -29247,6 +29248,12 @@ fi fi +# AC_PATH_XTRA creates X_LIBS and sometimes adds -R flags. When cross compiling +# this doesn't make sense so we remove it. +if test "x$COMPILE_TYPE" = xcross; then + X_LIBS=`$ECHO $X_LIBS | $SED 's/-R \{0,1\}[^ ]*//g'` +fi + if test "x$no_x" = xyes && test "x$X11_NOT_NEEDED" != xyes; then # Print a helpful message on how to acquire the necessary build dependency. diff --git a/common/makefiles/Jprt.gmk b/common/makefiles/Jprt.gmk index b8bc418fbae..c70cf8872b4 100644 --- a/common/makefiles/Jprt.gmk +++ b/common/makefiles/Jprt.gmk @@ -179,27 +179,52 @@ jprt_bundle: $(JPRT_ARCHIVE_BUNDLE) $(JPRT_ARCHIVE_BUNDLE): bundles $(MKDIR) -p $(@D) $(RM) $@ - $(CP) $(BUILD_OUTPUT)/bundles/j2sdk-image.zip $@ + $(CP) $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip $@ -# This target must be called in the context of a SPEC file -bundles: all +ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_BITS),solaris-64) + SRC_JDK_IMAGE_DIR := $(JDK_OVERLAY_IMAGE_DIR) + SRC_JRE_IMAGE_DIR := $(JRE_OVERLAY_IMAGE_DIR) +else + SRC_JDK_IMAGE_DIR := $(JDK_IMAGE_DIR) + SRC_JRE_IMAGE_DIR := $(JRE_IMAGE_DIR) +endif +SRC_JDK_BUNDLE_DIR := $(JDK_BUNDLE_DIR) +SRC_JRE_BUNDLE_DIR := $(JRE_BUNDLE_DIR) + +# Bundle up the images +bundles: all bundles-only +bundles-only: start-make @$(call TargetEnter) $(MKDIR) -p $(BUILD_OUTPUT)/bundles -ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_BITS),solaris-64) - $(CD) $(JDK_OVERLAY_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/j2sdk-image.zip . - $(CD) $(JRE_OVERLAY_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/j2re-image.zip . -else - $(CD) $(JDK_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/j2sdk-image.zip . - $(CD) $(JRE_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/j2re-image.zip . + $(CD) $(SRC_JDK_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip . + $(CD) $(SRC_JRE_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/$(JRE_IMAGE_SUBDIR).zip . if [ -d $(BUILD_OUTPUT)/install/bundles ] ; then \ $(CD) $(BUILD_OUTPUT)/install/bundles && $(ZIP) -q -r $(JPRT_ARCHIVE_INSTALL_BUNDLE) . ; \ fi + @$(call TargetExit) + +# Copy images to one unified location regardless of platform etc. +final-images: all final-images-only +final-images-only: start-make + @$(call TargetEnter) + $(RM) -r $(BUILD_OUTPUT)/final-images + $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JDK_IMAGE_SUBDIR) + $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JRE_IMAGE_SUBDIR) + $(CP) -R -P $(SRC_JDK_IMAGE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JDK_IMAGE_SUBDIR)/ + $(CP) -R -P $(SRC_JRE_IMAGE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JRE_IMAGE_SUBDIR)/ +ifeq ($(OPENJDK_TARGET_OS),macosx) + $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JDK_BUNDLE_SUBDIR) + $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JRE_BUNDLE_SUBDIR) + $(CP) -R -P $(SRC_JDK_BUNDLE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JDK_BUNDLE_SUBDIR)/ + $(CP) -R -P $(SRC_JRE_BUNDLE_DIR)/* $(BUILD_OUTPUT)/final-images/$(JRE_BUNDLE_SUBDIR)/ endif @$(call TargetExit) + # Keep track of phony targets PHONY_LIST += jprt_build_product jprt_build_fastdebug jprt_build_debug \ - jprt_build_generic bundles jprt_bundle + jprt_build_generic bundles jprt_bundle \ + final-images final-images-only ########################################################################### # Phony targets From eaa663b2412290c3006d64124f3cf88e917a3a08 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Mon, 4 Feb 2013 10:28:39 -0800 Subject: [PATCH 085/158] 8007403: Incorrect format arguments in adlparse.cpp Reviewed-by: kvn, twisti --- hotspot/src/share/vm/adlc/adlparse.cpp | 54 +++++++++++++------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/hotspot/src/share/vm/adlc/adlparse.cpp b/hotspot/src/share/vm/adlc/adlparse.cpp index 6d08eab8010..04fb735c38c 100644 --- a/hotspot/src/share/vm/adlc/adlparse.cpp +++ b/hotspot/src/share/vm/adlc/adlparse.cpp @@ -168,7 +168,7 @@ void ADLParser::instr_parse(void) { // Check for block delimiter if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "missing '%{' in instruction definition\n"); + parse_err(SYNERR, "missing '%%{' in instruction definition\n"); return; } next_char(); // Maintain the invariant @@ -253,7 +253,7 @@ void ADLParser::instr_parse(void) { } while(_curchar != '%'); next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing '%}' in instruction definition\n"); + parse_err(SYNERR, "missing '%%}' in instruction definition\n"); return; } // Check for "Set" form of chain rule @@ -423,7 +423,7 @@ void ADLParser::oper_parse(void) { skipws(); // Check for block delimiter if ((_curchar != '%') || (*(_ptr+1) != '{')) { // If not open block - parse_err(SYNERR, "missing '%c{' in operand definition\n","%"); + parse_err(SYNERR, "missing '%%{' in operand definition\n"); return; } next_char(); next_char(); // Skip over "%{" symbol @@ -483,7 +483,7 @@ void ADLParser::oper_parse(void) { } while(_curchar != '%'); next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing '%}' in operand definition\n"); + parse_err(SYNERR, "missing '%%}' in operand definition\n"); return; } // Add operand to tail of operand list @@ -1324,7 +1324,7 @@ void ADLParser::pipe_parse(void) { // Check for block delimiter if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "missing '%{' in pipeline definition\n"); + parse_err(SYNERR, "missing '%%{' in pipeline definition\n"); return; } next_char(); // Maintain the invariant @@ -1341,7 +1341,7 @@ void ADLParser::pipe_parse(void) { skipws(); if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "expected '%{'\n"); + parse_err(SYNERR, "expected '%%{'\n"); return; } next_char(); skipws(); @@ -1397,7 +1397,7 @@ void ADLParser::pipe_parse(void) { skipws(); if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "expected '%{'\n"); + parse_err(SYNERR, "expected '%%{'\n"); return; } next_char(); skipws(); @@ -1586,7 +1586,7 @@ void ADLParser::pipe_parse(void) { if ( (_curchar != '%') || ( next_char(), (_curchar != '}')) ) { - parse_err(SYNERR, "expected '%}', found \"%c\"\n", _curchar); + parse_err(SYNERR, "expected '%%}', found \"%c\"\n", _curchar); } next_char(); skipws(); @@ -1612,7 +1612,7 @@ void ADLParser::pipe_parse(void) { next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing \"%}\" in pipeline definition\n"); + parse_err(SYNERR, "missing \"%%}\" in pipeline definition\n"); return; } @@ -1775,7 +1775,7 @@ void ADLParser::pipe_class_parse(PipelineForm &pipeline) { // Check for block delimiter if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "missing \"%{\" in pipe_class definition\n"); + parse_err(SYNERR, "missing \"%%{\" in pipe_class definition\n"); return; } next_char(); @@ -2062,7 +2062,7 @@ void ADLParser::pipe_class_parse(PipelineForm &pipeline) { next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing \"%}\" in pipe_class definition\n"); + parse_err(SYNERR, "missing \"%%}\" in pipe_class definition\n"); return; } @@ -3341,12 +3341,12 @@ Interface *ADLParser::mem_interface_parse(void) { char *disp = NULL; if (_curchar != '%') { - parse_err(SYNERR, "Missing '%{' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'interface' block.\n"); return NULL; } next_char(); // Skip '%' if (_curchar != '{') { - parse_err(SYNERR, "Missing '%{' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'interface' block.\n"); return NULL; } next_char(); // Skip '{' @@ -3354,7 +3354,7 @@ Interface *ADLParser::mem_interface_parse(void) { do { char *field = get_ident(); if (field == NULL) { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } if ( strcmp(field,"base") == 0 ) { @@ -3370,13 +3370,13 @@ Interface *ADLParser::mem_interface_parse(void) { disp = interface_field_parse(); } else { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } } while( _curchar != '%' ); next_char(); // Skip '%' if ( _curchar != '}' ) { - parse_err(SYNERR, "Missing '%}' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%}' for 'interface' block.\n"); return NULL; } next_char(); // Skip '}' @@ -3403,12 +3403,12 @@ Interface *ADLParser::cond_interface_parse(void) { const char *greater_format = "gt"; if (_curchar != '%') { - parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'cond_interface' block.\n"); return NULL; } next_char(); // Skip '%' if (_curchar != '{') { - parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'cond_interface' block.\n"); return NULL; } next_char(); // Skip '{' @@ -3416,7 +3416,7 @@ Interface *ADLParser::cond_interface_parse(void) { do { char *field = get_ident(); if (field == NULL) { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } if ( strcmp(field,"equal") == 0 ) { @@ -3438,13 +3438,13 @@ Interface *ADLParser::cond_interface_parse(void) { greater = interface_field_parse(&greater_format); } else { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } } while( _curchar != '%' ); next_char(); // Skip '%' if ( _curchar != '}' ) { - parse_err(SYNERR, "Missing '%}' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%}' for 'interface' block.\n"); return NULL; } next_char(); // Skip '}' @@ -3543,7 +3543,7 @@ MatchRule *ADLParser::match_parse(FormDict &operands) { } else if ((cnstr = find_cpp_block("match constructor")) == NULL ) { parse_err(SYNERR, "invalid construction of match rule\n" - "Missing ';' or invalid '%{' and '%}' constructor\n"); + "Missing ';' or invalid '%%{' and '%%}' constructor\n"); return NULL; // No MatchRule to return } if (_AD._adl_debug > 1) @@ -3646,7 +3646,7 @@ FormatRule* ADLParser::format_parse(void) { // Check for closing '"' and '%}' in format description skipws(); // Move to closing '%}' if ( _curchar != '%' ) { - parse_err(SYNERR, "non-blank characters between closing '\"' and '%' in format"); + parse_err(SYNERR, "non-blank characters between closing '\"' and '%%' in format"); return NULL; } } // Done with format description inside @@ -3654,7 +3654,7 @@ FormatRule* ADLParser::format_parse(void) { skipws(); // Past format description, at '%' if ( _curchar != '%' || *(_ptr+1) != '}' ) { - parse_err(SYNERR, "missing '%}' at end of format block"); + parse_err(SYNERR, "missing '%%}' at end of format block"); return NULL; } next_char(); // Move past the '%' @@ -3785,7 +3785,7 @@ FormatRule* ADLParser::template_parse(void) { skipws(); // Past format description, at '%' if ( _curchar != '%' || *(_ptr+1) != '}' ) { - parse_err(SYNERR, "missing '%}' at end of format block"); + parse_err(SYNERR, "missing '%%}' at end of format block"); return NULL; } next_char(); // Move past the '%' @@ -3834,7 +3834,7 @@ ExpandRule* ADLParser::expand_parse(InstructForm *instr) { skipws(); // Skip leading whitespace if ((_curchar != '%') || (next_char(), (_curchar != '{')) ) { // If not open block - parse_err(SYNERR, "missing '%{' in expand definition\n"); + parse_err(SYNERR, "missing '%%{' in expand definition\n"); return(NULL); } next_char(); // Maintain the invariant @@ -3933,7 +3933,7 @@ ExpandRule* ADLParser::expand_parse(InstructForm *instr) { } while(_curchar != '%'); next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing '%}' in expand rule definition\n"); + parse_err(SYNERR, "missing '%%}' in expand rule definition\n"); return(NULL); } next_char(); From da5499f4ed5ea185e7ed2ec58973c87d1463458e Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Mon, 4 Feb 2013 11:30:37 +0100 Subject: [PATCH 086/158] 8007144: Incremental inlining mistakes some call sites for dead ones and doesn't inline them Wrong detection for dead call sites. Reviewed-by: kvn --- hotspot/src/share/vm/opto/callGenerator.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index 89a7c46f6ed..8cac8ee769b 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -305,11 +305,13 @@ class LateInlineCallGenerator : public DirectCallGenerator { void LateInlineCallGenerator::do_late_inline() { // Can't inline it if (call_node() == NULL || call_node()->outcnt() == 0 || - call_node()->in(0) == NULL || call_node()->in(0)->is_top()) + call_node()->in(0) == NULL || call_node()->in(0)->is_top()) { return; + } + const TypeTuple *r = call_node()->tf()->domain(); for (int i1 = 0; i1 < method()->arg_size(); i1++) { - if (call_node()->in(TypeFunc::Parms + i1)->is_top()) { + if (call_node()->in(TypeFunc::Parms + i1)->is_top() && r->field_at(TypeFunc::Parms + i1) != Type::HALF) { assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing"); return; } From 1831def9cc6a97c3a6dde21e69d9e25b2db5468c Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Mon, 4 Feb 2013 08:26:02 -0500 Subject: [PATCH 087/158] 8000968: NPG: UseCompressedKlassPointers asserts with ObjectAlignmentInBytes for > 32G CompressedOops Pick a base that works for both CompressedOpps alignment and CompressedKlassPtrs alignment. Reviewed-by: kvn, roland --- hotspot/src/share/vm/memory/universe.cpp | 38 ++++++-- hotspot/src/share/vm/memory/universe.hpp | 12 ++- hotspot/src/share/vm/oops/oop.inline.hpp | 6 +- hotspot/src/share/vm/runtime/arguments.cpp | 19 ++-- hotspot/test/runtime/8000968/Test8000968.sh | 99 +++++++++++++++++++++ 5 files changed, 154 insertions(+), 20 deletions(-) create mode 100644 hotspot/test/runtime/8000968/Test8000968.sh diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index c9199228cb9..b0d43d3895e 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -144,6 +144,7 @@ NarrowPtrStruct Universe::_narrow_oop = { NULL, 0, true }; NarrowPtrStruct Universe::_narrow_klass = { NULL, 0, true }; address Universe::_narrow_ptrs_base; +size_t Universe::_class_metaspace_size; void Universe::basic_type_classes_do(void f(Klass*)) { f(boolArrayKlassObj()); @@ -689,8 +690,15 @@ char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) { // Return specified base for the first request. if (!FLAG_IS_DEFAULT(HeapBaseMinAddress) && (mode == UnscaledNarrowOop)) { base = HeapBaseMinAddress; - } else if (total_size <= OopEncodingHeapMax && (mode != HeapBasedNarrowOop)) { - if (total_size <= NarrowOopHeapMax && (mode == UnscaledNarrowOop) && + + // If the total size and the metaspace size are small enough to allow + // UnscaledNarrowOop then just use UnscaledNarrowOop. + } else if ((total_size <= OopEncodingHeapMax) && (mode != HeapBasedNarrowOop) && + (!UseCompressedKlassPointers || + (((OopEncodingHeapMax - heap_size) + Universe::class_metaspace_size()) <= KlassEncodingMetaspaceMax))) { + // We don't need to check the metaspace size here because it is always smaller + // than total_size. + if ((total_size <= NarrowOopHeapMax) && (mode == UnscaledNarrowOop) && (Universe::narrow_oop_shift() == 0)) { // Use 32-bits oops without encoding and // place heap's top on the 4Gb boundary @@ -706,14 +714,24 @@ char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) { base = (OopEncodingHeapMax - heap_size); } } + + // See if ZeroBaseNarrowOop encoding will work for a heap based at + // (KlassEncodingMetaspaceMax - class_metaspace_size()). + } else if (UseCompressedKlassPointers && (mode != HeapBasedNarrowOop) && + (Universe::class_metaspace_size() + HeapBaseMinAddress <= KlassEncodingMetaspaceMax) && + (KlassEncodingMetaspaceMax + heap_size - Universe::class_metaspace_size() <= OopEncodingHeapMax)) { + base = (KlassEncodingMetaspaceMax - Universe::class_metaspace_size()); } else { - // Can't reserve below 32Gb. + // UnscaledNarrowOop encoding didn't work, and no base was found for ZeroBasedOops or + // HeapBasedNarrowOop encoding was requested. So, can't reserve below 32Gb. Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); } + // Set narrow_oop_base and narrow_oop_use_implicit_null_checks // used in ReservedHeapSpace() constructors. // The final values will be set in initialize_heap() below. - if (base != 0 && (base + heap_size) <= OopEncodingHeapMax) { + if ((base != 0) && ((base + heap_size) <= OopEncodingHeapMax) && + (!UseCompressedKlassPointers || (base + Universe::class_metaspace_size()) <= KlassEncodingMetaspaceMax)) { // Use zero based compressed oops Universe::set_narrow_oop_base(NULL); // Don't need guard page for implicit checks in indexed @@ -796,7 +814,9 @@ jint Universe::initialize_heap() { tty->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB", Universe::heap()->base(), Universe::heap()->reserved_region().byte_size()/M); } - if ((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) { + if (((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) || + (UseCompressedKlassPointers && + ((uint64_t)Universe::heap()->base() + Universe::class_metaspace_size() > KlassEncodingMetaspaceMax))) { // Can't reserve heap below 32Gb. // keep the Universe::narrow_oop_base() set in Universe::reserve_heap() Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); @@ -862,8 +882,8 @@ ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { // be compressed the same as instances. // Need to round class space size up because it's below the heap and // the actual alignment depends on its size. - size_t metaspace_size = align_size_up(ClassMetaspaceSize, alignment); - size_t total_reserved = align_size_up(heap_size + metaspace_size, alignment); + Universe::set_class_metaspace_size(align_size_up(ClassMetaspaceSize, alignment)); + size_t total_reserved = align_size_up(heap_size + Universe::class_metaspace_size(), alignment); char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop); ReservedHeapSpace total_rs(total_reserved, alignment, UseLargePages, addr); @@ -904,8 +924,8 @@ ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { // compressed oops is greater than the one used for compressed klass // ptrs, a metadata space on top of the heap could become // unreachable. - ReservedSpace class_rs = total_rs.first_part(metaspace_size); - ReservedSpace heap_rs = total_rs.last_part(metaspace_size, alignment); + ReservedSpace class_rs = total_rs.first_part(Universe::class_metaspace_size()); + ReservedSpace heap_rs = total_rs.last_part(Universe::class_metaspace_size(), alignment); Metaspace::initialize_class_space(class_rs); if (UseCompressedOops) { diff --git a/hotspot/src/share/vm/memory/universe.hpp b/hotspot/src/share/vm/memory/universe.hpp index ca7b09c7b19..2bf0b653f58 100644 --- a/hotspot/src/share/vm/memory/universe.hpp +++ b/hotspot/src/share/vm/memory/universe.hpp @@ -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 @@ -211,6 +211,9 @@ class Universe: AllStatic { static struct NarrowPtrStruct _narrow_klass; static address _narrow_ptrs_base; + // Aligned size of the metaspace. + static size_t _class_metaspace_size; + // array of dummy objects used with +FullGCAlot debug_only(static objArrayOop _fullgc_alot_dummy_array;) // index of next entry to clear @@ -278,6 +281,13 @@ class Universe: AllStatic { static bool reserve_metaspace_helper(bool with_base = false); static ReservedHeapSpace reserve_heap_metaspace(size_t heap_size, size_t alignment, bool& contiguous); + static size_t class_metaspace_size() { + return _class_metaspace_size; + } + static void set_class_metaspace_size(size_t metaspace_size) { + _class_metaspace_size = metaspace_size; + } + // Debugging static int _verify_count; // number of verifies done // True during call to verify(). Should only be set/cleared in verify(). diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index c097617478d..a4b535f08ab 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -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 @@ -227,12 +227,12 @@ inline oop oopDesc::decode_heap_oop(oop v) { return v; } // might not be the same as oop. inline narrowOop oopDesc::encode_klass_not_null(Klass* v) { - assert(!is_null(v), "oop value can never be zero"); + assert(!is_null(v), "klass value can never be zero"); assert(check_klass_alignment(v), "Address not aligned"); address base = Universe::narrow_klass_base(); int shift = Universe::narrow_klass_shift(); uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)base, 1)); - assert(OopEncodingHeapMax > pd, "change encoding max if new encoding"); + assert(KlassEncodingMetaspaceMax > pd, "change encoding max if new encoding"); uint64_t result = pd >> shift; assert((result & CONST64(0xffffffff00000000)) == 0, "narrow klass pointer overflow"); assert(decode_klass(result) == v, "reversibility"); diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 47851058cd9..b0d87df7080 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1446,13 +1446,18 @@ void Arguments::set_ergonomics_flags() { } // Set the ClassMetaspaceSize to something that will not need to be // expanded, since it cannot be expanded. - if (UseCompressedKlassPointers && FLAG_IS_DEFAULT(ClassMetaspaceSize)) { - // 100,000 classes seems like a good size, so 100M assumes around 1K - // per klass. The vtable and oopMap is embedded so we don't have a fixed - // size per klass. Eventually, this will be parameterized because it - // would also be useful to determine the optimal size of the - // systemDictionary. - FLAG_SET_ERGO(uintx, ClassMetaspaceSize, 100*M); + if (UseCompressedKlassPointers) { + if (ClassMetaspaceSize > KlassEncodingMetaspaceMax) { + warning("Class metaspace size is too large for UseCompressedKlassPointers"); + FLAG_SET_DEFAULT(UseCompressedKlassPointers, false); + } else if (FLAG_IS_DEFAULT(ClassMetaspaceSize)) { + // 100,000 classes seems like a good size, so 100M assumes around 1K + // per klass. The vtable and oopMap is embedded so we don't have a fixed + // size per klass. Eventually, this will be parameterized because it + // would also be useful to determine the optimal size of the + // systemDictionary. + FLAG_SET_ERGO(uintx, ClassMetaspaceSize, 100*M); + } } } // Also checks that certain machines are slower with compressed oops diff --git a/hotspot/test/runtime/8000968/Test8000968.sh b/hotspot/test/runtime/8000968/Test8000968.sh new file mode 100644 index 00000000000..cd7183476cf --- /dev/null +++ b/hotspot/test/runtime/8000968/Test8000968.sh @@ -0,0 +1,99 @@ +# +# Copyright (c) 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 +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# 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. +# + + +# @test Test8000968.sh +# @bug 8000968 +# @summary NPG: UseCompressedKlassPointers asserts with ObjectAlignmentInBytes=32 +# @run shell Test8000968.sh +# + +if [ "${TESTJAVA}" = "" ] +then + PARENT=`dirname \`which java\`` + TESTJAVA=`dirname ${PARENT}` + printf "TESTJAVA not set, selecting " ${TESTJAVA} + printf " If this is incorrect, try setting the variable manually.\n" +fi + + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + Windows_* ) + FS="\\" + NULL=NUL + ;; + * ) + FS="/" + NULL=/dev/null + ;; +esac + +JAVA=${TESTJAVA}${FS}bin${FS}java + +# +# See if platform has 64 bit java. +# +${JAVA} ${TESTVMOPTS} -d64 -version 2>&1 | grep -i "does not support" > ${NULL} +if [ "$?" != "1" ] +then + printf "Platform is 32 bit, does not support -XX:ObjectAlignmentInBytes= option.\n" + printf "Passed.\n" + exit 0 +fi + +# +# Test -XX:ObjectAlignmentInBytes with -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops. +# +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=16 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=16 option did not work.\n" + exit 1 +fi + +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=32 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=32 option did not work.\n" + exit 1 +fi + +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=64 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=64 option did not work.\n" + exit 1 +fi + +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=128 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=128 option did not work.\n" + exit 1 +fi + + +printf "Passed.\n" +exit 0 From ab3443893820bc0c964d4e8aa5c632fc8cae5e20 Mon Sep 17 00:00:00 2001 From: Petr Pchelko Date: Mon, 4 Feb 2013 13:54:53 +0000 Subject: [PATCH 088/158] 8005405: [macosx] Drag and Drop: wrong animation when dropped outside any drop target Changed the calculation of the drag image offset Reviewed-by: serb, kizune --- .../lwawt/macosx/CDragSourceContextPeer.java | 45 +++++++------------ jdk/src/macosx/native/sun/awt/CDragSource.m | 14 +++--- 2 files changed, 20 insertions(+), 39 deletions(-) diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java index cec7c552b94..b4f9fd7abb5 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java @@ -88,40 +88,25 @@ public final class CDragSourceContextPeer extends SunDragSourceContextPeer { DragGestureEvent trigger = getTrigger(); InputEvent triggerEvent = trigger.getTriggerEvent(); - Point dragOrigin = trigger.getDragOrigin(); + Point dragOrigin = new Point(trigger.getDragOrigin()); int extModifiers = (triggerEvent.getModifiers() | triggerEvent.getModifiersEx()); long timestamp = triggerEvent.getWhen(); int clickCount = ((triggerEvent instanceof MouseEvent) ? (((MouseEvent) triggerEvent).getClickCount()) : 1); - // Get drag source component and its peer: Component component = trigger.getComponent(); - Point componentOffset = new Point(); - ComponentPeer peer = component.getPeer(); - - // For a lightweight component traverse up the hierarchy to the first heavyweight - // which will be used as the ComponentModel for the native drag source. - if (component.isLightweight()) { - Point loc = component.getLocation(); - componentOffset.translate(loc.x, loc.y); - - for (Component parent = component.getParent(); parent != null; parent = parent.getParent()) { - if (parent.isLightweight() == false) { - peer = parent.getPeer(); - break; - } - - loc = parent.getLocation(); - componentOffset.translate(loc.x, loc.y); - } + // For a lightweight component traverse up the hierarchy to the root + Point loc = component.getLocation(); + Component rootComponent = component; + while (!(rootComponent instanceof Window)) { + dragOrigin.translate(loc.x, loc.y); + rootComponent = rootComponent.getParent(); + loc = rootComponent.getLocation(); } - // Make sure the drop target is a ComponentModel: - if (!(peer instanceof LWComponentPeer)) - throw new IllegalArgumentException("DragSource's peer must be a ComponentModel."); - - // Get model pointer (CButton.m and such) and its native peer: - LWComponentPeer model = (LWComponentPeer) peer; - CPlatformWindow platformWindow = (CPlatformWindow) model.getPlatformWindow(); + //It sure will be LWComponentPeer instance as rootComponent is a Window + LWComponentPeer peer = (LWComponentPeer)rootComponent.getPeer(); + //Get a pointer to a native window + CPlatformWindow platformWindow = (CPlatformWindow) peer.getPlatformWindow(); long nativeWindowPtr = platformWindow.getNSWindowPtr(); // Get drag cursor: @@ -155,7 +140,7 @@ public final class CDragSourceContextPeer extends SunDragSourceContextPeer { try { // Create native dragging source: final long nativeDragSource = createNativeDragSource(component, peer, nativeWindowPtr, transferable, triggerEvent, - (int) (dragOrigin.getX() + componentOffset.x), (int) (dragOrigin.getY() + componentOffset.y), extModifiers, + (int) (dragOrigin.getX()), (int) (dragOrigin.getY()), extModifiers, clickCount, timestamp, cursor, fDragCImage, dragImageOffset.x, dragImageOffset.y, getDragSourceContext().getSourceActions(), formats, formatMap); @@ -165,8 +150,8 @@ public final class CDragSourceContextPeer extends SunDragSourceContextPeer { setNativeContext(nativeDragSource); CCursorManager.getInstance().startDrag( - (int) (dragOrigin.getX() + componentOffset.x), - (int) (dragOrigin.getY() + componentOffset.y)); + (int) (dragOrigin.getX()), + (int) (dragOrigin.getY())); } catch (Exception e) { diff --git a/jdk/src/macosx/native/sun/awt/CDragSource.m b/jdk/src/macosx/native/sun/awt/CDragSource.m index ef7b09a6edc..635026483d3 100644 --- a/jdk/src/macosx/native/sun/awt/CDragSource.m +++ b/jdk/src/macosx/native/sun/awt/CDragSource.m @@ -443,9 +443,9 @@ static BOOL sNeedsEnter; NSGraphicsContext* graphicsContext = [NSGraphicsContext graphicsContextWithWindow:window]; // Convert mouse coordinates to NS: - NSPoint location = NSMakePoint(fDragPos.x, fDragPos.y); - NSPoint eventLocation = [fView convertPoint:location toView:nil]; - + NSPoint eventLocation = [fView convertPoint:NSMakePoint(fDragPos.x, fDragPos.y) toView:nil]; + eventLocation.y = [[fView window] frame].size.height - eventLocation.y; + // Convert fTriggerEventTimeStamp to NS - AWTEvent.h defines UTC(nsEvent) as ((jlong)[event timestamp] * 1000): NSTimeInterval timeStamp = fTriggerEventTimeStamp / 1000; @@ -497,12 +497,9 @@ static BOOL sNeedsEnter; NSImage* dragImage = fDragImage; // Get drag origin and offset: - NSPoint dragOrigin; - dragOrigin.x = fDragPos.x; - dragOrigin.y = fDragPos.y; - dragOrigin = [view convertPoint:[dragEvent locationInWindow] fromView:nil]; + NSPoint dragOrigin = [dragEvent locationInWindow]; dragOrigin.x += fDragImageOffset.x; - dragOrigin.y += [dragImage size].height + fDragImageOffset.y; + dragOrigin.y -= fDragImageOffset.y + [dragImage size].height; // Drag offset values don't seem to matter: NSSize dragOffset = NSMakeSize(0, 0); @@ -516,7 +513,6 @@ static BOOL sNeedsEnter; DLog5(@" - drag image: %f, %f (%f x %f)", fDragImageOffset.x, fDragImageOffset.y, [dragImage size].width, [dragImage size].height); DLog3(@" - event point (window) %f, %f", [dragEvent locationInWindow].x, [dragEvent locationInWindow].y); DLog3(@" - drag point (view) %f, %f", dragOrigin.x, dragOrigin.y); - // Set up the fDragKeyModifier, so we know if the operation has changed // Set up the fDragMouseModifier, so we can |= it later (since CoreDrag doesn't tell us mouse states during a drag) fDragKeyModifiers = [DnDUtilities extractJavaExtKeyModifiersFromJavaExtModifiers:fModifiers]; From 7add1f152df5a65b00418c481f1959f60c3feffb Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Mon, 4 Feb 2013 19:50:06 +0400 Subject: [PATCH 089/158] 8004821: Graphics2D.drawPolygon() fails with IllegalPathStateException Reviewed-by: prr, flar --- .../java2d/pipe/PixelToShapeConverter.java | 14 ++--- jdk/test/sun/java2d/pipe/Test8004821.java | 60 +++++++++++++++++++ 2 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 jdk/test/sun/java2d/pipe/Test8004821.java diff --git a/jdk/src/share/classes/sun/java2d/pipe/PixelToShapeConverter.java b/jdk/src/share/classes/sun/java2d/pipe/PixelToShapeConverter.java index c130068612e..5a01e000790 100644 --- a/jdk/src/share/classes/sun/java2d/pipe/PixelToShapeConverter.java +++ b/jdk/src/share/classes/sun/java2d/pipe/PixelToShapeConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1998, 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 @@ -103,12 +103,12 @@ public class PixelToShapeConverter GeneralPath gp = new GeneralPath(GeneralPath.WIND_EVEN_ODD); if (nPoints > 0) { gp.moveTo(xPoints[0], yPoints[0]); - } - for (int i = 1; i < nPoints; i++) { - gp.lineTo(xPoints[i], yPoints[i]); - } - if (close) { - gp.closePath(); + for (int i = 1; i < nPoints; i++) { + gp.lineTo(xPoints[i], yPoints[i]); + } + if (close) { + gp.closePath(); + } } return gp; } diff --git a/jdk/test/sun/java2d/pipe/Test8004821.java b/jdk/test/sun/java2d/pipe/Test8004821.java new file mode 100644 index 00000000000..c2143dda308 --- /dev/null +++ b/jdk/test/sun/java2d/pipe/Test8004821.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +import java.awt.Graphics2D; +import java.awt.Polygon; +import java.awt.image.BufferedImage; + +/** + * @test + * @bug 8004821 + * @summary Verifies that drawPolygon() works with empty arrays. + * @author Sergey Bylokhov + */ +public final class Test8004821 { + + public static void main(final String[] args) { + final int[] arrEmpty = {}; + final int[] arr1elem = {150}; + final BufferedImage bi = new BufferedImage(300, 300, + BufferedImage.TYPE_INT_RGB); + final Graphics2D g = (Graphics2D) bi.getGraphics(); + test(g, arrEmpty); + test(g, arr1elem); + g.translate(2.0, 2.0); + test(g, arrEmpty); + test(g, arr1elem); + g.scale(2.0, 2.0); + test(g, arrEmpty); + test(g, arr1elem); + g.dispose(); + } + + private static void test(final Graphics2D g, final int[] arr) { + g.drawPolygon(arr, arr, arr.length); + g.drawPolygon(new Polygon(arr, arr, arr.length)); + g.fillPolygon(arr, arr, arr.length); + g.fillPolygon(new Polygon(arr, arr, arr.length)); + g.drawPolyline(arr, arr, arr.length); + } +} From 5712b216b4ad44dd7b981c3104c14917d70b262f Mon Sep 17 00:00:00 2001 From: Konstantin Shefov Date: Mon, 4 Feb 2013 16:01:06 +0000 Subject: [PATCH 090/158] 7077259: [TEST_BUG] [macosx] Test work correctly only when default L&F is Metal Reviewed-by: serb, alexsch --- jdk/test/javax/swing/JSlider/4252173/bug4252173.java | 12 ++++++------ .../javax/swing/JSpinner/6532833/bug6532833.java | 11 ++++++----- .../swing/plaf/metal/MetalSliderUI/Test6657026.java | 9 ++++----- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/jdk/test/javax/swing/JSlider/4252173/bug4252173.java b/jdk/test/javax/swing/JSlider/4252173/bug4252173.java index 128a32a1e79..1db70adb993 100644 --- a/jdk/test/javax/swing/JSlider/4252173/bug4252173.java +++ b/jdk/test/javax/swing/JSlider/4252173/bug4252173.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -22,11 +22,11 @@ */ /* @test - @bug 4252173 - @summary Inability to reuse the HorizontalSliderThumbIcon - @author Pavel Porvatov - @run main bug4252173 -*/ + * @bug 4252173 7077259 + * @summary Inability to reuse the HorizontalSliderThumbIcon + * @author Pavel Porvatov + * @run main/othervm -Dswing.defaultlaf=javax.swing.plaf.metal.MetalLookAndFeel bug4252173 + */ import javax.swing.*; import javax.swing.plaf.metal.DefaultMetalTheme; diff --git a/jdk/test/javax/swing/JSpinner/6532833/bug6532833.java b/jdk/test/javax/swing/JSpinner/6532833/bug6532833.java index 184fe69d96d..80013da7a81 100644 --- a/jdk/test/javax/swing/JSpinner/6532833/bug6532833.java +++ b/jdk/test/javax/swing/JSpinner/6532833/bug6532833.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -22,10 +22,11 @@ */ /* @test - @bug 6532833 - @summary PIT: Metal LAF - The right side border is not shown for the Spinner after the removing the buttons - @author Pavel Porvatov -*/ + * @bug 6532833 7077259 + * @summary PIT: Metal LAF - The right side border is not shown for the Spinner after the removing the buttons + * @author Pavel Porvatov + * @run main/othervm -Dswing.defaultlaf=javax.swing.plaf.metal.MetalLookAndFeel bug6532833 + */ import javax.swing.*; import java.awt.*; diff --git a/jdk/test/javax/swing/plaf/metal/MetalSliderUI/Test6657026.java b/jdk/test/javax/swing/plaf/metal/MetalSliderUI/Test6657026.java index 5c65b15ce45..924999e46f8 100644 --- a/jdk/test/javax/swing/plaf/metal/MetalSliderUI/Test6657026.java +++ b/jdk/test/javax/swing/plaf/metal/MetalSliderUI/Test6657026.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -23,22 +23,21 @@ /* * @test - * @bug 6657026 + * @bug 6657026 7077259 * @summary Tests shared MetalSliderUI in different application contexts * @author Sergey Malenkov + * @run main/othervm -Dswing.defaultlaf=javax.swing.plaf.metal.MetalLookAndFeel Test6657026 */ -import sun.awt.SunToolkit; - import javax.swing.JSlider; import javax.swing.UIManager; import javax.swing.plaf.metal.MetalLookAndFeel; import javax.swing.plaf.metal.MetalSliderUI; +import sun.awt.SunToolkit; public class Test6657026 extends MetalSliderUI implements Runnable { public static void main(String[] args) throws Exception { - UIManager.setLookAndFeel(new MetalLookAndFeel()); JSlider slider = new JSlider(); test(slider); From ddbfa5fe533275175c38fc7acedc124f1684df68 Mon Sep 17 00:00:00 2001 From: Vinnie Ryan Date: Mon, 4 Feb 2013 17:20:26 +0000 Subject: [PATCH 091/158] 8006994: Cleanup PKCS12 tests to ensure streams get closed Reviewed-by: mullan --- jdk/test/java/security/KeyStore/PBETest.java | 63 ++++++++------- .../security/pkcs12/StorePasswordTest.java | 50 ++++++------ .../security/pkcs12/StoreSecretKeyTest.java | 41 +++++----- .../security/pkcs12/StoreTrustedCertTest.java | 80 +++++++++---------- 4 files changed, 116 insertions(+), 118 deletions(-) diff --git a/jdk/test/java/security/KeyStore/PBETest.java b/jdk/test/java/security/KeyStore/PBETest.java index be437d03bbd..2186165ea68 100644 --- a/jdk/test/java/security/KeyStore/PBETest.java +++ b/jdk/test/java/security/KeyStore/PBETest.java @@ -58,45 +58,46 @@ public class PBETest { new File(NEW_KEYSTORE).delete(); - try { - KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD); - KeyStore.Entry entry = - keystore.getEntry(ALIAS, - new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry named '" + ALIAS + "'"); - - // Set entry - KeyStore keystore2 = load(NEW_KEYSTORE_TYPE, null, null); - keystore2.setEntry(ALIAS, entry, - new KeyStore.PasswordProtection(PASSWORD, PBE_ALGO, - new PBEParameterSpec(SALT, ITERATION_COUNT, - new IvParameterSpec(IV)))); - System.out.println("Encrypted entry using: " + PBE_ALGO); - - System.out.println("Storing keystore to: " + NEW_KEYSTORE); - keystore2.store(new FileOutputStream(NEW_KEYSTORE), PASSWORD); - - keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD); - entry = keystore2.getEntry(ALIAS, + KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD); + KeyStore.Entry entry = + keystore.getEntry(ALIAS, new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry named '" + ALIAS + "'"); + System.out.println("Retrieved entry named '" + ALIAS + "'"); - } finally { - new File(NEW_KEYSTORE).delete(); - System.out.println("Deleted keystore: " + NEW_KEYSTORE); + // Set entry + KeyStore keystore2 = load(NEW_KEYSTORE_TYPE, null, null); + keystore2.setEntry(ALIAS, entry, + new KeyStore.PasswordProtection(PASSWORD, PBE_ALGO, + new PBEParameterSpec(SALT, ITERATION_COUNT, + new IvParameterSpec(IV)))); + System.out.println("Encrypted entry using: " + PBE_ALGO); + + try (FileOutputStream outStream = new FileOutputStream(NEW_KEYSTORE)) { + System.out.println("Storing keystore to: " + NEW_KEYSTORE); + keystore2.store(outStream, PASSWORD); } + + keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD); + entry = keystore2.getEntry(ALIAS, + new KeyStore.PasswordProtection(PASSWORD)); + System.out.println("Retrieved entry named '" + ALIAS + "'"); } private static KeyStore load(String type, String path, char[] password) throws Exception { - - FileInputStream stream = null; - if (path != null) { - stream = new FileInputStream(path); - } KeyStore keystore = KeyStore.getInstance(type); - System.out.println("Loading keystore from: " + path); - keystore.load(stream, password); + + if (path != null) { + + try (FileInputStream inStream = new FileInputStream(path)) { + System.out.println("Loading keystore from: " + path); + keystore.load(inStream, password); + System.out.println("Loaded keystore with " + keystore.size() + + " entries"); + } + } else { + keystore.load(null, null); + } return keystore; } diff --git a/jdk/test/sun/security/pkcs12/StorePasswordTest.java b/jdk/test/sun/security/pkcs12/StorePasswordTest.java index fc2f77c51c1..d258aaa10a7 100644 --- a/jdk/test/sun/security/pkcs12/StorePasswordTest.java +++ b/jdk/test/sun/security/pkcs12/StorePasswordTest.java @@ -47,40 +47,40 @@ public class StorePasswordTest { new File(KEYSTORE).delete(); - try { + KeyStore keystore = KeyStore.getInstance("PKCS12"); + keystore.load(null, null); - KeyStore keystore = KeyStore.getInstance("PKCS12"); - keystore.load(null, null); - - // Set entry - keystore.setEntry(ALIAS, - new KeyStore.SecretKeyEntry(convertPassword(USER_PASSWORD)), - new KeyStore.PasswordProtection(PASSWORD)); + // Set entry + keystore.setEntry(ALIAS, + new KeyStore.SecretKeyEntry(convertPassword(USER_PASSWORD)), + new KeyStore.PasswordProtection(PASSWORD)); + try (FileOutputStream outStream = new FileOutputStream(KEYSTORE)) { System.out.println("Storing keystore to: " + KEYSTORE); - keystore.store(new FileOutputStream(KEYSTORE), PASSWORD); + keystore.store(outStream, PASSWORD); + } + try (FileInputStream inStream = new FileInputStream(KEYSTORE)) { System.out.println("Loading keystore from: " + KEYSTORE); - keystore.load(new FileInputStream(KEYSTORE), PASSWORD); + keystore.load(inStream, PASSWORD); System.out.println("Loaded keystore with " + keystore.size() + " entries"); - KeyStore.Entry entry = keystore.getEntry(ALIAS, - new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry: " + entry); + } - SecretKey key = (SecretKey) keystore.getKey(ALIAS, PASSWORD); - SecretKeyFactory factory = - SecretKeyFactory.getInstance(key.getAlgorithm()); - PBEKeySpec keySpec = - (PBEKeySpec) factory.getKeySpec(key, PBEKeySpec.class); - char[] pwd = keySpec.getPassword(); - System.out.println("Recovered credential: " + new String(pwd)); + KeyStore.Entry entry = keystore.getEntry(ALIAS, + new KeyStore.PasswordProtection(PASSWORD)); + System.out.println("Retrieved entry: " + entry); - if (!Arrays.equals(USER_PASSWORD.toCharArray(), pwd)) { - throw new Exception("Failed to recover the stored password"); - } - } finally { - new File(KEYSTORE).delete(); + SecretKey key = (SecretKey) keystore.getKey(ALIAS, PASSWORD); + SecretKeyFactory factory = + SecretKeyFactory.getInstance(key.getAlgorithm()); + PBEKeySpec keySpec = + (PBEKeySpec) factory.getKeySpec(key, PBEKeySpec.class); + char[] pwd = keySpec.getPassword(); + System.out.println("Recovered credential: " + new String(pwd)); + + if (!Arrays.equals(USER_PASSWORD.toCharArray(), pwd)) { + throw new Exception("Failed to recover the stored password"); } } diff --git a/jdk/test/sun/security/pkcs12/StoreSecretKeyTest.java b/jdk/test/sun/security/pkcs12/StoreSecretKeyTest.java index f002ef7506a..84c28899126 100644 --- a/jdk/test/sun/security/pkcs12/StoreSecretKeyTest.java +++ b/jdk/test/sun/security/pkcs12/StoreSecretKeyTest.java @@ -53,35 +53,34 @@ public class StoreSecretKeyTest { new File(KEYSTORE).delete(); - try { + KeyStore keystore = KeyStore.getInstance("PKCS12"); + keystore.load(null, null); - KeyStore keystore = KeyStore.getInstance("PKCS12"); - keystore.load(null, null); - - // Set entry - keystore.setEntry(ALIAS, - new KeyStore.SecretKeyEntry(generateSecretKey("AES", 128)), - new KeyStore.PasswordProtection(PASSWORD)); + // Set entry + keystore.setEntry(ALIAS, + new KeyStore.SecretKeyEntry(generateSecretKey("AES", 128)), + new KeyStore.PasswordProtection(PASSWORD)); + try (FileOutputStream outStream = new FileOutputStream(KEYSTORE)) { System.out.println("Storing keystore to: " + KEYSTORE); - keystore.store(new FileOutputStream(KEYSTORE), PASSWORD); + keystore.store(outStream, PASSWORD); + } + try (FileInputStream inStream = new FileInputStream(KEYSTORE)) { System.out.println("Loading keystore from: " + KEYSTORE); - keystore.load(new FileInputStream(KEYSTORE), PASSWORD); + keystore.load(inStream, PASSWORD); System.out.println("Loaded keystore with " + keystore.size() + " entries"); - KeyStore.Entry entry = keystore.getEntry(ALIAS, - new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry: " + entry); + } - if (entry instanceof KeyStore.SecretKeyEntry) { - System.out.println("Retrieved secret key entry: " + - entry); - } else { - throw new Exception("Not a secret key entry"); - } - } finally { - new File(KEYSTORE).delete(); + KeyStore.Entry entry = keystore.getEntry(ALIAS, + new KeyStore.PasswordProtection(PASSWORD)); + System.out.println("Retrieved entry: " + entry); + + if (entry instanceof KeyStore.SecretKeyEntry) { + System.out.println("Retrieved secret key entry: " + entry); + } else { + throw new Exception("Not a secret key entry"); } } diff --git a/jdk/test/sun/security/pkcs12/StoreTrustedCertTest.java b/jdk/test/sun/security/pkcs12/StoreTrustedCertTest.java index a1481749d7e..0cbca31e2d1 100644 --- a/jdk/test/sun/security/pkcs12/StoreTrustedCertTest.java +++ b/jdk/test/sun/security/pkcs12/StoreTrustedCertTest.java @@ -49,59 +49,57 @@ public class StoreTrustedCertTest { new File(KEYSTORE).delete(); - try { - KeyStore keystore = KeyStore.getInstance("PKCS12"); - keystore.load(null, null); + KeyStore keystore = KeyStore.getInstance("PKCS12"); + keystore.load(null, null); - Certificate cert = loadCertificate(CERT); - Set attributes = new HashSet<>(); - attributes.add(new PKCS12Attribute("1.3.5.7.9", "that's odd")); - attributes.add(new PKCS12Attribute("2.4.6.8.10", "that's even")); + Certificate cert = loadCertificate(CERT); + Set attributes = new HashSet<>(); + attributes.add(new PKCS12Attribute("1.3.5.7.9", "that's odd")); + attributes.add(new PKCS12Attribute("2.4.6.8.10", "that's even")); - // Set trusted certificate entry - keystore.setEntry(ALIAS, - new KeyStore.TrustedCertificateEntry(cert), null); + // Set trusted certificate entry + keystore.setEntry(ALIAS, + new KeyStore.TrustedCertificateEntry(cert), null); - // Set trusted certificate entry with attributes - keystore.setEntry(ALIAS2, - new KeyStore.TrustedCertificateEntry(cert, attributes), null); + // Set trusted certificate entry with attributes + keystore.setEntry(ALIAS2, + new KeyStore.TrustedCertificateEntry(cert, attributes), null); + try (FileOutputStream outStream = new FileOutputStream(KEYSTORE)) { System.out.println("Storing keystore to: " + KEYSTORE); - keystore.store(new FileOutputStream(KEYSTORE), PASSWORD); + keystore.store(outStream, PASSWORD); + } + try (FileInputStream inStream = new FileInputStream(KEYSTORE)) { System.out.println("Loading keystore from: " + KEYSTORE); - keystore.load(new FileInputStream(KEYSTORE), PASSWORD); + keystore.load(inStream, PASSWORD); System.out.println("Loaded keystore with " + keystore.size() + " entries"); + } - KeyStore.Entry entry = keystore.getEntry(ALIAS, null); - if (entry instanceof KeyStore.TrustedCertificateEntry) { - System.out.println("Retrieved trusted certificate entry: " + - entry); + KeyStore.Entry entry = keystore.getEntry(ALIAS, null); + if (entry instanceof KeyStore.TrustedCertificateEntry) { + System.out.println("Retrieved trusted certificate entry: " + entry); + } else { + throw new Exception("Not a trusted certificate entry"); + } + System.out.println(); + + entry = keystore.getEntry(ALIAS2, null); + if (entry instanceof KeyStore.TrustedCertificateEntry) { + KeyStore.TrustedCertificateEntry trustedEntry = + (KeyStore.TrustedCertificateEntry) entry; + Set entryAttributes = + trustedEntry.getAttributes(); + + if (entryAttributes.containsAll(attributes)) { + System.out.println("Retrieved trusted certificate entry " + + "with attributes: " + entry); } else { - throw new Exception("Not a trusted certificate entry"); + throw new Exception("Failed to retrieve entry attributes"); } - System.out.println(); - - entry = keystore.getEntry(ALIAS2, null); - if (entry instanceof KeyStore.TrustedCertificateEntry) { - KeyStore.TrustedCertificateEntry trustedEntry = - (KeyStore.TrustedCertificateEntry) entry; - Set entryAttributes = - trustedEntry.getAttributes(); - - if (entryAttributes.containsAll(attributes)) { - System.out.println("Retrieved trusted certificate entry " + - "with attributes: " + entry); - } else { - throw new Exception("Failed to retrieve entry attributes"); - } - } else { - throw new Exception("Not a trusted certificate entry"); - } - - } finally { - new File(KEYSTORE).delete(); + } else { + throw new Exception("Not a trusted certificate entry"); } } From 16990e896a57b12c15a611241d4464a5410950fd Mon Sep 17 00:00:00 2001 From: Eric McCorkle Date: Mon, 4 Feb 2013 13:05:32 -0500 Subject: [PATCH 092/158] 8006949: Update hotspot for MethodParameters format change 8006907: Hotspot should reject classfiles with multiple MethodParameters attributes Update to Hotspot's processing of MethodParameters attributes in classfiles Reviewed-by: coleenp, jrose --- .../share/vm/classfile/classFileParser.cpp | 47 ++++++++++++------- hotspot/src/share/vm/oops/constMethod.hpp | 7 +-- hotspot/src/share/vm/prims/jvm.cpp | 2 +- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 557707ba432..d46a1eab840 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -1947,6 +1947,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, u2** localvariable_type_table_start; u2 method_parameters_length = 0; u1* method_parameters_data = NULL; + bool method_parameters_seen = false; + bool method_parameters_four_byte_flags; bool parsed_code_attribute = false; bool parsed_checked_exceptions_attribute = false; bool parsed_stackmap_attribute = false; @@ -2157,22 +2159,32 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, method_attribute_length, cp, CHECK_(nullHandle)); } else if (method_attribute_name == vmSymbols::tag_method_parameters()) { + // reject multiple method parameters + if (method_parameters_seen) { + classfile_parse_error("Multiple MethodParameters attributes in class file %s", CHECK_(nullHandle)); + } + method_parameters_seen = true; method_parameters_length = cfs->get_u1_fast(); // Track the actual size (note: this is written for clarity; a // decent compiler will CSE and constant-fold this into a single // expression) - u2 actual_size = 1; - method_parameters_data = cfs->get_u1_buffer(); - actual_size += 2 * method_parameters_length; - cfs->skip_u2_fast(method_parameters_length); - actual_size += 4 * method_parameters_length; - cfs->skip_u4_fast(method_parameters_length); - // Enforce attribute length - if (method_attribute_length != actual_size) { + // Use the attribute length to figure out the size of flags + if (method_attribute_length == (method_parameters_length * 6u) + 1u) { + method_parameters_four_byte_flags = true; + } else if (method_attribute_length == (method_parameters_length * 4u) + 1u) { + method_parameters_four_byte_flags = false; + } else { classfile_parse_error( - "Invalid MethodParameters method attribute length %u in class file %s", + "Invalid MethodParameters method attribute length %u in class file", method_attribute_length, CHECK_(nullHandle)); } + method_parameters_data = cfs->get_u1_buffer(); + cfs->skip_u2_fast(method_parameters_length); + if (method_parameters_four_byte_flags) { + cfs->skip_u4_fast(method_parameters_length); + } else { + cfs->skip_u2_fast(method_parameters_length); + } // ignore this attribute if it cannot be reflected if (!SystemDictionary::Parameter_klass_loaded()) method_parameters_length = 0; @@ -2316,15 +2328,16 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, // Copy method parameters if (method_parameters_length > 0) { MethodParametersElement* elem = m->constMethod()->method_parameters_start(); - for(int i = 0; i < method_parameters_length; i++) { - elem[i].name_cp_index = - Bytes::get_Java_u2(method_parameters_data); + for (int i = 0; i < method_parameters_length; i++) { + elem[i].name_cp_index = Bytes::get_Java_u2(method_parameters_data); method_parameters_data += 2; - u4 flags = Bytes::get_Java_u4(method_parameters_data); - // This caused an alignment fault on Sparc, if flags was a u4 - elem[i].flags_lo = extract_low_short_from_int(flags); - elem[i].flags_hi = extract_high_short_from_int(flags); - method_parameters_data += 4; + if (method_parameters_four_byte_flags) { + elem[i].flags = Bytes::get_Java_u4(method_parameters_data); + method_parameters_data += 4; + } else { + elem[i].flags = Bytes::get_Java_u2(method_parameters_data); + method_parameters_data += 2; + } } } diff --git a/hotspot/src/share/vm/oops/constMethod.hpp b/hotspot/src/share/vm/oops/constMethod.hpp index bd3acd23188..12a36c24470 100644 --- a/hotspot/src/share/vm/oops/constMethod.hpp +++ b/hotspot/src/share/vm/oops/constMethod.hpp @@ -122,12 +122,7 @@ class ExceptionTableElement VALUE_OBJ_CLASS_SPEC { class MethodParametersElement VALUE_OBJ_CLASS_SPEC { public: u2 name_cp_index; - // This has to happen, otherwise it will cause SIGBUS from a - // misaligned u4 on some architectures (ie SPARC) - // because MethodParametersElements are only aligned mod 2 - // within the ConstMethod container u2 flags_hi; - u2 flags_hi; - u2 flags_lo; + u2 flags; }; class KlassSizeStats; diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 7fffe0020c2..84ab5f04828 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -1620,7 +1620,7 @@ JVM_ENTRY(jobjectArray, JVM_GetMethodParameters(JNIEnv *env, jobject method)) // For a 0 index, give a NULL symbol Symbol* const sym = 0 != params[i].name_cp_index ? mh->constants()->symbol_at(params[i].name_cp_index) : NULL; - int flags = build_int_from_shorts(params[i].flags_lo, params[i].flags_hi); + int flags = params[i].flags; oop param = Reflection::new_parameter(reflected_method, i, sym, flags, CHECK_NULL); result->obj_at_put(i, param); From 37d83019d0e05267dd343fa114a60b0b5725ffd8 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Mon, 4 Feb 2013 13:14:12 -0500 Subject: [PATCH 093/158] 8007475: Memory stomp with UseMallocOnly Fix off-by-one error Reviewed-by: coleenp, hseigel --- .../src/share/vm/classfile/stackMapFrame.hpp | 2 +- .../runtime/8007475/StackMapFrameTest.java | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 hotspot/test/runtime/8007475/StackMapFrameTest.java diff --git a/hotspot/src/share/vm/classfile/stackMapFrame.hpp b/hotspot/src/share/vm/classfile/stackMapFrame.hpp index 3329f7a9e8b..bdeb956ba68 100644 --- a/hotspot/src/share/vm/classfile/stackMapFrame.hpp +++ b/hotspot/src/share/vm/classfile/stackMapFrame.hpp @@ -178,7 +178,7 @@ class StackMapFrame : public ResourceObj { #ifdef DEBUG // Put bogus type to indicate it's no longer valid. if (_stack_mark != -1) { - for (int i = _stack_mark; i >= _stack_size; --i) { + for (int i = _stack_mark - 1; i >= _stack_size; --i) { _stack[i] = VerificationType::bogus_type(); } } diff --git a/hotspot/test/runtime/8007475/StackMapFrameTest.java b/hotspot/test/runtime/8007475/StackMapFrameTest.java new file mode 100644 index 00000000000..b927ae76db6 --- /dev/null +++ b/hotspot/test/runtime/8007475/StackMapFrameTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @bug 8007475 + * @summary Test memory stomp in stack map test + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseMallocOnly StackMapFrameTest + */ +public class StackMapFrameTest { + + public static void foo() { + Object o = new Object(); + } + + public static void main(String args[]) { + for (int i = 0; i < 25000; i++) { + foo(); + } + } +} From db8ced219f196ccdbae9f1121dd5411412dbdf90 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Mon, 4 Feb 2013 11:58:43 -0800 Subject: [PATCH 094/158] 8006295: Base64.Decoder.wrap(java.io.InputStream) returns InputStream which throws unspecified IOException on attempt to decode invalid Base64 byte stream 8006315: Base64.Decoder decoding methods are not consistent in treating non-padded data 8006530: Base64.getMimeDecoder().decode() throws exception for non-base64 character after adding = Updated the spec to describe the expected behave explicitly and the implementation to follow Reviewed-by: alanb, chegar, lancea --- jdk/src/share/classes/java/util/Base64.java | 121 +++++++++++++------- jdk/test/java/util/Base64/TestBase64.java | 83 +++++++++++++- 2 files changed, 161 insertions(+), 43 deletions(-) diff --git a/jdk/src/share/classes/java/util/Base64.java b/jdk/src/share/classes/java/util/Base64.java index 471b4e28620..88b17406799 100644 --- a/jdk/src/share/classes/java/util/Base64.java +++ b/jdk/src/share/classes/java/util/Base64.java @@ -64,7 +64,8 @@ import java.nio.charset.StandardCharsets; * RFC 2045 for encoding and decoding operation. The encoded output * must be represented in lines of no more than 76 characters each * and uses a carriage return {@code '\r'} followed immediately by - * a linefeed {@code '\n'} as the line separator. All line separators + * a linefeed {@code '\n'} as the line separator. No line separator + * is added to the end of the encoded output. All line separators * or other characters not found in the base64 alphabet table are * ignored in decoding operation.

* @@ -614,6 +615,13 @@ public class Base64 { * This class implements a decoder for decoding byte data using the * Base64 encoding scheme as specified in RFC 4648 and RFC 2045. * + *

The Base64 padding character {@code '='} is accepted and + * interpreted as the end of the encoded byte data, but is not + * required. So if the final unit of the encoded byte data only has + * two or three Base64 characters (without the corresponding padding + * character(s) padded), they are decoded as if followed by padding + * character(s). + * *

Instances of {@link Decoder} class are safe for use by * multiple concurrent threads. * @@ -857,6 +865,9 @@ public class Base64 { /** * Returns an input stream for decoding {@link Base64} encoded byte stream. * + *

The {@code read} methods of the returned {@code InputStream} will + * throw {@code IOException} when reading bytes that cannot be decoded. + * *

Closing the returned input stream will close the underlying * input stream. * @@ -883,13 +894,16 @@ public class Base64 { int dl = dst.arrayOffset() + dst.limit(); int dp0 = dp; int mark = sp; - boolean padding = false; try { while (sp < sl) { int b = sa[sp++] & 0xff; if ((b = base64[b]) < 0) { if (b == -2) { // padding byte - padding = true; + if (shiftto == 6 && (sp == sl || sa[sp++] != '=') || + shiftto == 18) { + throw new IllegalArgumentException( + "Input byte array has wrong 4-byte ending unit"); + } break; } if (isMIME) // skip if for rfc2045 @@ -915,24 +929,23 @@ public class Base64 { if (shiftto == 6) { if (dl - dp < 1) return dp - dp0; - if (padding && (sp + 1 != sl || sa[sp++] != '=')) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); da[dp++] = (byte)(bits >> 16); - mark = sp; } else if (shiftto == 0) { if (dl - dp < 2) return dp - dp0; - if (padding && sp != sl) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); da[dp++] = (byte)(bits >> 16); da[dp++] = (byte)(bits >> 8); - mark = sp; - } else if (padding || shiftto != 18) { + } else if (shiftto == 12) { throw new IllegalArgumentException( "Last unit does not have enough valid bits"); } + while (sp < sl) { + if (isMIME && base64[sa[sp++]] < 0) + continue; + throw new IllegalArgumentException( + "Input byte array has incorrect ending byte at " + sp); + } + mark = sp; return dp - dp0; } finally { src.position(mark); @@ -950,14 +963,16 @@ public class Base64 { int dl = dst.limit(); int dp0 = dp; int mark = sp; - boolean padding = false; - try { while (sp < sl) { int b = src.get(sp++) & 0xff; if ((b = base64[b]) < 0) { if (b == -2) { // padding byte - padding = true; + if (shiftto == 6 && (sp == sl || src.get(sp++) != '=') || + shiftto == 18) { + throw new IllegalArgumentException( + "Input byte array has wrong 4-byte ending unit"); + } break; } if (isMIME) // skip if for rfc2045 @@ -983,24 +998,23 @@ public class Base64 { if (shiftto == 6) { if (dl - dp < 1) return dp - dp0; - if (padding && (sp + 1 != sl || src.get(sp++) != '=')) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); dst.put(dp++, (byte)(bits >> 16)); - mark = sp; } else if (shiftto == 0) { if (dl - dp < 2) return dp - dp0; - if (padding && sp != sl) - throw new IllegalArgumentException( - "Input buffer has wrong 4-byte ending unit"); dst.put(dp++, (byte)(bits >> 16)); dst.put(dp++, (byte)(bits >> 8)); - mark = sp; - } else if (padding || shiftto != 18) { + } else if (shiftto == 12) { throw new IllegalArgumentException( "Last unit does not have enough valid bits"); } + while (sp < sl) { + if (isMIME && base64[src.get(sp++)] < 0) + continue; + throw new IllegalArgumentException( + "Input byte array has incorrect ending byte at " + sp); + } + mark = sp; return dp - dp0; } finally { src.position(mark); @@ -1048,12 +1062,20 @@ public class Base64 { int dp = 0; int bits = 0; int shiftto = 18; // pos of first byte of 4-byte atom - boolean padding = false; while (sp < sl) { int b = src[sp++] & 0xff; if ((b = base64[b]) < 0) { - if (b == -2) { // padding byte - padding = true; + if (b == -2) { // padding byte '=' + // xx= shiftto==6&&sp==sl missing last = + // xx=y shiftto==6 last is not = + // = shiftto==18 unnecessary padding + // x= shiftto==12 be taken care later + // together with single x, invalid anyway + if (shiftto == 6 && (sp == sl || src[sp++] != '=') || + shiftto == 18) { + throw new IllegalArgumentException( + "Input byte array has wrong 4-byte ending unit"); + } break; } if (isMIME) // skip if for rfc2045 @@ -1073,22 +1095,23 @@ public class Base64 { bits = 0; } } - // reach end of byte arry or hit padding '=' characters. - // if '=' presents, they must be the last one or two. - if (shiftto == 6) { // xx== - if (padding && (sp + 1 != sl || src[sp] != '=')) - throw new IllegalArgumentException( - "Input byte array has wrong 4-byte ending unit"); + // reached end of byte array or hit padding '=' characters. + if (shiftto == 6) { dst[dp++] = (byte)(bits >> 16); - } else if (shiftto == 0) { // xxx= - if (padding && sp != sl) - throw new IllegalArgumentException( - "Input byte array has wrong 4-byte ending unit"); + } else if (shiftto == 0) { dst[dp++] = (byte)(bits >> 16); dst[dp++] = (byte)(bits >> 8); - } else if (padding || shiftto != 18) { - throw new IllegalArgumentException( - "last unit does not have enough bytes"); + } else if (shiftto == 12) { + throw new IllegalArgumentException( + "Last unit does not have enough valid bits"); + } + // anything left is invalid, if is not MIME. + // if MIME, ignore all non-base64 character + while (sp < sl) { + if (isMIME && base64[src[sp++]] < 0) + continue; + throw new IllegalArgumentException( + "Input byte array has incorrect ending byte at " + sp); } return dp; } @@ -1252,8 +1275,22 @@ public class Base64 { int v = is.read(); if (v == -1) { eof = true; - if (nextin != 18) - throw new IOException("Base64 stream has un-decoded dangling byte(s)."); + if (nextin != 18) { + if (nextin == 12) + throw new IOException("Base64 stream has one un-decoded dangling byte."); + // treat ending xx/xxx without padding character legal. + // same logic as v == 'v' below + b[off++] = (byte)(bits >> (16)); + len--; + if (nextin == 0) { // only one padding byte + if (len == 0) { // no enough output space + bits >>= 8; // shift to lowest byte + nextout = 0; + } else { + b[off++] = (byte) (bits >> 8); + } + } + } if (off == oldOff) return -1; else diff --git a/jdk/test/java/util/Base64/TestBase64.java b/jdk/test/java/util/Base64/TestBase64.java index 0a8eea6e4aa..e0af4de23b7 100644 --- a/jdk/test/java/util/Base64/TestBase64.java +++ b/jdk/test/java/util/Base64/TestBase64.java @@ -22,7 +22,7 @@ */ /** - * @test 4235519 8004212 8005394 8007298 + * @test 4235519 8004212 8005394 8007298 8006295 8006315 8006530 * @summary tests java.util.Base64 */ @@ -112,6 +112,12 @@ public class TestBase64 { // test single-non-base64 character for mime decoding testSingleNonBase64MimeDec(); + + // test decoding of unpadded data + testDecodeUnpadded(); + + // test mime decoding with ignored character after padding + testDecodeIgnoredAfterPadding(); } private static sun.misc.BASE64Encoder sunmisc = new sun.misc.BASE64Encoder(); @@ -359,6 +365,81 @@ public class TestBase64 { } catch (IllegalArgumentException iae) {} } + private static void testDecodeIgnoredAfterPadding() throws Throwable { + for (byte nonBase64 : new byte[] {'#', '(', '!', '\\', '-', '_', '\n', '\r'}) { + byte[][] src = new byte[][] { + "A".getBytes("ascii"), + "AB".getBytes("ascii"), + "ABC".getBytes("ascii"), + "ABCD".getBytes("ascii"), + "ABCDE".getBytes("ascii") + }; + Base64.Encoder encM = Base64.getMimeEncoder(); + Base64.Decoder decM = Base64.getMimeDecoder(); + Base64.Encoder enc = Base64.getEncoder(); + Base64.Decoder dec = Base64.getDecoder(); + for (int i = 0; i < src.length; i++) { + // decode(byte[]) + byte[] encoded = encM.encode(src[i]); + encoded = Arrays.copyOf(encoded, encoded.length + 1); + encoded[encoded.length - 1] = nonBase64; + checkEqual(decM.decode(encoded), src[i], "Non-base64 char is not ignored"); + try { + dec.decode(encoded); + throw new RuntimeException("No IAE for non-base64 char"); + } catch (IllegalArgumentException iae) {} + + // decode(ByteBuffer[], ByteBuffer[]) + ByteBuffer encodedBB = ByteBuffer.wrap(encoded); + ByteBuffer decodedBB = ByteBuffer.allocate(100); + int ret = decM.decode(encodedBB, decodedBB); + byte[] buf = new byte[ret]; + decodedBB.flip(); + decodedBB.get(buf); + checkEqual(buf, src[i], "Non-base64 char is not ignored"); + try { + encodedBB.rewind(); + decodedBB.clear(); + dec.decode(encodedBB, decodedBB); + throw new RuntimeException("No IAE for non-base64 char"); + } catch (IllegalArgumentException iae) {} + // direct + encodedBB.rewind(); + decodedBB = ByteBuffer.allocateDirect(100); + ret = decM.decode(encodedBB, decodedBB); + buf = new byte[ret]; + decodedBB.flip(); + decodedBB.get(buf); + checkEqual(buf, src[i], "Non-base64 char is not ignored"); + try { + encodedBB.rewind(); + decodedBB.clear(); + dec.decode(encodedBB, decodedBB); + throw new RuntimeException("No IAE for non-base64 char"); + } catch (IllegalArgumentException iae) {} + } + } + } + + private static void testDecodeUnpadded() throws Throwable { + byte[] srcA = new byte[] { 'Q', 'Q' }; + byte[] srcAA = new byte[] { 'Q', 'Q', 'E'}; + Base64.Decoder dec = Base64.getDecoder(); + byte[] ret = dec.decode(srcA); + if (ret[0] != 'A') + throw new RuntimeException("Decoding unpadding input A failed"); + ret = dec.decode(srcAA); + if (ret[0] != 'A' && ret[1] != 'A') + throw new RuntimeException("Decoding unpadding input AA failed"); + ret = new byte[10]; + if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 1 && + ret[0] != 'A') + throw new RuntimeException("Decoding unpadding input A from stream failed"); + if (dec.wrap(new ByteArrayInputStream(srcA)).read(ret) != 2 && + ret[0] != 'A' && ret[1] != 'A') + throw new RuntimeException("Decoding unpadding input AA from stream failed"); + } + // single-non-base64-char should be ignored for mime decoding, but // iae for basic decoding private static void testSingleNonBase64MimeDec() throws Throwable { From 78b547afa764065c3a7a5e7240fb1998359410dc Mon Sep 17 00:00:00 2001 From: Jia-Hong Chen Date: Mon, 4 Feb 2013 12:04:38 -0800 Subject: [PATCH 095/158] 8005052: [parfait] #416 X11SurfaceData.c UNINITIALISED OR MISSING RETURN VALUE 8005054: [parfait] #417 X11SurfaceData.c UNINITIALISED OR MISSING RETURN VALUE Reviewed-by: prr, vadim --- jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c index 5b8aeb4be20..cee9bb75bfd 100644 --- a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c +++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c @@ -135,11 +135,11 @@ jboolean XShared_initIDs(JNIEnv *env, jboolean allowShmPixmaps) useMitShmPixmaps = JNI_FALSE; } } - - return JNI_TRUE; #endif /* MITSHM */ #endif /* !HEADLESS */ + + return JNI_TRUE; } @@ -468,8 +468,8 @@ jboolean XShared_initSurface(JNIEnv *env, X11SDOps *xsdo, jint depth, jint width return JNI_FALSE; } - return JNI_TRUE; #endif /* !HEADLESS */ + return JNI_TRUE; } From 13339482664abfc3ab5f7c3c6fe5a3710628e2c9 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Mon, 4 Feb 2013 13:24:57 -0800 Subject: [PATCH 096/158] 8001384: G1: assert(!is_null(v)) failed: narrow oop value can never be zero Flush any deferred card mark before a Java thread exits. Reviewed-by: brutisso, jmasa --- hotspot/src/share/vm/runtime/thread.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index ff6adde6eee..b2357878954 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -1500,7 +1500,7 @@ JavaThread::JavaThread(bool is_attaching_via_jni) : } else { _jni_attach_state = _not_attaching_via_jni; } - assert(_deferred_card_mark.is_empty(), "Default MemRegion ctor"); + assert(deferred_card_mark().is_empty(), "Default MemRegion ctor"); _safepoint_visible = false; } @@ -1896,9 +1896,16 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { JvmtiExport::cleanup_thread(this); } -#ifndef SERIALGC - // We must flush G1-related buffers before removing a thread from + // We must flush any deferred card marks before removing a thread from // the list of active threads. + Universe::heap()->flush_deferred_store_barrier(this); + assert(deferred_card_mark().is_empty(), "Should have been flushed"); + +#ifndef SERIALGC + // We must flush the G1-related buffers before removing a thread + // from the list of active threads. We must do this after any deferred + // card marks have been flushed (above) so that any entries that are + // added to the thread's dirty card queue as a result are not lost. if (UseG1GC) { flush_barrier_queues(); } From 4d8014cefadf0e9aead5b3c3cad80301e6c3a410 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 4 Feb 2013 15:30:10 -0800 Subject: [PATCH 097/158] 8007490: NPE from DocumentationTool.run Reviewed-by: darcy --- .../sun/tools/javadoc/api/JavadocTool.java | 6 +-- .../test/tools/javadoc/api/basic/RunTest.java | 52 +++++++++++++++++-- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java b/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java index a8aa2786577..e36dfd0913f 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -139,8 +139,8 @@ public class JavadocTool implements DocumentationTool { @Override public int run(InputStream in, OutputStream out, OutputStream err, String... arguments) { - PrintWriter err_pw = new PrintWriter(err, true); - PrintWriter out_pw = new PrintWriter(out); + PrintWriter err_pw = new PrintWriter(err == null ? System.err : err, true); + PrintWriter out_pw = new PrintWriter(out == null ? System.out : out); try { String standardDocletName = "com.sun.tools.doclets.standard.Standard"; return com.sun.tools.javadoc.Main.execute( diff --git a/langtools/test/tools/javadoc/api/basic/RunTest.java b/langtools/test/tools/javadoc/api/basic/RunTest.java index 2e6c65252df..380f5b69a9d 100644 --- a/langtools/test/tools/javadoc/api/basic/RunTest.java +++ b/langtools/test/tools/javadoc/api/basic/RunTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 6493690 + * @bug 6493690 8007490 * @summary javadoc should have a javax.tools.Tool service provider * @build APITest * @run main RunTest @@ -31,6 +31,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.PrintStream; import javax.tools.DocumentationTool; import javax.tools.ToolProvider; @@ -46,7 +47,7 @@ public class RunTest extends APITest { * Verify that run method can be invoked. */ @Test - public void testRun() throws Exception { + public void testRunOK() throws Exception { File testSrc = new File(System.getProperty("test.src")); File srcFile = new File(testSrc, "pkg/C.java"); File outDir = getOutDir(); @@ -77,7 +78,7 @@ public class RunTest extends APITest { * Verify that run method can be invoked. */ @Test - public void testRun2() throws Exception { + public void testRunFail() throws Exception { File outDir = getOutDir(); String badfile = "badfile.java"; String[] args = { "-d", outDir.getPath(), badfile }; @@ -100,5 +101,48 @@ public class RunTest extends APITest { } } + /** + * Verify that null args are accepted. + */ + @Test + public void testNullArgs() throws Exception { + File testSrc = new File(System.getProperty("test.src")); + File srcFile = new File(testSrc, "pkg/C.java"); + File outDir = getOutDir(); + String[] args = { "-d", outDir.getPath(), srcFile.getPath() }; + + ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + PrintStream prevStdout = System.out; + System.setOut(new PrintStream(stdout)); + + ByteArrayOutputStream stderr = new ByteArrayOutputStream(); + PrintStream prevStderr = System.err; + System.setErr(new PrintStream(stderr)); + + int rc ; + try { + DocumentationTool tool = ToolProvider.getSystemDocumentationTool(); + rc = tool.run(null, null, null, args); + } finally { + System.setOut(prevStdout); + System.setErr(prevStderr); + } + + System.err.println("stdout >>" + stdout.toString() + "<<"); + System.err.println("stderr >>" + stderr.toString() + "<<"); + + if (rc == 0) { + System.err.println("call succeeded"); + checkFiles(outDir, standardExpectFiles); + String out = stdout.toString(); + for (String f: standardExpectFiles) { + String f1 = f.replace('/', File.separatorChar); + if (f1.endsWith(".html") && !out.contains(f1)) + error("expected string not found: " + f1); + } + } else { + error("call failed"); + } + } } From 920d11993cab6fa85589e06887af42d1192b3a36 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 4 Feb 2013 17:56:29 -0800 Subject: [PATCH 098/158] 8007113: Upgrade AnnotatedElement.isAnnotionPresent to be a default method Reviewed-by: chegar, jfranck --- jdk/src/share/classes/java/lang/Class.java | 10 ---------- jdk/src/share/classes/java/lang/Package.java | 11 +---------- .../classes/java/lang/reflect/AccessibleObject.java | 8 -------- .../classes/java/lang/reflect/AnnotatedElement.java | 7 ++++++- .../share/classes/java/lang/reflect/Parameter.java | 8 -------- .../sun/reflect/annotation/AnnotatedTypeFactory.java | 5 ----- .../generics/reflectiveObjects/TypeVariableImpl.java | 5 ----- 7 files changed, 7 insertions(+), 47 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index 31e2294ebf6..dab6c98e47a 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -3083,16 +3083,6 @@ public final return (A) annotations.get(annotationClass); } - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - public boolean isAnnotationPresent(Class annotationClass) { - Objects.requireNonNull(annotationClass); - - return getAnnotation(annotationClass) != null; - } - /** * @throws NullPointerException {@inheritDoc} * @since 1.8 diff --git a/jdk/src/share/classes/java/lang/Package.java b/jdk/src/share/classes/java/lang/Package.java index 744a292d6ee..234f807181a 100644 --- a/jdk/src/share/classes/java/lang/Package.java +++ b/jdk/src/share/classes/java/lang/Package.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 @@ -385,15 +385,6 @@ public class Package implements java.lang.reflect.AnnotatedElement { return getPackageInfo().getAnnotation(annotationClass); } - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - public boolean isAnnotationPresent( - Class annotationClass) { - return getPackageInfo().isAnnotationPresent(annotationClass); - } - /** * @throws NullPointerException {@inheritDoc} * @since 1.8 diff --git a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java index baaec298a85..9986aef6cf7 100644 --- a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java +++ b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java @@ -180,14 +180,6 @@ public class AccessibleObject implements AnnotatedElement { throw new AssertionError("All subclasses should override this method"); } - /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - public boolean isAnnotationPresent(Class annotationClass) { - return getAnnotation(annotationClass) != null; - } - /** * @throws NullPointerException {@inheritDoc} * @since 1.8 diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java index e7de9429b0c..85472ff5b00 100644 --- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java @@ -91,6 +91,9 @@ public interface AnnotatedElement { *

The truth value returned by this method is equivalent to: * {@code getAnnotation(annotationClass) != null} * + *

The body of the default method is specified to be the code + * above. + * * @param annotationClass the Class object corresponding to the * annotation type * @return true if an annotation for the specified annotation @@ -98,7 +101,9 @@ public interface AnnotatedElement { * @throws NullPointerException if the given annotation class is null * @since 1.5 */ - boolean isAnnotationPresent(Class annotationClass); + default boolean isAnnotationPresent(Class annotationClass) { + return getAnnotation(annotationClass) != null; + } /** * Returns this element's annotation for the specified type if diff --git a/jdk/src/share/classes/java/lang/reflect/Parameter.java b/jdk/src/share/classes/java/lang/reflect/Parameter.java index 4fda579c5fc..04bc274ca9f 100644 --- a/jdk/src/share/classes/java/lang/reflect/Parameter.java +++ b/jdk/src/share/classes/java/lang/reflect/Parameter.java @@ -280,14 +280,6 @@ public final class Parameter implements AnnotatedElement { return getDeclaredAnnotations(); } - /** - * @throws NullPointerException {@inheritDoc} - */ - public boolean isAnnotationPresent( - Class annotationClass) { - return getAnnotation(annotationClass) != null; - } - private transient Map, Annotation> declaredAnnotations; private synchronized Map, Annotation> declaredAnnotations() { diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java index afb4c4865e7..e0524e849dc 100644 --- a/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java @@ -137,11 +137,6 @@ public class AnnotatedTypeFactory { } // AnnotatedElement - @Override - public final boolean isAnnotationPresent(Class annotation) { - return annotations.get(annotation) != null; - } - @Override public final Annotation[] getAnnotations() { return getDeclaredAnnotations(); diff --git a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java index 4bc3356278b..528658d0d16 100644 --- a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java +++ b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java @@ -188,11 +188,6 @@ public class TypeVariableImpl } // Implementations of AnnotatedElement methods. - public boolean isAnnotationPresent(Class annotationClass) { - Objects.requireNonNull(annotationClass); - return false; - } - @SuppressWarnings("unchecked") public T getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); From 05a047b442e8bdb345cb7dfdeca0b405a2216a46 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 4 Feb 2013 18:14:24 -0800 Subject: [PATCH 099/158] 8007492: DocumentationTool cannot locate standard doclet when invoked from JRE Reviewed-by: darcy --- .../share/classes/com/sun/tools/javadoc/api/JavadocTool.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java b/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java index e36dfd0913f..5df92804aa1 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java @@ -143,8 +143,9 @@ public class JavadocTool implements DocumentationTool { PrintWriter out_pw = new PrintWriter(out == null ? System.out : out); try { String standardDocletName = "com.sun.tools.doclets.standard.Standard"; + ClassLoader cl = getClass().getClassLoader(); return com.sun.tools.javadoc.Main.execute( - "javadoc", err_pw, err_pw, out_pw, standardDocletName, arguments); + "javadoc", err_pw, err_pw, out_pw, standardDocletName, cl, arguments); } finally { err_pw.flush(); out_pw.flush(); From 329bc97900d65183fb4abf9f59e29fbc42244e8a Mon Sep 17 00:00:00 2001 From: Jeremy Manson Date: Mon, 4 Feb 2013 23:53:10 -0500 Subject: [PATCH 100/158] 8006508: Wrong frame constructor is called in os_linux_x86.cpp Reviewed-by: dholmes, coleenp --- hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp | 2 +- hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp | 2 +- hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp index fc55e4ec71e..9eabc200bb8 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp @@ -372,7 +372,7 @@ frame os::current_frame() { CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + return frame(); } else { return os::get_sender_for_C_frame(&myframe); } diff --git a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp index 907395bb22a..bfb0e960a0c 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp +++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp @@ -189,7 +189,7 @@ frame os::current_frame() { CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + return frame(); } else { return os::get_sender_for_C_frame(&myframe); } diff --git a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp index e8bd38dc13e..1ef29f99a55 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp +++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp @@ -399,7 +399,7 @@ frame os::current_frame() { typedef intptr_t* get_fp_func (); get_fp_func* func = CAST_TO_FN_PTR(get_fp_func*, StubRoutines::x86::get_previous_fp_entry()); - if (func == NULL) return frame(NULL, NULL, NULL); + if (func == NULL) return frame(); intptr_t* fp = (*func)(); #else intptr_t* fp = _get_previous_fp(); @@ -410,7 +410,7 @@ frame os::current_frame() { CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + return frame(); } else { return os::get_sender_for_C_frame(&myframe); } From d1a58e452a8ae757003428dd077ca9bbfb85a0f7 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 5 Feb 2013 12:28:47 +0100 Subject: [PATCH 101/158] 7170447: Intermittent DeadListenerTest.java failure Due to asynchronous nature of processing server notifications it may happen that an "unregister" notification ha$ Reviewed-by: sjiang --- .../mandatory/notif/DeadListenerTest.java | 58 +++++++++++-------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java b/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java index d5fd91e527f..db313040c25 100644 --- a/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java +++ b/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java @@ -31,6 +31,7 @@ import com.sun.jmx.remote.internal.ServerNotifForwarder; import java.io.IOException; import java.lang.management.ManagementFactory; +import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; @@ -86,20 +87,26 @@ public class DeadListenerTest { Map> listenerMap = (Map>) listenerMapF.get(serverNotifForwarder); assertTrue("Server listenerMap initially empty", mapWithoutKey(listenerMap, delegateName).isEmpty()); - CountListener count1 = new CountListener(); + final AtomicInteger count1Val = new AtomicInteger(); + CountListener count1 = new CountListener(count1Val); mbsc.addNotificationListener(name, count1, null, null); + WeakReference count1Ref = new WeakReference<>(count1); + count1 = null; - CountListener count2 = new CountListener(); + final AtomicInteger count2Val = new AtomicInteger(); + CountListener count2 = new CountListener(count2Val); NotificationFilterSupport dummyFilter = new NotificationFilterSupport(); dummyFilter.enableType(""); mbsc.addNotificationListener(name, count2, dummyFilter, "noddy"); + WeakReference count2Ref = new WeakReference<>(count2); + count2 = null; assertTrue("One entry in listenerMap for two listeners on same MBean", mapWithoutKey(listenerMap, delegateName).size() == 1); Set set = listenerMap.get(name); assertTrue("Set in listenerMap for MBean has two elements", set != null && set.size() == 2); - assertTrue("Initial value of count1 == 0", count1.count() == 0); - assertTrue("Initial value of count2 == 0", count2.count() == 0); + assertTrue("Initial value of count1 == 0", count1Val.get() == 0); + assertTrue("Initial value of count2 == 0", count2Val.get() == 0); Notification notif = new Notification("type", name, 0); @@ -107,11 +114,11 @@ public class DeadListenerTest { // Make sure notifs are working normally. long deadline = System.currentTimeMillis() + 2000; - while ((count1.count() != 1 || count2.count() != 1) && System.currentTimeMillis() < deadline) { + while ((count1Val.get() != 1 || count2Val.get() != 1) && System.currentTimeMillis() < deadline) { Thread.sleep(10); } - assertTrue("New value of count1 == 1", count1.count() == 1); - assertTrue("Initial value of count2 == 1", count2.count() == 1); + assertTrue("New value of count1 == 1", count1Val.get() == 1); + assertTrue("Initial value of count2 == 1", count2Val.get() == 1); // Make sure that removing a nonexistent listener from an existent MBean produces ListenerNotFoundException CountListener count3 = new CountListener(); @@ -136,28 +143,29 @@ public class DeadListenerTest { mbs.unregisterMBean(name); mbean.sendNotification(notif); Thread.sleep(200); - assertTrue("New value of count1 == 1", count1.count() == 1); - assertTrue("Initial value of count2 == 1", count2.count() == 1); + + assertTrue("New value of count1 == 1", count1Val.get() == 1); + assertTrue("Initial value of count2 == 1", count2Val.get() == 1); + + // wait for the listener cleanup to take place upon processing notifications + int countdown = 50; // waiting max. 5 secs + while (countdown-- > 0 && + (count1Ref.get() != null || + count2Ref.get() != null)) { + System.gc(); + Thread.sleep(100); + System.gc(); + } + // listener has been removed or the wait has timed out + + assertTrue("count1 notification listener has not been cleaned up", count1Ref.get() == null); + assertTrue("count2 notification listener has not been cleaned up", count2Ref.get() == null); // Check that there is no trace of the listeners any more in ServerNotifForwarder.listenerMap. // THIS DEPENDS ON JMX IMPLEMENTATION DETAILS. // If the JMX implementation changes, the code here may have to change too. Set setForUnreg = listenerMap.get(name); assertTrue("No trace of unregistered MBean: " + setForUnreg, setForUnreg == null); - - // Remove attempts should fail. - try { - mbsc.removeNotificationListener(name, count1); - assertTrue("Remove of count1 listener should have failed", false); - } catch (ListenerNotFoundException e) { - // OK: expected - } - try { - mbsc.removeNotificationListener(name, count2, dummyFilter, "noddy"); - assertTrue("Remove of count2 listener should have failed", false); - } catch (ListenerNotFoundException e) { - // OK: expected - } } private static Map mapWithoutKey(Map map, K key) { @@ -173,6 +181,10 @@ public class DeadListenerTest { public static class CountListener implements NotificationListener { final AtomicInteger count; + public CountListener(AtomicInteger i) { + count = i; + } + public CountListener() { this.count = new AtomicInteger(); } From 631c9a9bada048a16e31f07f30cbaa60b52250e3 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 5 Feb 2013 12:36:32 +0100 Subject: [PATCH 102/158] 8005791: Remove java.beans.* imports from com.sun.jmx.mbeanserver.Introspector Reviewed-by: rbackman --- jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java index 2e259a818c8..5680cc66631 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java @@ -50,8 +50,6 @@ import javax.management.MBeanInfo; import javax.management.NotCompliantMBeanException; import com.sun.jmx.remote.util.EnvHelp; -import java.beans.BeanInfo; -import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import javax.management.AttributeNotFoundException; From 85c0519ca648a5da2a3ada8b7a0b3683b09574ec Mon Sep 17 00:00:00 2001 From: Vinnie Ryan Date: Tue, 5 Feb 2013 14:25:47 +0000 Subject: [PATCH 103/158] 8007483: attributes are ignored when loading keys from a PKCS12 keystore Reviewed-by: mullan --- .../classes/sun/security/pkcs12/PKCS12KeyStore.java | 7 ++++++- jdk/test/sun/security/pkcs12/StorePasswordTest.java | 13 +++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java index eefdbff811f..d40e033d9f0 100644 --- a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java +++ b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java @@ -1116,7 +1116,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { if (privateKeyCount > 0 || secretKeyCount > 0) { if (debug != null) { - debug.println("Storing " + privateKeyCount + + debug.println("Storing " + (privateKeyCount + secretKeyCount) + " protected key(s) in a PKCS#7 data content-type"); } @@ -2122,6 +2122,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { SecretKeyEntry kEntry = new SecretKeyEntry(); kEntry.protectedSecretKey = secretValue.getOctetString(); bagItem = kEntry; + secretKeyCount++; } else { if (debug != null) { @@ -2220,6 +2221,10 @@ public final class PKCS12KeyStore extends KeyStoreSpi { if (bagItem instanceof PrivateKeyEntry) { keyList.add((PrivateKeyEntry) entry); } + if (entry.attributes == null) { + entry.attributes = new HashSet<>(); + } + entry.attributes.addAll(attributes); if (alias == null) { alias = getUnfriendlyName(); } diff --git a/jdk/test/sun/security/pkcs12/StorePasswordTest.java b/jdk/test/sun/security/pkcs12/StorePasswordTest.java index d258aaa10a7..821b1759a2c 100644 --- a/jdk/test/sun/security/pkcs12/StorePasswordTest.java +++ b/jdk/test/sun/security/pkcs12/StorePasswordTest.java @@ -51,8 +51,12 @@ public class StorePasswordTest { keystore.load(null, null); // Set entry + Set attrs = new HashSet<>(); + attrs.add(new PKCS12Attribute("1.3.5.7.9", "printable1")); + attrs.add(new PKCS12Attribute("2.4.6.8.10", "1F:2F:3F:4F:5F")); + int originalAttrCount = attrs.size() + 2; keystore.setEntry(ALIAS, - new KeyStore.SecretKeyEntry(convertPassword(USER_PASSWORD)), + new KeyStore.SecretKeyEntry(convertPassword(USER_PASSWORD), attrs), new KeyStore.PasswordProtection(PASSWORD)); try (FileOutputStream outStream = new FileOutputStream(KEYSTORE)) { @@ -69,7 +73,12 @@ public class StorePasswordTest { KeyStore.Entry entry = keystore.getEntry(ALIAS, new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry: " + entry); + int attrCount = entry.getAttributes().size(); + System.out.println("Retrieved entry with " + attrCount + " attrs: " + + entry); + if (attrCount != originalAttrCount) { + throw new Exception("Failed to recover all the entry attributes"); + } SecretKey key = (SecretKey) keystore.getKey(ALIAS, PASSWORD); SecretKeyFactory factory = From 3d09f6b621ca7de743e4058ae0e2cee682d5ba62 Mon Sep 17 00:00:00 2001 From: Eric McCorkle Date: Tue, 5 Feb 2013 14:56:34 +0000 Subject: [PATCH 104/158] 8007389: Remove uses of _ as identifier in jaxp Reviewed-by: lancea, joehw --- jaxp/src/javax/xml/validation/SchemaFactoryFinder.java | 4 ++-- jaxp/src/javax/xml/xpath/XPathFactoryFinder.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jaxp/src/javax/xml/validation/SchemaFactoryFinder.java b/jaxp/src/javax/xml/validation/SchemaFactoryFinder.java index 39c76ed428f..abd0a7ca0af 100644 --- a/jaxp/src/javax/xml/validation/SchemaFactoryFinder.java +++ b/jaxp/src/javax/xml/validation/SchemaFactoryFinder.java @@ -68,7 +68,7 @@ class SchemaFactoryFinder { // Use try/catch block to support applets try { debug = ss.getSystemProperty("jaxp.debug") != null; - } catch (Exception _) { + } catch (Exception unused) { debug = false; } } @@ -113,7 +113,7 @@ class SchemaFactoryFinder { debugPrintln("using thread context class loader ("+classLoader+") for search"); return; } - } catch( Throwable _ ) { + } catch( Throwable unused ) { ; // getContextClassLoader() undefined in JDK1.1 } diff --git a/jaxp/src/javax/xml/xpath/XPathFactoryFinder.java b/jaxp/src/javax/xml/xpath/XPathFactoryFinder.java index 6db1dae1794..b22120da26a 100644 --- a/jaxp/src/javax/xml/xpath/XPathFactoryFinder.java +++ b/jaxp/src/javax/xml/xpath/XPathFactoryFinder.java @@ -56,7 +56,7 @@ class XPathFactoryFinder { // Use try/catch block to support applets try { debug = ss.getSystemProperty("jaxp.debug") != null; - } catch (Exception _) { + } catch (Exception unused) { debug = false; } } @@ -111,7 +111,7 @@ class XPathFactoryFinder { debugPrintln("using thread context class loader ("+classLoader+") for search"); return; } - } catch( Throwable _ ) { + } catch( Throwable unused ) { ; // getContextClassLoader() undefined in JDK1.1 } From 99468dc6c0de703f0232b5bd307c9baffc8062d8 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Tue, 5 Feb 2013 16:50:05 +0100 Subject: [PATCH 105/158] 8007524: build-infra: Incremental build of tools.jar broken Reviewed-by: tbell --- common/makefiles/JavaCompilation.gmk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/makefiles/JavaCompilation.gmk b/common/makefiles/JavaCompilation.gmk index 22c199ad5b5..27257183ac6 100644 --- a/common/makefiles/JavaCompilation.gmk +++ b/common/makefiles/JavaCompilation.gmk @@ -143,8 +143,8 @@ define SetupArchive ifneq (,$2) $1_DEPS:=$2 else - $1_DEPS:=$$(filter $$(addprefix %,$$($1_FIND_PATTERNS)),\ - $$(call CacheFind $$($1_SRCS))) + $1_DEPS:=$$(filter $$(addprefix %,$$($1_SUFFIXES)),\ + $$(call CacheFind,$$($1_SRCS))) ifneq (,$$($1_GREP_INCLUDE_PATTERNS)) $1_DEPS:=$$(filter $$(addsuffix %,$$($1_GREP_INCLUDE_PATTERNS)),$$($1_DEPS)) endif From 014d9489bbe33c841a1a4928d67ef30cac1fc773 Mon Sep 17 00:00:00 2001 From: Igor Ignatyev Date: Tue, 5 Feb 2013 08:25:51 -0800 Subject: [PATCH 106/158] 8006613: adding reason to made_not_compilable Reviewed-by: kvn, vlivanov --- hotspot/src/share/vm/ci/ciMethod.cpp | 4 ++-- hotspot/src/share/vm/ci/ciMethod.hpp | 2 +- .../src/share/vm/compiler/compileBroker.cpp | 2 +- hotspot/src/share/vm/oops/method.cpp | 19 +++++++++++++------ hotspot/src/share/vm/oops/method.hpp | 6 +++--- hotspot/src/share/vm/oops/methodData.hpp | 2 +- .../src/share/vm/runtime/deoptimization.cpp | 2 +- 7 files changed, 22 insertions(+), 15 deletions(-) diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index e5c5e72de9b..0fa11470c94 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -977,7 +977,7 @@ bool ciMethod::can_be_compiled() { // ciMethod::set_not_compilable // // Tell the VM that this method cannot be compiled at all. -void ciMethod::set_not_compilable() { +void ciMethod::set_not_compilable(const char* reason) { check_is_loaded(); VM_ENTRY_MARK; ciEnv* env = CURRENT_ENV; @@ -986,7 +986,7 @@ void ciMethod::set_not_compilable() { } else { _is_c2_compilable = false; } - get_Method()->set_not_compilable(env->comp_level()); + get_Method()->set_not_compilable(env->comp_level(), true, reason); } // ------------------------------------------------------------------ diff --git a/hotspot/src/share/vm/ci/ciMethod.hpp b/hotspot/src/share/vm/ci/ciMethod.hpp index 193eb68de05..c98f2c0dccf 100644 --- a/hotspot/src/share/vm/ci/ciMethod.hpp +++ b/hotspot/src/share/vm/ci/ciMethod.hpp @@ -252,7 +252,7 @@ class ciMethod : public ciMetadata { bool has_option(const char *option); bool can_be_compiled(); bool can_be_osr_compiled(int entry_bci); - void set_not_compilable(); + void set_not_compilable(const char* reason = NULL); bool has_compiled_code(); void log_nmethod_identity(xmlStream* log); bool is_not_reached(int bci); diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 41883d1b44d..6f4e671c165 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -1398,7 +1398,7 @@ bool CompileBroker::compilation_is_prohibited(methodHandle method, int osr_bci, method->print_short_name(tty); tty->cr(); } - method->set_not_compilable_quietly(); + method->set_not_compilable(CompLevel_all, !quietly, "excluded by CompilerOracle"); } return false; diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 936090f50c0..7ab6042475b 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -699,7 +699,7 @@ void Method::set_signature_handler(address handler) { } -void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report) { +void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason) { if (PrintCompilation && report) { ttyLocker ttyl; tty->print("made not %scompilable on ", is_osr ? "OSR " : ""); @@ -713,14 +713,21 @@ void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report) } this->print_short_name(tty); int size = this->code_size(); - if (size > 0) + if (size > 0) { tty->print(" (%d bytes)", size); + } + if (reason != NULL) { + tty->print(" %s", reason); + } tty->cr(); } if ((TraceDeoptimization || LogCompilation) && (xtty != NULL)) { ttyLocker ttyl; xtty->begin_elem("make_not_%scompilable thread='" UINTX_FORMAT "'", is_osr ? "osr_" : "", os::current_thread_id()); + if (reason != NULL) { + xtty->print(" reason=\'%s\'", reason); + } xtty->method(this); xtty->stamp(); xtty->end_elem(); @@ -742,8 +749,8 @@ bool Method::is_not_compilable(int comp_level) const { } // call this when compiler finds that this method is not compilable -void Method::set_not_compilable(int comp_level, bool report) { - print_made_not_compilable(comp_level, /*is_osr*/ false, report); +void Method::set_not_compilable(int comp_level, bool report, const char* reason) { + print_made_not_compilable(comp_level, /*is_osr*/ false, report, reason); if (comp_level == CompLevel_all) { set_not_c1_compilable(); set_not_c2_compilable(); @@ -768,8 +775,8 @@ bool Method::is_not_osr_compilable(int comp_level) const { return false; } -void Method::set_not_osr_compilable(int comp_level, bool report) { - print_made_not_compilable(comp_level, /*is_osr*/ true, report); +void Method::set_not_osr_compilable(int comp_level, bool report, const char* reason) { + print_made_not_compilable(comp_level, /*is_osr*/ true, report, reason); if (comp_level == CompLevel_all) { set_not_c1_osr_compilable(); set_not_c2_osr_compilable(); diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 72a4faf11d7..fad601e2aaf 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -760,18 +760,18 @@ class Method : public Metadata { // whether it is not compilable for another reason like having a // breakpoint set in it. bool is_not_compilable(int comp_level = CompLevel_any) const; - void set_not_compilable(int comp_level = CompLevel_all, bool report = true); + void set_not_compilable(int comp_level = CompLevel_all, bool report = true, const char* reason = NULL); void set_not_compilable_quietly(int comp_level = CompLevel_all) { set_not_compilable(comp_level, false); } bool is_not_osr_compilable(int comp_level = CompLevel_any) const; - void set_not_osr_compilable(int comp_level = CompLevel_all, bool report = true); + void set_not_osr_compilable(int comp_level = CompLevel_all, bool report = true, const char* reason = NULL); void set_not_osr_compilable_quietly(int comp_level = CompLevel_all) { set_not_osr_compilable(comp_level, false); } private: - void print_made_not_compilable(int comp_level, bool is_osr, bool report); + void print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason); public: bool is_not_c1_compilable() const { return access_flags().is_not_c1_compilable(); } diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp index 133278878ef..728305c1120 100644 --- a/hotspot/src/share/vm/oops/methodData.hpp +++ b/hotspot/src/share/vm/oops/methodData.hpp @@ -1465,7 +1465,7 @@ public: void inc_decompile_count() { _nof_decompiles += 1; if (decompile_count() > (uint)PerMethodRecompilationCutoff) { - method()->set_not_compilable(CompLevel_full_optimization); + method()->set_not_compilable(CompLevel_full_optimization, true, "decompile_count > PerMethodRecompilationCutoff"); } } diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index 63df5aa5f88..8f735b7d6fb 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -1559,7 +1559,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra if (trap_method() == nm->method()) { make_not_compilable = true; } else { - trap_method->set_not_compilable(CompLevel_full_optimization); + trap_method->set_not_compilable(CompLevel_full_optimization, true, "overflow_recompile_count > PerBytecodeRecompilationCutoff"); // But give grace to the enclosing nm->method(). } } From c2bb152e6c6f09fa30986b1d6f6b25a1284ae0e4 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Tue, 5 Feb 2013 09:13:05 -0800 Subject: [PATCH 107/158] 8005032: G1: Cleanup serial reference processing closures in concurrent marking Reuse the parallel reference processing oop closures during serial reference processing. Reviewed-by: brutisso --- .../gc_implementation/g1/concurrentMark.cpp | 244 +++++++++--------- .../gc_implementation/g1/concurrentMark.hpp | 4 +- 2 files changed, 117 insertions(+), 131 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index b77cd155e74..28c733c150f 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -2167,7 +2167,8 @@ void ConcurrentMark::completeCleanup() { assert(tmp_free_list.is_empty(), "post-condition"); } -// Support closures for reference procssing in G1 +// Supporting Object and Oop closures for reference discovery +// and processing in during marking bool G1CMIsAliveClosure::do_object_b(oop obj) { HeapWord* addr = (HeapWord*)obj; @@ -2175,73 +2176,26 @@ bool G1CMIsAliveClosure::do_object_b(oop obj) { (!_g1->is_in_g1_reserved(addr) || !_g1->is_obj_ill(obj)); } -class G1CMKeepAliveClosure: public ExtendedOopClosure { - G1CollectedHeap* _g1; - ConcurrentMark* _cm; - public: - G1CMKeepAliveClosure(G1CollectedHeap* g1, ConcurrentMark* cm) : - _g1(g1), _cm(cm) { - assert(Thread::current()->is_VM_thread(), "otherwise fix worker id"); - } +// 'Keep Alive' oop closure used by both serial parallel reference processing. +// Uses the CMTask associated with a worker thread (for serial reference +// processing the CMTask for worker 0 is used) to preserve (mark) and +// trace referent objects. +// +// Using the CMTask and embedded local queues avoids having the worker +// threads operating on the global mark stack. This reduces the risk +// of overflowing the stack - which we would rather avoid at this late +// state. Also using the tasks' local queues removes the potential +// of the workers interfering with each other that could occur if +// operating on the global stack. - virtual void do_oop(narrowOop* p) { do_oop_work(p); } - virtual void do_oop( oop* p) { do_oop_work(p); } - - template void do_oop_work(T* p) { - oop obj = oopDesc::load_decode_heap_oop(p); - HeapWord* addr = (HeapWord*)obj; - - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("\t[0] we're looking at location " - "*"PTR_FORMAT" = "PTR_FORMAT, - p, (void*) obj); - } - - if (_g1->is_in_g1_reserved(addr) && _g1->is_obj_ill(obj)) { - _cm->mark_and_count(obj); - _cm->mark_stack_push(obj); - } - } -}; - -class G1CMDrainMarkingStackClosure: public VoidClosure { - ConcurrentMark* _cm; - CMMarkStack* _markStack; - G1CMKeepAliveClosure* _oopClosure; - public: - G1CMDrainMarkingStackClosure(ConcurrentMark* cm, CMMarkStack* markStack, - G1CMKeepAliveClosure* oopClosure) : - _cm(cm), - _markStack(markStack), - _oopClosure(oopClosure) { } - - void do_void() { - _markStack->drain(_oopClosure, _cm->nextMarkBitMap(), false); - } -}; - -// 'Keep Alive' closure used by parallel reference processing. -// An instance of this closure is used in the parallel reference processing -// code rather than an instance of G1CMKeepAliveClosure. We could have used -// the G1CMKeepAliveClosure as it is MT-safe. Also reference objects are -// placed on to discovered ref lists once so we can mark and push with no -// need to check whether the object has already been marked. Using the -// G1CMKeepAliveClosure would mean, however, having all the worker threads -// operating on the global mark stack. This means that an individual -// worker would be doing lock-free pushes while it processes its own -// discovered ref list followed by drain call. If the discovered ref lists -// are unbalanced then this could cause interference with the other -// workers. Using a CMTask (and its embedded local data structures) -// avoids that potential interference. -class G1CMParKeepAliveAndDrainClosure: public OopClosure { +class G1CMKeepAliveAndDrainClosure: public OopClosure { ConcurrentMark* _cm; CMTask* _task; int _ref_counter_limit; int _ref_counter; public: - G1CMParKeepAliveAndDrainClosure(ConcurrentMark* cm, CMTask* task) : - _cm(cm), _task(task), - _ref_counter_limit(G1RefProcDrainInterval) { + G1CMKeepAliveAndDrainClosure(ConcurrentMark* cm, CMTask* task) : + _cm(cm), _task(task), _ref_counter_limit(G1RefProcDrainInterval) { assert(_ref_counter_limit > 0, "sanity"); _ref_counter = _ref_counter_limit; } @@ -2262,18 +2216,22 @@ class G1CMParKeepAliveAndDrainClosure: public OopClosure { _ref_counter--; if (_ref_counter == 0) { - // We have dealt with _ref_counter_limit references, pushing them and objects - // reachable from them on to the local stack (and possibly the global stack). - // Call do_marking_step() to process these entries. We call the routine in a - // loop, which we'll exit if there's nothing more to do (i.e. we're done - // with the entries that we've pushed as a result of the deal_with_reference - // calls above) or we overflow. - // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag - // while there may still be some work to do. (See the comment at the - // beginning of CMTask::do_marking_step() for those conditions - one of which - // is reaching the specified time target.) It is only when - // CMTask::do_marking_step() returns without setting the has_aborted() flag - // that the marking has completed. + // We have dealt with _ref_counter_limit references, pushing them + // and objects reachable from them on to the local stack (and + // possibly the global stack). Call CMTask::do_marking_step() to + // process these entries. + // + // We call CMTask::do_marking_step() in a loop, which we'll exit if + // there's nothing more to do (i.e. we're done with the entries that + // were pushed as a result of the CMTask::deal_with_reference() calls + // above) or we overflow. + // + // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() + // flag while there may still be some work to do. (See the comment at + // the beginning of CMTask::do_marking_step() for those conditions - + // one of which is reaching the specified time target.) It is only + // when CMTask::do_marking_step() returns without setting the + // has_aborted() flag that the marking step has completed. do { double mark_step_duration_ms = G1ConcMarkStepDurationMillis; _task->do_marking_step(mark_step_duration_ms, @@ -2290,36 +2248,59 @@ class G1CMParKeepAliveAndDrainClosure: public OopClosure { } }; -class G1CMParDrainMarkingStackClosure: public VoidClosure { +// 'Drain' oop closure used by both serial and parallel reference processing. +// Uses the CMTask associated with a given worker thread (for serial +// reference processing the CMtask for worker 0 is used). Calls the +// do_marking_step routine, with an unbelievably large timeout value, +// to drain the marking data structures of the remaining entries +// added by the 'keep alive' oop closure above. + +class G1CMDrainMarkingStackClosure: public VoidClosure { ConcurrentMark* _cm; - CMTask* _task; + CMTask* _task; + bool _do_stealing; + bool _do_termination; public: - G1CMParDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task) : - _cm(cm), _task(task) { } + G1CMDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task, bool is_par) : + _cm(cm), _task(task) { + assert(is_par || _task->worker_id() == 0, + "Only task for worker 0 should be used if ref processing is single threaded"); + // We only allow stealing and only enter the termination protocol + // in CMTask::do_marking_step() if this closure is being instantiated + // for parallel reference processing. + _do_stealing = _do_termination = is_par; + } void do_void() { do { if (_cm->verbose_high()) { - gclog_or_tty->print_cr("\t[%u] Drain: Calling do marking_step", - _task->worker_id()); + gclog_or_tty->print_cr("\t[%u] Drain: Calling do_marking_step - " + "stealing: %s, termination: %s", + _task->worker_id(), + BOOL_TO_STR(_do_stealing), + BOOL_TO_STR(_do_termination)); } - // We call CMTask::do_marking_step() to completely drain the local and - // global marking stacks. The routine is called in a loop, which we'll - // exit if there's nothing more to do (i.e. we'completely drained the - // entries that were pushed as a result of applying the - // G1CMParKeepAliveAndDrainClosure to the entries on the discovered ref - // lists above) or we overflow the global marking stack. - // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag - // while there may still be some work to do. (See the comment at the - // beginning of CMTask::do_marking_step() for those conditions - one of which - // is reaching the specified time target.) It is only when - // CMTask::do_marking_step() returns without setting the has_aborted() flag - // that the marking has completed. + // We call CMTask::do_marking_step() to completely drain the local + // and global marking stacks of entries pushed by the 'keep alive' + // oop closure (an instance of G1CMKeepAliveAndDrainClosure above). + // + // CMTask::do_marking_step() is called in a loop, which we'll exit + // if there's nothing more to do (i.e. we'completely drained the + // entries that were pushed as a a result of applying the 'keep alive' + // closure to the entries on the discovered ref lists) or we overflow + // the global marking stack. + // + // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() + // flag while there may still be some work to do. (See the comment at + // the beginning of CMTask::do_marking_step() for those conditions - + // one of which is reaching the specified time target.) It is only + // when CMTask::do_marking_step() returns without setting the + // has_aborted() flag that the marking step has completed. _task->do_marking_step(1000000000.0 /* something very large */, - true /* do_stealing */, - true /* do_termination */); + _do_stealing, + _do_termination); } while (_task->has_aborted() && !_cm->has_overflown()); } }; @@ -2352,19 +2333,23 @@ class G1CMRefProcTaskProxy: public AbstractGangTask { ProcessTask& _proc_task; G1CollectedHeap* _g1h; ConcurrentMark* _cm; + bool _processing_is_mt; public: G1CMRefProcTaskProxy(ProcessTask& proc_task, G1CollectedHeap* g1h, ConcurrentMark* cm) : AbstractGangTask("Process reference objects in parallel"), - _proc_task(proc_task), _g1h(g1h), _cm(cm) { } + _proc_task(proc_task), _g1h(g1h), _cm(cm) { + ReferenceProcessor* rp = _g1h->ref_processor_cm(); + _processing_is_mt = rp->processing_is_mt(); + } virtual void work(uint worker_id) { CMTask* marking_task = _cm->task(worker_id); G1CMIsAliveClosure g1_is_alive(_g1h); - G1CMParKeepAliveAndDrainClosure g1_par_keep_alive(_cm, marking_task); - G1CMParDrainMarkingStackClosure g1_par_drain(_cm, marking_task); + G1CMKeepAliveAndDrainClosure g1_par_keep_alive(_cm, marking_task); + G1CMDrainMarkingStackClosure g1_par_drain(_cm, marking_task, _processing_is_mt); _proc_task.work(worker_id, g1_is_alive, g1_par_keep_alive, g1_par_drain); } @@ -2372,6 +2357,7 @@ public: void G1CMRefProcTaskExecutor::execute(ProcessTask& proc_task) { assert(_workers != NULL, "Need parallel worker threads."); + assert(_g1h->ref_processor_cm()->processing_is_mt(), "processing is not MT"); G1CMRefProcTaskProxy proc_task_proxy(proc_task, _g1h, _cm); @@ -2399,6 +2385,7 @@ public: void G1CMRefProcTaskExecutor::execute(EnqueueTask& enq_task) { assert(_workers != NULL, "Need parallel worker threads."); + assert(_g1h->ref_processor_cm()->processing_is_mt(), "processing is not MT"); G1CMRefEnqueueTaskProxy enq_task_proxy(enq_task); @@ -2429,59 +2416,58 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { // See the comment in G1CollectedHeap::ref_processing_init() // about how reference processing currently works in G1. - // Process weak references. + // Set the soft reference policy rp->setup_policy(clear_all_soft_refs); assert(_markStack.isEmpty(), "mark stack should be empty"); - G1CMKeepAliveClosure g1_keep_alive(g1h, this); - G1CMDrainMarkingStackClosure - g1_drain_mark_stack(this, &_markStack, &g1_keep_alive); + // Non-MT instances 'Keep Alive' and 'Complete GC' oop closures. + G1CMKeepAliveAndDrainClosure g1_keep_alive(this, task(0)); + G1CMDrainMarkingStackClosure g1_drain_mark_stack(this, task(0), false); + + // We need at least one active thread. If reference processing is + // not multi-threaded we use the current (ConcurrentMarkThread) thread, + // otherwise we use the work gang from the G1CollectedHeap and we + // utilize all the worker threads we can. + uint active_workers = (rp->processing_is_mt() && g1h->workers() != NULL + ? g1h->workers()->active_workers() + : 1U); - // We use the work gang from the G1CollectedHeap and we utilize all - // the worker threads. - uint active_workers = g1h->workers() ? g1h->workers()->active_workers() : 1U; active_workers = MAX2(MIN2(active_workers, _max_worker_id), 1U); G1CMRefProcTaskExecutor par_task_executor(g1h, this, g1h->workers(), active_workers); - if (rp->processing_is_mt()) { - // Set the degree of MT here. If the discovery is done MT, there - // may have been a different number of threads doing the discovery - // and a different number of discovered lists may have Ref objects. - // That is OK as long as the Reference lists are balanced (see - // balance_all_queues() and balance_queues()). - rp->set_active_mt_degree(active_workers); + AbstractRefProcTaskExecutor* executor = (rp->processing_is_mt() + ? &par_task_executor + : NULL); - rp->process_discovered_references(&g1_is_alive, + // Set the degree of MT processing here. If the discovery was done MT, + // the number of threads involved during discovery could differ from + // the number of active workers. This is OK as long as the discovered + // Reference lists are balanced (see balance_all_queues() and balance_queues()). + rp->set_active_mt_degree(active_workers); + + // Process the weak references. + rp->process_discovered_references(&g1_is_alive, &g1_keep_alive, &g1_drain_mark_stack, - &par_task_executor); + executor); - // The work routines of the parallel keep_alive and drain_marking_stack - // will set the has_overflown flag if we overflow the global marking - // stack. - } else { - rp->process_discovered_references(&g1_is_alive, - &g1_keep_alive, - &g1_drain_mark_stack, - NULL); - } + // The do_oop work routines of the keep_alive and drain_marking_stack + // oop closures will set the has_overflown flag if we overflow the + // global marking stack. assert(_markStack.overflow() || _markStack.isEmpty(), "mark stack should be empty (unless it overflowed)"); if (_markStack.overflow()) { - // Should have been done already when we tried to push an + // This should have been done already when we tried to push an // entry on to the global mark stack. But let's do it again. set_has_overflown(); } - if (rp->processing_is_mt()) { - assert(rp->num_q() == active_workers, "why not"); - rp->enqueue_discovered_references(&par_task_executor); - } else { - rp->enqueue_discovered_references(); - } + assert(rp->num_q() == active_workers, "why not"); + + rp->enqueue_discovered_references(executor); rp->verify_no_references_recorded(); assert(!rp->discovery_enabled(), "Post condition"); diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index 6701e9f4171..6ec27c7d9fa 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -371,8 +371,8 @@ class ConcurrentMark: public CHeapObj { friend class CalcLiveObjectsClosure; friend class G1CMRefProcTaskProxy; friend class G1CMRefProcTaskExecutor; - friend class G1CMParKeepAliveAndDrainClosure; - friend class G1CMParDrainMarkingStackClosure; + friend class G1CMKeepAliveAndDrainClosure; + friend class G1CMDrainMarkingStackClosure; protected: ConcurrentMarkThread* _cmThread; // the thread doing the work From 8985a7c2aca7355bcdca70c0627d3c50712a523a Mon Sep 17 00:00:00 2001 From: Jim Holmlund Date: Tue, 5 Feb 2013 18:55:13 +0000 Subject: [PATCH 108/158] 8007504: Remove @ignore from tests that no longer need it Reviewed-by: mcimadamore --- langtools/test/tools/javac/api/T6306137.java | 3 --- .../tools/javac/defaultMethods/TestNoBridgeOnDefaults.java | 1 - langtools/test/tools/javac/lambda/LambdaCapture06.java | 1 - langtools/test/tools/javac/lambda/LambdaExpr15.java | 1 - 4 files changed, 6 deletions(-) diff --git a/langtools/test/tools/javac/api/T6306137.java b/langtools/test/tools/javac/api/T6306137.java index b961d800e4b..8ccf577b088 100644 --- a/langtools/test/tools/javac/api/T6306137.java +++ b/langtools/test/tools/javac/api/T6306137.java @@ -26,9 +26,6 @@ * @bug 6306137 * @summary JSR 199: encoding option doesn't affect standard file manager * @author Peter von der Ahé - * @ignore - * Need to make the contentCache in JavacFileManager be aware of changes to the encoding. - * Need to propogate -source (and -encoding?) down to the JavacFileManager */ import java.io.File; diff --git a/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java b/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java index a52cfb7240e..328629c51e7 100644 --- a/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java +++ b/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java @@ -23,7 +23,6 @@ /* * @test - * @ignore awaits for VM support * @summary check that javac does not generate bridge methods for defaults */ diff --git a/langtools/test/tools/javac/lambda/LambdaCapture06.java b/langtools/test/tools/javac/lambda/LambdaCapture06.java index 85a6feb0e23..99a72d26af6 100644 --- a/langtools/test/tools/javac/lambda/LambdaCapture06.java +++ b/langtools/test/tools/javac/lambda/LambdaCapture06.java @@ -23,7 +23,6 @@ /* * @test - * @ignore investigate as to whether code generation fails * @bug 8003280 * @summary Add lambda tests * Compiler crash when local inner class nested inside lambda captures local variables from enclosing scope diff --git a/langtools/test/tools/javac/lambda/LambdaExpr15.java b/langtools/test/tools/javac/lambda/LambdaExpr15.java index 3b38e8039b6..fd5f4e14bf0 100644 --- a/langtools/test/tools/javac/lambda/LambdaExpr15.java +++ b/langtools/test/tools/javac/lambda/LambdaExpr15.java @@ -23,7 +23,6 @@ /* * @test - * @ignore investigate as to whether code generation fails * @bug 8003280 * @summary Add lambda tests * check that nested inner class in statement lambdas don't get corrupted return statements From c572f25040710e6b16ffa1ff820eb89a12cd808d Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Wed, 6 Feb 2013 16:53:47 +0400 Subject: [PATCH 109/158] 8007277: JDK-8002048 testcase fails to compile Sun.* classes is not included to ct.sym file and symbol file have to be ignored Reviewed-by: alanb --- jdk/test/sun/management/jdp/JdpTest.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/jdk/test/sun/management/jdp/JdpTest.sh b/jdk/test/sun/management/jdp/JdpTest.sh index 2aded729953..764a19f2595 100644 --- a/jdk/test/sun/management/jdp/JdpTest.sh +++ b/jdk/test/sun/management/jdp/JdpTest.sh @@ -23,7 +23,7 @@ # @test # @bug 7169888 -# @build JdpUnitTest JdpClient JdpDoSomething +# @compile -XDignore.symbol.file JdpUnitTest.java JdpClient.java JdpDoSomething.java # @run shell JdpTest.sh --jtreg --no-compile # @summary No word Failed expected in the test output @@ -46,6 +46,10 @@ _last_pid="" _compile(){ + # If the test run without JTReg, we have to compile it by our self + # Under JTReg see @compile statement above + # sun.* packages is not included to symbol file lib/ct.sym so we have + # to ignore it if [ ! -e ${_testclasses} ] then @@ -55,7 +59,8 @@ _compile(){ rm -f ${_testclasses}/*.class # Compile testcase - ${TESTJAVA}/bin/javac -d ${_testclasses} JdpUnitTest.java \ + ${COMPILEJAVA}/bin/javac -XDignore.symbol.file -d ${_testclasses} \ + JdpUnitTest.java \ JdpDoSomething.java \ JdpClient.java @@ -266,6 +271,13 @@ then exit fi +# COMPILEJAVA variable is set when we test jre +if [ "x${COMPILEJAVA}" = "x" ] +then + COMPILEJAVA="${TESTJAVA}" +fi + + #------------------------------------------------------------------------------ # reading parameters From ac96c41fe80f99196d031ae271a5c7283d8ee5cf Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Wed, 6 Feb 2013 18:25:06 +0400 Subject: [PATCH 110/158] 8000326: Focus unable to traverse in the menubar Reviewed-by: alexsch, malenkov --- jdk/src/share/classes/javax/swing/JMenuBar.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/javax/swing/JMenuBar.java b/jdk/src/share/classes/javax/swing/JMenuBar.java index 0a16c865d15..22dbe6274fe 100644 --- a/jdk/src/share/classes/javax/swing/JMenuBar.java +++ b/jdk/src/share/classes/javax/swing/JMenuBar.java @@ -70,7 +70,14 @@ import javax.accessibility.*; * of all JavaBeansTM * has been added to the java.beans package. * Please see {@link java.beans.XMLEncoder}. - * + *

+ * Warning: + * By default, pressing the Tab key does not transfer focus from a + * JMenuBar which is added to a container together with other Swing + * components, because the focusTraversalKeysEnabled property + * of JMenuBar is set to false. To resolve this, + * you should call the JMenuBar.setFocusTraversalKeysEnabled(true) + * method. * @beaninfo * attribute: isContainer true * description: A container for holding and displaying menus. From 218dc713ff1a2488b3d75bfdd3ce5623b40ecb92 Mon Sep 17 00:00:00 2001 From: Lance Andersen Date: Wed, 6 Feb 2013 14:15:05 -0500 Subject: [PATCH 111/158] 8006505: additional changes for JSR 310 support Reviewed-by: naoto, ulfzibis --- jdk/src/share/classes/java/sql/JDBCType.java | 12 +++++- jdk/src/share/classes/java/sql/SQLInput.java | 36 +++++++++++++++- jdk/src/share/classes/java/sql/SQLOutput.java | 42 ++++++++++++++++++- jdk/src/share/classes/java/sql/Types.java | 18 ++++++++ 4 files changed, 104 insertions(+), 4 deletions(-) diff --git a/jdk/src/share/classes/java/sql/JDBCType.java b/jdk/src/share/classes/java/sql/JDBCType.java index f1453059605..74ee8e01682 100644 --- a/jdk/src/share/classes/java/sql/JDBCType.java +++ b/jdk/src/share/classes/java/sql/JDBCType.java @@ -190,7 +190,17 @@ public enum JDBCType implements SQLType { /** * Identifies the generic SQL type {@code REF_CURSOR}. */ - REF_CURSOR(Types.REF_CURSOR); + REF_CURSOR(Types.REF_CURSOR), + + /** + * Identifies the generic SQL type {@code TIME_WITH_TIMEZONE}. + */ + TIME_WITH_TIMEZONE(Types.TIME_WITH_TIMEZONE), + + /** + * Identifies the generic SQL type {@code TIMESTAMP_WITH_TIMEZONE}. + */ + TIMESTAMP_WITH_TIMEZONE(Types.TIMESTAMP_WITH_TIMEZONE); /** * The Integer value for the JDBCType. It maps to a value in diff --git a/jdk/src/share/classes/java/sql/SQLInput.java b/jdk/src/share/classes/java/sql/SQLInput.java index c607e83cbcb..8d2540dc499 100644 --- a/jdk/src/share/classes/java/sql/SQLInput.java +++ b/jdk/src/share/classes/java/sql/SQLInput.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -421,4 +421,38 @@ public interface SQLInput { */ RowId readRowId() throws SQLException; + //--------------------------JDBC 4.2 ----------------------------- + + /** + * Reads the next attribute in the stream and returns it as an + * {@code Object} in the Java programming language. The + * actual type of the object returned is determined by the specified + * Java data type, and any customizations present in this + * stream's type map. + * + *

A type map is registered with the stream by the JDBC driver before the + * stream is passed to the application. + * + *

When the attribute at the head of the stream is an SQL {@code NULL} + * the method returns {@code null}. If the attribute is an SQL + * structured or distinct + * type, it determines the SQL type of the attribute at the head of the stream. + * If the stream's type map has an entry for that SQL type, the driver + * constructs an object of the appropriate class and calls the method + * {@code SQLData.readSQL} on that object, which reads additional data from the + * stream, using the protocol described for that method. + *

+ * The default implementation will throw {@code SQLFeatureNotSupportedException} + * + * @param type Class representing the Java data type to convert the attribute to. + * @return the attribute at the head of the stream as an {@code Object} in the + * Java programming language;{@code null} if the attribute is SQL {@code NULL} + * @exception SQLException if a database access error occurs + * @exception SQLFeatureNotSupportedException if the JDBC driver does not support + * this method + * @since 1.8 + */ + default T readObject(Class type) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } } diff --git a/jdk/src/share/classes/java/sql/SQLOutput.java b/jdk/src/share/classes/java/sql/SQLOutput.java index 8aa1d145329..0edfc998aa3 100644 --- a/jdk/src/share/classes/java/sql/SQLOutput.java +++ b/jdk/src/share/classes/java/sql/SQLOutput.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -272,7 +272,7 @@ package java.sql; * Otherwise, it calls the SQLData.writeSQL * method of the given object, which * writes the object's attributes to the stream. - * The implementation of the method SQLData.writeSQ + * The implementation of the method SQLData.writeSQL * calls the appropriate SQLOutput writer method(s) * for writing each of the object's attributes in order. * The attributes must be read from an SQLInput @@ -433,5 +433,43 @@ package java.sql; */ void writeSQLXML(SQLXML x) throws SQLException; + //--------------------------JDBC 4.2 ----------------------------- + + /** + * Writes to the stream the data contained in the given object. The + * object will be converted to the specified targetSqlType + * before being sent to the stream. + *

+ * When the {@code object} is {@code null}, this + * method writes an SQL {@code NULL} to the stream. + *

+ * If the object has a custom mapping (is of a class implementing the + * interface {@code SQLData}), + * the JDBC driver should call the method {@code SQLData.writeSQL} to + * write it to the SQL data stream. + * If, on the other hand, the object is of a class implementing + * {@code Ref}, {@code Blob}, {@code Clob}, {@code NClob}, + * {@code Struct}, {@code java.net.URL}, + * or {@code Array}, the driver should pass it to the database as a + * value of the corresponding SQL type. + *

+ * The default implementation will throw {@code SQLFeatureNotSupportedException} + * + * @param x the object containing the input parameter value + * @param targetSqlType the SQL type to be sent to the database. + * @exception SQLException if a database access error occurs or + * if the Java Object specified by x is an InputStream + * or Reader object and the value of the scale parameter is less + * than zero + * @exception SQLFeatureNotSupportedException if + * the JDBC driver does not support this data type + * @see JDBCType + * @see SQLType + * @since 1.8 + */ + default void writeObject(Object x, SQLType targetSqlType) throws SQLException { + throw new SQLFeatureNotSupportedException(); + } } + diff --git a/jdk/src/share/classes/java/sql/Types.java b/jdk/src/share/classes/java/sql/Types.java index d6fc80a3232..f12ff0dc1da 100644 --- a/jdk/src/share/classes/java/sql/Types.java +++ b/jdk/src/share/classes/java/sql/Types.java @@ -319,6 +319,24 @@ public class Types { */ public static final int REF_CURSOR = 2012; + /** + * The constant in the Java programming language, sometimes referred to + * as a type code, that identifies the generic SQL type + * {@code TIME WITH TIMEZONE}. + * + * @since 1.8 + */ + public static final int TIME_WITH_TIMEZONE = 2013; + + /** + * The constant in the Java programming language, sometimes referred to + * as a type code, that identifies the generic SQL type + * {@code TIMESTAMP WITH TIMEZONE}. + * + * @since 1.8 + */ + public static final int TIMESTAMP_WITH_TIMEZONE = 2014; + // Prevent instantiation private Types() {} } From 925fe9142b1581b531068d1760fe2f48c7684bc9 Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Wed, 6 Feb 2013 17:59:54 -0800 Subject: [PATCH 112/158] 8006995: java launcher fails to open executable JAR > 2GB Use O_LARGEFILE consistently when opening jar files Reviewed-by: alanb, sherman --- jdk/src/share/bin/parse_manifest.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/bin/parse_manifest.c b/jdk/src/share/bin/parse_manifest.c index ec3014931f2..61c5b883081 100644 --- a/jdk/src/share/bin/parse_manifest.c +++ b/jdk/src/share/bin/parse_manifest.c @@ -563,7 +563,7 @@ JLI_ParseManifest(char *jarfile, manifest_info *info) if ((fd = open(jarfile, O_RDONLY #ifdef O_LARGEFILE - | O_LARGEFILE /* large file mode on solaris */ + | O_LARGEFILE /* large file mode */ #endif #ifdef O_BINARY | O_BINARY /* use binary mode on windows */ @@ -618,6 +618,9 @@ JLI_JarUnpackFile(const char *jarfile, const char *filename, int *size) { void *data = NULL; fd = open(jarfile, O_RDONLY +#ifdef O_LARGEFILE + | O_LARGEFILE /* large file mode */ +#endif #ifdef O_BINARY | O_BINARY /* use binary mode on windows */ #endif @@ -661,6 +664,9 @@ JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data) int rc; if ((fd = open(jarfile, O_RDONLY +#ifdef O_LARGEFILE + | O_LARGEFILE /* large file mode */ +#endif #ifdef O_BINARY | O_BINARY /* use binary mode on windows */ #endif From 19982b2e807269a49a362b1f84516284dbab761e Mon Sep 17 00:00:00 2001 From: Katja Kantserova Date: Thu, 7 Feb 2013 11:22:04 +0100 Subject: [PATCH 113/158] 8007142: Add utility classes for writing better multiprocess tests in jtreg Reviewed-by: alanb, rbackman --- .../lib/testlibrary/OutputAnalyzerTest.java | 181 ++++++++++ .../testlibrary/jdk/testlibrary/JcmdBase.java | 79 +++++ .../jdk/testlibrary/JdkFinder.java | 82 +++++ .../jdk/testlibrary/OutputAnalyzer.java | 324 ++++++++++++++++++ .../jdk/testlibrary/OutputBuffer.java | 61 ++++ .../jdk/testlibrary/ProcessTools.java | 151 ++++++++ .../jdk/testlibrary/StreamPumper.java | 78 +++++ 7 files changed, 956 insertions(+) create mode 100644 jdk/test/lib/testlibrary/OutputAnalyzerTest.java create mode 100644 jdk/test/lib/testlibrary/jdk/testlibrary/JcmdBase.java create mode 100644 jdk/test/lib/testlibrary/jdk/testlibrary/JdkFinder.java create mode 100644 jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java create mode 100644 jdk/test/lib/testlibrary/jdk/testlibrary/OutputBuffer.java create mode 100644 jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java create mode 100644 jdk/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java diff --git a/jdk/test/lib/testlibrary/OutputAnalyzerTest.java b/jdk/test/lib/testlibrary/OutputAnalyzerTest.java new file mode 100644 index 00000000000..f8ad49e7a43 --- /dev/null +++ b/jdk/test/lib/testlibrary/OutputAnalyzerTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @summary Test the OutputAnalyzer utility class + * @library /testlibrary + */ + +import jdk.testlibrary.OutputAnalyzer; + +public class OutputAnalyzerTest { + + public static void main(String args[]) throws Exception { + + String stdout = "aaaaaa"; + String stderr = "bbbbbb"; + String nonExistingString = "cccc"; + + OutputAnalyzer output = new OutputAnalyzer(stdout, stderr); + + if (!stdout.equals(output.getStdout())) { + throw new Exception("getStdout() returned '" + output.getStdout() + + "', expected '" + stdout + "'"); + } + + if (!stderr.equals(output.getStderr())) { + throw new Exception("getStderr() returned '" + output.getStderr() + + "', expected '" + stderr + "'"); + } + + try { + output.shouldContain(stdout); + output.stdoutShouldContain(stdout); + output.shouldContain(stderr); + output.stderrShouldContain(stderr); + } catch (RuntimeException e) { + throw new Exception("shouldContain() failed", e); + } + + try { + output.shouldContain(nonExistingString); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldContain(stderr); + throw new Exception( + "stdoutShouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stderrShouldContain(stdout); + throw new Exception( + "stdoutShouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.shouldNotContain(nonExistingString); + output.stdoutShouldNotContain(nonExistingString); + output.stderrShouldNotContain(nonExistingString); + } catch (RuntimeException e) { + throw new Exception("shouldNotContain() failed", e); + } + + try { + output.shouldNotContain(stdout); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldNotContain(stdout); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stderrShouldNotContain(stderr); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + String stdoutPattern = "[a]"; + String stderrPattern = "[b]"; + String nonExistingPattern = "[c]"; + + // Should match + try { + output.shouldMatch(stdoutPattern); + output.stdoutShouldMatch(stdoutPattern); + output.shouldMatch(stderrPattern); + output.stderrShouldMatch(stderrPattern); + } catch (RuntimeException e) { + throw new Exception("shouldMatch() failed", e); + } + + try { + output.shouldMatch(nonExistingPattern); + throw new Exception("shouldMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldMatch(stderrPattern); + throw new Exception( + "stdoutShouldMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stderrShouldMatch(stdoutPattern); + throw new Exception( + "stderrShouldMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + // Should not match + try { + output.shouldNotMatch(nonExistingPattern); + output.stdoutShouldNotMatch(nonExistingPattern); + output.stderrShouldNotMatch(nonExistingPattern); + } catch (RuntimeException e) { + throw new Exception("shouldNotMatch() failed", e); + } + + try { + output.shouldNotMatch(stdoutPattern); + throw new Exception("shouldNotMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldNotMatch(stdoutPattern); + throw new Exception("shouldNotMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stderrShouldNotMatch(stderrPattern); + throw new Exception("shouldNotMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + } + +} diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/JcmdBase.java b/jdk/test/lib/testlibrary/jdk/testlibrary/JcmdBase.java new file mode 100644 index 00000000000..de5807f9bec --- /dev/null +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JcmdBase.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 jdk.testlibrary; + +import java.util.ArrayList; + +public class JcmdBase { + + private static ProcessBuilder processBuilder = new ProcessBuilder(); + + /** + * Attach jcmd to the current process + * + * @param commandArgs + * jcmd command line parameters, e.g. JFR.start + * @return jcmd output + * @throws Exception + */ + public final static OutputAnalyzer jcmd(String... commandArgs) + throws Exception { + ArrayList cmd = new ArrayList(); + String cmdString = ""; + + // jcmd from the jdk to be tested + String jcmdPath = JdkFinder.getTool("jcmd", false); + cmd.add(jcmdPath); + cmdString += jcmdPath; + + String pid = Integer.toString(ProcessTools.getProcessId()); + cmd.add(pid); + cmdString += " " + pid; + + for (int i = 0; i < commandArgs.length; i++) { + cmd.add(commandArgs[i]); + cmdString += " " + commandArgs[i]; + } + + // Log command line for debugging purpose + System.out.println("Command line:"); + System.out.println(cmdString); + + processBuilder.command(cmd); + OutputAnalyzer output = new OutputAnalyzer(processBuilder.start()); + + // Log output for debugging purpose + System.out.println("Command output:"); + System.out.println(output.getOutput()); + + if (output.getExitValue() != 0) { + throw new Exception(processBuilder.command() + + " resulted in exit value " + output.getExitValue() + + " , expected to get 0"); + } + + return output; + } + +} diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/JdkFinder.java b/jdk/test/lib/testlibrary/jdk/testlibrary/JdkFinder.java new file mode 100644 index 00000000000..fa038faccd4 --- /dev/null +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JdkFinder.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 jdk.testlibrary; + +import java.io.File; + +public final class JdkFinder { + + private JdkFinder() { + } + + private static String getExecutable(String executable, String property) { + String binPath = System.getProperty(property); + if (binPath == null) { + throw new RuntimeException( + "System property '" + property + "' not set"); + } + + binPath += File.separatorChar + "bin" + File.separatorChar + executable; + File toolFile = new File(binPath); + if (!toolFile.exists()) { + throw new RuntimeException(binPath + " does not exist"); + } + + return binPath; + } + + /** + * Returns the full path to a java launcher in jdk/bin based on system + * property. + * + * @param stableJdk + * see {@link #getTool(String, boolean)} + * @return Full path to a java launcher in jdk/bin. + */ + public static String getJavaLauncher(boolean stableJdk) { + return getTool("java", stableJdk); + } + + /** + * Returns the full path to an executable in jdk/bin based on system + * property. Depending on value of {@code stableJdk} the method will look for + * either 'compile.jdk' or 'test.jdk' system properties. + * 'test.jdk' is normally set by jtreg. When running test separately, + * set this property using '-Dtest.jdk=/path/to/jdk'. + * + * @param stableJdk + * If {@code true} the {@code tool} will be retrieved + * from the compile (stable) JDK. + * If {@code false} the {@code tool} will be retrieved + * from the test JDK. + * @return Full path to an executable in jdk/bin. + */ + public static String getTool(String tool, boolean stableJdk) { + if (stableJdk) { + return getExecutable(tool, "compile.jdk"); + } else { + return getExecutable(tool, "test.jdk"); + } + } +} diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java new file mode 100644 index 00000000000..ba02081398a --- /dev/null +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java @@ -0,0 +1,324 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 jdk.testlibrary; + +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public final class OutputAnalyzer { + + private final String stdout; + private final String stderr; + private final int exitValue; + + /** + * Create an OutputAnalyzer, a utility class for verifying output and exit + * value from a Process + * + * @param process + * Process to analyze + * @throws IOException + * If an I/O error occurs. + */ + public OutputAnalyzer(Process process) throws IOException { + OutputBuffer output = ProcessTools.getOutput(process); + exitValue = process.exitValue(); + this.stdout = output.getStdout(); + this.stderr = output.getStderr(); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param buf + * String buffer to analyze + */ + public OutputAnalyzer(String buf) { + this(buf, buf); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param stdout + * stdout buffer to analyze + * @param stderr + * stderr buffer to analyze + */ + public OutputAnalyzer(String stdout, String stderr) { + this.stdout = stdout; + this.stderr = stderr; + exitValue = -1; + } + + /** + * Verify that the stdout and stderr contents of output buffer contains the + * string + * + * @param expectedString + * String that buffer should contain + * @throws RuntimeException + * If the string was not found + */ + public void shouldContain(String expectedString) { + if (!stdout.contains(expectedString) + && !stderr.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + + "' missing from stdout/stderr: [" + stdout + stderr + + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer contains the string + * + * @param expectedString + * String that buffer should contain + * @throws RuntimeException + * If the string was not found + */ + public void stdoutShouldContain(String expectedString) { + if (!stdout.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + + "' missing from stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer contains the string + * + * @param expectedString + * String that buffer should contain + * @throws RuntimeException + * If the string was not found + */ + public void stderrShouldContain(String expectedString) { + if (!stderr.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + + "' missing from stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout and stderr contents of output buffer does not + * contain the string + * + * @param expectedString + * String that the buffer should not contain + * @throws RuntimeException + * If the string was found + */ + public void shouldNotContain(String notExpectedString) { + if (stdout.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + + "' found in stdout: [" + stdout + "]\n"); + } + if (stderr.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer does not contain the + * string + * + * @param expectedString + * String that the buffer should not contain + * @throws RuntimeException + * If the string was found + */ + public void stdoutShouldNotContain(String notExpectedString) { + if (stdout.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + + "' found in stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer does not contain the + * string + * + * @param expectedString + * String that the buffer should not contain + * @throws RuntimeException + * If the string was found + */ + public void stderrShouldNotContain(String notExpectedString) { + if (stderr.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout and stderr contents of output buffer matches + * the pattern + * + * @param pattern + * @throws RuntimeException If the pattern was not found + */ + public void shouldMatch(String pattern) { + Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); + Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (!stdoutMatcher.find() && !stderrMatcher.find()) { + throw new RuntimeException("'" + pattern + + "' missing from stdout/stderr: [" + stdout + stderr + + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer matches the + * pattern + * + * @param pattern + * @throws RuntimeException If the pattern was not found + */ + public void stdoutShouldMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); + if (!matcher.find()) { + throw new RuntimeException("'" + pattern + + "' missing from stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer matches the + * pattern + * + * @param pattern + * @throws RuntimeException If the pattern was not found + */ + public void stderrShouldMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (!matcher.find()) { + throw new RuntimeException("'" + pattern + + "' missing from stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout and stderr contents of output buffer does not + * match the pattern + * + * @param pattern + * @throws RuntimeException If the pattern was found + */ + public void shouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); + if (matcher.find()) { + throw new RuntimeException("'" + pattern + + "' found in stdout: [" + stdout + "]\n"); + } + matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (matcher.find()) { + throw new RuntimeException("'" + pattern + + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer does not match the + * pattern + * + * @param pattern + * @throws RuntimeException If the pattern was found + */ + public void stdoutShouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); + if (matcher.find()) { + throw new RuntimeException("'" + pattern + + "' found in stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer does not match the + * pattern + * + * @param pattern + * @throws RuntimeException If the pattern was found + */ + public void stderrShouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (matcher.find()) { + throw new RuntimeException("'" + pattern + + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** + * Verifiy the exit value of the process + * + * @param expectedExitValue + * Expected exit value from process + * @throws RuntimeException + * If the exit value from the process did not match the expected + * value + */ + public void shouldHaveExitValue(int expectedExitValue) { + if (getExitValue() != expectedExitValue) { + throw new RuntimeException("Exit value " + getExitValue() + + " , expected to get " + expectedExitValue); + } + } + + /** + * Get the contents of the output buffer (stdout and stderr) + * + * @return Content of the output buffer + */ + public String getOutput() { + return stdout + stderr; + } + + /** + * Get the contents of the stdout buffer + * + * @return Content of the stdout buffer + */ + public String getStdout() { + return stdout; + } + + /** + * Get the contents of the stderr buffer + * + * @return Content of the stderr buffer + */ + public String getStderr() { + return stderr; + } + + /** + * Get the process exit value + * + * @return Process exit value + */ + public int getExitValue() { + return exitValue; + } +} diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/OutputBuffer.java b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputBuffer.java new file mode 100644 index 00000000000..b5e021e8a9d --- /dev/null +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputBuffer.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 jdk.testlibrary; + +public class OutputBuffer { + private final String stdout; + private final String stderr; + + /** + * Create an OutputBuffer, a class for storing and managing stdout and + * stderr results separately + * + * @param stdout + * stdout result + * @param stderr + * stderr result + */ + public OutputBuffer(String stdout, String stderr) { + this.stdout = stdout; + this.stderr = stderr; + } + + /** + * Returns the stdout result + * + * @return stdout result + */ + public String getStdout() { + return stdout; + } + + /** + * Returns the stderr result + * + * @return stderr result + */ + public String getStderr() { + return stderr; + } +} diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java new file mode 100644 index 00000000000..16783aebc06 --- /dev/null +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 jdk.testlibrary; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; + +import sun.management.VMManagement; + +public final class ProcessTools { + + private ProcessTools() { + } + + /** + * Pumps stdout and stderr from running the process into a String. + * + * @param processHandler + * ProcessHandler to run. + * @return Output from process. + * @throws IOException + * If an I/O error occurs. + */ + public static OutputBuffer getOutput(ProcessBuilder processBuilder) + throws IOException { + return getOutput(processBuilder.start()); + } + + /** + * Pumps stdout and stderr the running process into a String. + * + * @param process + * Process to pump. + * @return Output from process. + * @throws IOException + * If an I/O error occurs. + */ + public static OutputBuffer getOutput(Process process) throws IOException { + ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream(); + ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream(); + StreamPumper outPumper = new StreamPumper(process.getInputStream(), + stdoutBuffer); + StreamPumper errPumper = new StreamPumper(process.getErrorStream(), + stderrBuffer); + Thread outPumperThread = new Thread(outPumper); + Thread errPumperThread = new Thread(errPumper); + + outPumperThread.setDaemon(true); + errPumperThread.setDaemon(true); + + outPumperThread.start(); + errPumperThread.start(); + + try { + process.waitFor(); + outPumperThread.join(); + errPumperThread.join(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return null; + } + + return new OutputBuffer(stdoutBuffer.toString(), + stderrBuffer.toString()); + } + + /** + * Get the process id of the current running Java process + * + * @return Process id + */ + public static int getProcessId() throws Exception { + + // Get the current process id using a reflection hack + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + Field jvm = runtime.getClass().getDeclaredField("jvm"); + + jvm.setAccessible(true); + VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime); + + Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId"); + + pid_method.setAccessible(true); + + int pid = (Integer) pid_method.invoke(mgmt); + + return pid; + } + + /** + * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris) + * + * @return String[] with platform specific arguments, empty if there are + * none + */ + public static String[] getPlatformSpecificVMArgs() { + String osName = System.getProperty("os.name"); + String dataModel = System.getProperty("sun.arch.data.model"); + + if (osName.equals("SunOS") && dataModel.equals("64")) { + return new String[] { "-d64" }; + } + + return new String[] {}; + } + + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested + * and with any platform specific arguments prepended + */ + public static ProcessBuilder createJavaProcessBuilder(String... command) + throws Exception { + String javapath = JdkFinder.getJavaLauncher(false); + + ArrayList args = new ArrayList<>(); + args.add(javapath); + Collections.addAll(args, getPlatformSpecificVMArgs()); + Collections.addAll(args, command); + + return new ProcessBuilder(args.toArray(new String[args.size()])); + + } + +} diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java b/jdk/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java new file mode 100644 index 00000000000..60adca4e3da --- /dev/null +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 jdk.testlibrary; + +import java.io.OutputStream; +import java.io.InputStream; +import java.io.IOException; + +public final class StreamPumper implements Runnable { + + private static final int BUF_SIZE = 256; + + private final OutputStream out; + private final InputStream in; + + /** + * Create a StreamPumper that reads from in and writes to out. + * + * @param in + * The stream to read from. + * @param out + * The stream to write to. + */ + public StreamPumper(InputStream in, OutputStream out) { + this.in = in; + this.out = out; + } + + /** + * Implements Thread.run(). Continuously read from {@code in} and write to + * {@code out} until {@code in} has reached end of stream. Abort on + * interruption. Abort on IOExceptions. + */ + @Override + public void run() { + int length; + InputStream localIn = in; + OutputStream localOut = out; + byte[] buffer = new byte[BUF_SIZE]; + + try { + while ((length = localIn.read(buffer)) > 0 && !Thread.interrupted()) { + localOut.write(buffer, 0, length); + } + } catch (IOException e) { + // Just abort if something like this happens. + e.printStackTrace(); + } finally { + try { + localOut.flush(); + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} From ea5819f8d36ba632a81e7654181701f3d2053d19 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Fri, 8 Feb 2013 09:35:14 -0800 Subject: [PATCH 114/158] 8007038: ArrayIndexOutOfBoundsException on calling localizedDateTime().print() with JapaneseChrono Reviewed-by: okutsu --- .../provider/CalendarNameProviderImpl.java | 3 + jdk/test/java/util/Calendar/Bug8007038.java | 108 ++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 jdk/test/java/util/Calendar/Bug8007038.java diff --git a/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java b/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java index 6aa2893e173..79cbe0a4d60 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java +++ b/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java @@ -58,6 +58,9 @@ public class CalendarNameProviderImpl extends CalendarNameProvider implements Av if (field == DAY_OF_WEEK || field == YEAR) { --value; } + if (value < 0 || value >= strings.length) { + return null; + } name = strings[value]; // If name is empty in standalone, try its `format' style. if (name.length() == 0 diff --git a/jdk/test/java/util/Calendar/Bug8007038.java b/jdk/test/java/util/Calendar/Bug8007038.java new file mode 100644 index 00000000000..e4f1a66082b --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug8007038.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * @test + * @bug 8007038 + * @summary Verify ArrayIndexOutOfBoundsException is not thrown on + * on calling localizedDateTime().print() with JapaneseChrono + * @compile -XDignore.symbol.file Bug8007038.java + * @run main Bug8007038 + */ + +import java.util.*; +import static java.util.Calendar.*; +import sun.util.locale.provider.CalendarDataUtility; + +public class Bug8007038 { + private final static String[] calTypes = { + "gregory", + "buddhist", + "japanese", + "roc", + "islamic", + }; + private final static int[][] eraMinMax = { + {GregorianCalendar.BC, GregorianCalendar.AD}, + {0, 1}, + {0, 4}, + {0, 1}, + {0, 1}, + {0, 1}, + }; + private final static Locale[] testLocs = { + Locale.ROOT, + Locale.forLanguageTag("ja-JP-u-ca-japanese"), + Locale.forLanguageTag("th-TH"), + Locale.forLanguageTag("th-TH-u-ca-buddhist"), + Locale.forLanguageTag("zh-TW-u-ca-roc"), + Locale.forLanguageTag("ar-EG-u-ca-islamic"), + Locale.forLanguageTag("xx-YY-u-ca-bogus"), + }; + + public static void main(String[] args) { + for (int calIdx = 0; calIdx < calTypes.length; calIdx++) { + for (int locIdx = 0; locIdx < testLocs.length; locIdx++) { + // era + for (int fieldIdx = eraMinMax[calIdx][0]; fieldIdx <= eraMinMax[calIdx][1]; fieldIdx++) { + checkValueRange(calTypes[calIdx], ERA, fieldIdx, LONG, testLocs[locIdx], true); + } + checkValueRange(calTypes[calIdx], ERA, eraMinMax[calIdx][0]-1, LONG, + testLocs[locIdx], false); + checkValueRange(calTypes[calIdx], ERA, eraMinMax[calIdx][1]+1, + LONG, testLocs[locIdx], false); + + // month + for (int fieldIdx = JANUARY; fieldIdx <= UNDECIMBER ; fieldIdx++) { + checkValueRange(calTypes[calIdx], MONTH, fieldIdx, LONG, testLocs[locIdx], true); + } + checkValueRange(calTypes[calIdx], MONTH, JANUARY-1, LONG, testLocs[locIdx], false); + checkValueRange(calTypes[calIdx], MONTH, UNDECIMBER+1, LONG, testLocs[locIdx], false); + + // day-of-week + for (int fieldIdx = SUNDAY; fieldIdx <= SATURDAY; fieldIdx++) { + checkValueRange(calTypes[calIdx], DAY_OF_WEEK, fieldIdx, LONG, testLocs[locIdx], true); + } + checkValueRange(calTypes[calIdx], DAY_OF_WEEK, SUNDAY-1, LONG, testLocs[locIdx], false); + checkValueRange(calTypes[calIdx], DAY_OF_WEEK, SATURDAY+1, LONG, testLocs[locIdx], false); + + // am/pm + for (int fieldIdx = AM; fieldIdx <= PM; fieldIdx++) { + checkValueRange(calTypes[calIdx], AM_PM, fieldIdx, LONG, testLocs[locIdx], true); + } + checkValueRange(calTypes[calIdx], AM_PM, AM-1, LONG, testLocs[locIdx], false); + checkValueRange(calTypes[calIdx], AM_PM, PM+1, LONG, testLocs[locIdx], false); + } + } + } + + private static void checkValueRange(String calType, int field, int value, int style, Locale l, boolean isNonNull) { + String ret = CalendarDataUtility.retrieveFieldValueName(calType, field, value, style, l); + System.out.print("retrieveFieldValueName("+calType+", "+field+", "+value+", "+style+", "+l+")"); + if ((ret != null) == isNonNull) { + System.out.println(" returned "+ret); + } else { + throw new RuntimeException("The call returned "+ret); + } + } +} From 826105d54895223e1a3dc976a727b7062aaf5a24 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 8 Feb 2013 16:00:23 -0800 Subject: [PATCH 115/158] 8005623: Retrofit FunctionalInterface annotations to core platform interfaces Reviewed-by: mduigou, chegar, alanb --- jdk/src/share/classes/java/io/Closeable.java | 4 ++-- jdk/src/share/classes/java/io/FileFilter.java | 4 ++-- jdk/src/share/classes/java/io/FilenameFilter.java | 6 +++--- jdk/src/share/classes/java/io/Flushable.java | 4 ++-- jdk/src/share/classes/java/lang/AutoCloseable.java | 3 ++- jdk/src/share/classes/java/lang/Comparable.java | 4 ++-- jdk/src/share/classes/java/lang/Iterable.java | 3 ++- jdk/src/share/classes/java/lang/Readable.java | 5 ++--- jdk/src/share/classes/java/lang/Runnable.java | 6 +++--- jdk/src/share/classes/java/lang/Thread.java | 3 ++- jdk/src/share/classes/java/nio/file/DirectoryStream.java | 6 +++--- jdk/src/share/classes/java/nio/file/PathMatcher.java | 4 ++-- jdk/src/share/classes/java/util/Comparator.java | 4 ++-- .../share/classes/java/util/function/BinaryOperator.java | 3 ++- jdk/src/share/classes/java/util/function/Block.java | 3 ++- .../classes/java/util/function/DoubleBinaryOperator.java | 3 ++- jdk/src/share/classes/java/util/function/DoubleBlock.java | 3 ++- .../share/classes/java/util/function/DoubleFunction.java | 3 ++- .../share/classes/java/util/function/DoubleSupplier.java | 3 ++- .../classes/java/util/function/DoubleUnaryOperator.java | 3 ++- jdk/src/share/classes/java/util/function/Function.java | 3 ++- .../share/classes/java/util/function/IntBinaryOperator.java | 3 ++- jdk/src/share/classes/java/util/function/IntBlock.java | 3 ++- jdk/src/share/classes/java/util/function/IntFunction.java | 3 ++- jdk/src/share/classes/java/util/function/IntSupplier.java | 3 ++- .../share/classes/java/util/function/IntUnaryOperator.java | 3 ++- .../classes/java/util/function/LongBinaryOperator.java | 3 ++- jdk/src/share/classes/java/util/function/LongBlock.java | 3 ++- jdk/src/share/classes/java/util/function/LongFunction.java | 3 ++- jdk/src/share/classes/java/util/function/LongSupplier.java | 3 ++- .../share/classes/java/util/function/LongUnaryOperator.java | 3 ++- jdk/src/share/classes/java/util/function/Predicate.java | 3 ++- jdk/src/share/classes/java/util/function/Supplier.java | 3 ++- jdk/src/share/classes/java/util/function/UnaryOperator.java | 3 ++- jdk/src/share/classes/java/util/logging/Filter.java | 5 ++--- .../classes/java/util/prefs/PreferenceChangeListener.java | 3 ++- 36 files changed, 75 insertions(+), 52 deletions(-) diff --git a/jdk/src/share/classes/java/io/Closeable.java b/jdk/src/share/classes/java/io/Closeable.java index 26c7ea00e36..530cde86171 100644 --- a/jdk/src/share/classes/java/io/Closeable.java +++ b/jdk/src/share/classes/java/io/Closeable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -34,7 +34,7 @@ import java.io.IOException; * * @since 1.5 */ - +@FunctionalInterface public interface Closeable extends AutoCloseable { /** diff --git a/jdk/src/share/classes/java/io/FileFilter.java b/jdk/src/share/classes/java/io/FileFilter.java index 15f00d630d3..f973d77cea7 100644 --- a/jdk/src/share/classes/java/io/FileFilter.java +++ b/jdk/src/share/classes/java/io/FileFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -35,6 +35,7 @@ package java.io; * * @since 1.2 */ +@FunctionalInterface public interface FileFilter { /** @@ -46,5 +47,4 @@ public interface FileFilter { * should be included */ boolean accept(File pathname); - } diff --git a/jdk/src/share/classes/java/io/FilenameFilter.java b/jdk/src/share/classes/java/io/FilenameFilter.java index 915adf54097..71b88af4646 100644 --- a/jdk/src/share/classes/java/io/FilenameFilter.java +++ b/jdk/src/share/classes/java/io/FilenameFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 1998, 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 @@ -39,8 +39,8 @@ package java.io; * @see java.io.File#list(java.io.FilenameFilter) * @since JDK1.0 */ -public -interface FilenameFilter { +@FunctionalInterface +public interface FilenameFilter { /** * Tests if a specified file should be included in a file list. * diff --git a/jdk/src/share/classes/java/io/Flushable.java b/jdk/src/share/classes/java/io/Flushable.java index e598ea88426..8912316d4d2 100644 --- a/jdk/src/share/classes/java/io/Flushable.java +++ b/jdk/src/share/classes/java/io/Flushable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -34,7 +34,7 @@ import java.io.IOException; * * @since 1.5 */ - +@FunctionalInterface public interface Flushable { /** diff --git a/jdk/src/share/classes/java/lang/AutoCloseable.java b/jdk/src/share/classes/java/lang/AutoCloseable.java index d928a9d0f1c..ce0fffe5939 100644 --- a/jdk/src/share/classes/java/lang/AutoCloseable.java +++ b/jdk/src/share/classes/java/lang/AutoCloseable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -31,6 +31,7 @@ package java.lang; * @author Josh Bloch * @since 1.7 */ +@FunctionalInterface public interface AutoCloseable { /** * Closes this resource, relinquishing any underlying resources. diff --git a/jdk/src/share/classes/java/lang/Comparable.java b/jdk/src/share/classes/java/lang/Comparable.java index d8531972bb3..123e10aa4da 100644 --- a/jdk/src/share/classes/java/lang/Comparable.java +++ b/jdk/src/share/classes/java/lang/Comparable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, 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 @@ -93,7 +93,7 @@ import java.util.*; * @see java.util.Comparator * @since 1.2 */ - +@FunctionalInterface public interface Comparable { /** * Compares this object with the specified object for order. Returns a diff --git a/jdk/src/share/classes/java/lang/Iterable.java b/jdk/src/share/classes/java/lang/Iterable.java index 24efc8644af..a47319243f0 100644 --- a/jdk/src/share/classes/java/lang/Iterable.java +++ b/jdk/src/share/classes/java/lang/Iterable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -35,6 +35,7 @@ import java.util.Iterator; * * @since 1.5 */ +@FunctionalInterface public interface Iterable { /** diff --git a/jdk/src/share/classes/java/lang/Readable.java b/jdk/src/share/classes/java/lang/Readable.java index 7e4e924390e..e3d08d34b62 100644 --- a/jdk/src/share/classes/java/lang/Readable.java +++ b/jdk/src/share/classes/java/lang/Readable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -34,7 +34,7 @@ import java.io.IOException; * * @since 1.5 */ - +@FunctionalInterface public interface Readable { /** @@ -51,5 +51,4 @@ public interface Readable { * @throws java.nio.ReadOnlyBufferException if cb is a read only buffer */ public int read(java.nio.CharBuffer cb) throws IOException; - } diff --git a/jdk/src/share/classes/java/lang/Runnable.java b/jdk/src/share/classes/java/lang/Runnable.java index 6aeb8928c98..b9f1df7a0cc 100644 --- a/jdk/src/share/classes/java/lang/Runnable.java +++ b/jdk/src/share/classes/java/lang/Runnable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2005, 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 @@ -52,8 +52,8 @@ package java.lang; * @see java.util.concurrent.Callable * @since JDK1.0 */ -public -interface Runnable { +@FunctionalInterface +public interface Runnable { /** * When an object implementing interface Runnable is used * to create a thread, starting the thread causes the object's diff --git a/jdk/src/share/classes/java/lang/Thread.java b/jdk/src/share/classes/java/lang/Thread.java index 64987bdc2fa..8aab573ded7 100644 --- a/jdk/src/share/classes/java/lang/Thread.java +++ b/jdk/src/share/classes/java/lang/Thread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, 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 @@ -1851,6 +1851,7 @@ class Thread implements Runnable { * @see ThreadGroup#uncaughtException * @since 1.5 */ + @FunctionalInterface public interface UncaughtExceptionHandler { /** * Method invoked when the given thread terminates due to the diff --git a/jdk/src/share/classes/java/nio/file/DirectoryStream.java b/jdk/src/share/classes/java/nio/file/DirectoryStream.java index dd13c9a3f6b..48da97e7b4d 100644 --- a/jdk/src/share/classes/java/nio/file/DirectoryStream.java +++ b/jdk/src/share/classes/java/nio/file/DirectoryStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -117,8 +117,7 @@ import java.io.IOException; */ public interface DirectoryStream - extends Closeable, Iterable -{ + extends Closeable, Iterable { /** * An interface that is implemented by objects that decide if a directory * entry should be accepted or filtered. A {@code Filter} is passed as the @@ -130,6 +129,7 @@ public interface DirectoryStream * * @since 1.7 */ + @FunctionalInterface public static interface Filter { /** * Decides if the given directory entry should be accepted or filtered. diff --git a/jdk/src/share/classes/java/nio/file/PathMatcher.java b/jdk/src/share/classes/java/nio/file/PathMatcher.java index ab4b7ce0f00..24e61493c8b 100644 --- a/jdk/src/share/classes/java/nio/file/PathMatcher.java +++ b/jdk/src/share/classes/java/nio/file/PathMatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -34,7 +34,7 @@ package java.nio.file; * @see FileSystem#getPathMatcher * @see Files#newDirectoryStream(Path,String) */ - +@FunctionalInterface public interface PathMatcher { /** * Tells if given path matches this matcher's pattern. diff --git a/jdk/src/share/classes/java/util/Comparator.java b/jdk/src/share/classes/java/util/Comparator.java index 453e9b71909..35ead373b82 100644 --- a/jdk/src/share/classes/java/util/Comparator.java +++ b/jdk/src/share/classes/java/util/Comparator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, 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 @@ -98,7 +98,7 @@ package java.util; * @see java.io.Serializable * @since 1.2 */ - +@FunctionalInterface public interface Comparator { /** * Compares its two arguments for order. Returns a negative integer, diff --git a/jdk/src/share/classes/java/util/function/BinaryOperator.java b/jdk/src/share/classes/java/util/function/BinaryOperator.java index 37653b63b37..2e9050e59f2 100644 --- a/jdk/src/share/classes/java/util/function/BinaryOperator.java +++ b/jdk/src/share/classes/java/util/function/BinaryOperator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -32,6 +32,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface BinaryOperator { /** diff --git a/jdk/src/share/classes/java/util/function/Block.java b/jdk/src/share/classes/java/util/function/Block.java index e468396be22..c41e9a45a5a 100644 --- a/jdk/src/share/classes/java/util/function/Block.java +++ b/jdk/src/share/classes/java/util/function/Block.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -32,6 +32,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface Block { /** diff --git a/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java b/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java index 07ff741be96..f63403bb37e 100644 --- a/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java +++ b/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -29,6 +29,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface DoubleBinaryOperator /* extends BinaryOperator */ { // // @Override diff --git a/jdk/src/share/classes/java/util/function/DoubleBlock.java b/jdk/src/share/classes/java/util/function/DoubleBlock.java index d5abd87b880..ae000841ae1 100644 --- a/jdk/src/share/classes/java/util/function/DoubleBlock.java +++ b/jdk/src/share/classes/java/util/function/DoubleBlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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,6 +33,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface DoubleBlock { /** diff --git a/jdk/src/share/classes/java/util/function/DoubleFunction.java b/jdk/src/share/classes/java/util/function/DoubleFunction.java index 06c405e6d8c..d9c522c8e94 100644 --- a/jdk/src/share/classes/java/util/function/DoubleFunction.java +++ b/jdk/src/share/classes/java/util/function/DoubleFunction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -32,6 +32,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface DoubleFunction { /** diff --git a/jdk/src/share/classes/java/util/function/DoubleSupplier.java b/jdk/src/share/classes/java/util/function/DoubleSupplier.java index 7e718a3c141..19d75353045 100644 --- a/jdk/src/share/classes/java/util/function/DoubleSupplier.java +++ b/jdk/src/share/classes/java/util/function/DoubleSupplier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -32,6 +32,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface DoubleSupplier { /** diff --git a/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java b/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java index b9ac7f6fda7..3843f8bc7ee 100644 --- a/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java +++ b/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -30,6 +30,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface DoubleUnaryOperator { /** diff --git a/jdk/src/share/classes/java/util/function/Function.java b/jdk/src/share/classes/java/util/function/Function.java index ce8ab1ed2e8..82bae01701d 100644 --- a/jdk/src/share/classes/java/util/function/Function.java +++ b/jdk/src/share/classes/java/util/function/Function.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -35,6 +35,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface Function { /** diff --git a/jdk/src/share/classes/java/util/function/IntBinaryOperator.java b/jdk/src/share/classes/java/util/function/IntBinaryOperator.java index 312fb2db046..e25c2ba101f 100644 --- a/jdk/src/share/classes/java/util/function/IntBinaryOperator.java +++ b/jdk/src/share/classes/java/util/function/IntBinaryOperator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -29,6 +29,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface IntBinaryOperator { /** diff --git a/jdk/src/share/classes/java/util/function/IntBlock.java b/jdk/src/share/classes/java/util/function/IntBlock.java index e0163163e1e..33cdbe79f51 100644 --- a/jdk/src/share/classes/java/util/function/IntBlock.java +++ b/jdk/src/share/classes/java/util/function/IntBlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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,6 +33,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface IntBlock { /** diff --git a/jdk/src/share/classes/java/util/function/IntFunction.java b/jdk/src/share/classes/java/util/function/IntFunction.java index af8d4486254..6e1418533fe 100644 --- a/jdk/src/share/classes/java/util/function/IntFunction.java +++ b/jdk/src/share/classes/java/util/function/IntFunction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -32,6 +32,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface IntFunction { /** diff --git a/jdk/src/share/classes/java/util/function/IntSupplier.java b/jdk/src/share/classes/java/util/function/IntSupplier.java index e930e0bc407..c73fc84e3be 100644 --- a/jdk/src/share/classes/java/util/function/IntSupplier.java +++ b/jdk/src/share/classes/java/util/function/IntSupplier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -32,6 +32,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface IntSupplier { /** diff --git a/jdk/src/share/classes/java/util/function/IntUnaryOperator.java b/jdk/src/share/classes/java/util/function/IntUnaryOperator.java index 315619dcab1..2c429951c28 100644 --- a/jdk/src/share/classes/java/util/function/IntUnaryOperator.java +++ b/jdk/src/share/classes/java/util/function/IntUnaryOperator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -29,6 +29,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface IntUnaryOperator { /** diff --git a/jdk/src/share/classes/java/util/function/LongBinaryOperator.java b/jdk/src/share/classes/java/util/function/LongBinaryOperator.java index 07056784e34..f767c92a355 100644 --- a/jdk/src/share/classes/java/util/function/LongBinaryOperator.java +++ b/jdk/src/share/classes/java/util/function/LongBinaryOperator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -29,6 +29,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface LongBinaryOperator { /** diff --git a/jdk/src/share/classes/java/util/function/LongBlock.java b/jdk/src/share/classes/java/util/function/LongBlock.java index d9af3660f8b..71606ecf9ed 100644 --- a/jdk/src/share/classes/java/util/function/LongBlock.java +++ b/jdk/src/share/classes/java/util/function/LongBlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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,6 +33,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface LongBlock { /** diff --git a/jdk/src/share/classes/java/util/function/LongFunction.java b/jdk/src/share/classes/java/util/function/LongFunction.java index 449543d0764..61c4fbf6475 100644 --- a/jdk/src/share/classes/java/util/function/LongFunction.java +++ b/jdk/src/share/classes/java/util/function/LongFunction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -32,6 +32,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface LongFunction { /** diff --git a/jdk/src/share/classes/java/util/function/LongSupplier.java b/jdk/src/share/classes/java/util/function/LongSupplier.java index fb76068c970..f56ad7df282 100644 --- a/jdk/src/share/classes/java/util/function/LongSupplier.java +++ b/jdk/src/share/classes/java/util/function/LongSupplier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -32,6 +32,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface LongSupplier { /** diff --git a/jdk/src/share/classes/java/util/function/LongUnaryOperator.java b/jdk/src/share/classes/java/util/function/LongUnaryOperator.java index ea2c1fc7338..f27ddf5a81a 100644 --- a/jdk/src/share/classes/java/util/function/LongUnaryOperator.java +++ b/jdk/src/share/classes/java/util/function/LongUnaryOperator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -29,6 +29,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface LongUnaryOperator { /** diff --git a/jdk/src/share/classes/java/util/function/Predicate.java b/jdk/src/share/classes/java/util/function/Predicate.java index f4e6196fbce..9b440787485 100644 --- a/jdk/src/share/classes/java/util/function/Predicate.java +++ b/jdk/src/share/classes/java/util/function/Predicate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -31,6 +31,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface Predicate { /** diff --git a/jdk/src/share/classes/java/util/function/Supplier.java b/jdk/src/share/classes/java/util/function/Supplier.java index 404af55af99..60bc801eb91 100644 --- a/jdk/src/share/classes/java/util/function/Supplier.java +++ b/jdk/src/share/classes/java/util/function/Supplier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -32,6 +32,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface Supplier { /** diff --git a/jdk/src/share/classes/java/util/function/UnaryOperator.java b/jdk/src/share/classes/java/util/function/UnaryOperator.java index 9fa99c8d96a..a8aaa0dcd6b 100644 --- a/jdk/src/share/classes/java/util/function/UnaryOperator.java +++ b/jdk/src/share/classes/java/util/function/UnaryOperator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -32,6 +32,7 @@ package java.util.function; * * @since 1.8 */ +@FunctionalInterface public interface UnaryOperator { /** diff --git a/jdk/src/share/classes/java/util/logging/Filter.java b/jdk/src/share/classes/java/util/logging/Filter.java index 73bbad11448..43837073114 100644 --- a/jdk/src/share/classes/java/util/logging/Filter.java +++ b/jdk/src/share/classes/java/util/logging/Filter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -37,7 +37,7 @@ package java.util.logging; * * @since 1.4 */ - +@FunctionalInterface public interface Filter { /** @@ -46,5 +46,4 @@ public interface Filter { * @return true if the log record should be published. */ public boolean isLoggable(LogRecord record); - } diff --git a/jdk/src/share/classes/java/util/prefs/PreferenceChangeListener.java b/jdk/src/share/classes/java/util/prefs/PreferenceChangeListener.java index 2c0c51e867a..0fb96c598cb 100644 --- a/jdk/src/share/classes/java/util/prefs/PreferenceChangeListener.java +++ b/jdk/src/share/classes/java/util/prefs/PreferenceChangeListener.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -34,6 +34,7 @@ package java.util.prefs; * @see NodeChangeListener * @since 1.4 */ +@FunctionalInterface public interface PreferenceChangeListener extends java.util.EventListener { /** * This method gets called when a preference is added, removed or when From 724f325f44f63a2b7383655a9d804d166e3e26a7 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Sat, 9 Feb 2013 08:35:57 +0000 Subject: [PATCH 116/158] 8005697: Add StampedLock Reviewed-by: chegar, alanb, dice, martin --- jdk/make/java/java/FILES_java.gmk | 1 + .../util/concurrent/locks/LockSupport.java | 77 +- .../util/concurrent/locks/StampedLock.java | 1377 +++++++++++++++++ .../concurrent/locks/StampedLock/Basic.java | 609 ++++++++ 4 files changed, 2040 insertions(+), 24 deletions(-) create mode 100644 jdk/src/share/classes/java/util/concurrent/locks/StampedLock.java create mode 100644 jdk/test/java/util/concurrent/locks/StampedLock/Basic.java diff --git a/jdk/make/java/java/FILES_java.gmk b/jdk/make/java/java/FILES_java.gmk index bf0f9833670..bcf92eb44d0 100644 --- a/jdk/make/java/java/FILES_java.gmk +++ b/jdk/make/java/java/FILES_java.gmk @@ -389,6 +389,7 @@ JAVA_JAVA_java = \ java/util/concurrent/locks/ReadWriteLock.java \ java/util/concurrent/locks/ReentrantLock.java \ java/util/concurrent/locks/ReentrantReadWriteLock.java \ + java/util/concurrent/locks/StampedLock.java \ java/util/regex/Pattern.java \ java/util/regex/Matcher.java \ java/util/regex/MatchResult.java \ diff --git a/jdk/src/share/classes/java/util/concurrent/locks/LockSupport.java b/jdk/src/share/classes/java/util/concurrent/locks/LockSupport.java index 08bd8878a81..20abfacc3c8 100644 --- a/jdk/src/share/classes/java/util/concurrent/locks/LockSupport.java +++ b/jdk/src/share/classes/java/util/concurrent/locks/LockSupport.java @@ -101,14 +101,14 @@ import sun.misc.Unsafe; * // Block while not first in queue or cannot acquire lock * while (waiters.peek() != current || * !locked.compareAndSet(false, true)) { - * LockSupport.park(this); - * if (Thread.interrupted()) // ignore interrupts while waiting - * wasInterrupted = true; + * LockSupport.park(this); + * if (Thread.interrupted()) // ignore interrupts while waiting + * wasInterrupted = true; * } * * waiters.remove(); * if (wasInterrupted) // reassert interrupt status on exit - * current.interrupt(); + * current.interrupt(); * } * * public void unlock() { @@ -120,20 +120,9 @@ import sun.misc.Unsafe; public class LockSupport { private LockSupport() {} // Cannot be instantiated. - // Hotspot implementation via intrinsics API - private static final Unsafe unsafe = Unsafe.getUnsafe(); - private static final long parkBlockerOffset; - - static { - try { - parkBlockerOffset = unsafe.objectFieldOffset - (java.lang.Thread.class.getDeclaredField("parkBlocker")); - } catch (Exception ex) { throw new Error(ex); } - } - private static void setBlocker(Thread t, Object arg) { // Even though volatile, hotspot doesn't need a write barrier here. - unsafe.putObject(t, parkBlockerOffset, arg); + UNSAFE.putObject(t, parkBlockerOffset, arg); } /** @@ -149,7 +138,7 @@ public class LockSupport { */ public static void unpark(Thread thread) { if (thread != null) - unsafe.unpark(thread); + UNSAFE.unpark(thread); } /** @@ -183,7 +172,7 @@ public class LockSupport { public static void park(Object blocker) { Thread t = Thread.currentThread(); setBlocker(t, blocker); - unsafe.park(false, 0L); + UNSAFE.park(false, 0L); setBlocker(t, null); } @@ -223,7 +212,7 @@ public class LockSupport { if (nanos > 0) { Thread t = Thread.currentThread(); setBlocker(t, blocker); - unsafe.park(false, nanos); + UNSAFE.park(false, nanos); setBlocker(t, null); } } @@ -264,7 +253,7 @@ public class LockSupport { public static void parkUntil(Object blocker, long deadline) { Thread t = Thread.currentThread(); setBlocker(t, blocker); - unsafe.park(true, deadline); + UNSAFE.park(true, deadline); setBlocker(t, null); } @@ -283,7 +272,7 @@ public class LockSupport { public static Object getBlocker(Thread t) { if (t == null) throw new NullPointerException(); - return unsafe.getObjectVolatile(t, parkBlockerOffset); + return UNSAFE.getObjectVolatile(t, parkBlockerOffset); } /** @@ -312,7 +301,7 @@ public class LockSupport { * for example, the interrupt status of the thread upon return. */ public static void park() { - unsafe.park(false, 0L); + UNSAFE.park(false, 0L); } /** @@ -346,7 +335,7 @@ public class LockSupport { */ public static void parkNanos(long nanos) { if (nanos > 0) - unsafe.park(false, nanos); + UNSAFE.park(false, nanos); } /** @@ -380,6 +369,46 @@ public class LockSupport { * to wait until */ public static void parkUntil(long deadline) { - unsafe.park(true, deadline); + UNSAFE.park(true, deadline); } + + /** + * Returns the pseudo-randomly initialized or updated secondary seed. + * Copied from ThreadLocalRandom due to package access restrictions. + */ + static final int nextSecondarySeed() { + int r; + Thread t = Thread.currentThread(); + if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) { + r ^= r << 13; // xorshift + r ^= r >>> 17; + r ^= r << 5; + } + else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0) + r = 1; // avoid zero + UNSAFE.putInt(t, SECONDARY, r); + return r; + } + + // Hotspot implementation via intrinsics API + private static final sun.misc.Unsafe UNSAFE; + private static final long parkBlockerOffset; + private static final long SEED; + private static final long PROBE; + private static final long SECONDARY; + static { + try { + UNSAFE = sun.misc.Unsafe.getUnsafe(); + Class tk = Thread.class; + parkBlockerOffset = UNSAFE.objectFieldOffset + (tk.getDeclaredField("parkBlocker")); + SEED = UNSAFE.objectFieldOffset + (tk.getDeclaredField("threadLocalRandomSeed")); + PROBE = UNSAFE.objectFieldOffset + (tk.getDeclaredField("threadLocalRandomProbe")); + SECONDARY = UNSAFE.objectFieldOffset + (tk.getDeclaredField("threadLocalRandomSecondarySeed")); + } catch (Exception ex) { throw new Error(ex); } + } + } diff --git a/jdk/src/share/classes/java/util/concurrent/locks/StampedLock.java b/jdk/src/share/classes/java/util/concurrent/locks/StampedLock.java new file mode 100644 index 00000000000..0ca43f630f7 --- /dev/null +++ b/jdk/src/share/classes/java/util/concurrent/locks/StampedLock.java @@ -0,0 +1,1377 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +package java.util.concurrent.locks; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.LockSupport; + +/** + * A capability-based lock with three modes for controlling read/write + * access. The state of a StampedLock consists of a version and mode. + * Lock acquisition methods return a stamp that represents and + * controls access with respect to a lock state; "try" versions of + * these methods may instead return the special value zero to + * represent failure to acquire access. Lock release and conversion + * methods require stamps as arguments, and fail if they do not match + * the state of the lock. The three modes are: + * + *

    + * + *
  • Writing. Method {@link #writeLock} possibly blocks + * waiting for exclusive access, returning a stamp that can be used + * in method {@link #unlockWrite} to release the lock. Untimed and + * timed versions of {@code tryWriteLock} are also provided. When + * the lock is held in write mode, no read locks may be obtained, + * and all optimistic read validations will fail.
  • + * + *
  • Reading. Method {@link #readLock} possibly blocks + * waiting for non-exclusive access, returning a stamp that can be + * used in method {@link #unlockRead} to release the lock. Untimed + * and timed versions of {@code tryReadLock} are also provided.
  • + * + *
  • Optimistic Reading. Method {@link #tryOptimisticRead} + * returns a non-zero stamp only if the lock is not currently held + * in write mode. Method {@link #validate} returns true if the lock + * has not been acquired in write mode since obtaining a given + * stamp. This mode can be thought of as an extremely weak version + * of a read-lock, that can be broken by a writer at any time. The + * use of optimistic mode for short read-only code segments often + * reduces contention and improves throughput. However, its use is + * inherently fragile. Optimistic read sections should only read + * fields and hold them in local variables for later use after + * validation. Fields read while in optimistic mode may be wildly + * inconsistent, so usage applies only when you are familiar enough + * with data representations to check consistency and/or repeatedly + * invoke method {@code validate()}. For example, such steps are + * typically required when first reading an object or array + * reference, and then accessing one of its fields, elements or + * methods.
  • + * + *
+ * + *

This class also supports methods that conditionally provide + * conversions across the three modes. For example, method {@link + * #tryConvertToWriteLock} attempts to "upgrade" a mode, returning + * a valid write stamp if (1) already in writing mode (2) in reading + * mode and there are no other readers or (3) in optimistic mode and + * the lock is available. The forms of these methods are designed to + * help reduce some of the code bloat that otherwise occurs in + * retry-based designs. + * + *

StampedLocks are designed for use as internal utilities in the + * development of thread-safe components. Their use relies on + * knowledge of the internal properties of the data, objects, and + * methods they are protecting. They are not reentrant, so locked + * bodies should not call other unknown methods that may try to + * re-acquire locks (although you may pass a stamp to other methods + * that can use or convert it). The use of read lock modes relies on + * the associated code sections being side-effect-free. Unvalidated + * optimistic read sections cannot call methods that are not known to + * tolerate potential inconsistencies. Stamps use finite + * representations, and are not cryptographically secure (i.e., a + * valid stamp may be guessable). Stamp values may recycle after (no + * sooner than) one year of continuous operation. A stamp held without + * use or validation for longer than this period may fail to validate + * correctly. StampedLocks are serializable, but always deserialize + * into initial unlocked state, so they are not useful for remote + * locking. + * + *

The scheduling policy of StampedLock does not consistently + * prefer readers over writers or vice versa. All "try" methods are + * best-effort and do not necessarily conform to any scheduling or + * fairness policy. A zero return from any "try" method for acquiring + * or converting locks does not carry any information about the state + * of the lock; a subsequent invocation may succeed. + * + *

Because it supports coordinated usage across multiple lock + * modes, this class does not directly implement the {@link Lock} or + * {@link ReadWriteLock} interfaces. However, a StampedLock may be + * viewed {@link #asReadLock()}, {@link #asWriteLock()}, or {@link + * #asReadWriteLock()} in applications requiring only the associated + * set of functionality. + * + *

Sample Usage. The following illustrates some usage idioms + * in a class that maintains simple two-dimensional points. The sample + * code illustrates some try/catch conventions even though they are + * not strictly needed here because no exceptions can occur in their + * bodies.
+ * + *

{@code
+ * class Point {
+ *   private double x, y;
+ *   private final StampedLock sl = new StampedLock();
+ *
+ *   void move(double deltaX, double deltaY) { // an exclusively locked method
+ *     long stamp = sl.writeLock();
+ *     try {
+ *       x += deltaX;
+ *       y += deltaY;
+ *     } finally {
+ *       sl.unlockWrite(stamp);
+ *     }
+ *   }
+ *
+ *   double distanceFromOrigin() { // A read-only method
+ *     long stamp = sl.tryOptimisticRead();
+ *     double currentX = x, currentY = y;
+ *     if (!sl.validate(stamp)) {
+ *        stamp = sl.readLock();
+ *        try {
+ *          currentX = x;
+ *          currentY = y;
+ *        } finally {
+ *           sl.unlockRead(stamp);
+ *        }
+ *     }
+ *     return Math.sqrt(currentX * currentX + currentY * currentY);
+ *   }
+ *
+ *   void moveIfAtOrigin(double newX, double newY) { // upgrade
+ *     // Could instead start with optimistic, not read mode
+ *     long stamp = sl.readLock();
+ *     try {
+ *       while (x == 0.0 && y == 0.0) {
+ *         long ws = sl.tryConvertToWriteLock(stamp);
+ *         if (ws != 0L) {
+ *           stamp = ws;
+ *           x = newX;
+ *           y = newY;
+ *           break;
+ *         }
+ *         else {
+ *           sl.unlockRead(stamp);
+ *           stamp = sl.writeLock();
+ *         }
+ *       }
+ *     } finally {
+ *       sl.unlock(stamp);
+ *     }
+ *   }
+ * }}
+ * + * @since 1.8 + * @author Doug Lea + */ +public class StampedLock implements java.io.Serializable { + /* + * Algorithmic notes: + * + * The design employs elements of Sequence locks + * (as used in linux kernels; see Lameter's + * http://www.lameter.com/gelato2005.pdf + * and elsewhere; see + * Boehm's http://www.hpl.hp.com/techreports/2012/HPL-2012-68.html) + * and Ordered RW locks (see Shirako et al + * http://dl.acm.org/citation.cfm?id=2312015) + * + * Conceptually, the primary state of the lock includes a sequence + * number that is odd when write-locked and even otherwise. + * However, this is offset by a reader count that is non-zero when + * read-locked. The read count is ignored when validating + * "optimistic" seqlock-reader-style stamps. Because we must use + * a small finite number of bits (currently 7) for readers, a + * supplementary reader overflow word is used when the number of + * readers exceeds the count field. We do this by treating the max + * reader count value (RBITS) as a spinlock protecting overflow + * updates. + * + * Waiters use a modified form of CLH lock used in + * AbstractQueuedSynchronizer (see its internal documentation for + * a fuller account), where each node is tagged (field mode) as + * either a reader or writer. Sets of waiting readers are grouped + * (linked) under a common node (field cowait) so act as a single + * node with respect to most CLH mechanics. By virtue of the + * queue structure, wait nodes need not actually carry sequence + * numbers; we know each is greater than its predecessor. This + * simplifies the scheduling policy to a mainly-FIFO scheme that + * incorporates elements of Phase-Fair locks (see Brandenburg & + * Anderson, especially http://www.cs.unc.edu/~bbb/diss/). In + * particular, we use the phase-fair anti-barging rule: If an + * incoming reader arrives while read lock is held but there is a + * queued writer, this incoming reader is queued. (This rule is + * responsible for some of the complexity of method acquireRead, + * but without it, the lock becomes highly unfair.) + * + * These rules apply to threads actually queued. All tryLock forms + * opportunistically try to acquire locks regardless of preference + * rules, and so may "barge" their way in. Randomized spinning is + * used in the acquire methods to reduce (increasingly expensive) + * context switching while also avoiding sustained memory + * thrashing among many threads. We limit spins to the head of + * queue. A thread spin-waits up to SPINS times (where each + * iteration decreases spin count with 50% probability) before + * blocking. If, upon wakening it fails to obtain lock, and is + * still (or becomes) the first waiting thread (which indicates + * that some other thread barged and obtained lock), it escalates + * spins (up to MAX_HEAD_SPINS) to reduce the likelihood of + * continually losing to barging threads. + * + * Nearly all of these mechanics are carried out in methods + * acquireWrite and acquireRead, that, as typical of such code, + * sprawl out because actions and retries rely on consistent sets + * of locally cached reads. + * + * As noted in Boehm's paper (above), sequence validation (mainly + * method validate()) requires stricter ordering rules than apply + * to normal volatile reads (of "state"). To force orderings of + * reads before a validation and the validation itself in those + * cases where this is not already forced, we use + * Unsafe.loadFence. + * + * The memory layout keeps lock state and queue pointers together + * (normally on the same cache line). This usually works well for + * read-mostly loads. In most other cases, the natural tendency of + * adaptive-spin CLH locks to reduce memory contention lessens + * motivation to further spread out contended locations, but might + * be subject to future improvements. + */ + + private static final long serialVersionUID = -6001602636862214147L; + + /** Number of processors, for spin control */ + private static final int NCPU = Runtime.getRuntime().availableProcessors(); + + /** Maximum number of retries before blocking on acquisition */ + private static final int SPINS = (NCPU > 1) ? 1 << 6 : 0; + + /** Maximum number of retries before re-blocking */ + private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 12 : 0; + + /** The period for yielding when waiting for overflow spinlock */ + private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1 + + /** The number of bits to use for reader count before overflowing */ + private static final int LG_READERS = 7; + + // Values for lock state and stamp operations + private static final long RUNIT = 1L; + private static final long WBIT = 1L << LG_READERS; + private static final long RBITS = WBIT - 1L; + private static final long RFULL = RBITS - 1L; + private static final long ABITS = RBITS | WBIT; + private static final long SBITS = ~RBITS; // note overlap with ABITS + + // Initial value for lock state; avoid failure value zero + private static final long ORIGIN = WBIT << 1; + + // Special value from cancelled acquire methods so caller can throw IE + private static final long INTERRUPTED = 1L; + + // Values for node status; order matters + private static final int WAITING = -1; + private static final int CANCELLED = 1; + + // Modes for nodes (int not boolean to allow arithmetic) + private static final int RMODE = 0; + private static final int WMODE = 1; + + /** Wait nodes */ + static final class WNode { + volatile WNode prev; + volatile WNode next; + volatile WNode cowait; // list of linked readers + volatile Thread thread; // non-null while possibly parked + volatile int status; // 0, WAITING, or CANCELLED + final int mode; // RMODE or WMODE + WNode(int m, WNode p) { mode = m; prev = p; } + } + + /** Head of CLH queue */ + private transient volatile WNode whead; + /** Tail (last) of CLH queue */ + private transient volatile WNode wtail; + + // views + transient ReadLockView readLockView; + transient WriteLockView writeLockView; + transient ReadWriteLockView readWriteLockView; + + /** Lock sequence/state */ + private transient volatile long state; + /** extra reader count when state read count saturated */ + private transient int readerOverflow; + + /** + * Creates a new lock, initially in unlocked state. + */ + public StampedLock() { + state = ORIGIN; + } + + /** + * Exclusively acquires the lock, blocking if necessary + * until available. + * + * @return a stamp that can be used to unlock or convert mode + */ + public long writeLock() { + long s, next; // bypass acquireWrite in fully unlocked case only + return ((((s = state) & ABITS) == 0L && + U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ? + next : acquireWrite(false, 0L)); + } + + /** + * Exclusively acquires the lock if it is immediately available. + * + * @return a stamp that can be used to unlock or convert mode, + * or zero if the lock is not available + */ + public long tryWriteLock() { + long s, next; + return ((((s = state) & ABITS) == 0L && + U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ? + next : 0L); + } + + /** + * Exclusively acquires the lock if it is available within the + * given time and the current thread has not been interrupted. + * Behavior under timeout and interruption matches that specified + * for method {@link Lock#tryLock(long,TimeUnit)}. + * + * @return a stamp that can be used to unlock or convert mode, + * or zero if the lock is not available + * @throws InterruptedException if the current thread is interrupted + * before acquiring the lock + */ + public long tryWriteLock(long time, TimeUnit unit) + throws InterruptedException { + long nanos = unit.toNanos(time); + if (!Thread.interrupted()) { + long next, deadline; + if ((next = tryWriteLock()) != 0L) + return next; + if (nanos <= 0L) + return 0L; + if ((deadline = System.nanoTime() + nanos) == 0L) + deadline = 1L; + if ((next = acquireWrite(true, deadline)) != INTERRUPTED) + return next; + } + throw new InterruptedException(); + } + + /** + * Exclusively acquires the lock, blocking if necessary + * until available or the current thread is interrupted. + * Behavior under interruption matches that specified + * for method {@link Lock#lockInterruptibly()}. + * + * @return a stamp that can be used to unlock or convert mode + * @throws InterruptedException if the current thread is interrupted + * before acquiring the lock + */ + public long writeLockInterruptibly() throws InterruptedException { + long next; + if (!Thread.interrupted() && + (next = acquireWrite(true, 0L)) != INTERRUPTED) + return next; + throw new InterruptedException(); + } + + /** + * Non-exclusively acquires the lock, blocking if necessary + * until available. + * + * @return a stamp that can be used to unlock or convert mode + */ + public long readLock() { + long s, next; // bypass acquireRead on fully unlocked case only + return ((((s = state) & ABITS) == 0L && + U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ? + next : acquireRead(false, 0L)); + } + + /** + * Non-exclusively acquires the lock if it is immediately available. + * + * @return a stamp that can be used to unlock or convert mode, + * or zero if the lock is not available + */ + public long tryReadLock() { + for (;;) { + long s, m, next; + if ((m = (s = state) & ABITS) == WBIT) + return 0L; + else if (m < RFULL) { + if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) + return next; + } + else if ((next = tryIncReaderOverflow(s)) != 0L) + return next; + } + } + + /** + * Non-exclusively acquires the lock if it is available within the + * given time and the current thread has not been interrupted. + * Behavior under timeout and interruption matches that specified + * for method {@link Lock#tryLock(long,TimeUnit)}. + * + * @return a stamp that can be used to unlock or convert mode, + * or zero if the lock is not available + * @throws InterruptedException if the current thread is interrupted + * before acquiring the lock + */ + public long tryReadLock(long time, TimeUnit unit) + throws InterruptedException { + long s, m, next, deadline; + long nanos = unit.toNanos(time); + if (!Thread.interrupted()) { + if ((m = (s = state) & ABITS) != WBIT) { + if (m < RFULL) { + if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) + return next; + } + else if ((next = tryIncReaderOverflow(s)) != 0L) + return next; + } + if (nanos <= 0L) + return 0L; + if ((deadline = System.nanoTime() + nanos) == 0L) + deadline = 1L; + if ((next = acquireRead(true, deadline)) != INTERRUPTED) + return next; + } + throw new InterruptedException(); + } + + /** + * Non-exclusively acquires the lock, blocking if necessary + * until available or the current thread is interrupted. + * Behavior under interruption matches that specified + * for method {@link Lock#lockInterruptibly()}. + * + * @return a stamp that can be used to unlock or convert mode + * @throws InterruptedException if the current thread is interrupted + * before acquiring the lock + */ + public long readLockInterruptibly() throws InterruptedException { + long next; + if (!Thread.interrupted() && + (next = acquireRead(true, 0L)) != INTERRUPTED) + return next; + throw new InterruptedException(); + } + + /** + * Returns a stamp that can later be validated, or zero + * if exclusively locked. + * + * @return a stamp, or zero if exclusively locked + */ + public long tryOptimisticRead() { + long s; + return (((s = state) & WBIT) == 0L) ? (s & SBITS) : 0L; + } + + /** + * Returns true if the lock has not been exclusively acquired + * since issuance of the given stamp. Always returns false if the + * stamp is zero. Always returns true if the stamp represents a + * currently held lock. Invoking this method with a value not + * obtained from {@link #tryOptimisticRead} or a locking method + * for this lock has no defined effect or result. + * + * @return true if the lock has not been exclusively acquired + * since issuance of the given stamp; else false + */ + public boolean validate(long stamp) { + U.loadFence(); + return (stamp & SBITS) == (state & SBITS); + } + + /** + * If the lock state matches the given stamp, releases the + * exclusive lock. + * + * @param stamp a stamp returned by a write-lock operation + * @throws IllegalMonitorStateException if the stamp does + * not match the current state of this lock + */ + public void unlockWrite(long stamp) { + WNode h; + if (state != stamp || (stamp & WBIT) == 0L) + throw new IllegalMonitorStateException(); + state = (stamp += WBIT) == 0L ? ORIGIN : stamp; + if ((h = whead) != null && h.status != 0) + release(h); + } + + /** + * If the lock state matches the given stamp, releases the + * non-exclusive lock. + * + * @param stamp a stamp returned by a read-lock operation + * @throws IllegalMonitorStateException if the stamp does + * not match the current state of this lock + */ + public void unlockRead(long stamp) { + long s, m; WNode h; + for (;;) { + if (((s = state) & SBITS) != (stamp & SBITS) || + (stamp & ABITS) == 0L || (m = s & ABITS) == 0L || m == WBIT) + throw new IllegalMonitorStateException(); + if (m < RFULL) { + if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) { + if (m == RUNIT && (h = whead) != null && h.status != 0) + release(h); + break; + } + } + else if (tryDecReaderOverflow(s) != 0L) + break; + } + } + + /** + * If the lock state matches the given stamp, releases the + * corresponding mode of the lock. + * + * @param stamp a stamp returned by a lock operation + * @throws IllegalMonitorStateException if the stamp does + * not match the current state of this lock + */ + public void unlock(long stamp) { + long a = stamp & ABITS, m, s; WNode h; + while (((s = state) & SBITS) == (stamp & SBITS)) { + if ((m = s & ABITS) == 0L) + break; + else if (m == WBIT) { + if (a != m) + break; + state = (s += WBIT) == 0L ? ORIGIN : s; + if ((h = whead) != null && h.status != 0) + release(h); + return; + } + else if (a == 0L || a >= WBIT) + break; + else if (m < RFULL) { + if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) { + if (m == RUNIT && (h = whead) != null && h.status != 0) + release(h); + return; + } + } + else if (tryDecReaderOverflow(s) != 0L) + return; + } + throw new IllegalMonitorStateException(); + } + + /** + * If the lock state matches the given stamp, performs one of + * the following actions. If the stamp represents holding a write + * lock, returns it. Or, if a read lock, if the write lock is + * available, releases the read lock and returns a write stamp. + * Or, if an optimistic read, returns a write stamp only if + * immediately available. This method returns zero in all other + * cases. + * + * @param stamp a stamp + * @return a valid write stamp, or zero on failure + */ + public long tryConvertToWriteLock(long stamp) { + long a = stamp & ABITS, m, s, next; + while (((s = state) & SBITS) == (stamp & SBITS)) { + if ((m = s & ABITS) == 0L) { + if (a != 0L) + break; + if (U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) + return next; + } + else if (m == WBIT) { + if (a != m) + break; + return stamp; + } + else if (m == RUNIT && a != 0L) { + if (U.compareAndSwapLong(this, STATE, s, + next = s - RUNIT + WBIT)) + return next; + } + else + break; + } + return 0L; + } + + /** + * If the lock state matches the given stamp, performs one of + * the following actions. If the stamp represents holding a write + * lock, releases it and obtains a read lock. Or, if a read lock, + * returns it. Or, if an optimistic read, acquires a read lock and + * returns a read stamp only if immediately available. This method + * returns zero in all other cases. + * + * @param stamp a stamp + * @return a valid read stamp, or zero on failure + */ + public long tryConvertToReadLock(long stamp) { + long a = stamp & ABITS, m, s, next; WNode h; + while (((s = state) & SBITS) == (stamp & SBITS)) { + if ((m = s & ABITS) == 0L) { + if (a != 0L) + break; + else if (m < RFULL) { + if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) + return next; + } + else if ((next = tryIncReaderOverflow(s)) != 0L) + return next; + } + else if (m == WBIT) { + if (a != m) + break; + state = next = s + (WBIT + RUNIT); + if ((h = whead) != null && h.status != 0) + release(h); + return next; + } + else if (a != 0L && a < WBIT) + return stamp; + else + break; + } + return 0L; + } + + /** + * If the lock state matches the given stamp then, if the stamp + * represents holding a lock, releases it and returns an + * observation stamp. Or, if an optimistic read, returns it if + * validated. This method returns zero in all other cases, and so + * may be useful as a form of "tryUnlock". + * + * @param stamp a stamp + * @return a valid optimistic read stamp, or zero on failure + */ + public long tryConvertToOptimisticRead(long stamp) { + long a = stamp & ABITS, m, s, next; WNode h; + U.loadFence(); + for (;;) { + if (((s = state) & SBITS) != (stamp & SBITS)) + break; + if ((m = s & ABITS) == 0L) { + if (a != 0L) + break; + return s; + } + else if (m == WBIT) { + if (a != m) + break; + state = next = (s += WBIT) == 0L ? ORIGIN : s; + if ((h = whead) != null && h.status != 0) + release(h); + return next; + } + else if (a == 0L || a >= WBIT) + break; + else if (m < RFULL) { + if (U.compareAndSwapLong(this, STATE, s, next = s - RUNIT)) { + if (m == RUNIT && (h = whead) != null && h.status != 0) + release(h); + return next & SBITS; + } + } + else if ((next = tryDecReaderOverflow(s)) != 0L) + return next & SBITS; + } + return 0L; + } + + /** + * Releases the write lock if it is held, without requiring a + * stamp value. This method may be useful for recovery after + * errors. + * + * @return true if the lock was held, else false + */ + public boolean tryUnlockWrite() { + long s; WNode h; + if (((s = state) & WBIT) != 0L) { + state = (s += WBIT) == 0L ? ORIGIN : s; + if ((h = whead) != null && h.status != 0) + release(h); + return true; + } + return false; + } + + /** + * Releases one hold of the read lock if it is held, without + * requiring a stamp value. This method may be useful for recovery + * after errors. + * + * @return true if the read lock was held, else false + */ + public boolean tryUnlockRead() { + long s, m; WNode h; + while ((m = (s = state) & ABITS) != 0L && m < WBIT) { + if (m < RFULL) { + if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) { + if (m == RUNIT && (h = whead) != null && h.status != 0) + release(h); + return true; + } + } + else if (tryDecReaderOverflow(s) != 0L) + return true; + } + return false; + } + + // status monitoring methods + + /** + * Returns combined state-held and overflow read count for given + * state s. + */ + private int getReadLockCount(long s) { + long readers; + if ((readers = s & RBITS) >= RFULL) + readers = RFULL + readerOverflow; + return (int) readers; + } + + /** + * Returns true if the lock is currently held exclusively. + * + * @return true if the lock is currently held exclusively + */ + public boolean isWriteLocked() { + return (state & WBIT) != 0L; + } + + /** + * Returns true if the lock is currently held non-exclusively. + * + * @return true if the lock is currently held non-exclusively + */ + public boolean isReadLocked() { + return (state & RBITS) != 0L; + } + + /** + * Queries the number of read locks held for this lock. This + * method is designed for use in monitoring system state, not for + * synchronization control. + * @return the number of read locks held + */ + public int getReadLockCount() { + return getReadLockCount(state); + } + + /** + * Returns a string identifying this lock, as well as its lock + * state. The state, in brackets, includes the String {@code + * "Unlocked"} or the String {@code "Write-locked"} or the String + * {@code "Read-locks:"} followed by the current number of + * read-locks held. + * + * @return a string identifying this lock, as well as its lock state + */ + public String toString() { + long s = state; + return super.toString() + + ((s & ABITS) == 0L ? "[Unlocked]" : + (s & WBIT) != 0L ? "[Write-locked]" : + "[Read-locks:" + getReadLockCount(s) + "]"); + } + + // views + + /** + * Returns a plain {@link Lock} view of this StampedLock in which + * the {@link Lock#lock} method is mapped to {@link #readLock}, + * and similarly for other methods. The returned Lock does not + * support a {@link Condition}; method {@link + * Lock#newCondition()} throws {@code + * UnsupportedOperationException}. + * + * @return the lock + */ + public Lock asReadLock() { + ReadLockView v; + return ((v = readLockView) != null ? v : + (readLockView = new ReadLockView())); + } + + /** + * Returns a plain {@link Lock} view of this StampedLock in which + * the {@link Lock#lock} method is mapped to {@link #writeLock}, + * and similarly for other methods. The returned Lock does not + * support a {@link Condition}; method {@link + * Lock#newCondition()} throws {@code + * UnsupportedOperationException}. + * + * @return the lock + */ + public Lock asWriteLock() { + WriteLockView v; + return ((v = writeLockView) != null ? v : + (writeLockView = new WriteLockView())); + } + + /** + * Returns a {@link ReadWriteLock} view of this StampedLock in + * which the {@link ReadWriteLock#readLock()} method is mapped to + * {@link #asReadLock()}, and {@link ReadWriteLock#writeLock()} to + * {@link #asWriteLock()}. + * + * @return the lock + */ + public ReadWriteLock asReadWriteLock() { + ReadWriteLockView v; + return ((v = readWriteLockView) != null ? v : + (readWriteLockView = new ReadWriteLockView())); + } + + // view classes + + final class ReadLockView implements Lock { + public void lock() { readLock(); } + public void lockInterruptibly() throws InterruptedException { + readLockInterruptibly(); + } + public boolean tryLock() { return tryReadLock() != 0L; } + public boolean tryLock(long time, TimeUnit unit) + throws InterruptedException { + return tryReadLock(time, unit) != 0L; + } + public void unlock() { unstampedUnlockRead(); } + public Condition newCondition() { + throw new UnsupportedOperationException(); + } + } + + final class WriteLockView implements Lock { + public void lock() { writeLock(); } + public void lockInterruptibly() throws InterruptedException { + writeLockInterruptibly(); + } + public boolean tryLock() { return tryWriteLock() != 0L; } + public boolean tryLock(long time, TimeUnit unit) + throws InterruptedException { + return tryWriteLock(time, unit) != 0L; + } + public void unlock() { unstampedUnlockWrite(); } + public Condition newCondition() { + throw new UnsupportedOperationException(); + } + } + + final class ReadWriteLockView implements ReadWriteLock { + public Lock readLock() { return asReadLock(); } + public Lock writeLock() { return asWriteLock(); } + } + + // Unlock methods without stamp argument checks for view classes. + // Needed because view-class lock methods throw away stamps. + + final void unstampedUnlockWrite() { + WNode h; long s; + if (((s = state) & WBIT) == 0L) + throw new IllegalMonitorStateException(); + state = (s += WBIT) == 0L ? ORIGIN : s; + if ((h = whead) != null && h.status != 0) + release(h); + } + + final void unstampedUnlockRead() { + for (;;) { + long s, m; WNode h; + if ((m = (s = state) & ABITS) == 0L || m >= WBIT) + throw new IllegalMonitorStateException(); + else if (m < RFULL) { + if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) { + if (m == RUNIT && (h = whead) != null && h.status != 0) + release(h); + break; + } + } + else if (tryDecReaderOverflow(s) != 0L) + break; + } + } + + private void readObject(java.io.ObjectInputStream s) + throws java.io.IOException, ClassNotFoundException { + s.defaultReadObject(); + state = ORIGIN; // reset to unlocked state + } + + // internals + + /** + * Tries to increment readerOverflow by first setting state + * access bits value to RBITS, indicating hold of spinlock, + * then updating, then releasing. + * + * @param s a reader overflow stamp: (s & ABITS) >= RFULL + * @return new stamp on success, else zero + */ + private long tryIncReaderOverflow(long s) { + // assert (s & ABITS) >= RFULL; + if ((s & ABITS) == RFULL) { + if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) { + ++readerOverflow; + state = s; + return s; + } + } + else if ((LockSupport.nextSecondarySeed() & + OVERFLOW_YIELD_RATE) == 0) + Thread.yield(); + return 0L; + } + + /** + * Tries to decrement readerOverflow. + * + * @param s a reader overflow stamp: (s & ABITS) >= RFULL + * @return new stamp on success, else zero + */ + private long tryDecReaderOverflow(long s) { + // assert (s & ABITS) >= RFULL; + if ((s & ABITS) == RFULL) { + if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) { + int r; long next; + if ((r = readerOverflow) > 0) { + readerOverflow = r - 1; + next = s; + } + else + next = s - RUNIT; + state = next; + return next; + } + } + else if ((LockSupport.nextSecondarySeed() & + OVERFLOW_YIELD_RATE) == 0) + Thread.yield(); + return 0L; + } + + /** + * Wakes up the successor of h (normally whead). This is normally + * just h.next, but may require traversal from wtail if next + * pointers are lagging. This may fail to wake up an acquiring + * thread when one or more have been cancelled, but the cancel + * methods themselves provide extra safeguards to ensure liveness. + */ + private void release(WNode h) { + if (h != null) { + WNode q; Thread w; + U.compareAndSwapInt(h, WSTATUS, WAITING, 0); + if ((q = h.next) == null || q.status == CANCELLED) { + for (WNode t = wtail; t != null && t != h; t = t.prev) + if (t.status <= 0) + q = t; + } + if (q != null) { + for (WNode r = q;;) { // release co-waiters too + if ((w = r.thread) != null) { + r.thread = null; + U.unpark(w); + } + if ((r = q.cowait) == null) + break; + U.compareAndSwapObject(q, WCOWAIT, r, r.cowait); + } + } + } + } + + /** + * See above for explanation. + * + * @param interruptible true if should check interrupts and if so + * return INTERRUPTED + * @param deadline if nonzero, the System.nanoTime value to timeout + * at (and return zero) + * @return next state, or INTERRUPTED + */ + private long acquireWrite(boolean interruptible, long deadline) { + WNode node = null, p; + for (int spins = -1;;) { // spin while enqueuing + long s, ns; + if (((s = state) & ABITS) == 0L) { + if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT)) + return ns; + } + else if (spins > 0) { + if (LockSupport.nextSecondarySeed() >= 0) + --spins; + } + else if ((p = wtail) == null) { // initialize queue + WNode h = new WNode(WMODE, null); + if (U.compareAndSwapObject(this, WHEAD, null, h)) + wtail = h; + } + else if (spins < 0) + spins = (p == whead) ? SPINS : 0; + else if (node == null) + node = new WNode(WMODE, p); + else if (node.prev != p) + node.prev = p; + else if (U.compareAndSwapObject(this, WTAIL, p, node)) { + p.next = node; + break; + } + } + + for (int spins = SPINS;;) { + WNode np, pp; int ps; long s, ns; Thread w; + while ((np = node.prev) != p && np != null) + (p = np).next = node; // stale + if (whead == p) { + for (int k = spins;;) { // spin at head + if (((s = state) & ABITS) == 0L) { + if (U.compareAndSwapLong(this, STATE, s, ns = s+WBIT)) { + whead = node; + node.prev = null; + return ns; + } + } + else if (LockSupport.nextSecondarySeed() >= 0 && + --k <= 0) + break; + } + if (spins < MAX_HEAD_SPINS) + spins <<= 1; + } + if ((ps = p.status) == 0) + U.compareAndSwapInt(p, WSTATUS, 0, WAITING); + else if (ps == CANCELLED) { + if ((pp = p.prev) != null) { + node.prev = pp; + pp.next = node; + } + } + else { + long time; // 0 argument to park means no timeout + if (deadline == 0L) + time = 0L; + else if ((time = deadline - System.nanoTime()) <= 0L) + return cancelWaiter(node, node, false); + Thread wt = Thread.currentThread(); + U.putObject(wt, PARKBLOCKER, this); // emulate LockSupport.park + node.thread = wt; + if (node.prev == p && p.status == WAITING && // recheck + (p != whead || (state & ABITS) != 0L)) + U.park(false, time); + node.thread = null; + U.putObject(wt, PARKBLOCKER, null); + if (interruptible && Thread.interrupted()) + return cancelWaiter(node, node, true); + } + } + } + + /** + * See above for explanation. + * + * @param interruptible true if should check interrupts and if so + * return INTERRUPTED + * @param deadline if nonzero, the System.nanoTime value to timeout + * at (and return zero) + * @return next state, or INTERRUPTED + */ + private long acquireRead(boolean interruptible, long deadline) { + WNode node = null, group = null, p; + for (int spins = -1;;) { + for (;;) { + long s, m, ns; WNode h, q; Thread w; // anti-barging guard + if (group == null && (h = whead) != null && + (q = h.next) != null && q.mode != RMODE) + break; + if ((m = (s = state) & ABITS) < RFULL ? + U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) : + (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) { + if (group != null) { // help release others + for (WNode r = group;;) { + if ((w = r.thread) != null) { + r.thread = null; + U.unpark(w); + } + if ((r = group.cowait) == null) + break; + U.compareAndSwapObject(group, WCOWAIT, r, r.cowait); + } + } + return ns; + } + if (m >= WBIT) + break; + } + if (spins > 0) { + if (LockSupport.nextSecondarySeed() >= 0) + --spins; + } + else if ((p = wtail) == null) { + WNode h = new WNode(WMODE, null); + if (U.compareAndSwapObject(this, WHEAD, null, h)) + wtail = h; + } + else if (spins < 0) + spins = (p == whead) ? SPINS : 0; + else if (node == null) + node = new WNode(WMODE, p); + else if (node.prev != p) + node.prev = p; + else if (p.mode == RMODE && p != whead) { + WNode pp = p.prev; // become co-waiter with group p + if (pp != null && p == wtail && + U.compareAndSwapObject(p, WCOWAIT, + node.cowait = p.cowait, node)) { + node.thread = Thread.currentThread(); + for (long time;;) { + if (deadline == 0L) + time = 0L; + else if ((time = deadline - System.nanoTime()) <= 0L) + return cancelWaiter(node, p, false); + if (node.thread == null) + break; + if (p.prev != pp || p.status == CANCELLED || + p == whead || p.prev != pp) { + node.thread = null; + break; + } + Thread wt = Thread.currentThread(); + U.putObject(wt, PARKBLOCKER, this); + if (node.thread == null) // must recheck + break; + U.park(false, time); + U.putObject(wt, PARKBLOCKER, null); + if (interruptible && Thread.interrupted()) + return cancelWaiter(node, p, true); + } + group = p; + } + node = null; // throw away + } + else if (U.compareAndSwapObject(this, WTAIL, p, node)) { + p.next = node; + break; + } + } + + for (int spins = SPINS;;) { + WNode np, pp, r; int ps; long m, s, ns; Thread w; + while ((np = node.prev) != p && np != null) + (p = np).next = node; + if (whead == p) { + for (int k = spins;;) { + if ((m = (s = state) & ABITS) != WBIT) { + if (m < RFULL ? + U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT): + (ns = tryIncReaderOverflow(s)) != 0L) { + whead = node; + node.prev = null; + while ((r = node.cowait) != null) { + if (U.compareAndSwapObject(node, WCOWAIT, + r, r.cowait) && + (w = r.thread) != null) { + r.thread = null; + U.unpark(w); // release co-waiter + } + } + return ns; + } + } + else if (LockSupport.nextSecondarySeed() >= 0 && + --k <= 0) + break; + } + if (spins < MAX_HEAD_SPINS) + spins <<= 1; + } + if ((ps = p.status) == 0) + U.compareAndSwapInt(p, WSTATUS, 0, WAITING); + else if (ps == CANCELLED) { + if ((pp = p.prev) != null) { + node.prev = pp; + pp.next = node; + } + } + else { + long time; + if (deadline == 0L) + time = 0L; + else if ((time = deadline - System.nanoTime()) <= 0L) + return cancelWaiter(node, node, false); + Thread wt = Thread.currentThread(); + U.putObject(wt, PARKBLOCKER, this); + node.thread = wt; + if (node.prev == p && p.status == WAITING && + (p != whead || (state & ABITS) != WBIT)) + U.park(false, time); + node.thread = null; + U.putObject(wt, PARKBLOCKER, null); + if (interruptible && Thread.interrupted()) + return cancelWaiter(node, node, true); + } + } + } + + /** + * If node non-null, forces cancel status and unsplices it from + * queue if possible and wakes up any cowaiters (of the node, or + * group, as applicable), and in any case helps release current + * first waiter if lock is free. (Calling with null arguments + * serves as a conditional form of release, which is not currently + * needed but may be needed under possible future cancellation + * policies). This is a variant of cancellation methods in + * AbstractQueuedSynchronizer (see its detailed explanation in AQS + * internal documentation). + * + * @param node if nonnull, the waiter + * @param group either node or the group node is cowaiting with + * @param interrupted if already interrupted + * @return INTERRUPTED if interrupted or Thread.interrupted, else zero + */ + private long cancelWaiter(WNode node, WNode group, boolean interrupted) { + if (node != null && group != null) { + Thread w; + node.status = CANCELLED; + node.thread = null; + // unsplice cancelled nodes from group + for (WNode p = group, q; (q = p.cowait) != null;) { + if (q.status == CANCELLED) + U.compareAndSwapObject(p, WNEXT, q, q.next); + else + p = q; + } + if (group == node) { + WNode r; // detach and wake up uncancelled co-waiters + while ((r = node.cowait) != null) { + if (U.compareAndSwapObject(node, WCOWAIT, r, r.cowait) && + (w = r.thread) != null) { + r.thread = null; + U.unpark(w); + } + } + for (WNode pred = node.prev; pred != null; ) { // unsplice + WNode succ, pp; // find valid successor + while ((succ = node.next) == null || + succ.status == CANCELLED) { + WNode q = null; // find successor the slow way + for (WNode t = wtail; t != null && t != node; t = t.prev) + if (t.status != CANCELLED) + q = t; // don't link if succ cancelled + if (succ == q || // ensure accurate successor + U.compareAndSwapObject(node, WNEXT, + succ, succ = q)) { + if (succ == null && node == wtail) + U.compareAndSwapObject(this, WTAIL, node, pred); + break; + } + } + if (pred.next == node) // unsplice pred link + U.compareAndSwapObject(pred, WNEXT, node, succ); + if (succ != null && (w = succ.thread) != null) { + succ.thread = null; + U.unpark(w); // wake up succ to observe new pred + } + if (pred.status != CANCELLED || (pp = pred.prev) == null) + break; + node.prev = pp; // repeat if new pred wrong/cancelled + U.compareAndSwapObject(pp, WNEXT, pred, succ); + pred = pp; + } + } + } + WNode h; // Possibly release first waiter + while ((h = whead) != null) { + long s; WNode q; // similar to release() but check eligibility + if ((q = h.next) == null || q.status == CANCELLED) { + for (WNode t = wtail; t != null && t != h; t = t.prev) + if (t.status <= 0) + q = t; + } + if (h == whead) { + if (q != null && h.status == 0 && + ((s = state) & ABITS) != WBIT && // waiter is eligible + (s == 0L || q.mode == RMODE)) + release(h); + break; + } + } + return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L; + } + + // Unsafe mechanics + private static final sun.misc.Unsafe U; + private static final long STATE; + private static final long WHEAD; + private static final long WTAIL; + private static final long WNEXT; + private static final long WSTATUS; + private static final long WCOWAIT; + private static final long PARKBLOCKER; + + static { + try { + U = sun.misc.Unsafe.getUnsafe(); + Class k = StampedLock.class; + Class wk = WNode.class; + STATE = U.objectFieldOffset + (k.getDeclaredField("state")); + WHEAD = U.objectFieldOffset + (k.getDeclaredField("whead")); + WTAIL = U.objectFieldOffset + (k.getDeclaredField("wtail")); + WSTATUS = U.objectFieldOffset + (wk.getDeclaredField("status")); + WNEXT = U.objectFieldOffset + (wk.getDeclaredField("next")); + WCOWAIT = U.objectFieldOffset + (wk.getDeclaredField("cowait")); + Class tk = Thread.class; + PARKBLOCKER = U.objectFieldOffset + (tk.getDeclaredField("parkBlocker")); + + } catch (Exception e) { + throw new Error(e); + } + } +} diff --git a/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java b/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java new file mode 100644 index 00000000000..8c9f236d2d3 --- /dev/null +++ b/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java @@ -0,0 +1,609 @@ +/* + * 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. + * + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/* + * @test + * @bug 8005697 + * @summary Basic tests for StampedLock + * @author Chris Hegarty + */ + +import java.util.Iterator; +import java.util.concurrent.Phaser; +import java.util.concurrent.TimeUnit; +import static java.util.concurrent.TimeUnit.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.StampedLock; + +public class Basic { + + static void checkResult(Locker l, Class c) { + Throwable t = l.thrown(); + if (! ((t == null && c == null) || (c != null && c.isInstance(t)))) { + fail("Mismatch in thread " + + l.getName() + ": " + + t + ", " + + (c == null ? "" : c.getName())); + } + + if (c == null) + check(l.stamp() != 0L); // must have acquired the lock + else + check(l.stamp() == 0L); // must NOT have acquired the lock + } + + //---------------------------------------------------------------- + // Mechanism to get all test threads into "running" mode. + //---------------------------------------------------------------- + static void toTheStartingGate(Phaser gate) { + try { + gate.arriveAndAwaitAdvance(); + } catch (Throwable t) { + unexpected(t); + } + } + + static abstract class Locker extends Thread { + static AtomicInteger count = new AtomicInteger(1); + private volatile Throwable thrown; + private volatile long stamp;; + protected void thrown(Throwable thrown) { this.thrown = thrown; } + public Throwable thrown() { return thrown; } + protected void stamp(long stamp) { this.stamp = stamp; } + public long stamp() { return stamp; } + + Locker() { + this("Locker"); + } + + Locker(String name) { + this.setName(name + ":" + count.getAndIncrement()); + this.setDaemon(true); + } + } + + static abstract class Reader extends Locker { + Reader() { super("Reader"); } + Reader(String name) { super(name); } + } + + static Reader reader(final StampedLock sl, final Phaser gate) { + return new Reader() { public void run() { + if (gate != null ) toTheStartingGate(gate); + stamp(sl.readLock()); + try { + check(sl.validate(stamp())); + check(sl.isReadLocked()); + check(!sl.isWriteLocked()); + } finally { sl.unlockRead(stamp()); } }}; + } + + static Reader readerView(final StampedLock sl, final Phaser gate) { + return new Reader("ReaderView") { public void run() { + if (gate != null ) toTheStartingGate(gate); + final Lock rl = sl.asReadLock(); + rl.lock(); + try { + stamp(1L); // got the lock + check(sl.isReadLocked()); + check(!sl.isWriteLocked()); + } finally { rl.unlock(); } }}; + } + + static Reader reader(StampedLock sl, Phaser gate, boolean view) { + return view ? readerView(sl, gate) : reader(sl, gate); + } + + static Reader interruptibleReader(final StampedLock sl, + final long timeout, + final TimeUnit unit, + final Phaser gate) { + return new Reader("InterruptibleReader") { public void run() { + if (gate != null ) toTheStartingGate(gate); + try { + if (timeout < 0) + stamp(sl.readLockInterruptibly()); + else + stamp(sl.tryReadLock(timeout, unit)); + check(sl.validate(stamp())); + check(sl.isReadLocked()); + check(!sl.isWriteLocked()); + } catch (Throwable x) { thrown(x); + } finally { if (stamp() != 0L) sl.unlockRead(stamp()); } }}; + } + + static Reader interruptibleReaderView(final StampedLock sl, + final long timeout, + final TimeUnit unit, + final Phaser gate) { + return new Reader("InterruptibleReaderView") { public void run() { + if (gate != null ) toTheStartingGate(gate); + final Lock rl = sl.asReadLock(); + + try { + if (timeout < 0) + rl.lockInterruptibly(); + else + rl.tryLock(timeout, unit); + stamp(1L); // got the lock + check(sl.isReadLocked()); + check(!sl.isWriteLocked()); + } catch (Throwable x) { thrown(x); + } finally { if (stamp() != 0L) rl.unlock(); } }}; + } + + static Reader interruptibleReader(final StampedLock sl, + final long timeout, + final TimeUnit unit, + final Phaser gate, + final boolean view) { + return view ? interruptibleReaderView(sl, timeout, unit, gate) + : interruptibleReader(sl, timeout, unit, gate); + } + + static abstract class Writer extends Locker { + Writer() { super("Writer"); } + Writer(String name) { super(name); } + } + + static Writer writer(final StampedLock sl, final Phaser gate) { + return new Writer() { public void run() { + if (gate != null ) toTheStartingGate(gate); + try { + stamp(sl.writeLock()); + check(sl.validate(stamp())); + check(!sl.isReadLocked()); + check(sl.isWriteLocked()); + } finally { sl.unlockWrite(stamp()); } }}; + } + + static Writer writerView(final StampedLock sl, final Phaser gate) { + return new Writer("WriterView") { public void run() { + if (gate != null ) toTheStartingGate(gate); + Lock wl = sl.asWriteLock(); + wl.lock(); + try { + stamp(1L); // got the lock + check(!sl.isReadLocked()); + check(sl.isWriteLocked()); + } finally { wl.unlock(); } }}; + } + + static Writer writer(StampedLock sl, Phaser gate, boolean view) { + return view ? writerView(sl, gate) : writer(sl, gate); + } + + static Writer interruptibleWriter(final StampedLock sl, + final long timeout, + final TimeUnit unit, + final Phaser gate) { + return new Writer("InterruptibleWriter") { public void run() { + if (gate != null ) toTheStartingGate(gate); + try { + if (timeout < 0) + stamp(sl.writeLockInterruptibly()); + else + stamp(sl.tryWriteLock(timeout, unit)); + check(sl.validate(stamp())); + check(!sl.isReadLocked()); + check(sl.isWriteLocked()); + } catch (Throwable x) { thrown(x); + } finally { if (stamp() != 0L) sl.unlockWrite(stamp()); } }}; + } + + static Writer interruptibleWriterView(final StampedLock sl, + final long timeout, + final TimeUnit unit, + final Phaser gate) { + return new Writer("InterruptibleWriterView") { public void run() { + if (gate != null ) toTheStartingGate(gate); + Lock wl = sl.asWriteLock(); + try { + if (timeout < 0) + wl.lockInterruptibly(); + else + wl.tryLock(timeout, unit); + stamp(1L); // got the lock + check(!sl.isReadLocked()); + check(sl.isWriteLocked()); + } catch (Throwable x) { thrown(x); + } finally { if (stamp() != 0L) wl.unlock(); } }}; + } + + static Writer interruptibleWriter(final StampedLock sl, + final long timeout, + final TimeUnit unit, + final Phaser gate, + final boolean view) { + return view ? interruptibleWriterView(sl, timeout, unit, gate) + : interruptibleWriter(sl, timeout, unit, gate); + } + + // Returns an infinite lazy list of all possible reader combinations. + static Iterator readerIterator(final StampedLock sl, + final Phaser gate) { + return new Iterator() { + int i = 0; + boolean view = false; + public boolean hasNext() { return true; } + public Reader next() { + switch ((i++)&7) { + case 1: case 4: case 7: + return reader(sl, gate, view ^= true); + case 2: case 5: + return interruptibleReader(sl, -1, SECONDS, gate, view ^= true); + default: + return interruptibleReader(sl, 30, SECONDS, gate, view ^= true); }} + public void remove() {throw new UnsupportedOperationException();}}; + } + + // Returns an infinite lazy list of all possible writer combinations. + static Iterator writerIterator(final StampedLock sl, + final Phaser gate) { + return new Iterator() { + int i = 0; + boolean view = false; + public boolean hasNext() { return true; } + public Writer next() { + switch ((i++)&7) { + case 1: case 4: case 7: + return writer(sl, gate, view ^= true); + case 2: case 5: + return interruptibleWriter(sl, -1, SECONDS, gate, view ^= true); + default: + return interruptibleWriter(sl, 30, SECONDS, gate, view ^= true); }} + public void remove() {throw new UnsupportedOperationException();}}; + } + + private static void realMain(String[] args) throws Throwable { + + Thread.currentThread().setName("mainThread"); + + //---------------------------------------------------------------- + // Some basic sanity + //---------------------------------------------------------------- + try { + final StampedLock sl = new StampedLock(); + check(!sl.isReadLocked()); + check(!sl.isWriteLocked()); + long stamp = sl.tryOptimisticRead(); + check(stamp != 0L); + check(sl.validate(stamp)); + check(!sl.validate(0)); + + stamp = sl.writeLock(); + try { + check(sl.validate(stamp)); + check(!sl.isReadLocked()); + check(sl.isWriteLocked()); + check(sl.tryReadLock() == 0L); + check(sl.tryReadLock(100, MILLISECONDS) == 0L); + check(sl.tryOptimisticRead() == 0L); + check(sl.tryWriteLock() == 0L); + check(sl.tryWriteLock(100, MILLISECONDS) == 0L); + check(!sl.tryUnlockRead()); + check(sl.tryConvertToWriteLock(stamp) == stamp); + try { + sl.unlockRead(stamp); + fail("Expected unlockRead to throw when not holding read lock"); + } catch (IllegalMonitorStateException x) { + pass(); + } + check(sl.validate(stamp)); + } finally { + sl.unlockWrite(stamp); + } + check(!sl.isWriteLocked()); + + stamp = sl.readLock(); + try { + check(sl.validate(stamp)); + check(sl.isReadLocked()); + check(!sl.isWriteLocked()); + check(sl.tryOptimisticRead() != 0L); + check(sl.tryWriteLock() == 0L); + check(sl.tryWriteLock(100, MILLISECONDS) == 0L); + check(!sl.tryUnlockWrite()); + check(sl.tryConvertToReadLock(stamp) == stamp); + try { + sl.unlockWrite(stamp); + fail("Expected unlockWrite to throw when not holding read lock"); + } catch (IllegalMonitorStateException x) { + pass(); + } + check(sl.validate(stamp)); + } finally { + sl.unlockRead(stamp); + } + check(!sl.isReadLocked()); + + stamp = sl.tryReadLock(100, MILLISECONDS); + try { + check(stamp != 0L); + } finally { + sl.unlockRead(stamp); + } + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- + // Multiple writers single reader + //---------------------------------------------------------------- + try { + StampedLock sl = new StampedLock(); + Phaser gate = new Phaser(102); + Iterator writers = writerIterator(sl, gate); + Iterator readers = readerIterator(sl, gate); + for (int i = 0; i < 10; i++) { + check(!sl.isReadLocked()); + check(!sl.isWriteLocked()); + check(!sl.tryUnlockRead()); + check(!sl.tryUnlockWrite()); + check(sl.tryOptimisticRead() != 0L); + Locker[] wThreads = new Locker[100];; + for (int j=0; j<100; j++) + wThreads[j] = writers.next(); + for (int j=0; j<100; j++) + wThreads[j].start(); + Reader reader = readers.next(); reader.start(); + toTheStartingGate(gate); + reader.join(); + for (int j=0; j<100; j++) + wThreads[j].join(); + for (int j=0; j<100; j++) + checkResult(wThreads[j], null); + checkResult(reader, null); + } + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- + // Multiple readers single writer + //---------------------------------------------------------------- + try { + StampedLock sl = new StampedLock(); + Phaser gate = new Phaser(102); + Iterator writers = writerIterator(sl, gate); + Iterator readers = readerIterator(sl, gate); + for (int i = 0; i < 10; i++) { + check(!sl.isReadLocked()); + check(!sl.isWriteLocked()); + check(!sl.tryUnlockRead()); + check(!sl.tryUnlockWrite()); + check(sl.tryOptimisticRead() != 0L); + Locker[] rThreads = new Locker[100];; + for (int j=0; j<100; j++) + rThreads[j] = readers.next(); + for (int j=0; j<100; j++) + rThreads[j].start(); + Writer writer = writers.next(); writer.start(); + toTheStartingGate(gate); + writer.join(); + for (int j=0; j<100; j++) + rThreads[j].join(); + for (int j=0; j<100; j++) + checkResult(rThreads[j], null); + checkResult(writer, null); + } + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- + // thread interrupted + //---------------------------------------------------------------- + try { + boolean view = false; + StampedLock sl = new StampedLock(); + for (long timeout : new long[] { -1L, 30L, -1L, 30L }) { + long stamp = sl.writeLock(); + try { + Reader r = interruptibleReader(sl, timeout, SECONDS, null, view); + r.start(); + // allow r to block + Thread.sleep(2000); + r.interrupt(); + r.join(); + checkResult(r, InterruptedException.class); + } finally { + sl.unlockWrite(stamp); + } + stamp = sl.readLock(); + try { + Writer w = interruptibleWriter(sl, timeout, SECONDS, null, view); + w.start(); + // allow w to block + Thread.sleep(2000); + w.interrupt(); + w.join(); + checkResult(w, InterruptedException.class); + } finally { + sl.unlockRead(stamp); + } + check(!sl.isReadLocked()); + check(!sl.isWriteLocked()); + check(!sl.tryUnlockRead()); + check(!sl.tryUnlockWrite()); + check(sl.tryOptimisticRead() != 0L); + if (timeout == 30L) + view = true; + } + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- + // timeout + //---------------------------------------------------------------- + try { + StampedLock sl = new StampedLock(); + for (long timeout : new long[] { 0L, 5L }) { + long stamp = sl.writeLock(); + try { + check(sl.tryReadLock(timeout, SECONDS) == 0L); + } finally { + sl.unlockWrite(stamp); + } + stamp = sl.readLock(); + try { + check(sl.tryWriteLock(timeout, SECONDS) == 0L); + } finally { + sl.unlockRead(stamp); + } + check(!sl.isReadLocked()); + check(!sl.isWriteLocked()); + check(!sl.tryUnlockRead()); + check(!sl.tryUnlockWrite()); + check(sl.tryOptimisticRead() != 0L); + } + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- + // optimistic read + //---------------------------------------------------------------- + try { + StampedLock sl = new StampedLock(); + Iterator writers = writerIterator(sl, null); + Iterator readers = readerIterator(sl, null); + for (int i = 0; i < 10; i++) { + check(!sl.isReadLocked()); + check(!sl.isWriteLocked()); + check(!sl.tryUnlockRead()); + check(!sl.tryUnlockWrite()); + long stamp = sl.tryOptimisticRead(); + check(stamp != 0L); + check(sl.tryConvertToOptimisticRead(stamp) == stamp); + Reader r = readers.next(); r.start(); + r.join(); + checkResult(r, null); + check(sl.validate(stamp)); + check(sl.tryConvertToOptimisticRead(stamp) == stamp); + Writer w = writers.next(); w.start(); + w.join(); + checkResult(w, null); + check(sl.validate(stamp) == false); + } + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- + // convert + //---------------------------------------------------------------- + try { + StampedLock sl = new StampedLock(); + for (int i = 0; i < 2; i++) { + check(!sl.isReadLocked()); + check(!sl.isWriteLocked()); + check(!sl.tryUnlockRead()); + check(!sl.tryUnlockWrite()); + long stamp = sl.tryOptimisticRead(); + check(stamp != 0L); + check((stamp = sl.tryConvertToReadLock(stamp)) != 0L); + check(sl.validate(stamp)); + check(sl.isReadLocked()); + check(sl.tryWriteLock() == 0L); + check(sl.tryWriteLock(1L, SECONDS) == 0L); + check((stamp = sl.tryConvertToWriteLock(stamp)) != 0L); + check(sl.validate(stamp)); + check(!sl.isReadLocked()); + check(sl.isWriteLocked()); + check(sl.tryReadLock(1L, SECONDS) == 0L); + if (i != 0) { + sl.unlockWrite(stamp); + continue; + } + // convert down + check((stamp = sl.tryConvertToReadLock(stamp)) != 0L); + check(sl.validate(stamp)); + check(sl.isReadLocked()); + check(!sl.isWriteLocked()); + check(sl.tryWriteLock() == 0L); + check(sl.tryWriteLock(1L, SECONDS) == 0L); + check((stamp = sl.tryConvertToOptimisticRead(stamp)) != 0L); + check(sl.validate(stamp)); + check(!sl.isReadLocked()); + check(!sl.isWriteLocked()); + check(sl.validate(stamp)); + } + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- + // views + //---------------------------------------------------------------- + try { + StampedLock sl = new StampedLock(); + + Lock rl = sl.asReadLock(); + Lock wl = sl.asWriteLock(); + for (int i = 0; i < 2; i++) { + rl.lock(); + try { + check(sl.isReadLocked()); + check(!sl.isWriteLocked()); + check(sl.tryWriteLock() == 0L); + check(sl.tryWriteLock(1L, SECONDS) == 0L); + } finally { + rl.unlock(); + } + check(!sl.isReadLocked()); + check(!sl.isWriteLocked()); + + wl.lock(); + try { + check(!sl.isReadLocked()); + check(sl.isWriteLocked()); + check(sl.tryWriteLock() == 0L); + check(sl.tryWriteLock(1L, SECONDS) == 0L); + } finally { + wl.unlock(); + } + check(!sl.isReadLocked()); + check(!sl.isWriteLocked()); + + ReadWriteLock rwl = sl.asReadWriteLock(); + rl = rwl.readLock(); + wl = rwl.writeLock(); + } + } catch (Throwable t) { unexpected(t); } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void check(boolean cond) {if (cond) pass(); else fail();} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} From d8233ec65720cf0bb8536853588cc967c4dcca28 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Sat, 9 Feb 2013 16:43:49 +0800 Subject: [PATCH 117/158] 8001104: Unbound SASL service: the GSSAPI/krb5 mech Reviewed-by: valeriep --- .../security/auth/module/Krb5LoginModule.java | 118 ++++++++----- .../JavaxSecurityAuthKerberosAccessImpl.java | 6 +- .../javax/security/auth/kerberos/KeyTab.java | 160 ++++++++++++++++-- .../sun/security/jgss/LoginConfigImpl.java | 1 + .../sun/security/jgss/krb5/Krb5Util.java | 16 +- .../sun/security/jgss/krb5/ServiceCreds.java | 83 ++++++--- .../sun/security/jgss/krb5/SubjectComber.java | 59 ++++--- .../krb5/JavaxSecurityAuthKerberosAccess.java | 7 +- .../security/krb5/internal/ktab/KeyTab.java | 10 ++ .../sun/security/provider/ConfigSpiFile.java | 1 + .../krb5/ServiceCredsCombination.java | 33 ++++ .../security/krb5/auto/AcceptPermissions.java | 16 +- .../sun/security/krb5/auto/GSSUnbound.java | 61 +++++++ jdk/test/sun/security/krb5/auto/OneKDC.java | 5 +- .../sun/security/krb5/auto/SaslUnbound.java | 113 +++++++++++++ .../security/krb5/auto/UnboundService.java | 85 ++++++++++ 16 files changed, 652 insertions(+), 122 deletions(-) create mode 100644 jdk/test/sun/security/krb5/auto/GSSUnbound.java create mode 100644 jdk/test/sun/security/krb5/auto/SaslUnbound.java create mode 100644 jdk/test/sun/security/krb5/auto/UnboundService.java diff --git a/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java b/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java index 3d1744ba172..719aeee76d4 100644 --- a/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java +++ b/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java @@ -52,16 +52,19 @@ import sun.misc.HexDumpEncoder; * principal set and private credentials set are updated only when * commit is called. * When commit is called, the KerberosPrincipal - * is added to the Subject's - * principal set and KerberosTicket is + * is added to the Subject's principal set (unless the + * principal is specified as "*"). If isInitiator + * is true, the KerberosTicket is * added to the Subject's private credentials. * *

If the configuration entry for KerberosLoginModule * has the option storeKey set to true, then - * KerberosKey will also be added to the + * KerberosKey or KeyTab will also be added to the * subject's private credentials. KerberosKey, the principal's - * key will be either obtained from the keytab or - * derived from user's password. + * key(s) will be derived from user's password, and KeyTab is + * the keytab used when useKeyTab is set to true. The + * KeyTab object is restricted to be used by the specified + * principal unless the principal value is "*". * *

This LoginModule recognizes the doNotPrompt * option. If set to true the user will not be prompted for the password. @@ -75,8 +78,8 @@ import sun.misc.HexDumpEncoder; * *

The principal name can be specified in the configuration entry * by using the option principal. The principal name - * can either be a simple user name or a service name such as - * host/mission.eng.sun.com. The principal can also + * can either be a simple user name, a service name such as + * host/mission.eng.sun.com, or "*". The principal can also * be set using the system property sun.security.krb5.principal. * This property is checked during login. If this property is not set, then * the principal name from the configuration is used. In the @@ -87,11 +90,10 @@ import sun.misc.HexDumpEncoder; * *

The following is a list of configuration options supported * for Krb5LoginModule: - *

- *
refreshKrb5Config:
+ *
+ *
refreshKrb5Config:
*
Set this to true, if you want the configuration * to be refreshed before the login method is called.
- *

*

useTicketCache:
*
Set this to true, if you want the * TGT to be obtained @@ -112,19 +114,16 @@ import sun.misc.HexDumpEncoder; * ticketCache. * For Windows, if a ticket cannot be retrieved from the file ticket cache, * it will use Local Security Authority (LSA) API to get the TGT. - *

*

ticketCache:
*
Set this to the name of the ticket * cache that contains user's TGT. * If this is set, useTicketCache * must also be set to true; Otherwise a configuration error will * be returned.
- *

*

renewTGT:
*
Set this to true, if you want to renew * the TGT. If this is set, useTicketCache must also be * set to true; otherwise a configuration error will be returned.
- *

*

doNotPrompt:
*
Set this to true if you do not want to be * prompted for the password @@ -132,7 +131,6 @@ import sun.misc.HexDumpEncoder; * or through shared state.(Default is false) * If set to true, credential must be obtained through cache, keytab, * or shared state. Otherwise, authentication will fail.
- *

*

useKeyTab:
*
Set this to true if you * want the module to get the principal's key from the @@ -144,15 +142,15 @@ import sun.misc.HexDumpEncoder; * If it is not specified in the Kerberos configuration file * then it will look for the file * {user.home}{file.separator}krb5.keytab.
- *

*

keyTab:
*
Set this to the file name of the * keytab to get principal's secret key.
- *

*

storeKey:
- *
Set this to true to if you want the - * principal's key to be stored in the Subject's private credentials.
- *

+ *

Set this to true to if you want the keytab or the + * principal's key to be stored in the Subject's private credentials. + * For isInitiator being false, if principal + * is "*", the {@link KeyTab} stored can be used by anyone, otherwise, + * it's restricted to be used by the specified principal only.
*
principal:
*
The name of the principal that should * be used. The principal can be a simple username such as @@ -165,8 +163,13 @@ import sun.misc.HexDumpEncoder; * sun.security.krb5.principal. In addition, if this * system property is defined, then it will be used. If this property * is not set, then the principal name from the configuration will be - * used.
- *

+ * used. + * The principal name can be set to "*" when isInitiator is false. + * In this case, the acceptor is not bound to a single principal. It can + * act as any principal an initiator requests if keys for that principal + * can be found. When isInitiator is true, the principal name + * cannot be set to "*". + * *

isInitiator:
*
Set this to true, if initiator. Set this to false, if acceptor only. * (Default is true). @@ -177,18 +180,20 @@ import sun.misc.HexDumpEncoder; * Configuration * options that enable you to share username and passwords across different * authentication modules: - *
+ * 
* - * useFirstPass if, true, this LoginModule retrieves the + *
useFirstPass:
+ *
if, true, this LoginModule retrieves the * username and password from the module's shared state, * using "javax.security.auth.login.name" and * "javax.security.auth.login.password" as the respective * keys. The retrieved values are used for authentication. * If authentication fails, no attempt for a retry * is made, and the failure is reported back to the - * calling application. + * calling application.
* - * tryFirstPass if, true, this LoginModule retrieves the + *
tryFirstPass:
+ *
if, true, this LoginModule retrieves the * the username and password from the module's shared * state using "javax.security.auth.login.name" and * "javax.security.auth.login.password" as the respective @@ -198,26 +203,28 @@ import sun.misc.HexDumpEncoder; * CallbackHandler to retrieve a new username * and password, and another attempt to authenticate * is made. If the authentication fails, - * the failure is reported back to the calling application + * the failure is reported back to the calling application
* - * storePass if, true, this LoginModule stores the username and + *
storePass:
+ *
if, true, this LoginModule stores the username and * password obtained from the CallbackHandler in the * modules shared state, using * "javax.security.auth.login.name" and * "javax.security.auth.login.password" as the respective * keys. This is not performed if existing values already * exist for the username and password in the shared - * state, or if authentication fails. + * state, or if authentication fails.
* - * clearPass if, true, this LoginModule clears the + *
clearPass:
+ *
if, true, this LoginModule clears the * username and password stored in the module's shared * state after both phases of authentication - * (login and commit) have completed. - *
+ * (login and commit) have completed.
+ *
*

If the principal system property or key is already provided, the value of * "javax.security.auth.login.name" in the shared state is ignored. *

When multiple mechanisms to retrieve a ticket or key is provided, the - * preference order looks like this: + * preference order is: *

    *
  1. ticket cache *
  2. keytab @@ -225,7 +232,7 @@ import sun.misc.HexDumpEncoder; *
  3. user prompt *
*

Note that if any step fails, it will fallback to the next step. - * There's only one exception, it the shared state step fails and + * There's only one exception, if the shared state step fails and * useFirstPass=true, no user prompt is made. *

Examples of some configuration values for Krb5LoginModule in * JAAS config file and the results are: @@ -318,7 +325,7 @@ import sun.misc.HexDumpEncoder; *

useKeyTab = true * keyTab=<keytabname> * storeKey=true - * doNotPrompt=true; + * doNotPrompt=false; * *

The user will be prompted for the service principal name. * If the principal's @@ -328,6 +335,14 @@ import sun.misc.HexDumpEncoder; * If successful the TGT will be added to the * Subject's private credentials set. Otherwise the authentication will * fail. + *

    + *

    isInitiator = false useKeyTab = true + * keyTab=<keytabname> + * storeKey=true + * principal=*; + *

+ *

The acceptor will be an unbound acceptor and it can act as any principal + * as long that principal has keys in the keytab. *

    *

    * useTicketCache=true @@ -409,6 +424,7 @@ public class Krb5LoginModule implements LoginModule { private KerberosTicket kerbTicket = null; private KerberosKey[] kerbKeys = null; private StringBuffer krb5PrincName = null; + private boolean unboundServer = false; private char[] password = null; private static final String NAME = "javax.security.auth.login.name"; @@ -520,8 +536,6 @@ public class Krb5LoginModule implements LoginModule { */ public boolean login() throws LoginException { - int len; - validateConfiguration(); if (refreshKrb5Config) { try { if (debug) { @@ -544,6 +558,12 @@ public class Krb5LoginModule implements LoginModule { } } + validateConfiguration(); + + if (krb5PrincName != null && krb5PrincName.toString().equals("*")) { + unboundServer = true; + } + if (tryFirstPass) { try { attemptAuthentication(true); @@ -698,9 +718,17 @@ public class Krb5LoginModule implements LoginModule { * (encKeys == null) to check. */ if (useKeyTab) { - ktab = (keyTabName == null) - ? KeyTab.getInstance() - : KeyTab.getInstance(new File(keyTabName)); + if (!unboundServer) { + KerberosPrincipal kp = + new KerberosPrincipal(principal.getName()); + ktab = (keyTabName == null) + ? KeyTab.getInstance(kp) + : KeyTab.getInstance(kp, new File(keyTabName)); + } else { + ktab = (keyTabName == null) + ? KeyTab.getUnboundInstance() + : KeyTab.getUnboundInstance(new File(keyTabName)); + } if (isInitiator) { if (Krb5Util.keysFromJavaxKeyTab(ktab, principal).length == 0) { @@ -939,6 +967,13 @@ public class Krb5LoginModule implements LoginModule { ("Configuration Error" + " - either useTicketCache should be " + " true or renewTGT should be false"); + if (krb5PrincName != null && krb5PrincName.toString().equals("*")) { + if (isInitiator) { + throw new LoginException + ("Configuration Error" + + " - principal cannot be * when isInitiator is true"); + } + } } private boolean isCurrent(Credentials creds) @@ -1052,7 +1087,10 @@ public class Krb5LoginModule implements LoginModule { } // Let us add the kerbClientPrinc,kerbTicket and KeyTab/KerbKey (if // storeKey is true) - if (!princSet.contains(kerbClientPrinc)) { + + // We won't add "*" as a KerberosPrincipal + if (!unboundServer && + !princSet.contains(kerbClientPrinc)) { princSet.add(kerbClientPrinc); } diff --git a/jdk/src/share/classes/javax/security/auth/kerberos/JavaxSecurityAuthKerberosAccessImpl.java b/jdk/src/share/classes/javax/security/auth/kerberos/JavaxSecurityAuthKerberosAccessImpl.java index 4b20626ec75..fbf74718933 100644 --- a/jdk/src/share/classes/javax/security/auth/kerberos/JavaxSecurityAuthKerberosAccessImpl.java +++ b/jdk/src/share/classes/javax/security/auth/kerberos/JavaxSecurityAuthKerberosAccessImpl.java @@ -31,8 +31,8 @@ import sun.security.krb5.PrincipalName; class JavaxSecurityAuthKerberosAccessImpl implements JavaxSecurityAuthKerberosAccess { - public EncryptionKey[] keyTabGetEncryptionKeys( - KeyTab ktab, PrincipalName principal) { - return ktab.getEncryptionKeys(principal); + public sun.security.krb5.internal.ktab.KeyTab keyTabTakeSnapshot( + KeyTab ktab) { + return ktab.takeSnapshot(); } } diff --git a/jdk/src/share/classes/javax/security/auth/kerberos/KeyTab.java b/jdk/src/share/classes/javax/security/auth/kerberos/KeyTab.java index 3ebce9975a2..32f644b5906 100644 --- a/jdk/src/share/classes/javax/security/auth/kerberos/KeyTab.java +++ b/jdk/src/share/classes/javax/security/auth/kerberos/KeyTab.java @@ -41,6 +41,20 @@ import sun.security.krb5.RealmException; * {@link javax.security.auth.Subject Subject} during the commit phase of the * authentication process. *

    + * If a {@code KeyTab} object is obtained from {@link #getUnboundInstance()} + * or {@link #getUnboundInstance(java.io.File)}, it is unbound and thus can be + * used by any service principal. Otherwise, if it's obtained from + * {@link #getInstance(KerberosPrincipal)} or + * {@link #getInstance(KerberosPrincipal, java.io.File)}, it is bound to the + * specific service principal and can only be used by it. + *

    + * Please note the constructors {@link #getInstance()} and + * {@link #getInstance(java.io.File)} were created when there was no support + * for unbound keytabs. These methods should not be used anymore. An object + * created with either of these methods are considered to be bound to an + * unknown principal, which means, its {@link #isBound()} returns true and + * {@link #getPrincipal()} returns null. + *

    * It might be necessary for the application to be granted a * {@link javax.security.auth.PrivateCredentialPermission * PrivateCredentialPermission} if it needs to access the KeyTab @@ -52,7 +66,7 @@ import sun.security.krb5.RealmException; * The keytab file format is described at * * http://www.ioplex.com/utilities/keytab.txt. - * + *

    * @since 1.7 */ public final class KeyTab { @@ -74,21 +88,33 @@ public final class KeyTab { // is maintained in snapshot, this field is never "resolved". private final File file; + // Bound user: normally from the "principal" value in a JAAS krb5 + // login conf. Will be null if it's "*". + private final KerberosPrincipal princ; + + private final boolean bound; + // Set up JavaxSecurityAuthKerberosAccess in KerberosSecrets static { KerberosSecrets.setJavaxSecurityAuthKerberosAccess( new JavaxSecurityAuthKerberosAccessImpl()); } - private KeyTab(File file) { + private KeyTab(KerberosPrincipal princ, File file, boolean bound) { + this.princ = princ; this.file = file; + this.bound = bound; } /** - * Returns a {@code KeyTab} instance from a {@code File} object. + * Returns a {@code KeyTab} instance from a {@code File} object + * that is bound to an unknown service principal. *

    * The result of this method is never null. This method only associates * the returned {@code KeyTab} object with the file and does not read it. + *

    + * Developers should call {@link #getInstance(KerberosPrincipal,File)} + * when the bound service principal is known. * @param file the keytab {@code File} object, must not be null * @return the keytab instance * @throws NullPointerException if the {@code file} argument is null @@ -97,23 +123,99 @@ public final class KeyTab { if (file == null) { throw new NullPointerException("file must be non null"); } - return new KeyTab(file); + return new KeyTab(null, file, true); } /** - * Returns the default {@code KeyTab} instance. + * Returns an unbound {@code KeyTab} instance from a {@code File} + * object. + *

    + * The result of this method is never null. This method only associates + * the returned {@code KeyTab} object with the file and does not read it. + * @param file the keytab {@code File} object, must not be null + * @return the keytab instance + * @throws NullPointerException if the file argument is null + * @since 1.8 + */ + public static KeyTab getUnboundInstance(File file) { + if (file == null) { + throw new NullPointerException("file must be non null"); + } + return new KeyTab(null, file, false); + } + + /** + * Returns a {@code KeyTab} instance from a {@code File} object + * that is bound to the specified service principal. + *

    + * The result of this method is never null. This method only associates + * the returned {@code KeyTab} object with the file and does not read it. + * @param princ the bound service principal, must not be null + * @param file the keytab {@code File} object, must not be null + * @return the keytab instance + * @throws NullPointerException if either of the arguments is null + * @since 1.8 + */ + public static KeyTab getInstance(KerberosPrincipal princ, File file) { + if (princ == null) { + throw new NullPointerException("princ must be non null"); + } + if (file == null) { + throw new NullPointerException("file must be non null"); + } + return new KeyTab(princ, file, true); + } + + /** + * Returns the default {@code KeyTab} instance that is bound + * to an unknown service principal. *

    * The result of this method is never null. This method only associates * the returned {@code KeyTab} object with the default keytab file and * does not read it. + *

    + * Developers should call {@link #getInstance(KerberosPrincipal)} + * when the bound service principal is known. * @return the default keytab instance. */ public static KeyTab getInstance() { - return new KeyTab(null); + return new KeyTab(null, null, true); + } + + /** + * Returns the default unbound {@code KeyTab} instance. + *

    + * The result of this method is never null. This method only associates + * the returned {@code KeyTab} object with the default keytab file and + * does not read it. + * @return the default keytab instance + * @since 1.8 + */ + public static KeyTab getUnboundInstance() { + return new KeyTab(null, null, false); + } + + /** + * Returns the default {@code KeyTab} instance that is bound + * to the specified service principal. + *

    + * The result of this method is never null. This method only associates + * the returned {@code KeyTab} object with the default keytab file and + * does not read it. + * @param princ the bound service principal, must not be null + * @return the default keytab instance + * @throws NullPointerException if {@code princ} is null + * @since 1.8 + */ + public static KeyTab getInstance(KerberosPrincipal princ) { + if (princ == null) { + throw new NullPointerException("princ must be non null"); + } + return new KeyTab(princ, null, true); } //Takes a snapshot of the keytab content - private sun.security.krb5.internal.ktab.KeyTab takeSnapshot() { + sun.security.krb5.internal.ktab.KeyTab takeSnapshot() { return sun.security.krb5.internal.ktab.KeyTab.getInstance(file); } @@ -147,6 +249,9 @@ public final class KeyTab { *

    * Any unsupported key read from the keytab is ignored and not included * in the result. + *

    + * If this keytab is bound to a specific principal, calling this method on + * another principal will return an empty array. * * @param principal the Kerberos principal, must not be null. * @return the keys (never null, may be empty) @@ -157,8 +262,11 @@ public final class KeyTab { */ public KerberosKey[] getKeys(KerberosPrincipal principal) { try { - EncryptionKey[] keys = takeSnapshot().readServiceKeys( - new PrincipalName(principal.getName())); + if (princ != null && !principal.equals(princ)) { + return new KerberosKey[0]; + } + PrincipalName pn = new PrincipalName(principal.getName()); + EncryptionKey[] keys = takeSnapshot().readServiceKeys(pn); KerberosKey[] kks = new KerberosKey[keys.length]; for (int i=0; iKeyTab */ public int hashCode() { - return Objects.hash(file); + return Objects.hash(file, princ, bound); } /** @@ -225,6 +336,31 @@ public final class KeyTab { } KeyTab otherKtab = (KeyTab) other; - return Objects.equals(otherKtab.file, file); + return Objects.equals(otherKtab.princ, princ) && + Objects.equals(otherKtab.file, file) && + bound == otherKtab.bound; + } + + /** + * Returns the service principal this {@code KeyTab} object + * is bound to. Returns {@code null} if it's not bound. + *

    + * Please note the deprecated constructors create a KeyTab object bound for + * some unknown principal. In this case, this method also returns null. + * User can call {@link #isBound()} to verify this case. + * @return the service principal + * @since 1.8 + */ + public KerberosPrincipal getPrincipal() { + return princ; + } + + /** + * Returns if the keytab is bound to a principal + * @return if the keytab is bound to a principal + * @since 1.8 + */ + public boolean isBound() { + return bound; } } diff --git a/jdk/src/share/classes/sun/security/jgss/LoginConfigImpl.java b/jdk/src/share/classes/sun/security/jgss/LoginConfigImpl.java index 41a783afef3..52e2fa4728d 100644 --- a/jdk/src/share/classes/sun/security/jgss/LoginConfigImpl.java +++ b/jdk/src/share/classes/sun/security/jgss/LoginConfigImpl.java @@ -175,6 +175,7 @@ public class LoginConfigImpl extends Configuration { options.put("useKeyTab", "true"); options.put("storeKey", "true"); options.put("doNotPrompt", "true"); + options.put("principal", "*"); options.put("isInitiator", "false"); } else { options.put("useTicketCache", "true"); diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java index f0495eef872..0d5a314ffd7 100644 --- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java +++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Util.java @@ -242,15 +242,25 @@ public class Krb5Util { kerbTicket.getClientAddresses()); } + /** + * A helper method to get a sun..KeyTab from a javax..KeyTab + * @param ktab the javax..KeyTab object + * @return the sun..KeyTab object + */ + public static sun.security.krb5.internal.ktab.KeyTab + snapshotFromJavaxKeyTab(KeyTab ktab) { + return KerberosSecrets.getJavaxSecurityAuthKerberosAccess() + .keyTabTakeSnapshot(ktab); + } + /** * A helper method to get EncryptionKeys from a javax..KeyTab - * @param ktab the javax..KeyTab class + * @param ktab the javax..KeyTab object * @param cname the PrincipalName * @return the EKeys, never null, might be empty */ public static EncryptionKey[] keysFromJavaxKeyTab( KeyTab ktab, PrincipalName cname) { - return KerberosSecrets.getJavaxSecurityAuthKerberosAccess(). - keyTabGetEncryptionKeys(ktab, cname); + return snapshotFromJavaxKeyTab(ktab).readServiceKeys(cname); } } diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/ServiceCreds.java b/jdk/src/share/classes/sun/security/jgss/krb5/ServiceCreds.java index 21b8f57b229..824724bf34e 100644 --- a/jdk/src/share/classes/sun/security/jgss/krb5/ServiceCreds.java +++ b/jdk/src/share/classes/sun/security/jgss/krb5/ServiceCreds.java @@ -101,9 +101,22 @@ public final class ServiceCreds { if (serverPrincipal != null) { // A named principal sc.kp = new KerberosPrincipal(serverPrincipal); } else { - if (sc.allPrincs.size() == 1) { // choose the only one - sc.kp = sc.allPrincs.iterator().next(); - serverPrincipal = sc.kp.getName(); + // For compatibility reason, we set the name of default principal + // to the "only possible" name it can take, which means there is + // only one KerberosPrincipal and there is no unbound keytabs + if (sc.allPrincs.size() == 1) { + boolean hasUnbound = false; + for (KeyTab ktab: SubjectComber.findMany( + subj, null, null, KeyTab.class)) { + if (!ktab.isBound()) { + hasUnbound = true; + break; + } + } + if (!hasUnbound) { + sc.kp = sc.allPrincs.iterator().next(); + serverPrincipal = sc.kp.getName(); + } } } @@ -131,20 +144,35 @@ public final class ServiceCreds { } /** - * Gets keys for someone unknown. - * Used by TLS or as a fallback in getEKeys(). Can still return an - * empty array. + * Gets keys for "someone". Used in 2 cases: + * 1. By TLS because it needs to get keys before client comes in. + * 2. As a fallback in getEKeys() below. + * This method can still return an empty array. */ public KerberosKey[] getKKeys() { if (destroyed) { throw new IllegalStateException("This object is destroyed"); } - if (kp != null) { - return getKKeys(kp); - } else if (!allPrincs.isEmpty()) { - return getKKeys(allPrincs.iterator().next()); + KerberosPrincipal one = kp; // named principal + if (one == null && !allPrincs.isEmpty()) { // or, a known principal + one = allPrincs.iterator().next(); + } + if (one == null) { // Or, some random one + for (KeyTab ktab: ktabs) { + // Must be unbound keytab, otherwise, allPrincs is not empty + PrincipalName pn = + Krb5Util.snapshotFromJavaxKeyTab(ktab).getOneName(); + if (pn != null) { + one = new KerberosPrincipal(pn.getName()); + break; + } + } + } + if (one != null) { + return getKKeys(one); + } else { + return new KerberosKey[0]; } - return new KerberosKey[0]; } /** @@ -152,15 +180,13 @@ public final class ServiceCreds { * @param princ the target name initiator requests. Not null. * @return keys for the princ, never null, might be empty */ - private KerberosKey[] getKKeys(KerberosPrincipal princ) { - ArrayList keys = new ArrayList<>(); - if (kp != null && !princ.equals(kp)) { - return new KerberosKey[0]; // Not me + public KerberosKey[] getKKeys(KerberosPrincipal princ) { + if (destroyed) { + throw new IllegalStateException("This object is destroyed"); } - if (!allPrincs.contains(princ)) { - return new KerberosKey[0]; // Not someone I know, This check - // is necessary but a KeyTab has - // no principal name recorded. + ArrayList keys = new ArrayList<>(); + if (kp != null && !princ.equals(kp)) { // named principal + return new KerberosKey[0]; } for (KerberosKey k: kk) { if (k.getPrincipal().equals(princ)) { @@ -168,6 +194,13 @@ public final class ServiceCreds { } } for (KeyTab ktab: ktabs) { + if (ktab.getPrincipal() == null && ktab.isBound()) { + // legacy bound keytab. although we don't know who + // the bound principal is, it must be in allPrincs + if (!allPrincs.contains(princ)) { + continue; // skip this legacy bound keytab + } + } for (KerberosKey k: ktab.getKeys(princ)) { keys.add(k); } @@ -186,12 +219,12 @@ public final class ServiceCreds { } KerberosKey[] kkeys = getKKeys(new KerberosPrincipal(princ.getName())); if (kkeys.length == 0) { - // Note: old JDK does not perform real name checking. If the - // acceptor starts by name A but initiator requests for B, - // as long as their keys match (i.e. A's keys can decrypt B's - // service ticket), the authentication is OK. There are real - // customers depending on this to use different names for a - // single service. + // Fallback: old JDK does not perform real name checking. If the + // acceptor has host.sun.com but initiator requests for host, + // as long as their keys match (i.e. keys for one can decrypt + // the other's service ticket), the authentication is OK. + // There are real customers depending on this to use different + // names for a single service. kkeys = getKKeys(); } EncryptionKey[] ekeys = new EncryptionKey[kkeys.length]; diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/SubjectComber.java b/jdk/src/share/classes/sun/security/jgss/krb5/SubjectComber.java index d267dbd4b21..ad1723fe09e 100644 --- a/jdk/src/share/classes/sun/security/jgss/krb5/SubjectComber.java +++ b/jdk/src/share/classes/sun/security/jgss/krb5/SubjectComber.java @@ -86,36 +86,39 @@ class SubjectComber { List answer = (oneOnly ? null : new ArrayList()); if (credClass == KeyTab.class) { - // TODO: There is currently no good way to filter out keytabs - // not for serverPrincipal. We can only check the principal - // set. If the server is not there, we can be sure none of the - // keytabs should be used, otherwise, use all for safety. - boolean useAll = false; - if (serverPrincipal != null) { - for (KerberosPrincipal princ: - subject.getPrincipals(KerberosPrincipal.class)) { - if (princ.getName().equals(serverPrincipal)) { - useAll = true; - break; + Iterator iterator = + subject.getPrivateCredentials(KeyTab.class).iterator(); + while (iterator.hasNext()) { + KeyTab t = iterator.next(); + if (serverPrincipal != null && t.isBound()) { + KerberosPrincipal name = t.getPrincipal(); + if (name != null) { + if (!serverPrincipal.equals(name.getName())) { + continue; + } + } else { + // legacy bound keytab. although we don't know who + // the bound principal is, it must be in allPrincs + boolean found = false; + for (KerberosPrincipal princ: + subject.getPrincipals(KerberosPrincipal.class)) { + if (princ.getName().equals(serverPrincipal)) { + found = true; + break; + } + } + if (!found) continue; } } - } else { - useAll = true; - } - if (useAll) { - Iterator iterator = - subject.getPrivateCredentials(KeyTab.class).iterator(); - while (iterator.hasNext()) { - KeyTab t = iterator.next(); - if (DEBUG) { - System.out.println("Found " + credClass.getSimpleName() - + " " + t); - } - if (oneOnly) { - return t; - } else { - answer.add(credClass.cast(t)); - } + // Check passed, we can add now + if (DEBUG) { + System.out.println("Found " + credClass.getSimpleName() + + " " + t); + } + if (oneOnly) { + return t; + } else { + answer.add(credClass.cast(t)); } } } else if (credClass == KerberosKey.class) { diff --git a/jdk/src/share/classes/sun/security/krb5/JavaxSecurityAuthKerberosAccess.java b/jdk/src/share/classes/sun/security/krb5/JavaxSecurityAuthKerberosAccess.java index 3992e487108..ae3dc3d0b04 100644 --- a/jdk/src/share/classes/sun/security/krb5/JavaxSecurityAuthKerberosAccess.java +++ b/jdk/src/share/classes/sun/security/krb5/JavaxSecurityAuthKerberosAccess.java @@ -35,9 +35,8 @@ import sun.security.krb5.PrincipalName; */ public interface JavaxSecurityAuthKerberosAccess { /** - * Returns keys for a principal in a keytab. - * @return the keys, never null, can be empty. + * Returns a snapshot to the backing keytab */ - public EncryptionKey[] keyTabGetEncryptionKeys( - KeyTab ktab, PrincipalName principal); + public sun.security.krb5.internal.ktab.KeyTab keyTabTakeSnapshot( + KeyTab ktab); } diff --git a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java index d1023de9de3..b556c90524c 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java @@ -46,6 +46,7 @@ import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; import java.util.Vector; +import sun.security.jgss.krb5.ServiceCreds; /** * This class represents key table. The key table functions deal with storing @@ -267,6 +268,15 @@ public class KeyTab implements KeyTabConstants { } } + /** + * Returns a principal name in this keytab. Used by + * {@link ServiceCreds#getKKeys()}. + */ + public PrincipalName getOneName() { + int size = entries.size(); + return size > 0 ? entries.elementAt(size-1).service : null; + } + /** * Reads all keys for a service from the keytab file that have * etypes that have been configured for use. If there are multiple diff --git a/jdk/src/share/classes/sun/security/provider/ConfigSpiFile.java b/jdk/src/share/classes/sun/security/provider/ConfigSpiFile.java index 3a9ca47677a..03cdc5712d0 100644 --- a/jdk/src/share/classes/sun/security/provider/ConfigSpiFile.java +++ b/jdk/src/share/classes/sun/security/provider/ConfigSpiFile.java @@ -404,6 +404,7 @@ public final class ConfigSpiFile extends ConfigurationSpi { st.wordChars('$', '$'); st.wordChars('_', '_'); st.wordChars('-', '-'); + st.wordChars('*', '*'); st.lowerCaseMode(false); st.slashSlashComments(true); st.slashStarComments(true); diff --git a/jdk/test/sun/security/krb5/ServiceCredsCombination.java b/jdk/test/sun/security/krb5/ServiceCredsCombination.java index 3208560e788..5c6ac4b1894 100644 --- a/jdk/test/sun/security/krb5/ServiceCredsCombination.java +++ b/jdk/test/sun/security/krb5/ServiceCredsCombination.java @@ -62,11 +62,38 @@ public class ServiceCredsCombination { check("b", "b", princ("a"), princ("b"), oldktab(), oldktab()); check(null, null, princ("a"), princ("b"), oldktab(), oldktab()); check("x", "NOCRED", princ("a"), princ("b"), oldktab(), oldktab()); + // bound ktab + check("c", "c", princ("c"), ktab("c")); + check(null, "c", princ("c"), ktab("c")); + // unbound ktab + check("x", "x", ktab()); + check(null, null, ktab()); + // Two bound ktab + check("c1", "c1", princ("c1"), princ("c2"), ktab("c1"), ktab("c2")); + check("c2", "c2", princ("c1"), princ("c2"), ktab("c1"), ktab("c2")); + check("x", "NOCRED", princ("c1"), princ("c2"), ktab("c1"), ktab("c2")); + check(null, null, princ("c1"), princ("c2"), ktab("c1"), ktab("c2")); + // One bound, one unbound + check("c1", "c1", princ("c1"), ktab("c1"), ktab()); + check("x", "x", princ("c1"), ktab("c1"), ktab()); + check(null, null, princ("c1"), ktab("c1"), ktab()); + // Two unbound ktab + check("x", "x", ktab(), ktab()); + check(null, null, ktab(), ktab()); // pass + old ktab check("a", "a", princ("a"), princ("b"), key("a"), oldktab()); check("b", "b", princ("a"), princ("b"), key("a"), oldktab()); check(null, null, princ("a"), princ("b"), key("a"), oldktab()); check("x", "NOCRED", princ("a"), princ("b"), key("a"), oldktab()); + // pass + bound ktab + check("a", "a", princ("a"), princ("c"), key("a"), ktab("c")); + check("c", "c", princ("a"), princ("c"), key("a"), ktab("c")); + check("x", "NOCRED", princ("a"), princ("c"), key("a"), ktab("c")); + check(null, null, princ("a"), princ("c"), key("a"), ktab("c")); + // pass + unbound ktab + check("a", "a", princ("a"), key("a"), ktab()); + check("x", "x", princ("a"), key("a"), ktab()); + check(null, null, princ("a"), key("a"), ktab()); // Compatibility, automatically add princ for keys check(null, "a", key("a")); check("x", "NOCRED", key("a")); @@ -130,4 +157,10 @@ public class ServiceCredsCombination { private static KeyTab oldktab() { return KeyTab.getInstance(); } + static KeyTab ktab(String s) { + return KeyTab.getInstance(princ(s)); + } + static KeyTab ktab() { + return KeyTab.getUnboundInstance(); + } } diff --git a/jdk/test/sun/security/krb5/auto/AcceptPermissions.java b/jdk/test/sun/security/krb5/auto/AcceptPermissions.java index 3a6d422842f..1b562eaf99a 100644 --- a/jdk/test/sun/security/krb5/auto/AcceptPermissions.java +++ b/jdk/test/sun/security/krb5/auto/AcceptPermissions.java @@ -26,7 +26,8 @@ * @bug 9999999 * @summary default principal can act as anyone * @compile -XDignore.symbol.file AcceptPermissions.java - * @run main/othervm AcceptPermissions + * @run main/othervm AcceptPermissions two + * @run main/othervm AcceptPermissions unbound */ import java.nio.file.Files; @@ -83,15 +84,20 @@ public class AcceptPermissions extends SecurityManager { public static void main(String[] args) throws Exception { System.setSecurityManager(new AcceptPermissions()); new OneKDC(null).writeJAASConf(); - String two = "two {\n" + String moreEntries = "two {\n" + " com.sun.security.auth.module.Krb5LoginModule required" + " principal=\"" + OneKDC.SERVER + "\" useKeyTab=true" + " isInitiator=false storeKey=true;\n" + " com.sun.security.auth.module.Krb5LoginModule required" + " principal=\"" + OneKDC.BACKEND + "\" useKeyTab=true" + " isInitiator=false storeKey=true;\n" + + "};\n" + + "unbound {" + + " com.sun.security.auth.module.Krb5LoginModule required" + + " principal=* useKeyTab=true" + + " isInitiator=false storeKey=true;\n" + "};\n"; - Files.write(Paths.get(OneKDC.JAAS_CONF), two.getBytes(), + Files.write(Paths.get(OneKDC.JAAS_CONF), moreEntries.getBytes(), StandardOpenOption.APPEND); Context c, s; @@ -114,7 +120,7 @@ public class AcceptPermissions extends SecurityManager { // Named principal (even if there are 2 JAAS modules) initPerms(OneKDC.SERVER); c = Context.fromJAAS("client"); - s = Context.fromJAAS("two"); + s = Context.fromJAAS(args[0]); c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); s.startAsServer(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); checkPerms(); @@ -136,7 +142,7 @@ public class AcceptPermissions extends SecurityManager { // Default principal with no predictable name initPerms(); // permission not needed for cred !!! c = Context.fromJAAS("client"); - s = Context.fromJAAS("two"); + s = Context.fromJAAS(args[0]); c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); checkPerms(); diff --git a/jdk/test/sun/security/krb5/auto/GSSUnbound.java b/jdk/test/sun/security/krb5/auto/GSSUnbound.java new file mode 100644 index 00000000000..a1022d4f8c8 --- /dev/null +++ b/jdk/test/sun/security/krb5/auto/GSSUnbound.java @@ -0,0 +1,61 @@ +/* + * 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. + * + * 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. + */ + +/* + * @test + * @bug 8001104 + * @summary Unbound SASL service: the GSSAPI/krb5 mech + * @compile -XDignore.symbol.file GSSUnbound.java + * @run main/othervm GSSUnbound + */ + +import java.security.Security; +import sun.security.jgss.GSSUtil; + +// Testing JGSS without JAAS +public class GSSUnbound { + + public static void main(String[] args) throws Exception { + + new OneKDC(null); + + Context c, s; + c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false); + s = Context.fromThinAir(); + + // This is the only setting needed for JGSS without JAAS. The default + // JAAS config entries are already created by OneKDC. + System.setProperty("javax.security.auth.useSubjectCredsOnly", "false"); + + c.startAsClient(OneKDC.BACKEND, GSSUtil.GSS_KRB5_MECH_OID); + s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + + Context.handshake(c, s); + + Context.transmit("i say high --", c, s); + Context.transmit(" you say low", s, c); + + s.dispose(); + c.dispose(); + } +} diff --git a/jdk/test/sun/security/krb5/auto/OneKDC.java b/jdk/test/sun/security/krb5/auto/OneKDC.java index 5c87abb961a..90a7e8e8748 100644 --- a/jdk/test/sun/security/krb5/auto/OneKDC.java +++ b/jdk/test/sun/security/krb5/auto/OneKDC.java @@ -76,6 +76,8 @@ public class OneKDC extends KDC { Config.refresh(); writeKtab(KTAB); + Security.setProperty("auth.login.defaultCallbackHandler", + "OneKDC$CallbackForClient"); } /** @@ -93,7 +95,7 @@ public class OneKDC extends KDC { " com.sun.security.auth.module.Krb5LoginModule required;\n};\n" + "com.sun.security.jgss.krb5.accept {\n" + " com.sun.security.auth.module.Krb5LoginModule required\n" + - " principal=\"" + SERVER + "\"\n" + + " principal=\"*\"\n" + " useKeyTab=true\n" + " isInitiator=false\n" + " storeKey=true;\n};\n" + @@ -112,7 +114,6 @@ public class OneKDC extends KDC { " isInitiator=false;\n};\n" ).getBytes()); fos.close(); - Security.setProperty("auth.login.defaultCallbackHandler", "OneKDC$CallbackForClient"); } /** diff --git a/jdk/test/sun/security/krb5/auto/SaslUnbound.java b/jdk/test/sun/security/krb5/auto/SaslUnbound.java new file mode 100644 index 00000000000..64d9a1b3c6e --- /dev/null +++ b/jdk/test/sun/security/krb5/auto/SaslUnbound.java @@ -0,0 +1,113 @@ +/* + * 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. + * + * 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. + */ + +/* + * @test + * @bug 8001104 + * @summary Unbound SASL service: the GSSAPI/krb5 mech + * @compile -XDignore.symbol.file SaslUnbound.java + * @run main/othervm SaslUnbound 0 + * @run main/othervm/fail SaslUnbound 1 + * @run main/othervm/fail SaslUnbound 2 + * @run main/othervm/fail SaslUnbound 3 + * @run main/othervm/fail SaslUnbound 4 + */ +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.sasl.*; + +public class SaslUnbound { + + public static void main(String[] args) throws Exception { + + String serverProtocol, serverName; + switch (args[0].charAt(0)) { + case '1': // Using another protocol, should fail + serverProtocol = "serv"; + serverName = null; + break; + case '2': // Using another protocol, should fail + serverProtocol = "otherwise"; + serverName = null; + break; + case '3': // Using another protocol, should fail + serverProtocol = "otherwise"; + serverName = "host." + OneKDC.REALM; + break; + case '4': // Bound to another serverName, should fail. + serverProtocol = "server"; + serverName = "host2." + OneKDC.REALM; + break; + default: // Good unbound server + serverProtocol = "server"; + serverName = null; + break; + } + new OneKDC(null).writeJAASConf(); + System.setProperty("javax.security.auth.useSubjectCredsOnly", "false"); + + HashMap clntprops = new HashMap(); + clntprops.put(Sasl.QOP, "auth-conf"); + SaslClient sc = Sasl.createSaslClient( + new String[]{"GSSAPI"}, null, "server", + "host." + OneKDC.REALM, clntprops, null); + + final HashMap srvprops = new HashMap(); + srvprops.put(Sasl.QOP, "auth,auth-int,auth-conf"); + SaslServer ss = Sasl.createSaslServer("GSSAPI", serverProtocol, + serverName, srvprops, + new CallbackHandler() { + public void handle(Callback[] callbacks) + throws IOException, UnsupportedCallbackException { + for (Callback cb : callbacks) { + if (cb instanceof RealmCallback) { + ((RealmCallback) cb).setText(OneKDC.REALM); + } else if (cb instanceof AuthorizeCallback) { + ((AuthorizeCallback) cb).setAuthorized(true); + } + } + } + }); + + byte[] token = new byte[0]; + while (!sc.isComplete() || !ss.isComplete()) { + if (!sc.isComplete()) { + token = sc.evaluateChallenge(token); + } + if (!ss.isComplete()) { + token = ss.evaluateResponse(token); + } + } + System.out.println(ss.getNegotiatedProperty(Sasl.BOUND_SERVER_NAME)); + byte[] hello = "hello".getBytes(); + token = sc.wrap(hello, 0, hello.length); + token = ss.unwrap(token, 0, token.length); + if (!Arrays.equals(hello, token)) { + throw new Exception("Message altered"); + } + } +} diff --git a/jdk/test/sun/security/krb5/auto/UnboundService.java b/jdk/test/sun/security/krb5/auto/UnboundService.java new file mode 100644 index 00000000000..c6d093c9266 --- /dev/null +++ b/jdk/test/sun/security/krb5/auto/UnboundService.java @@ -0,0 +1,85 @@ +/* + * 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. + * + * 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. + */ + +/* + * @test + * @bug 8001104 + * @summary Unbound SASL service: the GSSAPI/krb5 mech + * @compile -XDignore.symbol.file UnboundService.java + * @run main/othervm UnboundService null null + * @run main/othervm UnboundService server/host.rabbit.hole null + * @run main/othervm UnboundService server/host.rabbit.hole@RABBIT.HOLE null + * @run main/othervm/fail UnboundService backend/host.rabbit.hole null + * @run main/othervm UnboundService null server@host.rabbit.hole + * @run main/othervm UnboundService server/host.rabbit.hole server@host.rabbit.hole + * @run main/othervm UnboundService server/host.rabbit.hole@RABBIT.HOLE server@host.rabbit.hole + * @run main/othervm/fail UnboundService backend/host.rabbit.hole server@host.rabbit.hole + */ + +import java.io.File; +import java.io.FileOutputStream; +import sun.security.jgss.GSSUtil; + +public class UnboundService { + + /** + * @param args JAAS config pricipal and GSSCredential creation name + */ + public static void main(String[] args) throws Exception { + + String principal = args[0]; + if (principal.equals("null")) principal = null; + + String server = args[1]; + if (server.equals("null")) server = null; + + new OneKDC(null).writeJAASConf(); + File f = new File(OneKDC.JAAS_CONF); + try (FileOutputStream fos = new FileOutputStream(f)) { + fos.write(( + "client {\n" + + " com.sun.security.auth.module.Krb5LoginModule required;\n};\n" + + "unbound {\n" + + " com.sun.security.auth.module.Krb5LoginModule required\n" + + " useKeyTab=true\n" + + " principal=" + + (principal==null? "*" :("\"" + principal + "\"")) + "\n" + + " doNotPrompt=true\n" + + " isInitiator=false\n" + + " storeKey=true;\n};\n" + ).getBytes()); + } + + Context c, s; + c = Context.fromJAAS("client"); + s = Context.fromJAAS("unbound"); + + c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); + s.startAsServer(server, GSSUtil.GSS_KRB5_MECH_OID); + + Context.handshake(c, s); + + s.dispose(); + c.dispose(); + } +} From 76953b4d1e941a364ef931eef42447adb30e397a Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Sat, 9 Feb 2013 16:43:58 +0800 Subject: [PATCH 118/158] 8007761: NTLM coding errors Reviewed-by: chegar --- .../share/classes/com/sun/security/ntlm/Client.java | 3 +-- .../share/classes/com/sun/security/ntlm/NTLM.java | 12 ++++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/jdk/src/share/classes/com/sun/security/ntlm/Client.java b/jdk/src/share/classes/com/sun/security/ntlm/Client.java index fcad176b052..7117cdcdc93 100644 --- a/jdk/src/share/classes/com/sun/security/ntlm/Client.java +++ b/jdk/src/share/classes/com/sun/security/ntlm/Client.java @@ -138,8 +138,7 @@ public final class Client extends NTLM { domain = domainFromServer; } if (domain == null) { - throw new NTLMException(NTLMException.NO_DOMAIN_INFO, - "No domain info"); + domain = ""; } int flags = 0x88200 | (inputFlags & 3); diff --git a/jdk/src/share/classes/com/sun/security/ntlm/NTLM.java b/jdk/src/share/classes/com/sun/security/ntlm/NTLM.java index f0949b13a0a..b85fcee7812 100644 --- a/jdk/src/share/classes/com/sun/security/ntlm/NTLM.java +++ b/jdk/src/share/classes/com/sun/security/ntlm/NTLM.java @@ -136,10 +136,10 @@ class NTLM { int readInt(int offset) throws NTLMException { try { - return internal[offset] & 0xff + - (internal[offset+1] & 0xff << 8) + - (internal[offset+2] & 0xff << 16) + - (internal[offset+3] & 0xff << 24); + return (internal[offset] & 0xff) + + ((internal[offset+1] & 0xff) << 8) + + ((internal[offset+2] & 0xff) << 16) + + ((internal[offset+3] & 0xff) << 24); } catch (ArrayIndexOutOfBoundsException ex) { throw new NTLMException(NTLMException.PACKET_READ_ERROR, "Input message incorrect size"); @@ -148,8 +148,8 @@ class NTLM { int readShort(int offset) throws NTLMException { try { - return internal[offset] & 0xff + - (internal[offset+1] & 0xff << 8); + return (internal[offset] & 0xff) + + ((internal[offset+1] & 0xff << 8)); } catch (ArrayIndexOutOfBoundsException ex) { throw new NTLMException(NTLMException.PACKET_READ_ERROR, "Input message incorrect size"); From 8a4107ab649f877a4a6ca29f978629aa19d606f2 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Sun, 10 Feb 2013 08:07:59 -0800 Subject: [PATCH 119/158] 8007519: [unpack200] produces bad class files when producing BootstrapMethods attribute Reviewed-by: alanb --- jdk/test/ProblemList.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 1870b0b9219..69255074326 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -317,13 +317,16 @@ sun/tools/jconsole/ImmutableResourceTest.sh generic-all # 7132203 sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all -# Tests take too long, see 7143279 -tools/pack200/CommandLineTests.java generic-all -tools/pack200/Pack200Test.java generic-all +# Tests take too long, on sparcs see 7143279 +tools/pack200/CommandLineTests.java solaris-all, macosx-all +tools/pack200/Pack200Test.java solaris-all, macosx-all # 7150569 tools/launcher/UnicodeTest.java macosx-all +# 8006039 +tools/launcher/I18NJarTest.java macosx-all + # 8007410 tools/launcher/FXLauncherTest.java linux-all From 83b9b38fc5e75b659f5327340318cb348b075228 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Sun, 10 Feb 2013 08:49:39 -0800 Subject: [PATCH 120/158] 8007902: [unpack200] incorrect BootstrapMethods attribute Reviewed-by: jjh --- .../com/sun/java/util/jar/pack/unpack.cpp | 3 ++- jdk/test/tools/pack200/Pack200Test.java | 4 ++-- .../pack200/pack200-verifier/data/golden.jar | Bin 423427 -> 433984 bytes 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp index bc91827f66c..4b5e38a0de1 100644 --- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp @@ -4758,8 +4758,8 @@ int unpacker::write_bsms(int naOffset, int na) { PTRLIST_QSORT(cp.requested_bsms, outputEntry_cmp); // append the BootstrapMethods attribute (after the InnerClasses attr): putref(cp.sym[cpool::s_BootstrapMethods]); + // make a note of the offset, for lazy patching int sizeOffset = (int)wpoffset(); - byte* sizewp = wp; putu4(-99); // attr size will be patched putu2(cur_class_local_bsm_count); int written_bsms = 0; @@ -4776,6 +4776,7 @@ int unpacker::write_bsms(int naOffset, int na) { written_bsms += 1; } assert(written_bsms == cur_class_local_bsm_count); // else insane + byte* sizewp = wp_at(sizeOffset); putu4_at(sizewp, (int)(wp - (sizewp+4))); // size of code attr putu2_at(wp_at(naOffset), ++na); // increment class attr count } diff --git a/jdk/test/tools/pack200/Pack200Test.java b/jdk/test/tools/pack200/Pack200Test.java index 476ece18216..d897bf86824 100644 --- a/jdk/test/tools/pack200/Pack200Test.java +++ b/jdk/test/tools/pack200/Pack200Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -30,7 +30,7 @@ import java.util.jar.*; /* * @test - * @bug 6521334 6712743 + * @bug 6521334 6712743 8007902 * @summary check for memory leaks, test general packer/unpacker functionality\ * using native and java unpackers * @compile -XDignore.symbol.file Utils.java Pack200Test.java diff --git a/jdk/test/tools/pack200/pack200-verifier/data/golden.jar b/jdk/test/tools/pack200/pack200-verifier/data/golden.jar index 913fe14340e22ba8b47f4fdceb2e0b1919cbd370..511cc0f43ab044021c1ed5ff60b76f4da4472e0f 100644 GIT binary patch delta 11227 zcmb7~Wl&sQv+t2%g1bu~xVr^+X9yaC1$TF!0E4>@5+Jw-cZcBa?gWAlt|2GS`<_$p zxgYMWx~po{+TFdocdu2o*N0#ILrzJ0x=1lUC?f*!;gFG$;ntNDq=GO*G2t6A5#H#6 zw-ptn;QrTO`TK0+Xzs(|ZsF$6VQb=P!r|d=W6$B{?rLG;z#;8qZ*O7d?&RvmZf0-d z=C&a6#+!U#;Uaca$;;Adk%F^m!!RPv* zb467A`gT(u&NxkQ3Z5eU1SnzHFX<@3>MlXpwoc_7k)YPI6 z+B)s6^p@yRa0LU?@qO#GOF3SJ3n|gu1}CzWiyc3a8}V-g1_N-&b<4LI1cRQc6@zh? zJ`CM{BnifV z>bIV!sKIUq+q7(8n6>z^o;ypUcrBR>!wYkse!i*f|w1?!#IB?-SMF;A@?>_l)v2&mOfcTP!$I(BQ z?Tut~^rHeMFY?ot!6;-&=u)U7Cz_16V+Liy8;?i;ENslO**8#SuwJ}#X0Wx>BYeq@ zaWUDSYwaD6croxyUPIw!`=E(&A@98Krf)*5fNLMcr(J3@jU5osy5$5o@z43rUZC9n z1{+le>E-NF^J>XA_?^=*8H@)1(%7))kVj7{X!|M-MA^5Eya+ME0L$&CJxiyxhOpMZ zl_72em$tIt-!$l!94z|&-kg?#RMs((Vb`4?Q~{-Sn5(yRDbB6=gH_+=E4_p@0TCH| zf1hE<)odVBtFUI(*=8LA)I0?DZ?&64f3uDI-I`W!;hh@I*#Jak3c~hnZ`r8Nc6klE>2Ho;oHd3AD^)Y zx~V0|a;DW-lm`>!GA23!k%zU86%5PPr^sZlgfx;UE-JV7&pBi_oE2XQHzvJ_q-MTU{gS$6`1P%ls@9`b>Ay zwys=|SP+FKUDI&{r}i3I?5W(a{v06+7IstdHZ^xno)LBOT-iZdUI(fu1`|*pDyxwU%sxHDR2W{fXA>Y5QF_@$GFt}Nm{r!=*uJ>=@ap-uM$YPoW30@)n@^XsTB!Ls*4Z

    gljgBPE%t%ikrIUk2b%&FYo%LziLeB zF8t;0p;zFXRa3QM>OB_gteqBR2s9KYA0$a26$&!@B zk(5MsHZttmcQ!CIN?#BOWLQ_{8c;688%~$tfr_w02jo7T#+T!=-EI4rj2)cEPtG%} z3zYJt`e39xq6rl^5t~nbtT6X*n6|!c@|Loh`%|H5;JHeDriqR(Z{b3<%_D-6_6>B$ zUxf2r+%q5K@Z>t2@-VIwcM8bws~C+|cwzzZ=F7t4IHaMpk~y3Jf7 zh4)MEpS9mHhLw7TPLz~#YULsLTcui*v0eswUv4|^W!8xFW=?bzg}{Oir}#=|l0_c;|L$a`Z+0#hk6(yDM7an7EU2w~`^YN@%#$EdITROr-+dQEdJ zk1L^J41+xHG4e)1YhX{@$*lNoMVE-RK+HTX31)cS^@<%a49Zzpj`!|0_M*krppGK- zoi)Sex>mL4Q@U`WQU2RZH|$BFmS(w5^9X|hn*jCTD)`dxhTJBW{8EPWl!uH>*8U$w zlw1V@>69|b9?eJPFn9``21?ZQ=D$c;!^m$Asa(8m3?XJXSn1qzD|1SPvt zB?hgObsZ>Zn31ZkoTs$zqZ}~B^{8C(0{eOi&B~zSjEtx6-Ak?vC_v#nj41`%>_2kx zJ^6|As)823_kj)k3ppt%i+sD$>fQa(CneKOy~2hvU)ZR7ML`k|0Gys&qJw^+zPmy+ zaBsGn`ZJW>UoZT6N1xZz+~lp;Uf<`-<$56lI3kT9H+KJ=^3UxsfzbC4!DwJ*!O!l! z@a2JreOuT2P*k^X8=)MUOOysMByF(!PHy@N3$MTI5LkRqQ|J{bwJl=C#F5MniTjW(=G{O|v5$)caYuW{=8i%{Lx&MXP4tqJ*yh2di#{{(fh%Sf zQTV2I49y7ok?CrBz?n;mXu!0PUhZfYn@bPRtQ1V|hHutdFGEyhN*>D8Mm&X$bz~Zx z9>F;RBcTWr*P7kEd`8SmvMhjfcX8_}O9kPoMT(zZr`ij&@o^~2CJSm7U;;|{93+BC*GDMj)xgbJIlC-JxNEdiFT@W1Kp!e8n^k;5lZLaS zFU}E$DIg}9;G+*wYu6nj_>n9WrrFl+QS>7H@Y$xK!Sq;|frWeJVjC!_E6~*Ai|eO* z2hZKkQDDh3W1LiJM9I9{btZKmqv~z1PYi#-hD_H4VO68oC@_3EX5V51<>67;1gtTr z%QutGPi~6VPe`X?$1BD6;)X~{tj$kn5h1DhV+L8%4=0225D2(OH2 z@#i3Cp*`tgJ1+2cPnO}m=Zu81AefkUdCWXjb>%BFHf2w2V@44x>`6L$cOh+;fii7B zq;Vx?nx8XL$=8CQF|&&=Xs#~hs~#?&WzztC#j&yxH0P%j<@+Z<7(V%I{(-U4{IE24JZB ze%ylJ?~yck8z9@v#soO!0>-x`6mW5RC3nJS7Whn78*Gq=DAt?byX+V9 zw6eXqK*IQA%xex)I}a<5$)qNzV#Bsa4P#<+sbJ5PTRCM=@?t`~_qg6k-|5u0SzVwi z0g74y|G|4?H}%v&of8oUrfo5Xw^6nW#3 z0e>1-BVb*L`S3A3psN8I5Gm>RLc59HtCfqeLRrMs#PluiOCt|CcUrSLf&;MJgNdZ> zKIe#tmkY8pol|A5{*l&4hjbSe;&SwxppO#?hT3#>sU(KGCpOwa$1r35c|=(>R4${1 zkWb)tTs1N&tEDtU6f6NDxVDuV8FFp(#6xuF!yC(p6bZS=AOGArxFMK6<+J(0y%|H< z`DEt#&8y3vj@pv#9&Kj!nLvfXsv`@=>Y2~{^7duz)bK6ItLN)t%Iw=+0gfj-?USaI z1J!Ghswz>dVCo^2?EN?;44GL>wM5-|hF_<=FIA!>PDWfX&3skdA;_@%qb&`07ZOD;$d@f0G!5l~M>UbOe0e>$7hG{-MQ1S+GAfeo0IFuIBr5Pak#8Uq^8- z_G0JXJ{=sb+B*JZP9<4MuSW{^fzL3se40M3^X2bxEAV)tyLv+h@yn$t?<7EIpz2E?7PZtql1?K>O zxP!?3z#W?iNy#%e8M#XhIS@`f1^GbnQ+PsUC_4CbH-9*|cj7682zkyavXjVW77cgJ zqVRrf2Q|{6(m*e^rZt)9!~(^guGX30MFF8IUp+0q(i96_&U%}#-~bzcUK9gT+=#+P_Te-M6G0=^>+YI8pYYCVS;OM0Kq2ggq`Ph{|2bAT>ogm@Zb%PGnB z*h((}E!`bn6t89!BEy$Uz`*k+$veF~IPg5(wwg+hAMLi~>TUyviCmEla|Mg)-lqgZ z8`81huUEUL<((f;YN(d9v|SusCLK$aoDuqw-%$OjRtw3)4o?WcD7s}zyE&)xz3&An zI^o(RlCVW^wviR%Rxjun4Jj<=X4c#fr6f~mWAFKYf67KQ0`k$?qy;e-mQG+oB+oW zoN}Ywxw)pRF;g6@(}qWWRQ&ciy&)$_f~BZ3xv1a#4X0X^%Iwse(x{g4jT$OR?>W3} zHuH<-q|Pmr0+^%XHdJQY#+yF1b5WP1{d3>%QHY;TA6tr!KygP@-1=(z!WlSJdIW#v z2KSN4n7Jih<-%pvPfg+L6wc(~&JymS3LZ@lETG1D&PXtZVs6KPb$8FN*1|#-1wTR~ z@|OVQ7m`qI67~X4zVBcyB)TZ(7cxtJB*Z#N<|covH?Jn<^WbRFqOR~*<*T|%{s_Kg z1wDsarh!s26D%$H(?#*+SqPXQYm`Yu&qh=-@j$bI{V-RFTKx-xa`|09>fFz>Anjnx zSgwKh1OxA}5^S88Y$eGoR0&&C!`6&b$o1?<^xEg}`3?vpW!S~gWgn2Wb^}X?hPJ2d zx2U=xN*J%)Uj_5_C0*-2xQY$#uip&&Z7V=pEQ5IuMm2@QE2l%faM;14a9&Cp zUQUM3kiCicSqN|9*&+M#A&T~KWf*Ve3v)#70#0%HXhj54a(wCQ_;+CPKxtD&WjJS% zf;R>d@=~9BM_j}QZu&^DN{LI3x|X8%xJMq_dO8M~7yS`y);e^o0ig7Y_Q7;yFTLEg zweq}pqozwrOiRy2R;1TnZ}WY_wWa1d4-}@J#&}uv&84YQ5#<-*zLplj;q>ArTthKg z{g*dCscEA!Li>mN(ZeGJgJBv#rpvezp*jkctQvbE&#>VzS(^$lpft^wiM85XSTO3$ zLzADeK`K!-sEk0#f1xLf#5t?wr9_mWxd6FXYUTAyZ78GCrAd9Xjd*A;t#smv0svu%w;`bIu4al*3maOwDjtLjB_9Hq7fRFvFm(DGTOXYf7X&l{ zcov#JY{VSy#JgR~>V9PdeS3lA>#a+;Fq-uEyMNPcLN%{I-VoGn3ftwZ=R=5gDYTCr z#t=!iK+%q%lL%Wcy~79qz+-ck_tug9=iRuEv=C+jxle~f#o>9>F6 z`jYL+8)0a9BGrM+@hbj7`3*9UhZ!A!5Dtz`2M!MWA26NmA@hHbXvY6HiProVkp6EB zU8RrWkH0|jr)z|3{f7LnRSmJe)`7YRnHHa@fP=Z>c#QoCvERC~ede zv2N7Kn*~QzY1cMVH_&5O>#UXE{t9vs_4S^w*S51e%bUKK=*Z5_wi9?bz;9{auEl2DT8;-RPthhbIic??zAxT043LsOrgmU2?7=MrOSrH_>rW@|7zk;tx zxFz_BSl+03%AH|Y93iM3T&tqgljN_^kGm)${R5nVi(hl#zW6ndAFT94110K{8@(N2 zt;`Qslw#A+h*aDZV_E*l2?CcK0FO&o1R8C6tTr`!%D0r%Xj(?IpQb3xH9~vnf8rB4 zOrS;7?8)Cy?UpB8aqQ@HD>uKg?V_TjnZ`!2(3SSO>6%fvxoL~Ft}vP=16VHC{f7q^ zDyzY=KXg!zYhy8suWJzr;jruv-sBuM9Bk z08epT3IK0!>eGyX>nT{=p*V;w85@o`T#UWG>!b6K^k);D6SGF;6}mq5-_&w+%RN8` zi60KgKC$}G`NEHU|I7h?C7A~fPQi71Ojc0g% zn+{GhUV-pD8M1n^elik7MK|4R6^)z_}<--KLODkJYLbrqQ2@qU3*ZfX_jUC+0tuYg^)%+I&yT`?~eYVLi@x-LP73UC9*DB~r+%v3-kcO0QW(sDMf>DH^yccOqZH zpv7}P1g8Yog+Vpv&dA~Eojv8khw*ur`D0VL@|Ub(^mdb3KfbgMJ+p`j<}BlrTRJ); zC_-f8%t*RhYM$m5rGR(&!twwTG7XZ)u2sDM4el`TwYp%S)FGT%(n-v%Pf+)^fT9v` z+(<*t=IE}mSv#uB2YJJ2HV9^AuO(&cMBdqtMM+4dq2xl`nf!B-Ubf#ZP&X z18_kqLTfVXp$Rja%HZVDnmwK=$7fb)>si+>8j;7!=G}3{hV`0it~F}`8B&uW#uybP zJ$x0BQhLBcy?c+%g~b?s+3lTgigx&PPTeix*lH4&fVGHOHL(Ze{m;xq(u}XJxLeFC zkOw#9PiLLBmYnv5a=7L>dcXYB>fWS1j)i$tj-dGF#|tf!I)D#{V^u?Sw8(y6Dwa&i z>X1z|zWZ!$<(Dg)9(%YI?Qlg_R8jcj0Al4sJh{4$7Cy+*|(=n=x|FD ztCH%7~?A0>zwKx;k%t0-oTO2B~6QmH|&D4|jwNkDC%wDe;CRzjK z*S&ma7Xy|_QKQI%HGH}1%p2NL(`fk^CcF(I`3?!74m27ZyF^P-SIIkv-9OO;B2=N= zJSvJ;Ww4mPP@{9ku^e%>Fq6k6RaRFoPRgX>#a;Ud*#N%%-cw@}D67U(Y z^z%8VqRVePlHB#jHVoB`u5)QaTH~KAxh~}JGET|cyyGVqUY}+vGl&8a(yeAbMO-|c0J7cv~ z_P~-PZ@;{;co9OM7U`hF!m53LgTb&a74}T8xTORRzlQOLJv51jqdH zBk=vGO$-!+VJ z&I8>f7$Z2AvubtEJ1asw;WFI28_$o=j1rvUf~;24*cq=gr-&17;SWcdvSTE83^3~J z!5Vqs9HU=53XZQ?#q?YmVQ>H1uW;m=Z^&Rlzh^dPlS zuL6T5AuEK3weJt;D*#o4EuGa&zi4s|9o6nL+v3{N(gq2eCOkywTMyk8A81}`(I^Lo zmYcy!!qi|!YORv1N`YkVoZPyxDY?tnh0JpoPoH4J9CK)H{g~$IZPUhPsB0naGqpZZ z+b)+Ee;j~;{;SQpZ(I_DJ(>uQ7F=)cZsj1QbV*6r0<-Z4ni!P*th9dn(`C7XJJKFh z{$`1tNG!VBd57cj<7hnQI`!)+ET3+Hrab%o>Pd^rPg*6ek*Gg4`K&+d=|B0R=DO`T z!J4CrCa7O0VV9ggd5S{HUM6&kU7cz5S>&9FY4LK0hzuU6y9(2nsdg_gw!p)3&f9LB z8h&IlCCY(OR%HcS+|55eA}K$ustLV(9OU)H*~TMDGz5QPcMdZI)sGFqP$*C={3);^ABtm~Y8n2lad(9@zZ)mp zk;1;@;C>~Dk9hbVbFqUXlo0D481>K<1MV-N4y4-KO7z6mrpXoM{!6~dgr^uoaFHF* zoGz#A)Ze~!*SWl%)k2Y9=8$WeHB9zp*bQ$G(d*k`Lv-f_%jFWk4+8s+zn>ynCBC_z z(xQWAQC52POlAiJu7OfL8a7aG$=#epRdukCY<&702T~w5gR{QU3RsU`(}J%&CV$L) zoqu==QYY)!YJN>Fzw+eOTdE!gd0Fas$$yH`s{*Me0c~&?_sefotnQW%luTc0vyuuw zsrbw(3eD@_h)boX&Vo-BklP33VN8>(9}viTvEZojrHG&4b~M`Xs1RhaL*dT?$!_P^ zGmk^Ln1DwG^1tu5Ia1wx949zS-=>Nl&Kk`$y90IA}Q~Tw{A~SaVa+spCktNW}=pPdcZaq$0Oq8Nhr^0X1Yz6 zz`B;(1nZ>cO~eR(1;W8E8N*5y{ARZ(C&pu}46~vS__p9$Zk+WZng{xITZ#&5n&W5M z0Afd;p>kcK3PrhjuJ0%Mkk_WL#es6&=u{NHZcM-Qb^d|!^!Gxah*}-_GK!!+W^~ZPzUYB{>T|8Nvz%H? zp6tB4Zx32>anG$_g^f+Ja`Oe`w{B9RvdKM#4z>AJs}au$dpYmc>tQT*4$3j5V7K{d z6c5xK9y|SVYkkWel%M4HWPQI01BYDr8ZeAo@?AaP>^dxdhSYR4nj+iA_pYF*B@nsA9CA--=lbpliQ&#opDx`X?`dN{TZ0Svut~do4#ef#F>?_;;zaq_8Cq%-F2MRCrgpt1lc$GE-~EjI zO5aiRm|dnz4a%U$2wMB)rG*oih4xXJ@XW>r6+^n-YqTNwMpD->`BQpXtD{B>;vg7V zIC78TAv*SiZF6Pcm&Gd}($p()=5}oOc4J>?ZR|I}W}|bbs@uljPq?zR22%8H70_0K zwl&S==~Ml5<@^AvYCWWoMb`~g{S_2J$~=SCbNbDVg(Gv%H%G0PRQOu9+DqQP3cTl4 zAWC3-bG|FKkR3O2JE2YgJ19$P2$-{&(@bQd>bvl}X3jm@N}B$;$Aga_(6dz!f}CkW zPw5$P9mAA%;O5cZm^3=0xubAMeDKD}?^A{e@ZVDX=B*^$L3|3Q?5Aa}JG#5@&-fiu zDh2_U=a}LR7!=?6rKF#1ILx){Cp+E=gpeB~k=(oMn6&9|kmu%kXZNNZ{Np zn%DX{VThV9`k~dM{-tpom5HcD!756>`PiekTL!HddlTpNEJfH^sG#N5)8yV5SD{NL znJ^$L{wAcTPk)-d1LFkZ)x*(&rVqKNqVB-*3yn9)g`uo7e+{GQBcU_8O$ZE|G^Y+# zc)Z8KqEH>+sUbEf_QZK506*Wui?U|z*8cX&`LU@DQ`D8AQ{I)zxHO5Uz31{zN?Jd{ z|2bJmKeS0)L>taDio!HnR76O0m&VdcZf+9hxo9|XKf)8&D?79^H?++&l$TZf%cUiq ze#Zrd(GR?!x*-oIxwnx)>Urhpbc?KsC6o}@pTkd2_avT8VDpEU1ux6|1T&(6ifH^e zilQu;Ir8dqM&VMk%GQ&ZdV#V&gq4Ry;ZU{?``w>PMvE|4Cd200EmI?%%evruD7-LB zeQc-Rt3{*?=J?zbx2pa?>83e?U4D2^C}g9xp1 z0P>+nQX;~+d6=5pxN>nosVsryP*g`CDIyIOB9y@qsEF9)#CLiU09Y1VFQY!g9poQG!s6C2<}&I$5ydx)GKL0& z&yaotF@w(vJx-WUQ!Snw>=8dd6Lt)4srvhiw9#AFhN2_QO_-fzH_n4yBJ-QjaYP(O zE7*aQs;DW5IdBhA2;nU6M@^R7>1n?u7b#|Y zj)N5K#7<7#65XhuQY-`!SCp+GsiE1F`|xs#y>hiz>5tpeiJClnX(a()o&z%ZK-KTo zZ!wGJDvWHtWe*(2YV{&#IApOSAL?dn0?H`PO{kFjX7kFJ(cQQ$tBn6+33 z$F|&yn*}xTWF9jG_KT4Z5{IgEr%_aYb?l==Ly-r?olg>}B6rfm7`BVtb^OE?*8KfF Zy Date: Mon, 11 Feb 2013 18:44:22 +0400 Subject: [PATCH 121/158] 8007536: Incorrect copyright header in JDP files Copyright header in JDP files missed the "classpath exception" rule. Reviewed-by: mikael --- .../sun/management/jdp/JdpBroadcaster.java | 6 +++-- .../sun/management/jdp/JdpController.java | 6 +++-- .../sun/management/jdp/JdpException.java | 6 +++-- .../sun/management/jdp/JdpGenericPacket.java | 6 +++-- .../sun/management/jdp/JdpJmxPacket.java | 6 +++-- .../classes/sun/management/jdp/JdpPacket.java | 7 +++--- .../sun/management/jdp/JdpPacketReader.java | 6 +++-- .../sun/management/jdp/JdpPacketWriter.java | 6 +++-- .../sun/management/jdp/package-info.java | 24 +++++++++++++++++++ 9 files changed, 56 insertions(+), 17 deletions(-) diff --git a/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java b/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java index df5f23458e5..b1766e6f7f6 100644 --- a/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java +++ b/jdk/src/share/classes/sun/management/jdp/JdpBroadcaster.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/jdk/src/share/classes/sun/management/jdp/JdpController.java b/jdk/src/share/classes/sun/management/jdp/JdpController.java index d8d0ed46930..3083c972cac 100644 --- a/jdk/src/share/classes/sun/management/jdp/JdpController.java +++ b/jdk/src/share/classes/sun/management/jdp/JdpController.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/jdk/src/share/classes/sun/management/jdp/JdpException.java b/jdk/src/share/classes/sun/management/jdp/JdpException.java index 03404223e94..7c312d45db7 100644 --- a/jdk/src/share/classes/sun/management/jdp/JdpException.java +++ b/jdk/src/share/classes/sun/management/jdp/JdpException.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java b/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java index 8e88b148265..74b8a589568 100644 --- a/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java +++ b/jdk/src/share/classes/sun/management/jdp/JdpGenericPacket.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java b/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java index 7d5ccc2f892..60aea2bd40f 100644 --- a/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java +++ b/jdk/src/share/classes/sun/management/jdp/JdpJmxPacket.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/jdk/src/share/classes/sun/management/jdp/JdpPacket.java b/jdk/src/share/classes/sun/management/jdp/JdpPacket.java index ba0ec4f97ac..9260112a52f 100644 --- a/jdk/src/share/classes/sun/management/jdp/JdpPacket.java +++ b/jdk/src/share/classes/sun/management/jdp/JdpPacket.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 @@ -20,7 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package sun.management.jdp; import java.io.IOException; diff --git a/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java b/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java index 9f3957ab5ce..f69c07d6c0c 100644 --- a/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java +++ b/jdk/src/share/classes/sun/management/jdp/JdpPacketReader.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java b/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java index 7ebd002608c..2af2fdc0100 100644 --- a/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java +++ b/jdk/src/share/classes/sun/management/jdp/JdpPacketWriter.java @@ -1,10 +1,12 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. + * 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 diff --git a/jdk/src/share/classes/sun/management/jdp/package-info.java b/jdk/src/share/classes/sun/management/jdp/package-info.java index e21e461214f..4a0d169efa7 100644 --- a/jdk/src/share/classes/sun/management/jdp/package-info.java +++ b/jdk/src/share/classes/sun/management/jdp/package-info.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 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 + * 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. + */ /** * Summary * ------- From 249b55b573809725df1c523da7091c06d75333b5 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Mon, 11 Feb 2013 10:07:01 -0800 Subject: [PATCH 122/158] 8007420: add test for 6805864 to com/sun/jdi, add test for 7182152 to java/lang/instrument Reviewed-by: coleenp, sspitsyn --- jdk/test/com/sun/jdi/RedefineAbstractClass.sh | 153 ++++++++++++++++ .../RedefineSubclassWithTwoInterfaces.sh | 167 ++++++++++++++++++ ...edefineSubclassWithTwoInterfacesAgent.java | 44 +++++ .../RedefineSubclassWithTwoInterfacesApp.java | 80 +++++++++ ...RedefineSubclassWithTwoInterfacesImpl.java | 34 ++++ ...defineSubclassWithTwoInterfacesImpl_1.java | 34 ++++ ...edefineSubclassWithTwoInterfacesIntf1.java | 28 +++ ...edefineSubclassWithTwoInterfacesIntf2.java | 28 +++ ...defineSubclassWithTwoInterfacesRemote.java | 47 +++++ ...defineSubclassWithTwoInterfacesTarget.java | 30 ++++ ...fineSubclassWithTwoInterfacesTarget_1.java | 30 ++++ 11 files changed, 675 insertions(+) create mode 100644 jdk/test/com/sun/jdi/RedefineAbstractClass.sh create mode 100644 jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfaces.sh create mode 100644 jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesAgent.java create mode 100644 jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesApp.java create mode 100644 jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesImpl.java create mode 100644 jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesImpl_1.java create mode 100644 jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesIntf1.java create mode 100644 jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesIntf2.java create mode 100644 jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesRemote.java create mode 100644 jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesTarget.java create mode 100644 jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesTarget_1.java diff --git a/jdk/test/com/sun/jdi/RedefineAbstractClass.sh b/jdk/test/com/sun/jdi/RedefineAbstractClass.sh new file mode 100644 index 00000000000..9e6e484dc04 --- /dev/null +++ b/jdk/test/com/sun/jdi/RedefineAbstractClass.sh @@ -0,0 +1,153 @@ +#!/bin/sh + +# +# Copyright (c) 2009, 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 +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# 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. +# + + +# @test +# @bug 6805864 +# @summary Redefine an abstract class that is called via a concrete +# class and via two interface objects and verify that the right +# methods are called. +# @author Daniel D. Daugherty +# +# @run shell RedefineAbstractClass.sh + +compileOptions=-g + +# Uncomment this to see the JDI trace +#jdbOptions=-dbgtrace + +createJavaFile() +{ + cat < $1.java.1 + +public class $1 { + public static void main(String[] args) { + System.out.println("This is RedefineAbstractClass"); + + MyConcreteClass foo = new MyConcreteClass(); + // do the work once before redefine + foo.doWork(); + + System.out.println("stop here for redefine"); // @1 breakpoint + + // do the work again after redefine + foo.doWork(); + + System.out.println("stop here to check results"); // @2 breakpoint + } +} + +interface MyInterface1 { + public boolean checkFunc(); + public boolean isMyInterface1(); +} + +interface MyInterface2 { + public boolean checkFunc(); + public boolean isMyInterface2(); +} + +abstract class MyAbstractClass implements MyInterface1, MyInterface2 { + static int counter = 0; + public boolean checkFunc() { + counter++; + System.out.println("MyAbstractClass.checkFunc() called."); + // @1 uncomment System.out.println("This is call " + counter + " to checkFunc"); + return true; + } + public boolean isMyInterface1() { + System.out.println("MyAbstractClass.isMyInterface1() called."); + return true; + } + public boolean isMyInterface2() { + System.out.println("MyAbstractClass.isMyInterface2() called."); + return true; + } +} + +class MyConcreteClass extends MyAbstractClass { + public void doWork() { + // checkFunc() is called via invokevirtual here; MyConcreteClass + // inherits via MyAbstractClass + System.out.println("In doWork() calling checkFunc(): " + checkFunc()); + + MyInterface1 if1 = (MyInterface1) this; + // checkFunc() is called via invokeinterface here; this call will + // use the first itable entry + System.out.println("In doWork() calling if1.checkFunc(): " + if1.checkFunc()); + + MyInterface2 if2 = (MyInterface2) this; + // checkFunc() is called via invokeinterface here; this call will + // use the second itable entry + System.out.println("In doWork() calling if2.checkFunc(): " + if2.checkFunc()); + } +} + +EOF +} + +# This is called to feed cmds to jdb. +dojdbCmds() +{ + setBkpts @1 + setBkpts @2 + runToBkpt @1 + # modified version of redefineClass function + vers=2 + abs_class=MyAbstractClass + cmd redefine $pkgDot$abs_class $tmpFileDir/vers$vers/$abs_class.class + cp $tmpFileDir/$classname.java.$vers \ + $tmpFileDir/$classname.java + # end modified version of redefineClass function + + # this will continue to the second breakpoint + cmd cont +} + + +mysetup() +{ + if [ -z "$TESTSRC" ] ; then + TESTSRC=. + fi + + for ii in . $TESTSRC $TESTSRC/.. ; do + if [ -r "$ii/ShellScaffold.sh" ] ; then + . $ii/ShellScaffold.sh + break + fi + done +} + +# You could replace this next line with the contents +# of ShellScaffold.sh and this script will run just the same. +mysetup + +runit + +debuggeeFailIfNotPresent 'This is call 4 to checkFunc' +debuggeeFailIfNotPresent 'This is call 5 to checkFunc' +debuggeeFailIfNotPresent 'This is call 6 to checkFunc' +pass diff --git a/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfaces.sh b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfaces.sh new file mode 100644 index 00000000000..8e1c81f3c17 --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfaces.sh @@ -0,0 +1,167 @@ +# +# Copyright (c) 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 +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# 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. +# + +# @test +# @bug 7182152 +# @summary Redefine a subclass that implements two interfaces and +# verify that the right methods are called. +# @author Daniel D. Daugherty +# +# @run shell MakeJAR3.sh RedefineSubclassWithTwoInterfacesAgent 'Can-Redefine-Classes: true' +# @run build RedefineSubclassWithTwoInterfacesApp +# @run shell RedefineSubclassWithTwoInterfaces.sh +# + +if [ "${TESTJAVA}" = "" ] +then + echo "TESTJAVA not set. Test cannot execute. Failed." + exit 1 +fi + +if [ "${TESTSRC}" = "" ] +then + echo "TESTSRC not set. Test cannot execute. Failed." + exit 1 +fi + +if [ "${TESTCLASSES}" = "" ] +then + echo "TESTCLASSES not set. Test cannot execute. Failed." + exit 1 +fi + +JAVAC="${TESTJAVA}"/bin/javac +JAVA="${TESTJAVA}"/bin/java + +echo "INFO: building the replacement classes." + +cp "${TESTSRC}"/RedefineSubclassWithTwoInterfacesTarget_1.java \ + RedefineSubclassWithTwoInterfacesTarget.java +cp "${TESTSRC}"/RedefineSubclassWithTwoInterfacesImpl_1.java \ + RedefineSubclassWithTwoInterfacesImpl.java +"${JAVAC}" -cp "${TESTCLASSES}" -d . \ + RedefineSubclassWithTwoInterfacesTarget.java \ + RedefineSubclassWithTwoInterfacesImpl.java +status="$?" +if [ "$status" != 0 ]; then + echo "FAIL: compile of *_1.java files failed." + exit "$status" +fi + +mv RedefineSubclassWithTwoInterfacesTarget.java \ + RedefineSubclassWithTwoInterfacesTarget_1.java +mv RedefineSubclassWithTwoInterfacesTarget.class \ + RedefineSubclassWithTwoInterfacesTarget_1.class +mv RedefineSubclassWithTwoInterfacesImpl.java \ + RedefineSubclassWithTwoInterfacesImpl_1.java +mv RedefineSubclassWithTwoInterfacesImpl.class \ + RedefineSubclassWithTwoInterfacesImpl_1.class + +echo "INFO: launching RedefineSubclassWithTwoInterfacesApp" + +# TraceRedefineClasses options: +# +# 0x00000001 | 1 - name each target class before loading, after +# loading and after redefinition is completed +# 0x00000002 | 2 - print info if parsing, linking or +# verification throws an exception +# 0x00000004 | 4 - print timer info for the VM operation +# 0x00001000 | 4096 - detect calls to obsolete methods +# 0x00002000 | 8192 - fail a guarantee() in addition to detection +# 0x00004000 | 16384 - detect old/obsolete methods in metadata +# 0x00100000 | 1048576 - impl details: vtable updates +# 0x00200000 | 2097152 - impl details: itable updates +# +# 1+2+4+4096+8192+16384+1048576+2097152 == 3174407 + +"${JAVA}" ${TESTVMOPTS} \ + -XX:TraceRedefineClasses=3174407 \ + -javaagent:RedefineSubclassWithTwoInterfacesAgent.jar \ + -classpath "${TESTCLASSES}" \ + RedefineSubclassWithTwoInterfacesApp > output.log 2>&1 +status="$?" + +echo "INFO: " +cat output.log +echo "INFO: " + +if [ "$status" != 0 ]; then + echo "FAIL: RedefineSubclassWithTwoInterfacesApp failed." + exit "$status" +fi + +# When this bug manifests, RedefineClasses() will fail to update +# one of the itable entries to refer to the new method. The log +# will include the following line when the bug occurs: +# +# guarantee(false) failed: OLD and/or OBSOLETE method(s) found +# +# If this guarantee happens, the test should fail in the status +# check above, but just in case it doesn't, we check for "guarantee". +# + +FAIL_MESG="guarantee" +grep "$FAIL_MESG" output.log +status=$? +if [ "$status" = 0 ]; then + echo "FAIL: found '$FAIL_MESG' in the test output." + result=1 +else + echo "INFO: did NOT find '$FAIL_MESG' in the test output." + # be optimistic here + result=0 +fi + +PASS1_MESG="before any redefines" +cnt=`grep "$PASS1_MESG" output.log | grep 'version-0' | wc -l | sed 's/^ *//'` +case "$cnt" in +2) + echo "INFO: found 2 version-0 '$PASS1_MESG' mesgs." + ;; +*) + echo "FAIL: did NOT find 2 version-0 '$PASS1_MESG' mesgs." + echo "INFO: grep '$PASS1_MESG' output:" + grep "$PASS1_MESG" output.log + result=1 + ;; +esac + +PASS2_MESG="after redefine" +cnt=`grep "$PASS2_MESG" output.log | grep 'version-1' | wc -l | sed 's/^ *//'` +case "$cnt" in +2) + echo "INFO: found 2 version-1 '$PASS2_MESG' mesgs." + ;; +*) + echo "FAIL: did NOT find 2 version-1 '$PASS2_MESG' mesgs." + echo "INFO: grep '$PASS2_MESG' output:" + grep "$PASS2_MESG" output.log + result=1 + ;; +esac + +if [ "$result" = 0 ]; then + echo "PASS: test passed both positive and negative output checks." +fi + +exit $result diff --git a/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesAgent.java b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesAgent.java new file mode 100644 index 00000000000..abd9931d88e --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesAgent.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +import java.lang.instrument.Instrumentation; + +public class RedefineSubclassWithTwoInterfacesAgent { + private static Instrumentation instrumentation; + + private RedefineSubclassWithTwoInterfacesAgent() { + } + + public static void premain(String agentArgs, Instrumentation inst) { + System.out.println("Hello from " + + "RedefineSubclassWithTwoInterfacesAgent!"); + System.out.println("isRedefineClassesSupported()=" + + inst.isRedefineClassesSupported()); + + instrumentation = inst; + } + + public static Instrumentation getInstrumentation() { + return instrumentation; + } +} diff --git a/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesApp.java b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesApp.java new file mode 100644 index 00000000000..bb62058bfde --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesApp.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +import java.io.*; +import java.lang.instrument.*; + +public class RedefineSubclassWithTwoInterfacesApp { + public static void main(String args[]) throws Exception { + System.out.println("Hello from RedefineSubclassWithTwoInterfacesApp!"); + + new RedefineSubclassWithTwoInterfacesApp().doTest(); + + System.exit(0); + } + + private void doTest() throws Exception { + RedefineSubclassWithTwoInterfacesImpl impl + = new RedefineSubclassWithTwoInterfacesImpl(); + RedefineSubclassWithTwoInterfacesRemote remote + = new RedefineSubclassWithTwoInterfacesRemote(impl, impl); + String mesg; + + // make echo() calls before any redefinitions: + mesg = remote.echo1("test message #1.1"); + System.out.println("RedefineSubclassWithTwoInterfacesApp: echo1 mesg='" + + mesg + "' before any redefines"); + mesg = remote.echo2("test message #2.1"); + System.out.println("RedefineSubclassWithTwoInterfacesApp: echo2 mesg='" + + mesg + "' before any redefines"); + + + // redefining RedefineSubclassWithTwoInterfacesImpl before + // RedefineSubclassWithTwoInterfacesTarget fails: + do_redefine("RedefineSubclassWithTwoInterfacesImpl", 1); + do_redefine("RedefineSubclassWithTwoInterfacesTarget", 1); + + mesg = remote.echo1("test message #1.2"); + System.out.println("RedefineSubclassWithTwoInterfacesApp: echo1 mesg='" + + mesg + "' after redefine"); + mesg = remote.echo2("test message #2.2"); + System.out.println("RedefineSubclassWithTwoInterfacesApp: echo2 mesg='" + + mesg + "' after redefine"); + } + + private static void do_redefine(String className, int counter) + throws Exception { + File f = new File(className + "_" + counter + ".class"); + System.out.println("Reading test class from " + f); + InputStream redefineStream = new FileInputStream(f); + + byte[] redefineBuffer + = NamedBuffer.loadBufferFromStream(redefineStream); + + ClassDefinition redefineParamBlock = new ClassDefinition( + Class.forName(className), redefineBuffer); + + RedefineSubclassWithTwoInterfacesAgent.getInstrumentation(). + redefineClasses(new ClassDefinition[] {redefineParamBlock}); + } +} diff --git a/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesImpl.java b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesImpl.java new file mode 100644 index 00000000000..f42e79fc19a --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesImpl.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +// Reproducing this bug only requires an EMCP version of the +// RedefineSubclassWithTwoInterfacesImpl class so +// RedefineSubclassWithTwoInterfacesImpl.java and +// RedefineSubclassWithTwoInterfacesImpl_1.java are identical. +public class RedefineSubclassWithTwoInterfacesImpl + extends RedefineSubclassWithTwoInterfacesTarget + implements RedefineSubclassWithTwoInterfacesIntf1, + RedefineSubclassWithTwoInterfacesIntf2 { + // This class is acting in the role of: + // wlstest.unit.diagnostics.common.apps.echoejb.EchoBean4_nh7k_Impl +} diff --git a/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesImpl_1.java b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesImpl_1.java new file mode 100644 index 00000000000..f42e79fc19a --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesImpl_1.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +// Reproducing this bug only requires an EMCP version of the +// RedefineSubclassWithTwoInterfacesImpl class so +// RedefineSubclassWithTwoInterfacesImpl.java and +// RedefineSubclassWithTwoInterfacesImpl_1.java are identical. +public class RedefineSubclassWithTwoInterfacesImpl + extends RedefineSubclassWithTwoInterfacesTarget + implements RedefineSubclassWithTwoInterfacesIntf1, + RedefineSubclassWithTwoInterfacesIntf2 { + // This class is acting in the role of: + // wlstest.unit.diagnostics.common.apps.echoejb.EchoBean4_nh7k_Impl +} diff --git a/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesIntf1.java b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesIntf1.java new file mode 100644 index 00000000000..b6e2542c9d8 --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesIntf1.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +public interface RedefineSubclassWithTwoInterfacesIntf1 { + // This interface is acting in the role of: + // wlstest.unit.diagnostics.common.apps.echoejb.EchoBean4_nh7k_Intf + String echo(String s); +} diff --git a/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesIntf2.java b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesIntf2.java new file mode 100644 index 00000000000..66fe1624f2c --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesIntf2.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +public interface RedefineSubclassWithTwoInterfacesIntf2 { + // This interface is acting in the role of: + // weblogic.ejb.container.interfaces.WLEnterpriseBean + String echo(String s); +} diff --git a/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesRemote.java b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesRemote.java new file mode 100644 index 00000000000..e50e049413e --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesRemote.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +public class RedefineSubclassWithTwoInterfacesRemote { + // This class is acting in the role of: + // wlstest.unit.diagnostics.common.apps.echoejb.EchoBean4_nh7k_EchoRemoteImpl + // since it is calling the echo() method via an interface. + private RedefineSubclassWithTwoInterfacesIntf1 intf1; + private RedefineSubclassWithTwoInterfacesIntf2 intf2; + + RedefineSubclassWithTwoInterfacesRemote( + RedefineSubclassWithTwoInterfacesIntf1 intf1, + RedefineSubclassWithTwoInterfacesIntf2 intf2) { + this.intf1 = intf1; + this.intf2 = intf2; + } + + // There is actually a bit more logic in the call stack from + // EchoBean4_nh7k_EchoRemoteImpl.echo() to EchoBean4_nh7k_Intf.echo() + public String echo1(String s) { + return "intf1<" + intf1.echo(s) + ">"; + } + + public String echo2(String s) { + return "intf2<" + intf2.echo(s) + ">"; + } +} diff --git a/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesTarget.java b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesTarget.java new file mode 100644 index 00000000000..55c1d58ee59 --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesTarget.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +public class RedefineSubclassWithTwoInterfacesTarget { + // This class is acting in the role of: + // wlstest.unit.diagnostics.common.apps.echoejb.EchoBean4 + public String echo(String s) { + return "echo: (version-0) <" + s + ">"; + } +} diff --git a/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesTarget_1.java b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesTarget_1.java new file mode 100644 index 00000000000..429d0fe906f --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfacesTarget_1.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +public class RedefineSubclassWithTwoInterfacesTarget { + // This class is acting in the role of: + // wlstest.unit.diagnostics.common.apps.echoejb.EchoBean4 + public String echo(String s) { + return "echo: (version-1) <" + s + ">"; + } +} From b74073c0db5f5cb61f6b80e8ca168909bd5e09f5 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Mon, 11 Feb 2013 20:16:18 +0000 Subject: [PATCH 123/158] 8007405: Update java.lang.reflect API to replace SYNTHESIZED with MANDATED Reviewed-by: darcy --- .../classes/java/lang/reflect/Executable.java | 4 ++ .../classes/java/lang/reflect/Modifier.java | 6 +-- .../classes/java/lang/reflect/Parameter.java | 52 +++++++++++++------ 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/jdk/src/share/classes/java/lang/reflect/Executable.java b/jdk/src/share/classes/java/lang/reflect/Executable.java index ad1a5808632..4c785e3e87f 100644 --- a/jdk/src/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java @@ -278,6 +278,10 @@ public abstract class Executable extends AccessibleObject * this object. Returns an array of length 0 if the executable * has no parameters. * + * The parameters of the underlying executable do not necessarily + * have unique names, or names that are legal identifiers in the + * Java programming language (JLS 3.8). + * * @return an array of {@code Parameter} objects representing all * the parameters to the executable this object represents */ diff --git a/jdk/src/share/classes/java/lang/reflect/Modifier.java b/jdk/src/share/classes/java/lang/reflect/Modifier.java index 24cebe29f9f..8c2b2cc5f5e 100644 --- a/jdk/src/share/classes/java/lang/reflect/Modifier.java +++ b/jdk/src/share/classes/java/lang/reflect/Modifier.java @@ -342,13 +342,13 @@ class Modifier { static final int SYNTHETIC = 0x00001000; static final int ANNOTATION = 0x00002000; static final int ENUM = 0x00004000; - static final int SYNTHESIZED = 0x00010000; + static final int MANDATED = 0x00008000; static boolean isSynthetic(int mod) { return (mod & SYNTHETIC) != 0; } - static boolean isSynthesized(int mod) { - return (mod & SYNTHESIZED) != 0; + static boolean isMandated(int mod) { + return (mod & MANDATED) != 0; } /** diff --git a/jdk/src/share/classes/java/lang/reflect/Parameter.java b/jdk/src/share/classes/java/lang/reflect/Parameter.java index 04bc274ca9f..3ecd7c674ea 100644 --- a/jdk/src/share/classes/java/lang/reflect/Parameter.java +++ b/jdk/src/share/classes/java/lang/reflect/Parameter.java @@ -44,7 +44,7 @@ public final class Parameter implements AnnotatedElement { private final String name; private final int modifiers; private final Executable executable; - private int index; + private final int index; /** * Package-private constructor for {@code Parameter}. @@ -95,9 +95,14 @@ public final class Parameter implements AnnotatedElement { } /** - * Returns a string representation of the parameter's modifiers, - * its attributes, its type, its name, and a trailing ... if it is - * a variadic parameter. + * Returns a string describing this parameter. The format is the + * modifiers for the parameter, if any, in canonical order as + * recommended by The Java™ Language + * Specification, followed by the fully- qualified type of + * the parameter (excluding the last [] if the parameter is + * variable arity), followed by "..." if the parameter is variable + * arity, followed by a space, followed by the name of the + * parameter. * * @return A string representation of the parameter and associated * information. @@ -118,7 +123,7 @@ public final class Parameter implements AnnotatedElement { sb.append(typename); sb.append(" "); - sb.append(name); + sb.append(getName()); return sb.toString(); } @@ -143,11 +148,23 @@ public final class Parameter implements AnnotatedElement { } /** - * Returns the name of the parameter represented by this - * {@code Parameter} object. + * Returns the name of the parameter. The names of the parameters + * of a single executable must all the be distinct. When names + * from the originating source are available, they are returned. + * Otherwise, an implementation of this method is free to create a + * name of this parameter, subject to the unquiness requirments. */ public String getName() { - return name; + // As per the spec, if a parameter has no name, return argX, + // where x is the index. + // + // Note: spec updates now outlaw empty strings as parameter + // names. The .equals("") is for compatibility with current + // JVM behavior. It may be removed at some point. + if(name == null || name.equals("")) + return "arg" + index; + else + return name; } /** @@ -190,20 +207,21 @@ public final class Parameter implements AnnotatedElement { private transient volatile Class parameterClassCache = null; /** - * Returns {@code true} if this parameter is a synthesized - * construct; returns {@code false} otherwise. + * Returns {@code true} if this parameter is implicitly declared + * in source code; returns {@code false} otherwise. * - * @return true if and only if this parameter is a synthesized - * construct as defined by - * The Java™ Language Specification. + * @return true if and only if this parameter is implicitly + * declared as defined by The Java™ Language + * Specification. */ - public boolean isSynthesized() { - return Modifier.isSynthesized(getModifiers()); + public boolean isImplicit() { + return Modifier.isMandated(getModifiers()); } /** - * Returns {@code true} if this parameter is a synthetic - * construct; returns {@code false} otherwise. + * Returns {@code true} if this parameter is neither implicitly + * nor explicitly declared in source code; returns {@code false} + * otherwise. * * @jls 13.1 The Form of a Binary * @return true if and only if this parameter is a synthetic From 62b85e6a17801f4c702d149898da9a9d2df8ce95 Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Wed, 6 Feb 2013 11:28:25 -0800 Subject: [PATCH 124/158] 8006594: Add jdk_core target to jdk/test/Makefile Reviewed-by: alanb --- jdk/make/jprt.properties | 3 +++ jdk/test/Makefile | 19 ++++++++++++++----- jdk/test/ProblemList.txt | 4 ++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/jdk/make/jprt.properties b/jdk/make/jprt.properties index a6d2ea1d0d4..8f7038e1f3b 100644 --- a/jdk/make/jprt.properties +++ b/jdk/make/jprt.properties @@ -63,6 +63,7 @@ jprt.vm.default.test.targets= \ ${jprt.my.test.target.set:TESTNAME=jvm98} # Default jdk test targets (testset=default) +# NOTE: This does not match test/Makefile :: jdk_default jprt.make.rule.default.test.targets= \ ${jprt.my.test.target.set:TESTNAME=jdk_lang}, \ ${jprt.my.test.target.set:TESTNAME=jdk_math} @@ -72,6 +73,7 @@ jprt.vm.core.test.targets= \ ${jprt.vm.default.test.targets} # Core jdk test targets (testset=core) +# NOTE: please keep this in sync with test/Makefile :: jdk_core jprt.make.rule.core.test.targets= \ ${jprt.make.rule.default.test.targets}, \ ${jprt.my.test.target.set:TESTNAME=jdk_util}, \ @@ -97,6 +99,7 @@ jprt.vm.all.test.targets= \ ${jprt.my.test.target.set:TESTNAME=jbb_default} # All jdk test targets (testset=all) +# NOTE: This does not match test/Makefile :: jdk_all jprt.make.rule.all.test.targets= \ ${jprt.make.rule.core.test.targets}, \ ${jprt.my.test.target.set:TESTNAME=jdk_awt}, \ diff --git a/jdk/test/Makefile b/jdk/test/Makefile index 408aaaeed25..093d4649b21 100644 --- a/jdk/test/Makefile +++ b/jdk/test/Makefile @@ -342,8 +342,8 @@ prep: clean # Cleanup clean: - $(RM) -r $(ABS_TEST_OUTPUT_DIR) - $(RM) $(ARCHIVE_BUNDLE) + @$(RM) -r $(ABS_TEST_OUTPUT_DIR) + @$(RM) $(ARCHIVE_BUNDLE) ################################################################ @@ -401,7 +401,7 @@ $(EXCLUDELIST): $(PROBLEM_LISTS) $(TEST_DEPENDENCIES) ($(ECHO) "#") ;\ ) | $(SED) -e 's@^[\ ]*@@' \ | $(EGREP) -v '^#' > $@.temp1 - for tdir in $(TESTDIRS) SOLARIS_10_SH_BUG_NO_EMPTY_FORS ; do \ + @for tdir in $(TESTDIRS) SOLARIS_10_SH_BUG_NO_EMPTY_FORS ; do \ ( ( $(CAT) $@.temp1 | $(EGREP) "^$${tdir}" ) ; $(ECHO) "#" ) >> $@.temp2 ; \ done @$(ECHO) "# at least one line" >> $@.temp2 @@ -431,6 +431,7 @@ endef # ------------------------------------------------------------------ # Batches of tests (somewhat arbitrary assigments to jdk_* targets) +# NOTE: These *do not* run the same tests as make/jprt.properties JDK_DEFAULT_TARGETS = JDK_ALL_TARGETS = @@ -614,15 +615,24 @@ jdk_util: $(call TestDirs, java/util sun/util) # ------------------------------------------------------------------ # Run default tests +# note that this *does not* have the same meaning as jprt.properties :: jprt.make.rule.default.test.targets jdk_default: $(JDK_DEFAULT_TARGETS) @$(SummaryInfo) +# Run core tests +# please keep this in sync with jdk/make/jprt.properties :: jprt.make.rule.core.test.targets +jdk_core: jdk_lang jdk_math jdk_util jdk_io jdk_net jdk_nio \ + jdk_security1 jdk_security2 jdk_security3 jdk_rmi \ + jdk_management jdk_jmx jdk_text jdk_tools jdk_jfr jdk_other + @$(SummaryInfo) + # Run all tests +# note that this *does not* have the same meaning as jprt.properties :: jprt.make.rule.all.test.targets jdk_all: $(JDK_ALL_TARGETS) @$(SummaryInfo) # These are all phony targets -PHONY_LIST += $(JDK_ALL_TARGETS) +PHONY_LIST += $(JDK_ALL_TARGETS) jdk_default jdk_core jdk_all # ------------------------------------------------------------------ @@ -892,4 +902,3 @@ PHONY_LIST += jck_all _generic_jck_tests \ .PHONY: all clean prep $(PHONY_LIST) ################################################################ - diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 69255074326..840a9274293 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -45,8 +45,8 @@ # as to why they are here and use a label: # generic-all Problems on all platforms # generic-ARCH Where ARCH is one of: sparc, sparcv9, x64, i586, etc. -# OSNAME-all Where OSNAME is one of: solaris, linux, windows -# OSNAME-ARCH Specific on to one OSNAME and ARCH, e.g. solaris-x64 +# OSNAME-all Where OSNAME is one of: solaris, linux, windows, macosx +# OSNAME-ARCH Specific on to one OSNAME and ARCH, e.g. solaris-amd64 # OSNAME-REV Specific on to one OSNAME and REV, e.g. solaris-5.8 # # More than one label is allowed but must be on the same line. From 285249963c8f0bb5c9dc17d9475208897db9e8a8 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 6 Feb 2013 11:33:49 -0800 Subject: [PATCH 125/158] 8006807: C2 crash due to out of bounds array access in Parse::do_multianewarray Check ndimensions before accessing length[i] element Reviewed-by: kvn --- hotspot/src/share/vm/opto/parse3.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index ac6f4ec8f76..9de92a2ae54 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -487,7 +487,8 @@ void Parse::do_multianewarray() { fun, NULL, TypeRawPtr::BOTTOM, makecon(TypeKlassPtr::make(array_klass)), length[0], length[1], length[2], - length[3], length[4]); + (ndimensions > 2) ? length[3] : NULL, + (ndimensions > 3) ? length[4] : NULL); } else { // Create a java array for dimension sizes Node* dims = NULL; From fb6927c36c6bc9add551771dddfaf95d97e81dd7 Mon Sep 17 00:00:00 2001 From: Jia-Hong Chen Date: Wed, 6 Feb 2013 14:45:02 -0800 Subject: [PATCH 126/158] 8005194: [parfait] #353 sun/awt/image/jpeg/imageioJPEG.c Memory leak of pointer 'scale' allocated with calloc() Reviewed-by: prr, vadim --- jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c index 0f39761750a..b405618be98 100644 --- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c +++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c @@ -2694,6 +2694,11 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_writeImage scale[i] = (UINT8*) malloc((maxBandValue + 1) * sizeof(UINT8)); if (scale[i] == NULL) { + // Cleanup before throwing an out of memory exception + for (j = 0; j < i; j++) { + free(scale[j]); + } + free(scale); JNU_ThrowByName( env, "java/lang/OutOfMemoryError", "Writing JPEG Stream"); return JNI_FALSE; From 081316260859560e4a829612bdf745ba842ed787 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Feb 2013 12:32:32 -0800 Subject: [PATCH 127/158] Added tag jdk8-b76 for changeset 6bb57fea1027 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 4b6644480b7..b6c4116ea62 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -197,3 +197,4 @@ c1be681d80a1f1c848dc671d664fccb19e046a12 jdk8-b72 93b9664f97eeb6f89397a8842318ebacaac9feb9 jdk8-b73 b43aa5bd8ca5c8121336495382d35ecfa7a71536 jdk8-b74 2a713921952cbd77a1e699626976cb6cdfe3e57e jdk8-b75 +278af9fc67e7eba2884936b49ec07345f423aabb jdk8-b76 From a68198e6bc4952542efe09343943b5b8e04f41dc Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Feb 2013 12:32:39 -0800 Subject: [PATCH 128/158] Added tag jdk8-b76 for changeset 2fea158ee664 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 294902d0bc8..c292f1b787d 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -197,3 +197,4 @@ cb40427f47145b01b7e53c3e02b38ff7625efbda jdk8-b72 191afde59e7be0e1a1d76d06f2a32ff17444f0ec jdk8-b73 2132845cf5f717ff5c240a2431c0c0e03e66e3a5 jdk8-b74 d4e68ce17795601017ac2f952baad7272942c36e jdk8-b75 +58be6ca3c0603882a1ec478724e337aac85e0da0 jdk8-b76 From 2ac871a5a19e90cfbda90be9d6b57db03ca85a10 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Feb 2013 12:32:50 -0800 Subject: [PATCH 129/158] Added tag jdk8-b76 for changeset faf3f7a9a86f --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 494b1c8a523..c1c175fb80d 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -312,3 +312,4 @@ d5cb5830f570d1304ea4b196dde672a291b55f29 jdk8-b72 1a3e54283c54aaa8b3437813e8507fbdc966e5b6 jdk8-b74 b4391649e91ea8d37f66317a03d6d2573a93d10d hs25-b17 6778d0b1659323a506ca47600ca29a9d9f8b383d jdk8-b75 +20b605466ccb1b3725eb25314d9e8782199630c5 jdk8-b76 From b0b7e821de5ac83200d6a8068f6b666090ebd801 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Feb 2013 12:32:59 -0800 Subject: [PATCH 130/158] Added tag jdk8-b76 for changeset 503de5a7b5ef --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 172530e8a1a..ce25c2db0cb 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -197,3 +197,4 @@ bdf2af722a6b54fca47d8c51d17a1b8f41dd7a3e jdk8-b72 84946404d1e1de003ed2bf218ef8d48906a90e37 jdk8-b73 2087e24a4357eceb6432e94918e75fdc706a27d6 jdk8-b74 ff0b73a6b3f6cea644d37d56d746a37743419fa7 jdk8-b75 +0c08593944d0cd30645f6e1e4946c51ff2b10c8c jdk8-b76 From 2683bbdf2f194389e49b06aa1fecb036880519e5 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Feb 2013 12:33:01 -0800 Subject: [PATCH 131/158] Added tag jdk8-b76 for changeset 95266e83c5e7 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 5811938d611..54f020a17c1 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -197,3 +197,4 @@ d9707230294d54e695e745a90de6112909100f12 jdk8-b72 c606f644a5d9118c14b5822738bf23c300f14f24 jdk8-b73 12db3c5a3393b03eeb09ff26f418c4420c21aaab jdk8-b74 966bf9f3c41a59ff5d86ff4275291c52f329f984 jdk8-b75 +c4853f3f0e89ac60aa5b517f5f224f0f60e08577 jdk8-b76 From 45f09caa8de2244f5c695ceb174155ad6aa3d780 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Feb 2013 12:33:10 -0800 Subject: [PATCH 132/158] Added tag jdk8-b76 for changeset 0da59c40187c --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index ac37d19a025..ea4808559e0 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -197,3 +197,4 @@ a996b57e554198f4592a5f3c30f2f9f4075e545d jdk8-b70 733885f57e14cc27f5a5ff0dffe641d2fa3c704a jdk8-b73 57d5d954462831ac353a1f40d3bb05ddb4620952 jdk8-b74 4a67fdb752b7d6329d9be9c28d3f9d6cf7eb9a3c jdk8-b75 +3a263052866137b645ab86498a43693ff5c19e69 jdk8-b76 From 4f0f5861edb130c7277f65f0bf253626e5c9804e Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 7 Feb 2013 12:33:21 -0800 Subject: [PATCH 133/158] Added tag jdk8-b76 for changeset aa274a6f970a --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index b29a3af53a1..788268b7d8a 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -197,3 +197,4 @@ d7360bf35ee1f40ff78c2e83a22b5446ee464346 jdk8-b69 8d0baee36c7184d55c80354b45704c37d6b7ac79 jdk8-b73 56c97aff46bb577b8668874154c24115a7e8a3e8 jdk8-b74 c2e11e2ec4a3682513e566849e5562f31ded8c65 jdk8-b75 +e81839b3233792415daaab051698edc6067f1a16 jdk8-b76 From 59bf14707f22b1cdc2fa7effa59783e6ac2d852a Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 8 Feb 2013 08:07:07 -0800 Subject: [PATCH 134/158] Added tag hs25-b18 for changeset f3f52401a78c --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index c1c175fb80d..da10e708478 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -313,3 +313,4 @@ d5cb5830f570d1304ea4b196dde672a291b55f29 jdk8-b72 b4391649e91ea8d37f66317a03d6d2573a93d10d hs25-b17 6778d0b1659323a506ca47600ca29a9d9f8b383d jdk8-b75 20b605466ccb1b3725eb25314d9e8782199630c5 jdk8-b76 +412d722168bc23f8e6d98995202728678561417f hs25-b18 From fc6a9c2d07f467d276ad7d6d9f914456562248a3 Mon Sep 17 00:00:00 2001 From: Mikhail Cherkasov Date: Fri, 8 Feb 2013 22:08:10 +0400 Subject: [PATCH 135/158] 8005932: Java 7 on mac os x only provides text clipboard formats Reviewed-by: alexp, denis --- jdk/src/macosx/lib/flavormap.properties | 6 +- .../AbsoluteComponentCenterCalculator.java | 37 ++++ .../DataFlavorSearcher.java | 47 ++++ .../InterprocessMessages.java | 28 +++ .../MissedHtmlAndRtfBug.html | 27 +++ .../MissedHtmlAndRtfBug.java | 205 ++++++++++++++++++ .../MissedHtmlAndRtfBug/MyTransferable.java | 62 ++++++ .../NextFramePositionCalculator.java | 20 ++ .../MissedHtmlAndRtfBug/SourcePanel.java | 26 +++ .../MissedHtmlAndRtfBug/TargetPanel.java | 83 +++++++ 10 files changed, 539 insertions(+), 2 deletions(-) create mode 100644 jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/AbsoluteComponentCenterCalculator.java create mode 100644 jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/DataFlavorSearcher.java create mode 100644 jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/InterprocessMessages.java create mode 100644 jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.html create mode 100644 jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.java create mode 100644 jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/MyTransferable.java create mode 100644 jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/NextFramePositionCalculator.java create mode 100644 jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/SourcePanel.java create mode 100644 jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/TargetPanel.java diff --git a/jdk/src/macosx/lib/flavormap.properties b/jdk/src/macosx/lib/flavormap.properties index 5e17d6e3d83..4a9f5fe3ffe 100644 --- a/jdk/src/macosx/lib/flavormap.properties +++ b/jdk/src/macosx/lib/flavormap.properties @@ -1,7 +1,7 @@ # # This properties file is used to initialize the default -# java.awt.datatransfer.SystemFlavorMap. It contains the X11 platform-specific, -# default mappings between common X11 selection atoms and platform-independent +# java.awt.datatransfer.SystemFlavorMap. It contains the Mac OS X platform-specific, +# default mappings between common Mac OS X selection atoms and platform-independent # MIME type strings, which will be converted into # java.awt.datatransfer.DataFlavors. # @@ -76,3 +76,5 @@ FILE_NAME=application/x-java-file-list;class=java.util.List text/uri-list=application/x-java-file-list;class=java.util.List PNG=image/x-java-image;class=java.awt.Image JFIF=image/x-java-image;class=java.awt.Image +RICH_TEXT=text/rtf +HTML=text/html;charset=utf-8;eoln="\r\n";terminators=1 diff --git a/jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/AbsoluteComponentCenterCalculator.java b/jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/AbsoluteComponentCenterCalculator.java new file mode 100644 index 00000000000..6a9f630dec5 --- /dev/null +++ b/jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/AbsoluteComponentCenterCalculator.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +import java.awt.*; + +class AbsoluteComponentCenterCalculator { + private AbsoluteComponentCenterCalculator() { + } + + public static int calculateXCenterCoordinate(Component component) { + return (int) component.getLocationOnScreen().getX() + (component.getWidth() / 2); + } + + public static int calculateYCenterCoordinate(Component component) { + return (int) component.getLocationOnScreen().getY() + (component.getHeight() / 2); + } +} diff --git a/jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/DataFlavorSearcher.java b/jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/DataFlavorSearcher.java new file mode 100644 index 00000000000..2b46cf643ba --- /dev/null +++ b/jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/DataFlavorSearcher.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.FlavorTable; +import java.awt.datatransfer.SystemFlavorMap; +import java.util.Arrays; + +public class DataFlavorSearcher { + static public String[] HTML_NAMES = new String[]{"HTML", "HTML Format"}; + static public String[] RICH_TEXT_NAMES = new String[]{"RICH_TEXT", "Rich Text Format"}; + + static public DataFlavor getByteDataFlavorForNative(String[] nats) { + FlavorTable flavorTable = (FlavorTable) SystemFlavorMap.getDefaultFlavorMap(); + + for (String nat : nats) { + java.util.List flavors = flavorTable.getFlavorsForNative(nat); + for (DataFlavor flavor : flavors) { + if (flavor != null + && flavor.getRepresentationClass().equals(byte[].class)) { + return flavor; + } + } + } + throw new RuntimeException("No data flavor was found for natives: " + Arrays.toString(nats)); + } +} diff --git a/jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/InterprocessMessages.java b/jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/InterprocessMessages.java new file mode 100644 index 00000000000..d66982d0e31 --- /dev/null +++ b/jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/InterprocessMessages.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +interface InterprocessMessages { + final static int EXECUTION_IS_SUCCESSFULL = 0; + final static int DATA_IS_CORRUPTED = 212; +} + diff --git a/jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.html b/jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.html new file mode 100644 index 00000000000..03f470d2dec --- /dev/null +++ b/jdk/test/java/awt/DataFlavor/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.html @@ -0,0 +1,27 @@ + + ZoneInfo///////////////////////////////// + + // ZoneInfo starts with UTC1900 + private static final long UTC1900 = -2208988800L; + // ZoneInfo ends with UTC2037 + private static final long UTC2037 = + LocalDateTime.of(2038, 1, 1, 0, 0, 0).toEpochSecond(ZoneOffset.UTC) - 1; + + /* Get a ZoneInfo instance. + * + * @param standardTransitions the standard transitions, not null + * @param standardOffsets the standard offsets, not null + * @param savingsInstantTransitions the standard transitions, not null + * @param wallOffsets the wall offsets, not null + * @param lastRules the recurring last rules, size 15 or less, not null + */ + private static ZoneInfo getZoneInfo(String zoneId, + long[] standardTransitions, + int[] standardOffsets, + long[] savingsInstantTransitions, + int[] wallOffsets, + ZoneOffsetTransitionRule[] lastRules) { + int rawOffset = 0; + int dstSavings = 0; + int checksum = 0; + int[] params = null; + boolean willGMTOffsetChange = false; + + // rawOffset, pick the last one + if (standardTransitions.length > 0) + rawOffset = standardOffsets[standardOffsets.length - 1] * 1000; + else + rawOffset = standardOffsets[0] * 1000; + + // transitions, offsets; + long[] transitions = null; + int[] offsets = null; + int nOffsets = 0; + int nTrans = 0; + + if (savingsInstantTransitions.length != 0) { + transitions = new long[250]; + offsets = new int[100]; // TBD: ZoneInfo actually can't handle + // offsets.length > 16 (4-bit index limit) + // last year in trans table + // It should not matter to use before or after offset for year + int lastyear = LocalDateTime.ofEpochSecond( + savingsInstantTransitions[savingsInstantTransitions.length - 1], 0, + ZoneOffset.ofTotalSeconds(wallOffsets[savingsInstantTransitions.length - 1])).getYear(); + // int lastyear = savingsLocalTransitions[savingsLocalTransitions.length - 1].getYear(); + + int i = 0, k = 1; + while (i < savingsInstantTransitions.length && + savingsInstantTransitions[i] < UTC1900) { + i++; // skip any date before UTC1900 + } + if (i < savingsInstantTransitions.length) { + // javazic writes the last GMT offset into index 0! + if (i < savingsInstantTransitions.length) { + offsets[0] = standardOffsets[standardOffsets.length - 1] * 1000; + nOffsets = 1; + } + // ZoneInfo has a beginning entry for 1900. + // Only add it if this is not the only one in table + nOffsets = addTrans(transitions, nTrans++, offsets, nOffsets, + UTC1900, + wallOffsets[i], + getStandardOffset(standardTransitions, standardOffsets, UTC1900)); + } + for (; i < savingsInstantTransitions.length; i++) { + //if (savingsLocalTransitions[i * 2].getYear() > LASTYEAR) { + if (savingsInstantTransitions[i] > UTC2037) { + // no trans beyond LASTYEAR + lastyear = LASTYEAR; + break; + } + long trans = savingsInstantTransitions[i]; + while (k < standardTransitions.length) { + // some standard offset transitions don't exist in + // savingInstantTrans, if the offset "change" doesn't + // really change the "effectiveWallOffset". For example + // the 1999/2000 pair in Zone Arg/Buenos_Aires, in which + // the daylightsaving "happened" but it actually does + // not result in the timezone switch. ZoneInfo however + // needs them in its transitions table + long trans_s = standardTransitions[k]; + if (trans_s >= UTC1900) { + if (trans_s > trans) + break; + if (trans_s < trans) { + if (nOffsets + 2 >= offsets.length) { + offsets = Arrays.copyOf(offsets, offsets.length + 100); + } + if (nTrans + 1 >= transitions.length) { + transitions = Arrays.copyOf(transitions, transitions.length + 100); + } + nOffsets = addTrans(transitions, nTrans++, offsets, nOffsets, + trans_s, + wallOffsets[i], + standardOffsets[k+1]); + } + } + k++; + } + if (nOffsets + 2 >= offsets.length) { + offsets = Arrays.copyOf(offsets, offsets.length + 100); + } + if (nTrans + 1 >= transitions.length) { + transitions = Arrays.copyOf(transitions, transitions.length + 100); + } + nOffsets = addTrans(transitions, nTrans++, offsets, nOffsets, + trans, + wallOffsets[i + 1], + getStandardOffset(standardTransitions, standardOffsets, trans)); + } + // append any leftover standard trans + while (k < standardTransitions.length) { + long trans = standardTransitions[k]; + if (trans >= UTC1900) { + int offset = wallOffsets[i]; + int offsetIndex = indexOf(offsets, 0, nOffsets, offset); + if (offsetIndex == nOffsets) + nOffsets++; + transitions[nTrans++] = ((trans * 1000) << TRANSITION_NSHIFT) | + (offsetIndex & OFFSET_MASK); + } + k++; + } + if (lastRules.length > 1) { + // fill the gap between the last trans until LASTYEAR + while (lastyear++ < LASTYEAR) { + for (ZoneOffsetTransitionRule zotr : lastRules) { + ZoneOffsetTransition zot = zotr.createTransition(lastyear); + //long trans = zot.getDateTimeBefore().toEpochSecond(); + long trans = zot.toEpochSecond(); + if (nOffsets + 2 >= offsets.length) { + offsets = Arrays.copyOf(offsets, offsets.length + 100); + } + if (nTrans + 1 >= transitions.length) { + transitions = Arrays.copyOf(transitions, transitions.length + 100); + } + nOffsets = addTrans(transitions, nTrans++, offsets, nOffsets, + trans, + zot.getOffsetAfter().getTotalSeconds(), + getStandardOffset(standardTransitions, standardOffsets, trans)); + } + } + ZoneOffsetTransitionRule startRule = lastRules[lastRules.length - 2]; + ZoneOffsetTransitionRule endRule = lastRules[lastRules.length - 1]; + params = new int[10]; + if (startRule.getOffsetBefore().compareTo(startRule.getOffsetAfter()) < 0 && + endRule.getOffsetBefore().compareTo(endRule.getOffsetAfter()) > 0) { + ZoneOffsetTransitionRule tmp; + tmp = startRule; + startRule = endRule; + endRule = tmp; + } + params[0] = startRule.getMonth().getValue() - 1; + // params[1] = startRule.getDayOfMonthIndicator(); + // params[2] = toCalendarDOW[startRule.getDayOfWeek().getValue()]; + int dom = startRule.getDayOfMonthIndicator(); + DayOfWeek dow = startRule.getDayOfWeek(); + if (dow == null) { + params[1] = startRule.getDayOfMonthIndicator(); + params[2] = 0; + } else { + // ZoneRulesBuilder adjusts < 0 case (-1, for last, don't have + // "<=" case yet) to positive value if not February (it appears + // we don't have February cutoff in tzdata table yet) + // Ideally, if JSR310 can just pass in the nagative and + // we can then pass in the dom = -1, dow > 0 into ZoneInfo + // + // hacking, assume the >=24 is the result of ZRB optimization for + // "last", it works for now. + if (dom < 0 || dom >= 24) { + params[1] = -1; + params[2] = toCalendarDOW[dow.getValue()]; + } else { + params[1] = dom; + // To specify a day of week on or after an exact day of month, + // set the month to an exact month value, day-of-month to the + // day on or after which the rule is applied, and day-of-week + // to a negative Calendar.DAY_OF_WEEK DAY_OF_WEEK field value. + params[2] = -toCalendarDOW[dow.getValue()]; + } + } + params[3] = startRule.getLocalTime().toSecondOfDay() * 1000; + params[4] = toSTZTime[startRule.getTimeDefinition().ordinal()]; + + params[5] = endRule.getMonth().getValue() - 1; + // params[6] = endRule.getDayOfMonthIndicator(); + // params[7] = toCalendarDOW[endRule.getDayOfWeek().getValue()]; + dom = endRule.getDayOfMonthIndicator(); + dow = endRule.getDayOfWeek(); + if (dow == null) { + params[6] = dom; + params[7] = 0; + } else { + // hacking: see comment above + if (dom < 0 || dom >= 24) { + params[6] = -1; + params[7] = toCalendarDOW[dow.getValue()]; + } else { + params[6] = dom; + params[7] = -toCalendarDOW[dow.getValue()]; + } + } + params[8] = endRule.getLocalTime().toSecondOfDay() * 1000; + params[9] = toSTZTime[endRule.getTimeDefinition().ordinal()]; + dstSavings = (startRule.getOffsetAfter().getTotalSeconds() + - startRule.getOffsetBefore().getTotalSeconds()) * 1000; + // Note: known mismatching -> Asia/Amman + // ZoneInfo : startDayOfWeek=5 <= Thursday + // startTime=86400000 <= 24 hours + // This: startDayOfWeek=6 + // startTime=0 + // Below is the workaround, it probably slows down everyone a little + if (params[2] == 6 && params[3] == 0 && zoneId.equals("Asia/Amman")) { + params[2] = 5; + params[3] = 86400000; + } + } else if (nTrans > 0) { // only do this if there is something in table already + if (lastyear < LASTYEAR) { + // ZoneInfo has an ending entry for 2037 + long trans = OffsetDateTime.of(LASTYEAR, Month.JANUARY.getValue(), 1, 0, 0, 0, 0, + ZoneOffset.ofTotalSeconds(rawOffset/1000)) + .toEpochSecond(); + int offsetIndex = indexOf(offsets, 0, nOffsets, rawOffset/1000); + if (offsetIndex == nOffsets) + nOffsets++; + transitions[nTrans++] = (trans * 1000) << TRANSITION_NSHIFT | + (offsetIndex & OFFSET_MASK); + } else if (savingsInstantTransitions.length > 2) { + // Workaround: create the params based on the last pair for + // zones like Israel and Iran which have trans defined + // up until 2037, but no "transition rule" defined + // + // Note: Known mismatching for Israel, Asia/Jerusalem/Tel Aviv + // ZoneInfo: startMode=3 + // startMonth=2 + // startDay=26 + // startDayOfWeek=6 + // + // This: startMode=1 + // startMonth=2 + // startDay=27 + // startDayOfWeek=0 + // these two are actually the same for 2037, the SimpleTimeZone + // for the last "known" year + int m = savingsInstantTransitions.length; + long startTrans = savingsInstantTransitions[m - 2]; + int startOffset = wallOffsets[m - 2 + 1]; + int startStd = getStandardOffset(standardTransitions, standardOffsets, startTrans); + long endTrans = savingsInstantTransitions[m - 1]; + int endOffset = wallOffsets[m - 1 + 1]; + int endStd = getStandardOffset(standardTransitions, standardOffsets, endTrans); + + if (startOffset > startStd && endOffset == endStd) { + /* + m = savingsLocalTransitions.length; + LocalDateTime startLDT = savingsLocalTransitions[m -4]; //gap + LocalDateTime endLDT = savingsLocalTransitions[m - 1]; //over + */ + // last - 1 trans + m = savingsInstantTransitions.length - 2; + ZoneOffset before = ZoneOffset.ofTotalSeconds(wallOffsets[m]); + ZoneOffset after = ZoneOffset.ofTotalSeconds(wallOffsets[m + 1]); + ZoneOffsetTransition trans = ZoneOffsetTransition.of( + LocalDateTime.ofEpochSecond(savingsInstantTransitions[m], 0, before), + before, + after); + LocalDateTime startLDT; + if (trans.isGap()) { + startLDT = trans.getDateTimeBefore(); + } else { + startLDT = trans.getDateTimeAfter(); + } + // last trans + m = savingsInstantTransitions.length - 1; + before = ZoneOffset.ofTotalSeconds(wallOffsets[m]); + after = ZoneOffset.ofTotalSeconds(wallOffsets[m + 1]); + trans = ZoneOffsetTransition.of( + LocalDateTime.ofEpochSecond(savingsInstantTransitions[m], 0, before), + before, + after); + LocalDateTime endLDT; + if (trans.isGap()) { + endLDT = trans.getDateTimeAfter(); + } else { + endLDT = trans.getDateTimeBefore(); + } + params = new int[10]; + params[0] = startLDT.getMonthValue() - 1; + params[1] = startLDT.getDayOfMonth(); + params[2] = 0; + params[3] = startLDT.toLocalTime().toSecondOfDay() * 1000; + params[4] = SimpleTimeZone.WALL_TIME; + params[5] = endLDT.getMonthValue() - 1; + params[6] = endLDT.getDayOfMonth(); + params[7] = 0; + params[8] = endLDT.toLocalTime().toSecondOfDay() * 1000; + params[9] = SimpleTimeZone.WALL_TIME; + dstSavings = (startOffset - startStd) * 1000; + } + } + } + if (transitions != null && transitions.length != nTrans) { + if (nTrans == 0) { + transitions = null; + } else { + transitions = Arrays.copyOf(transitions, nTrans); + } + } + if (offsets != null && offsets.length != nOffsets) { + if (nOffsets == 0) { + offsets = null; + } else { + offsets = Arrays.copyOf(offsets, nOffsets); + } + } + if (transitions != null) { + Checksum sum = new Checksum(); + for (i = 0; i < transitions.length; i++) { + long val = transitions[i]; + int dst = (int)((val >>> DST_NSHIFT) & 0xfL); + int saving = (dst == 0) ? 0 : offsets[dst]; + int index = (int)(val & OFFSET_MASK); + int offset = offsets[index]; + long second = (val >> TRANSITION_NSHIFT); + // javazic uses "index of the offset in offsets", + // instead of the real offset value itself to + // calculate the checksum. Have to keep doing + // the same thing, checksum is part of the + // ZoneInfo serialization form. + sum.update(second + index); + sum.update(index); + sum.update(dst == 0 ? -1 : dst); + } + checksum = (int)sum.getValue(); + } + } + return new ZoneInfo(zoneId, rawOffset, dstSavings, checksum, transitions, + offsets, params, willGMTOffsetChange); + } + + private static int getStandardOffset(long[] standardTransitions, + int[] standardOffsets, + long epochSec) { + int index = Arrays.binarySearch(standardTransitions, epochSec); + if (index < 0) { + // switch negative insert position to start of matched range + index = -index - 2; + } + return standardOffsets[index + 1]; + } + + private static int toCalendarDOW[] = new int[] { + -1, + Calendar.MONDAY, + Calendar.TUESDAY, + Calendar.WEDNESDAY, + Calendar.THURSDAY, + Calendar.FRIDAY, + Calendar.SATURDAY, + Calendar.SUNDAY + }; + + private static int toSTZTime[] = new int[] { + SimpleTimeZone.UTC_TIME, + SimpleTimeZone.WALL_TIME, + SimpleTimeZone.STANDARD_TIME, + }; + + private static final long OFFSET_MASK = 0x0fL; + private static final long DST_MASK = 0xf0L; + private static final int DST_NSHIFT = 4; + private static final int TRANSITION_NSHIFT = 12; + private static final int LASTYEAR = 2037; + + // from: 0 for offset lookup, 1 for dstsvings lookup + private static int indexOf(int[] offsets, int from, int nOffsets, int offset) { + offset *= 1000; + for (; from < nOffsets; from++) { + if (offsets[from] == offset) + return from; + } + offsets[from] = offset; + return from; + } + + // return updated nOffsets + private static int addTrans(long transitions[], int nTrans, + int offsets[], int nOffsets, + long trans, int offset, int stdOffset) { + int offsetIndex = indexOf(offsets, 0, nOffsets, offset); + if (offsetIndex == nOffsets) + nOffsets++; + int dstIndex = 0; + if (offset != stdOffset) { + dstIndex = indexOf(offsets, 1, nOffsets, offset - stdOffset); + if (dstIndex == nOffsets) + nOffsets++; + } + transitions[nTrans] = ((trans * 1000) << TRANSITION_NSHIFT) | + ((dstIndex << DST_NSHIFT) & DST_MASK) | + (offsetIndex & OFFSET_MASK); + return nOffsets; + } + + ///////////////////////////////////////////////////////////// + // ZoneInfo checksum, copy/pasted from javazic + private static class Checksum extends CRC32 { + public void update(int val) { + byte[] b = new byte[4]; + b[0] = (byte)((val >>> 24) & 0xff); + b[1] = (byte)((val >>> 16) & 0xff); + b[2] = (byte)((val >>> 8) & 0xff); + b[3] = (byte)(val & 0xff); + update(b); + } + void update(long val) { + byte[] b = new byte[8]; + b[0] = (byte)((val >>> 56) & 0xff); + b[1] = (byte)((val >>> 48) & 0xff); + b[2] = (byte)((val >>> 40) & 0xff); + b[3] = (byte)((val >>> 32) & 0xff); + b[4] = (byte)((val >>> 24) & 0xff); + b[5] = (byte)((val >>> 16) & 0xff); + b[6] = (byte)((val >>> 8) & 0xff); + b[7] = (byte)(val & 0xff); + update(b); + } + } } diff --git a/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java b/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java index 5b11c6cd9ac..656b6958bc6 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java +++ b/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java @@ -66,17 +66,43 @@ public class CalendarDataUtility { LocaleServiceProviderPool pool = LocaleServiceProviderPool.getPool(CalendarNameProvider.class); return pool.getLocalizedObject(CalendarFieldValueNameGetter.INSTANCE, locale, normalizeCalendarType(id), - field, value, style); + field, value, style, false); + } + + public static String retrieveCldrFieldValueName(String id, int field, int value, int style, Locale locale) { + LocaleServiceProviderPool pool = + LocaleServiceProviderPool.getPool(CalendarNameProvider.class); + String name; + name = pool.getLocalizedObject(CalendarFieldValueNameGetter.INSTANCE, locale, normalizeCalendarType(id), + field, value, style, true); + if (name == null) { + name = pool.getLocalizedObject(CalendarFieldValueNameGetter.INSTANCE, locale, normalizeCalendarType(id), + field, value, style, false); + } + return name; } public static Map retrieveFieldValueNames(String id, int field, int style, Locale locale) { LocaleServiceProviderPool pool = LocaleServiceProviderPool.getPool(CalendarNameProvider.class); return pool.getLocalizedObject(CalendarFieldValueNamesMapGetter.INSTANCE, locale, - normalizeCalendarType(id), field, style); + normalizeCalendarType(id), field, style, false); } - private static String normalizeCalendarType(String requestID) { + public static Map retrieveCldrFieldValueNames(String id, int field, int style, Locale locale) { + LocaleServiceProviderPool pool = + LocaleServiceProviderPool.getPool(CalendarNameProvider.class); + Map map; + map = pool.getLocalizedObject(CalendarFieldValueNamesMapGetter.INSTANCE, locale, + normalizeCalendarType(id), field, style, true); + if (map == null) { + map = pool.getLocalizedObject(CalendarFieldValueNamesMapGetter.INSTANCE, locale, + normalizeCalendarType(id), field, style, false); + } + return map; + } + + static String normalizeCalendarType(String requestID) { String type; if (requestID.equals("gregorian") || requestID.equals("iso8601")) { type = "gregory"; @@ -103,10 +129,20 @@ public class CalendarDataUtility { Locale locale, String requestID, // calendarType Object... params) { - assert params.length == 3; + assert params.length == 4; int field = (int) params[0]; int value = (int) params[1]; int style = (int) params[2]; + boolean cldr = (boolean) params[3]; + + // If cldr is true, resources from CLDR have precedence over JRE + // native resources. + if (cldr && calendarNameProvider instanceof CalendarNameProviderImpl) { + String name; + name = ((CalendarNameProviderImpl)calendarNameProvider) + .getCldrDisplayName(requestID, field, value, style, locale); + return name; + } return calendarNameProvider.getDisplayName(requestID, field, value, style, locale); } } @@ -126,9 +162,19 @@ public class CalendarDataUtility { Locale locale, String requestID, // calendarType Object... params) { - assert params.length == 2; + assert params.length == 3; int field = (int) params[0]; int style = (int) params[1]; + boolean cldr = (boolean) params[2]; + + // If cldr is true, resources from CLDR have precedence over JRE + // native resources. + if (cldr && calendarNameProvider instanceof CalendarNameProviderImpl) { + Map map; + map = ((CalendarNameProviderImpl)calendarNameProvider) + .getCldrDisplayNames(requestID, field, style, locale); + return map; + } return calendarNameProvider.getDisplayNames(requestID, field, style, locale); } } diff --git a/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java b/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java index 79cbe0a4d60..afdfd072b8d 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java +++ b/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java @@ -50,8 +50,16 @@ public class CalendarNameProviderImpl extends CalendarNameProvider implements Av @Override public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) { + return getDisplayNameImpl(calendarType, field, value, style, locale, false); + } + + public String getCldrDisplayName(String calendarType, int field, int value, int style, Locale locale) { + return getDisplayNameImpl(calendarType, field, value, style, locale, true); + } + + public String getDisplayNameImpl(String calendarType, int field, int value, int style, Locale locale, boolean cldr) { String name = null; - String key = getResourceKey(calendarType, field, style); + String key = getResourceKey(calendarType, field, style, cldr); if (key != null) { String[] strings = LocaleProviderAdapter.forType(type).getLocaleResources(locale).getCalendarNames(key); if (strings != null && strings.length > 0) { @@ -79,24 +87,32 @@ public class CalendarNameProviderImpl extends CalendarNameProvider implements Av SHORT_STANDALONE, LONG_FORMAT, LONG_STANDALONE, NARROW_FORMAT, NARROW_STANDALONE }; + @Override public Map getDisplayNames(String calendarType, int field, int style, Locale locale) { Map names; if (style == ALL_STYLES) { - names = getDisplayNamesImpl(calendarType, field, SHORT_FORMAT, locale); + names = getDisplayNamesImpl(calendarType, field, SHORT_FORMAT, locale, false); for (int st : REST_OF_STYLES) { - names.putAll(getDisplayNamesImpl(calendarType, field, st, locale)); + names.putAll(getDisplayNamesImpl(calendarType, field, st, locale, false)); } } else { // specific style - names = getDisplayNamesImpl(calendarType, field, style, locale); + names = getDisplayNamesImpl(calendarType, field, style, locale, false); } return names.isEmpty() ? null : names; } + // NOTE: This method should be used ONLY BY JSR 310 classes. + public Map getCldrDisplayNames(String calendarType, int field, int style, Locale locale) { + Map names; + names = getDisplayNamesImpl(calendarType, field, style, locale, true); + return names.isEmpty() ? null : names; + } + private Map getDisplayNamesImpl(String calendarType, int field, - int style, Locale locale) { - String key = getResourceKey(calendarType, field, style); + int style, Locale locale, boolean cldr) { + String key = getResourceKey(calendarType, field, style, cldr); Map map = new TreeMap<>(LengthBasedComparator.INSTANCE); if (key != null) { String[] strings = LocaleProviderAdapter.forType(type).getLocaleResources(locale).getCalendarNames(key); @@ -204,7 +220,7 @@ public class CalendarNameProviderImpl extends CalendarNameProvider implements Av return false; } - private String getResourceKey(String type, int field, int style) { + private String getResourceKey(String type, int field, int style, boolean cldr) { int baseStyle = getBaseStyle(style); boolean isStandalone = (style != baseStyle); @@ -213,6 +229,10 @@ public class CalendarNameProviderImpl extends CalendarNameProvider implements Av } boolean isNarrow = (baseStyle == NARROW_FORMAT); StringBuilder key = new StringBuilder(); + // If cldr is true, use prefix "cldr.". + if (cldr) { + key.append("cldr."); + } switch (field) { case ERA: if (type != null) { @@ -225,6 +245,11 @@ public class CalendarNameProviderImpl extends CalendarNameProvider implements Av // due to historical reasons. (JRE DateFormatSymbols.getEras returns // abbreviations while other getShort*() return abbreviations.) if (this.type == LocaleProviderAdapter.Type.JRE) { + if (cldr) { + if (baseStyle == LONG) { + key.append("long."); + } + } if (baseStyle == SHORT) { key.append("short."); } diff --git a/jdk/src/share/classes/sun/util/locale/provider/LocaleResources.java b/jdk/src/share/classes/sun/util/locale/provider/LocaleResources.java index 009cc5b8a63..dafa74e2ab1 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/LocaleResources.java +++ b/jdk/src/share/classes/sun/util/locale/provider/LocaleResources.java @@ -332,23 +332,61 @@ public class LocaleResources { } public String getDateTimePattern(int timeStyle, int dateStyle, Calendar cal) { - String pattern; - if (cal == null) { cal = Calendar.getInstance(locale); } - String calType = cal.getCalendarType(); + return getDateTimePattern(null, timeStyle, dateStyle, cal.getCalendarType()); + } + + /** + * Returns a date-time format pattern + * @param timeStyle style of time; one of FULL, LONG, MEDIUM, SHORT in DateFormat, + * or -1 if not required + * @param dateStyle style of time; one of FULL, LONG, MEDIUM, SHORT in DateFormat, + * or -1 if not required + * @param calType the calendar type for the pattern + * @return the pattern string + */ + public String getCldrDateTimePattern(int timeStyle, int dateStyle, String calType) { + calType = CalendarDataUtility.normalizeCalendarType(calType); + String pattern; + pattern = getDateTimePattern("cldr.", timeStyle, dateStyle, calType); + if (pattern == null) { + pattern = getDateTimePattern(null, timeStyle, dateStyle, calType); + } + return pattern; + } + + private String getDateTimePattern(String prefix, int timeStyle, int dateStyle, String calType) { + String pattern; String timePattern = null; String datePattern = null; + if (timeStyle >= 0) { - timePattern = getDateTimePattern("TimePatterns", timeStyle, calType); + if (prefix != null) { + timePattern = getDateTimePattern(prefix, "TimePatterns", timeStyle, calType); + } + if (timePattern == null) { + timePattern = getDateTimePattern(null, "TimePatterns", timeStyle, calType); + } } if (dateStyle >= 0) { - datePattern = getDateTimePattern("DatePatterns", dateStyle, calType); + if (prefix != null) { + datePattern = getDateTimePattern(prefix, "DatePatterns", dateStyle, calType); + } + if (datePattern == null) { + datePattern = getDateTimePattern(null, "DatePatterns", dateStyle, calType); + } } if (timeStyle >= 0) { if (dateStyle >= 0) { - String dateTimePattern = getDateTimePattern("DateTimePatterns", 0, calType); + String dateTimePattern = null; + if (prefix != null) { + dateTimePattern = getDateTimePattern(prefix, "DateTimePatterns", 0, calType); + } + if (dateTimePattern == null) { + dateTimePattern = getDateTimePattern(null, "DateTimePatterns", 0, calType); + } switch (dateTimePattern) { case "{1} {0}": pattern = datePattern + " " + timePattern; @@ -396,27 +434,40 @@ public class LocaleResources { return localeData.getDateFormatData(locale); } - private String getDateTimePattern(String key, int styleIndex, String calendarType) { - String resourceKey = "gregory".equals(calendarType) ? key : calendarType + "." + key; - String cacheKey = DATE_TIME_PATTERN + resourceKey; - String[] patterns = null; + private String getDateTimePattern(String prefix, String key, int styleIndex, String calendarType) { + StringBuilder sb = new StringBuilder(); + if (prefix != null) { + sb.append(prefix); + } + if (!"gregory".equals(calendarType)) { + sb.append(calendarType).append('.'); + } + sb.append(key); + String resourceKey = sb.toString(); + String cacheKey = sb.insert(0, DATE_TIME_PATTERN).toString(); removeEmptyReferences(); ResourceReference data = cache.get(cacheKey); + Object value = NULLOBJECT; - if (data == null || ((patterns = (String[]) data.get()) == null)) { + if (data == null || ((value = data.get()) == null)) { ResourceBundle r = localeData.getDateFormatData(locale); if (r.containsKey(resourceKey)) { - patterns = r.getStringArray(resourceKey); + value = r.getStringArray(resourceKey); } else { assert !resourceKey.equals(key); - patterns = r.getStringArray(key); + if (r.containsKey(key)) { + value = r.getStringArray(key); + } } cache.put(cacheKey, - new ResourceReference(cacheKey, (Object) patterns, referenceQueue)); + new ResourceReference(cacheKey, value, referenceQueue)); } - - return patterns[styleIndex]; + if (value == NULLOBJECT) { + assert prefix != null; + return null; + } + return ((String[])value)[styleIndex]; } private static class ResourceReference extends SoftReference { diff --git a/jdk/test/java/sql/JavatimeTest.java b/jdk/test/java/sql/JavatimeTest.java new file mode 100644 index 00000000000..3ff70d007d1 --- /dev/null +++ b/jdk/test/java/sql/JavatimeTest.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + *@test + *@bug 8007520 + *@summary Test those bridge methods to/from java.time date/time classes + */ + +import java.util.Random; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; + +public class JavatimeTest { + + static final int NANOS_PER_SECOND = 1000000000; + + public static void main(String[] args) throws Throwable { + int N = 10000; + long t1970 = new java.util.Date(70, 0, 01).getTime(); + Random r = new Random(); + for (int i = 0; i < N; i++) { + int days = r.nextInt(50) * 365 + r.nextInt(365); + long secs = t1970 + days * 86400 + r.nextInt(86400); + int nanos = r.nextInt(NANOS_PER_SECOND); + int nanos_ms = nanos / 1000000 * 1000000; // millis precision + long millis = secs * 1000 + r.nextInt(1000); + + LocalDateTime ldt = LocalDateTime.ofEpochSecond(secs, nanos, ZoneOffset.UTC); + LocalDateTime ldt_ms = LocalDateTime.ofEpochSecond(secs, nanos_ms, ZoneOffset.UTC); + Instant inst = Instant.ofEpochSecond(secs, nanos); + Instant inst_ms = Instant.ofEpochSecond(secs, nanos_ms); + //System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + + /////////// Timestamp //////////////////////////////// + Timestamp ta = new Timestamp(millis); + ta.setNanos(nanos); + if (!isEqual(ta.toLocalDateTime(), ta)) { + System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + print(ta.toLocalDateTime(), ta); + throw new RuntimeException("FAILED: j.s.ts -> ldt"); + } + if (!isEqual(ldt, Timestamp.valueOf(ldt))) { + System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + print(ldt, Timestamp.valueOf(ldt)); + throw new RuntimeException("FAILED: ldt -> j.s.ts"); + } + Instant inst0 = ta.toInstant(); + if (ta.getTime() != inst0.toEpochMilli() || + ta.getNanos() != inst0.getNano() || + !ta.equals(Timestamp.from(inst0))) { + System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + throw new RuntimeException("FAILED: j.s.ts -> instant -> j.s.ts"); + } + inst = Instant.ofEpochSecond(secs, nanos); + Timestamp ta0 = Timestamp.from(inst); + if (ta0.getTime() != inst.toEpochMilli() || + ta0.getNanos() != inst.getNano() || + !inst.equals(ta0.toInstant())) { + System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + throw new RuntimeException("FAILED: instant -> timestamp -> instant"); + } + + ////////// java.sql.Date ///////////////////////////// + // j.s.d/t uses j.u.d.equals() !!!!!!!! + java.sql.Date jsd = new java.sql.Date(millis); + if (!isEqual(jsd.toLocalDate(), jsd)) { + System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + print(jsd.toLocalDate(), jsd); + throw new RuntimeException("FAILED: j.s.d -> ld"); + } + LocalDate ld = ldt.toLocalDate(); + if (!isEqual(ld, java.sql.Date.valueOf(ld))) { + System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + print(ld, java.sql.Date.valueOf(ld)); + throw new RuntimeException("FAILED: ld -> j.s.d"); + } + ////////// java.sql.Time ///////////////////////////// + java.sql.Time jst = new java.sql.Time(millis); + if (!isEqual(jst.toLocalTime(), jst)) { + System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + print(jst.toLocalTime(), jst); + throw new RuntimeException("FAILED: j.s.t -> lt"); + } + // millis precision + LocalTime lt = ldt_ms.toLocalTime(); + if (!isEqual(lt, java.sql.Time.valueOf(lt))) { + System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + print(lt, java.sql.Time.valueOf(lt)); + throw new RuntimeException("FAILED: lt -> j.s.t"); + } + } + System.out.println("Passed!"); + } + + private static boolean isEqual(LocalDateTime ldt, Timestamp ts) { + ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault()); + return zdt.getYear() == ts.getYear() + 1900 && + zdt.getMonthValue() == ts.getMonth() + 1 && + zdt.getDayOfMonth() == ts.getDate() && + zdt.getHour() == ts.getHours() && + zdt.getMinute() == ts.getMinutes() && + zdt.getSecond() == ts.getSeconds() && + zdt.getNano() == ts.getNanos(); + } + + private static void print(LocalDateTime ldt, Timestamp ts) { + ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault()); + System.out.printf("ldt:ts %d/%d, %d/%d, %d/%d, %d/%d, %d/%d, %d/%d, nano:[%d/%d]%n", + zdt.getYear(), ts.getYear() + 1900, + zdt.getMonthValue(), ts.getMonth() + 1, + zdt.getDayOfMonth(), ts.getDate(), + zdt.getHour(), ts.getHours(), + zdt.getMinute(), ts.getMinutes(), + zdt.getSecond(), ts.getSeconds(), + zdt.getNano(), ts.getNanos()); + } + + private static boolean isEqual(LocalDate ld, java.sql.Date d) { + return ld.getYear() == d.getYear() + 1900 && + ld.getMonthValue() == d.getMonth() + 1 && + ld.getDayOfMonth() == d.getDate(); + } + + private static void print(LocalDate ld, java.sql.Date d) { + System.out.printf("%d/%d, %d/%d, %d/%d%n", + ld.getYear(), d.getYear() + 1900, + ld.getMonthValue(), d.getMonth() + 1, + ld.getDayOfMonth(), d.getDate()); + } + + private static boolean isEqual(LocalTime lt, java.sql.Time t) { + return lt.getHour() == t.getHours() && + lt.getMinute() == t.getMinutes() && + lt.getSecond() == t.getSeconds(); + } + + private static void print(LocalTime lt, java.sql.Time t) { + System.out.printf("%d/%d, %d/%d, %d/%d%n", + lt.getHour(), t.getHours(), + lt.getMinute(), t.getMinutes(), + lt.getSecond(), t.getSeconds()); + } +} diff --git a/jdk/test/java/time/META-INF/services/java.time.chrono.Chronology b/jdk/test/java/time/META-INF/services/java.time.chrono.Chronology new file mode 100644 index 00000000000..d30ab01b8a1 --- /dev/null +++ b/jdk/test/java/time/META-INF/services/java.time.chrono.Chronology @@ -0,0 +1 @@ +tck.java.time.chrono.CopticChronology diff --git a/jdk/test/java/time/META-INF/services/java.time.temporal.Chrono b/jdk/test/java/time/META-INF/services/java.time.temporal.Chrono deleted file mode 100644 index 918ad84d621..00000000000 --- a/jdk/test/java/time/META-INF/services/java.time.temporal.Chrono +++ /dev/null @@ -1 +0,0 @@ -tck.java.time.calendar.CopticChrono diff --git a/jdk/test/java/time/tck/java/time/AbstractTCKTest.java b/jdk/test/java/time/tck/java/time/AbstractTCKTest.java index ce20d6b9386..ff7fc02aa1f 100644 --- a/jdk/test/java/time/tck/java/time/AbstractTCKTest.java +++ b/jdk/test/java/time/tck/java/time/AbstractTCKTest.java @@ -57,6 +57,7 @@ package tck.java.time; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertSame; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -89,6 +90,12 @@ public abstract class AbstractTCKTest { assertEquals(deserializedObject, object); } + protected static void assertSerializableSame(Object object) throws IOException, ClassNotFoundException { + assertEquals(object instanceof Serializable, true); + Object deserializedObject = writeThenRead(object); + assertSame(deserializedObject, object); + } + private static Object writeThenRead(Object object) throws IOException, ClassNotFoundException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (ObjectOutputStream oos = new ObjectOutputStream(baos) ) { diff --git a/jdk/test/java/time/tck/java/time/MockSimplePeriod.java b/jdk/test/java/time/tck/java/time/MockSimplePeriod.java new file mode 100644 index 00000000000..7b008341592 --- /dev/null +++ b/jdk/test/java/time/tck/java/time/MockSimplePeriod.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2012, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of JSR-310 nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package tck.java.time; + +import static java.time.temporal.ChronoUnit.DAYS; +import static java.time.temporal.ChronoUnit.FOREVER; +import static java.time.temporal.ChronoUnit.SECONDS; + +import java.time.DateTimeException; +import java.time.temporal.Temporal; +import java.time.temporal.TemporalAmount; +import java.time.temporal.TemporalUnit; +import java.util.List; +import java.util.Objects; + +/** + * Mock period of time measured using a single unit, such as {@code 3 Days}. + */ +public final class MockSimplePeriod + implements TemporalAmount, Comparable { + + /** + * A constant for a period of zero, measured in days. + */ + public static final MockSimplePeriod ZERO_DAYS = new MockSimplePeriod(0, DAYS); + /** + * A constant for a period of zero, measured in seconds. + */ + public static final MockSimplePeriod ZERO_SECONDS = new MockSimplePeriod(0, SECONDS); + + /** + * The amount of the period. + */ + private final long amount; + /** + * The unit the period is measured in. + */ + private final TemporalUnit unit; + + /** + * Obtains a {@code MockSimplePeriod} from an amount and unit. + *

    + * The parameters represent the two parts of a phrase like '6 Days'. + * + * @param amount the amount of the period, measured in terms of the unit, positive or negative + * @param unit the unit that the period is measured in, must not be the 'Forever' unit, not null + * @return the {@code MockSimplePeriod} instance, not null + * @throws java.time.DateTimeException if the period unit is {@link java.time.temporal.ChronoUnit#FOREVER}. + */ + public static MockSimplePeriod of(long amount, TemporalUnit unit) { + return new MockSimplePeriod(amount, unit); + } + + private MockSimplePeriod(long amount, TemporalUnit unit) { + Objects.requireNonNull(unit, "unit"); + if (unit == FOREVER) { + throw new DateTimeException("Cannot create a period of the Forever unit"); + } + this.amount = amount; + this.unit = unit; + } + + @Override + public long get(TemporalUnit unit) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List getUnits() { + throw new UnsupportedOperationException("Not supported yet."); + } + + //----------------------------------------------------------------------- + public long getAmount() { + return amount; + } + + public TemporalUnit getUnit() { + return unit; + } + + //------------------------------------------------------------------------- + @Override + public Temporal addTo(Temporal temporal) { + return temporal.plus(amount, unit); + } + + @Override + public Temporal subtractFrom(Temporal temporal) { + return temporal.minus(amount, unit); + } + + //----------------------------------------------------------------------- + @Override + public int compareTo(MockSimplePeriod otherPeriod) { + if (unit.equals(otherPeriod.getUnit()) == false) { + throw new IllegalArgumentException("Units cannot be compared: " + unit + " and " + otherPeriod.getUnit()); + } + return Long.compare(amount, otherPeriod.amount); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof MockSimplePeriod) { + MockSimplePeriod other = (MockSimplePeriod) obj; + return this.amount == other.amount && + this.unit.equals(other.unit); + } + return false; + } + + @Override + public int hashCode() { + return unit.hashCode() ^ (int) (amount ^ (amount >>> 32)); + } + + @Override + public String toString() { + return amount + " " + unit.getName(); + } + +} diff --git a/jdk/test/java/time/tck/java/time/TCKClock.java b/jdk/test/java/time/tck/java/time/TCKClock.java index e4a870e3796..82e47f7f681 100644 --- a/jdk/test/java/time/tck/java/time/TCKClock.java +++ b/jdk/test/java/time/tck/java/time/TCKClock.java @@ -83,6 +83,10 @@ public class TCKClock { return millis; } @Override + public Instant instant() { + return Instant.ofEpochMilli(millis()); + } + @Override public ZoneId getZone() { return zone; } diff --git a/jdk/test/java/time/tck/java/time/TCKClock_Fixed.java b/jdk/test/java/time/tck/java/time/TCKClock_Fixed.java index 20e66a2ed96..13cc7b4093d 100644 --- a/jdk/test/java/time/tck/java/time/TCKClock_Fixed.java +++ b/jdk/test/java/time/tck/java/time/TCKClock_Fixed.java @@ -154,13 +154,4 @@ public class TCKClock_Fixed extends AbstractTCKTest { Clock d = Clock.fixed(INSTANT.minusNanos(1), ZoneOffset.UTC); assertEquals(a.hashCode() == d.hashCode(), false); } - - //----------------------------------------------------------------------- - public void test_toString() { - // spec requires "full state" in toString() - Clock test = Clock.fixed(INSTANT, PARIS); - assertEquals(test.toString().contains("Europe/Paris"), true); - assertEquals(test.toString().contains("2008-06-30T09:30:10.000000500Z"), true); - } - } diff --git a/jdk/test/java/time/tck/java/time/TCKClock_Offset.java b/jdk/test/java/time/tck/java/time/TCKClock_Offset.java index b628c0ce4eb..3bab2acd52f 100644 --- a/jdk/test/java/time/tck/java/time/TCKClock_Offset.java +++ b/jdk/test/java/time/tck/java/time/TCKClock_Offset.java @@ -91,8 +91,8 @@ public class TCKClock_Offset extends AbstractTCKTest { //----------------------------------------------------------------------- public void test_offset_ClockDuration() { Clock test = Clock.offset(Clock.fixed(INSTANT, PARIS), OFFSET); - System.out.println(test.instant()); - System.out.println(INSTANT.plus(OFFSET)); + //System.out.println(test.instant()); + //System.out.println(INSTANT.plus(OFFSET)); assertEquals(test.instant(), INSTANT.plus(OFFSET)); assertEquals(test.getZone(), PARIS); } @@ -165,12 +165,4 @@ public class TCKClock_Offset extends AbstractTCKTest { assertEquals(a.hashCode() == d.hashCode(), false); } - //----------------------------------------------------------------------- - public void test_toString() { - // spec requires "full state" in toString() - Clock test = Clock.offset(Clock.system(PARIS), OFFSET); - assertEquals(test.toString().contains("Europe/Paris"), true); - assertEquals(test.toString().contains("PT2S"), true); - } - } diff --git a/jdk/test/java/time/tck/java/time/TCKClock_System.java b/jdk/test/java/time/tck/java/time/TCKClock_System.java index 8152a502ffa..b5440b2bfd5 100644 --- a/jdk/test/java/time/tck/java/time/TCKClock_System.java +++ b/jdk/test/java/time/tck/java/time/TCKClock_System.java @@ -197,11 +197,4 @@ public class TCKClock_System extends AbstractTCKTest { assertEquals(a.hashCode() == c.hashCode(), false); } - //----------------------------------------------------------------------- - public void test_toString() { - // spec requires "full state" in toString() - Clock test = Clock.system(PARIS); - assertEquals(test.toString().contains("Europe/Paris"), true); - } - } diff --git a/jdk/test/java/time/tck/java/time/TCKClock_Tick.java b/jdk/test/java/time/tck/java/time/TCKClock_Tick.java index 3022d77b747..b245d143ccb 100644 --- a/jdk/test/java/time/tck/java/time/TCKClock_Tick.java +++ b/jdk/test/java/time/tck/java/time/TCKClock_Tick.java @@ -248,13 +248,4 @@ public class TCKClock_Tick extends AbstractTCKTest { Clock d = Clock.tick(Clock.system(PARIS), Duration.ofMillis(499)); assertEquals(a.hashCode() == d.hashCode(), false); } - - //----------------------------------------------------------------------- - public void test_toString() { - // spec requires "full state" in toString() - Clock test = Clock.tick(Clock.system(PARIS), AMOUNT); - assertEquals(test.toString().contains("Europe/Paris"), true); - assertEquals(test.toString().contains("PT2S"), true); - } - } diff --git a/jdk/test/java/time/tck/java/time/TCKDayOfWeek.java b/jdk/test/java/time/tck/java/time/TCKDayOfWeek.java index a2460898039..196c0402a99 100644 --- a/jdk/test/java/time/tck/java/time/TCKDayOfWeek.java +++ b/jdk/test/java/time/tck/java/time/TCKDayOfWeek.java @@ -66,25 +66,24 @@ import static java.time.temporal.ChronoField.DAY_OF_WEEK; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertSame; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - import java.time.DateTimeException; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalTime; -import java.time.Month; +import java.time.chrono.IsoChronology; import java.time.format.TextStyle; import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; -import java.time.temporal.ISOChrono; import java.time.temporal.JulianFields; import java.time.temporal.Queries; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; +import java.time.temporal.TemporalQuery; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; @@ -177,34 +176,27 @@ public class TCKDayOfWeek extends AbstractDateTimeTest { //----------------------------------------------------------------------- // query(TemporalQuery) //----------------------------------------------------------------------- - @Test - public void test_query_chrono() { - assertEquals(DayOfWeek.FRIDAY.query(Queries.chrono()), null); - assertEquals(Queries.chrono().queryFrom(DayOfWeek.FRIDAY), null); + @DataProvider(name="query") + Object[][] data_query() { + return new Object[][] { + {DayOfWeek.FRIDAY, Queries.chronology(), null}, + {DayOfWeek.FRIDAY, Queries.zoneId(), null}, + {DayOfWeek.FRIDAY, Queries.precision(), ChronoUnit.DAYS}, + {DayOfWeek.FRIDAY, Queries.zone(), null}, + {DayOfWeek.FRIDAY, Queries.offset(), null}, + {DayOfWeek.FRIDAY, Queries.localDate(), null}, + {DayOfWeek.FRIDAY, Queries.localTime(), null}, + }; } - @Test - public void test_query_zoneId() { - assertEquals(DayOfWeek.FRIDAY.query(Queries.zoneId()), null); - assertEquals(Queries.zoneId().queryFrom(DayOfWeek.FRIDAY), null); + @Test(dataProvider="query") + public void test_query(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(temporal.query(query), expected); } - @Test - public void test_query_precision() { - assertEquals(DayOfWeek.FRIDAY.query(Queries.precision()), ChronoUnit.DAYS); - assertEquals(Queries.precision().queryFrom(DayOfWeek.FRIDAY), ChronoUnit.DAYS); - } - - @Test - public void test_query_offset() { - assertEquals(DayOfWeek.FRIDAY.query(Queries.offset()), null); - assertEquals(Queries.offset().queryFrom(DayOfWeek.FRIDAY), null); - } - - @Test - public void test_query_zone() { - assertEquals(DayOfWeek.FRIDAY.query(Queries.zone()), null); - assertEquals(Queries.zone().queryFrom(DayOfWeek.FRIDAY), null); + @Test(dataProvider="query") + public void test_queryFrom(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(query.queryFrom(temporal), expected); } @Test(expectedExceptions=NullPointerException.class) @@ -217,17 +209,17 @@ public class TCKDayOfWeek extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_getText() { - assertEquals(DayOfWeek.MONDAY.getText(TextStyle.SHORT, Locale.US), "Mon"); + assertEquals(DayOfWeek.MONDAY.getDisplayName(TextStyle.SHORT, Locale.US), "Mon"); } @Test(expectedExceptions = NullPointerException.class, groups={"tck"}) public void test_getText_nullStyle() { - DayOfWeek.MONDAY.getText(null, Locale.US); + DayOfWeek.MONDAY.getDisplayName(null, Locale.US); } @Test(expectedExceptions = NullPointerException.class, groups={"tck"}) public void test_getText_nullLocale() { - DayOfWeek.MONDAY.getText(TextStyle.FULL, null); + DayOfWeek.MONDAY.getDisplayName(TextStyle.FULL, null); } //----------------------------------------------------------------------- diff --git a/jdk/test/java/time/tck/java/time/TCKDuration.java b/jdk/test/java/time/tck/java/time/TCKDuration.java index aeba804291d..797b54b1f31 100644 --- a/jdk/test/java/time/tck/java/time/TCKDuration.java +++ b/jdk/test/java/time/tck/java/time/TCKDuration.java @@ -69,6 +69,7 @@ import static java.time.temporal.ChronoUnit.NANOS; import static java.time.temporal.ChronoUnit.SECONDS; import static java.time.temporal.ChronoUnit.WEEKS; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import java.io.ByteArrayInputStream; @@ -76,12 +77,17 @@ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; - import java.time.DateTimeException; import java.time.Duration; import java.time.Instant; +import java.time.LocalTime; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalUnit; +import java.util.List; +import java.util.Locale; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -436,8 +442,8 @@ public class TCKDuration extends AbstractTCKTest { //----------------------------------------------------------------------- // between() //----------------------------------------------------------------------- - @DataProvider(name="DurationBetween") - Object[][] provider_factory_between_Instant_Instant() { + @DataProvider(name="durationBetweenInstant") + Object[][] data_durationBetweenInstant() { return new Object[][] { {0, 0, 0, 0, 0, 0}, {3, 0, 7, 0, 4, 0}, @@ -447,8 +453,8 @@ public class TCKDuration extends AbstractTCKTest { }; } - @Test(dataProvider="DurationBetween", groups={"tck"}) - public void factory_between_Instant_Instant(long secs1, int nanos1, long secs2, int nanos2, long expectedSeconds, int expectedNanoOfSecond) { + @Test(dataProvider="durationBetweenInstant") + public void factory_between_TemporalTemporal_Instant(long secs1, int nanos1, long secs2, int nanos2, long expectedSeconds, int expectedNanoOfSecond) { Instant start = Instant.ofEpochSecond(secs1, nanos1); Instant end = Instant.ofEpochSecond(secs2, nanos2); Duration t = Duration.between(start, end); @@ -456,14 +462,36 @@ public class TCKDuration extends AbstractTCKTest { assertEquals(t.getNano(), expectedNanoOfSecond); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void factory_between_Instant_Instant_startNull() { + @DataProvider(name="durationBetweenLocalTime") + Object[][] data_durationBetweenLocalTime() { + return new Object[][] { + {LocalTime.of(11, 0, 30), LocalTime.of(11, 0, 45), 15L, 0}, + {LocalTime.of(11, 0, 30), LocalTime.of(11, 0, 25), -5L, 0}, + }; + } + + @Test(dataProvider="durationBetweenLocalTime") + public void factory_between_TemporalTemporal_LT(LocalTime start, LocalTime end, long expectedSeconds, int expectedNanoOfSecond) { + Duration t = Duration.between(start, end); + assertEquals(t.getSeconds(), expectedSeconds); + assertEquals(t.getNano(), expectedNanoOfSecond); + } + + @Test(expectedExceptions=DateTimeException.class) + public void factory_between_TemporalTemporal_mixedTypes() { + Instant start = Instant.ofEpochSecond(1); + ZonedDateTime end = Instant.ofEpochSecond(4).atZone(ZoneOffset.UTC); + Duration.between(start, end); + } + + @Test(expectedExceptions=NullPointerException.class) + public void factory_between__TemporalTemporal_startNull() { Instant end = Instant.ofEpochSecond(1); Duration.between(null, end); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void factory_between_Instant_Instant_endNull() { + @Test(expectedExceptions=NullPointerException.class) + public void factory_between__TemporalTemporal_endNull() { Instant start = Instant.ofEpochSecond(1); Duration.between(start, null); } @@ -471,140 +499,257 @@ public class TCKDuration extends AbstractTCKTest { //----------------------------------------------------------------------- // parse(String) //----------------------------------------------------------------------- - @DataProvider(name="Parse") - Object[][] provider_factory_parse() { + @DataProvider(name="parseSuccess") + Object[][] data_parseSuccess() { return new Object[][] { - {"PT0S", 0, 0}, - {"pT0S", 0, 0}, - {"Pt0S", 0, 0}, - {"PT0s", 0, 0}, + {"PT0S", 0, 0}, + {"PT1S", 1, 0}, + {"PT12S", 12, 0}, + {"PT123456789S", 123456789, 0}, + {"PT" + Long.MAX_VALUE + "S", Long.MAX_VALUE, 0}, - {"PT1S", 1, 0}, - {"PT12S", 12, 0}, - {"PT123456789S", 123456789, 0}, - {"PT" + Long.MAX_VALUE + "S", Long.MAX_VALUE, 0}, + {"PT+1S", 1, 0}, + {"PT+12S", 12, 0}, + {"PT+123456789S", 123456789, 0}, + {"PT+" + Long.MAX_VALUE + "S", Long.MAX_VALUE, 0}, - {"PT-1S", -1, 0}, - {"PT-12S", -12, 0}, - {"PT-123456789S", -123456789, 0}, - {"PT" + Long.MIN_VALUE + "S", Long.MIN_VALUE, 0}, + {"PT-1S", -1, 0}, + {"PT-12S", -12, 0}, + {"PT-123456789S", -123456789, 0}, + {"PT" + Long.MIN_VALUE + "S", Long.MIN_VALUE, 0}, - {"PT1.1S", 1, 100000000}, - {"PT1.12S", 1, 120000000}, - {"PT1.123S", 1, 123000000}, - {"PT1.1234S", 1, 123400000}, - {"PT1.12345S", 1, 123450000}, - {"PT1.123456S", 1, 123456000}, - {"PT1.1234567S", 1, 123456700}, - {"PT1.12345678S", 1, 123456780}, - {"PT1.123456789S", 1, 123456789}, + {"PT1.1S", 1, 100000000}, + {"PT1.12S", 1, 120000000}, + {"PT1.123S", 1, 123000000}, + {"PT1.1234S", 1, 123400000}, + {"PT1.12345S", 1, 123450000}, + {"PT1.123456S", 1, 123456000}, + {"PT1.1234567S", 1, 123456700}, + {"PT1.12345678S", 1, 123456780}, + {"PT1.123456789S", 1, 123456789}, - {"PT-1.1S", -2, 1000000000 - 100000000}, - {"PT-1.12S", -2, 1000000000 - 120000000}, - {"PT-1.123S", -2, 1000000000 - 123000000}, - {"PT-1.1234S", -2, 1000000000 - 123400000}, - {"PT-1.12345S", -2, 1000000000 - 123450000}, - {"PT-1.123456S", -2, 1000000000 - 123456000}, - {"PT-1.1234567S", -2, 1000000000 - 123456700}, - {"PT-1.12345678S", -2, 1000000000 - 123456780}, - {"PT-1.123456789S", -2, 1000000000 - 123456789}, + {"PT-1.1S", -2, 1000000000 - 100000000}, + {"PT-1.12S", -2, 1000000000 - 120000000}, + {"PT-1.123S", -2, 1000000000 - 123000000}, + {"PT-1.1234S", -2, 1000000000 - 123400000}, + {"PT-1.12345S", -2, 1000000000 - 123450000}, + {"PT-1.123456S", -2, 1000000000 - 123456000}, + {"PT-1.1234567S", -2, 1000000000 - 123456700}, + {"PT-1.12345678S", -2, 1000000000 - 123456780}, + {"PT-1.123456789S", -2, 1000000000 - 123456789}, - {"PT" + Long.MAX_VALUE + ".123456789S", Long.MAX_VALUE, 123456789}, - {"PT" + Long.MIN_VALUE + ".000000000S", Long.MIN_VALUE, 0}, + {"PT" + Long.MAX_VALUE + ".123456789S", Long.MAX_VALUE, 123456789}, + {"PT" + Long.MIN_VALUE + ".000000000S", Long.MIN_VALUE, 0}, + + {"PT01S", 1, 0}, + {"PT001S", 1, 0}, + {"PT000S", 0, 0}, + {"PT+01S", 1, 0}, + {"PT-01S", -1, 0}, + + {"PT1.S", 1, 0}, + {"PT+1.S", 1, 0}, + {"PT-1.S", -1, 0}, + + {"P0D", 0, 0}, + {"P0DT0H", 0, 0}, + {"P0DT0M", 0, 0}, + {"P0DT0S", 0, 0}, + {"P0DT0H0S", 0, 0}, + {"P0DT0M0S", 0, 0}, + {"P0DT0H0M0S", 0, 0}, + + {"P1D", 86400, 0}, + {"P1DT0H", 86400, 0}, + {"P1DT0M", 86400, 0}, + {"P1DT0S", 86400, 0}, + {"P1DT0H0S", 86400, 0}, + {"P1DT0M0S", 86400, 0}, + {"P1DT0H0M0S", 86400, 0}, + + {"P3D", 86400 * 3, 0}, + {"P3DT2H", 86400 * 3 + 3600 * 2, 0}, + {"P3DT2M", 86400 * 3 + 60 * 2, 0}, + {"P3DT2S", 86400 * 3 + 2, 0}, + {"P3DT2H1S", 86400 * 3 + 3600 * 2 + 1, 0}, + {"P3DT2M1S", 86400 * 3 + 60 * 2 + 1, 0}, + {"P3DT2H1M1S", 86400 * 3 + 3600 * 2 + 60 + 1, 0}, + + {"P-3D", -86400 * 3, 0}, + {"P-3DT2H", -86400 * 3 + 3600 * 2, 0}, + {"P-3DT2M", -86400 * 3 + 60 * 2, 0}, + {"P-3DT2S", -86400 * 3 + 2, 0}, + {"P-3DT2H1S", -86400 * 3 + 3600 * 2 + 1, 0}, + {"P-3DT2M1S", -86400 * 3 + 60 * 2 + 1, 0}, + {"P-3DT2H1M1S", -86400 * 3 + 3600 * 2 + 60 + 1, 0}, + + {"P-3DT-2H", -86400 * 3 - 3600 * 2, 0}, + {"P-3DT-2M", -86400 * 3 - 60 * 2, 0}, + {"P-3DT-2S", -86400 * 3 - 2, 0}, + {"P-3DT-2H1S", -86400 * 3 - 3600 * 2 + 1, 0}, + {"P-3DT-2M1S", -86400 * 3 - 60 * 2 + 1, 0}, + {"P-3DT-2H1M1S", -86400 * 3 - 3600 * 2 + 60 + 1, 0}, + + {"PT0H", 0, 0}, + {"PT0H0M", 0, 0}, + {"PT0H0S", 0, 0}, + {"PT0H0M0S", 0, 0}, + + {"PT1H", 3600, 0}, + {"PT3H", 3600 * 3, 0}, + {"PT-1H", -3600, 0}, + {"PT-3H", -3600 * 3, 0}, + + {"PT2H5M", 3600 * 2 + 60 * 5, 0}, + {"PT2H5S", 3600 * 2 + 5, 0}, + {"PT2H5M8S", 3600 * 2 + 60 * 5 + 8, 0}, + {"PT-2H5M", -3600 * 2 + 60 * 5, 0}, + {"PT-2H5S", -3600 * 2 + 5, 0}, + {"PT-2H5M8S", -3600 * 2 + 60 * 5 + 8, 0}, + {"PT-2H-5M", -3600 * 2 - 60 * 5, 0}, + {"PT-2H-5S", -3600 * 2 - 5, 0}, + {"PT-2H-5M8S", -3600 * 2 - 60 * 5 + 8, 0}, + {"PT-2H-5M-8S", -3600 * 2 - 60 * 5 - 8, 0}, + + {"PT0M", 0, 0}, + {"PT1M", 60, 0}, + {"PT3M", 60 * 3, 0}, + {"PT-1M", -60, 0}, + {"PT-3M", -60 * 3, 0}, + {"P0DT3M", 60 * 3, 0}, + {"P0DT-3M", -60 * 3, 0}, }; } - @Test(dataProvider="Parse", groups={"tck"}) + @Test(dataProvider="parseSuccess") public void factory_parse(String text, long expectedSeconds, int expectedNanoOfSecond) { - Duration t = Duration.parse(text); - assertEquals(t.getSeconds(), expectedSeconds); - assertEquals(t.getNano(), expectedNanoOfSecond); + Duration test = Duration.parse(text); + assertEquals(test.getSeconds(), expectedSeconds); + assertEquals(test.getNano(), expectedNanoOfSecond); } - @Test(dataProvider="Parse", groups={"tck"}) + @Test(dataProvider="parseSuccess") + public void factory_parse_plus(String text, long expectedSeconds, int expectedNanoOfSecond) { + Duration test = Duration.parse("+" + text); + assertEquals(test.getSeconds(), expectedSeconds); + assertEquals(test.getNano(), expectedNanoOfSecond); + } + + @Test(dataProvider="parseSuccess") + public void factory_parse_minus(String text, long expectedSeconds, int expectedNanoOfSecond) { + Duration test; + try { + test = Duration.parse("-" + text); + } catch (DateTimeParseException ex) { + assertEquals(expectedSeconds == Long.MIN_VALUE, true); + return; + } + // not inside try/catch or it breaks test + assertEquals(test, Duration.ofSeconds(expectedSeconds, expectedNanoOfSecond).negated()); + } + + @Test(dataProvider="parseSuccess") public void factory_parse_comma(String text, long expectedSeconds, int expectedNanoOfSecond) { text = text.replace('.', ','); - Duration t = Duration.parse(text); - assertEquals(t.getSeconds(), expectedSeconds); - assertEquals(t.getNano(), expectedNanoOfSecond); + Duration test = Duration.parse(text); + assertEquals(test.getSeconds(), expectedSeconds); + assertEquals(test.getNano(), expectedNanoOfSecond); } - @DataProvider(name="ParseFailures") - Object[][] provider_factory_parseFailures() { + @Test(dataProvider="parseSuccess") + public void factory_parse_lowerCase(String text, long expectedSeconds, int expectedNanoOfSecond) { + Duration test = Duration.parse(text.toLowerCase(Locale.ENGLISH)); + assertEquals(test.getSeconds(), expectedSeconds); + assertEquals(test.getNano(), expectedNanoOfSecond); + } + + @DataProvider(name="parseFailure") + Object[][] data_parseFailure() { return new Object[][] { - {""}, - {"PTS"}, - {"AT0S"}, - {"PA0S"}, - {"PT0A"}, + {""}, + {"ABCDEF"}, + {" PT0S"}, + {"PT0S "}, - {"PT+S"}, - {"PT-S"}, - {"PT.S"}, - {"PTAS"}, + {"PTS"}, + {"AT0S"}, + {"PA0S"}, + {"PT0A"}, - {"PT+0S"}, - {"PT+00S"}, - {"PT+000S"}, - {"PT-0S"}, - {"PT-00S"}, - {"PT-000S"}, - {"PT+1S"}, - {"PT-.S"}, - {"PT+.S"}, + {"P0Y"}, + {"P1Y"}, + {"P-2Y"}, + {"P0M"}, + {"P1M"}, + {"P-2M"}, + {"P3Y2D"}, + {"P3M2D"}, + {"P3W"}, + {"P-3W"}, + {"P2YT30S"}, + {"P2MT30S"}, - {"PT1ABC2S"}, - {"PT1.1ABC2S"}, + {"P1DT"}, - {"PT123456789123456789123456789S"}, - {"PT0.1234567891S"}, - {"PT1.S"}, - {"PT.1S"}, + {"PT+S"}, + {"PT-S"}, + {"PT.S"}, + {"PTAS"}, - {"PT2.-3"}, - {"PT-2.-3"}, - {"PT2.+3"}, - {"PT-2.+3"}, + {"PT-.S"}, + {"PT+.S"}, + + {"PT1ABC2S"}, + {"PT1.1ABC2S"}, + + {"PT123456789123456789123456789S"}, + {"PT0.1234567891S"}, + + {"PT2.-3"}, + {"PT-2.-3"}, + {"PT2.+3"}, + {"PT-2.+3"}, }; } - @Test(dataProvider="ParseFailures", expectedExceptions=DateTimeParseException.class, groups={"tck"}) + @Test(dataProvider="parseFailure", expectedExceptions=DateTimeParseException.class) public void factory_parseFailures(String text) { Duration.parse(text); } - @Test(dataProvider="ParseFailures", expectedExceptions=DateTimeParseException.class, groups={"tck"}) + @Test(dataProvider="parseFailure", expectedExceptions=DateTimeParseException.class) public void factory_parseFailures_comma(String text) { text = text.replace('.', ','); Duration.parse(text); } - @Test(expectedExceptions=DateTimeParseException.class, groups={"tck"}) + @Test(expectedExceptions=DateTimeParseException.class) public void factory_parse_tooBig() { Duration.parse("PT" + Long.MAX_VALUE + "1S"); } - @Test(expectedExceptions=DateTimeParseException.class, groups={"tck"}) + @Test(expectedExceptions=DateTimeParseException.class) public void factory_parse_tooBig_decimal() { Duration.parse("PT" + Long.MAX_VALUE + "1.1S"); } - @Test(expectedExceptions=DateTimeParseException.class, groups={"tck"}) + @Test(expectedExceptions=DateTimeParseException.class) public void factory_parse_tooSmall() { Duration.parse("PT" + Long.MIN_VALUE + "1S"); } - @Test(expectedExceptions=DateTimeParseException.class, groups={"tck"}) + @Test(expectedExceptions=DateTimeParseException.class) public void factory_parse_tooSmall_decimal() { Duration.parse("PT" + Long.MIN_VALUE + ".1S"); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void factory_parse_nullText() { - Duration.parse((String) null); + Duration.parse(null); } - @Test(groups={"tck"}) + //----------------------------------------------------------------------- + @Test public void test_deserialization() throws Exception { Duration orginal = Duration.ofSeconds(2); ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -620,7 +765,7 @@ public class TCKDuration extends AbstractTCKTest { //----------------------------------------------------------------------- // isZero(), isPositive(), isPositiveOrZero(), isNegative(), isNegativeOrZero() //----------------------------------------------------------------------- - @Test(groups={"tck"}) + @Test public void test_isZero() { assertEquals(Duration.ofNanos(0).isZero(), true); assertEquals(Duration.ofSeconds(0).isZero(), true); @@ -632,19 +777,7 @@ public class TCKDuration extends AbstractTCKTest { assertEquals(Duration.ofSeconds(-1, -1).isZero(), false); } - @Test(groups={"tck"}) - public void test_isPositive() { - assertEquals(Duration.ofNanos(0).isPositive(), false); - assertEquals(Duration.ofSeconds(0).isPositive(), false); - assertEquals(Duration.ofNanos(1).isPositive(), true); - assertEquals(Duration.ofSeconds(1).isPositive(), true); - assertEquals(Duration.ofSeconds(1, 1).isPositive(), true); - assertEquals(Duration.ofNanos(-1).isPositive(), false); - assertEquals(Duration.ofSeconds(-1).isPositive(), false); - assertEquals(Duration.ofSeconds(-1, -1).isPositive(), false); - } - - @Test(groups={"tck"}) + @Test public void test_isNegative() { assertEquals(Duration.ofNanos(0).isNegative(), false); assertEquals(Duration.ofSeconds(0).isNegative(), false); @@ -1989,18 +2122,12 @@ public class TCKDuration extends AbstractTCKTest { Duration b = durations[j]; if (i < j) { assertEquals(a.compareTo(b)< 0, true, a + " <=> " + b); - assertEquals(a.isLessThan(b), true, a + " <=> " + b); - assertEquals(a.isGreaterThan(b), false, a + " <=> " + b); assertEquals(a.equals(b), false, a + " <=> " + b); } else if (i > j) { assertEquals(a.compareTo(b) > 0, true, a + " <=> " + b); - assertEquals(a.isLessThan(b), false, a + " <=> " + b); - assertEquals(a.isGreaterThan(b), true, a + " <=> " + b); assertEquals(a.equals(b), false, a + " <=> " + b); } else { assertEquals(a.compareTo(b), 0, a + " <=> " + b); - assertEquals(a.isLessThan(b), false, a + " <=> " + b); - assertEquals(a.isGreaterThan(b), false, a + " <=> " + b); assertEquals(a.equals(b), true, a + " <=> " + b); } } @@ -2013,18 +2140,6 @@ public class TCKDuration extends AbstractTCKTest { a.compareTo(null); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_isLessThan_ObjectNull() { - Duration a = Duration.ofSeconds(0L, 0); - a.isLessThan(null); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_isGreaterThan_ObjectNull() { - Duration a = Duration.ofSeconds(0L, 0); - a.isGreaterThan(null); - } - @Test(expectedExceptions=ClassCastException.class, groups={"tck"}) @SuppressWarnings({ "unchecked", "rawtypes" }) public void compareToNonDuration() { @@ -2096,7 +2211,7 @@ public class TCKDuration extends AbstractTCKTest { //----------------------------------------------------------------------- // toString() //----------------------------------------------------------------------- - @DataProvider(name="ToString") + @DataProvider(name="toString") Object[][] provider_toString() { return new Object[][] { {0, 0, "PT0S"}, @@ -2118,18 +2233,72 @@ public class TCKDuration extends AbstractTCKTest { {0, 123456780, "PT0.12345678S"}, {0, 123456789, "PT0.123456789S"}, {1, 0, "PT1S"}, + {59, 0, "PT59S"}, + {60, 0, "PT1M"}, + {61, 0, "PT1M1S"}, + {3599, 0, "PT59M59S"}, + {3600, 0, "PT1H"}, + {3601, 0, "PT1H1S"}, + {3661, 0, "PT1H1M1S"}, + {86399, 0, "PT23H59M59S"}, + {86400, 0, "PT24H"}, + {59, 0, "PT59S"}, + {59, 0, "PT59S"}, {-1, 0, "PT-1S"}, {-1, 1000, "PT-0.999999S"}, {-1, 900000000, "PT-0.1S"}, - {Long.MAX_VALUE, 0, "PT9223372036854775807S"}, - {Long.MIN_VALUE, 0, "PT-9223372036854775808S"}, + {Long.MAX_VALUE, 0, "PT" + (Long.MAX_VALUE / 3600) + "H" + + ((Long.MAX_VALUE % 3600) / 60) + "M" + (Long.MAX_VALUE % 60) + "S"}, + {Long.MIN_VALUE, 0, "PT" + (Long.MIN_VALUE / 3600) + "H" + + ((Long.MIN_VALUE % 3600) / 60) + "M" + (Long.MIN_VALUE % 60) + "S"}, }; } - @Test(dataProvider="ToString", groups={"tck"}) + @Test(dataProvider="toString") public void test_toString(long seconds, int nanos, String expected) { Duration t = Duration.ofSeconds(seconds, nanos); assertEquals(t.toString(), expected); } + //----------------------------------------------------------------------- + @Test(groups="{tck}") + public void test_duration_getUnits() { + Duration duration = Duration.ofSeconds(5000, 1000); + List units = duration.getUnits(); + assertEquals(units.size(), 2, "Period.getUnits length"); + assertTrue(units.contains(ChronoUnit.SECONDS), "Period.getUnits contains ChronoUnit.SECONDS"); + assertTrue(units.contains(ChronoUnit.NANOS), "contains ChronoUnit.NANOS"); + } + + @Test() + public void test_getUnit() { + Duration test = Duration.ofSeconds(2000, 1000); + long seconds = test.get(ChronoUnit.SECONDS); + assertEquals(seconds, 2000, "duration.get(SECONDS)"); + long nanos = test.get(ChronoUnit.NANOS); + assertEquals(nanos, 1000, "duration.get(NANOS)"); + } + + @DataProvider(name="BadTemporalUnit") + Object[][] provider_factory_of_badTemporalUnit() { + return new Object[][] { + {0, MICROS}, + {0, MILLIS}, + {0, MINUTES}, + {0, HOURS}, + {0, HALF_DAYS}, + {0, DAYS}, + {0, ChronoUnit.MONTHS}, + {0, ChronoUnit.YEARS}, + {0, ChronoUnit.DECADES}, + {0, ChronoUnit.CENTURIES}, + {0, ChronoUnit.MILLENNIA}, + }; + } + + @Test(dataProvider="BadTemporalUnit", expectedExceptions=DateTimeException.class) + public void test_bad_getUnit(long amount, TemporalUnit unit) { + Duration t = Duration.of(amount, unit); + long actual = t.get(unit); + } } diff --git a/jdk/test/java/time/tck/java/time/TCKInstant.java b/jdk/test/java/time/tck/java/time/TCKInstant.java index e1f99d925ed..0dd745d88e5 100644 --- a/jdk/test/java/time/tck/java/time/TCKInstant.java +++ b/jdk/test/java/time/tck/java/time/TCKInstant.java @@ -64,30 +64,42 @@ import static java.time.temporal.ChronoField.MICRO_OF_SECOND; import static java.time.temporal.ChronoField.MILLI_OF_SECOND; import static java.time.temporal.ChronoField.NANO_OF_SECOND; import static java.time.temporal.ChronoUnit.DAYS; +import static java.time.temporal.ChronoUnit.HOURS; +import static java.time.temporal.ChronoUnit.MICROS; +import static java.time.temporal.ChronoUnit.MILLIS; +import static java.time.temporal.ChronoUnit.MINUTES; +import static java.time.temporal.ChronoUnit.MONTHS; import static java.time.temporal.ChronoUnit.NANOS; import static java.time.temporal.ChronoUnit.SECONDS; +import static java.time.temporal.ChronoUnit.WEEKS; +import static java.time.temporal.ChronoUnit.YEARS; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - import java.time.Clock; import java.time.DateTimeException; import java.time.Duration; import java.time.Instant; import java.time.LocalDateTime; +import java.time.OffsetDateTime; import java.time.ZoneOffset; +import java.time.ZonedDateTime; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoField; import java.time.temporal.JulianFields; import java.time.temporal.Queries; +import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalField; +import java.time.temporal.TemporalQuery; +import java.time.temporal.TemporalUnit; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; @@ -396,34 +408,27 @@ public class TCKInstant extends AbstractDateTimeTest { //----------------------------------------------------------------------- // query(TemporalQuery) //----------------------------------------------------------------------- - @Test - public void test_query_chrono() { - assertEquals(TEST_12345_123456789.query(Queries.chrono()), null); - assertEquals(Queries.chrono().queryFrom(TEST_12345_123456789), null); + @DataProvider(name="query") + Object[][] data_query() { + return new Object[][] { + {TEST_12345_123456789, Queries.chronology(), null}, + {TEST_12345_123456789, Queries.zoneId(), null}, + {TEST_12345_123456789, Queries.precision(), NANOS}, + {TEST_12345_123456789, Queries.zone(), null}, + {TEST_12345_123456789, Queries.offset(), null}, + {TEST_12345_123456789, Queries.localDate(), null}, + {TEST_12345_123456789, Queries.localTime(), null}, + }; } - @Test - public void test_query_zoneId() { - assertEquals(TEST_12345_123456789.query(Queries.zoneId()), null); - assertEquals(Queries.zoneId().queryFrom(TEST_12345_123456789), null); + @Test(dataProvider="query") + public void test_query(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(temporal.query(query), expected); } - @Test - public void test_query_precision() { - assertEquals(TEST_12345_123456789.query(Queries.precision()), NANOS); - assertEquals(Queries.precision().queryFrom(TEST_12345_123456789), NANOS); - } - - @Test - public void test_query_offset() { - assertEquals(TEST_12345_123456789.query(Queries.offset()), null); - assertEquals(Queries.offset().queryFrom(TEST_12345_123456789), null); - } - - @Test - public void test_query_zone() { - assertEquals(TEST_12345_123456789.query(Queries.zone()), null); - assertEquals(Queries.zone().queryFrom(TEST_12345_123456789), null); + @Test(dataProvider="query") + public void test_queryFrom(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(query.queryFrom(temporal), expected); } @Test(expectedExceptions=NullPointerException.class) @@ -431,6 +436,147 @@ public class TCKInstant extends AbstractDateTimeTest { TEST_12345_123456789.query(null); } + //----------------------------------------------------------------------- + // truncated(TemporalUnit) + //----------------------------------------------------------------------- + TemporalUnit NINETY_MINS = new TemporalUnit() { + @Override + public String getName() { + return "NinetyMins"; + } + @Override + public Duration getDuration() { + return Duration.ofMinutes(90); + } + @Override + public boolean isDurationEstimated() { + return false; + } + @Override + public boolean isSupportedBy(Temporal temporal) { + return false; + } + @Override + public R addTo(R temporal, long amount) { + throw new UnsupportedOperationException(); + } + @Override + public long between(Temporal temporal1, Temporal temporal2) { + throw new UnsupportedOperationException(); + } + }; + + TemporalUnit NINETY_FIVE_MINS = new TemporalUnit() { + @Override + public String getName() { + return "NinetyFiveMins"; + } + @Override + public Duration getDuration() { + return Duration.ofMinutes(95); + } + @Override + public boolean isDurationEstimated() { + return false; + } + @Override + public boolean isSupportedBy(Temporal temporal) { + return false; + } + @Override + public R addTo(R temporal, long amount) { + throw new UnsupportedOperationException(); + } + @Override + public long between(Temporal temporal1, Temporal temporal2) { + throw new UnsupportedOperationException(); + } + }; + + @DataProvider(name="truncatedToValid") + Object[][] data_truncatedToValid() { + return new Object[][] { + {Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 123_456_789), NANOS, Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 123_456_789)}, + {Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 123_456_789), MICROS, Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 123_456_000)}, + {Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 123_456_789), MILLIS, Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 1230_00_000)}, + {Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 123_456_789), SECONDS, Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 0)}, + {Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 123_456_789), MINUTES, Instant.ofEpochSecond(86400 + 3600 + 60, 0)}, + {Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 123_456_789), HOURS, Instant.ofEpochSecond(86400 + 3600, 0)}, + {Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 123_456_789), DAYS, Instant.ofEpochSecond(86400, 0)}, + + {Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 123_456_789), NINETY_MINS, Instant.ofEpochSecond(86400 + 0, 0)}, + {Instant.ofEpochSecond(86400 + 7200 + 60 + 1, 123_456_789), NINETY_MINS, Instant.ofEpochSecond(86400 + 5400, 0)}, + {Instant.ofEpochSecond(86400 + 10800 + 60 + 1, 123_456_789), NINETY_MINS, Instant.ofEpochSecond(86400 + 10800, 0)}, + }; + } + @Test(groups={"tck"}, dataProvider="truncatedToValid") + public void test_truncatedTo_valid(Instant input, TemporalUnit unit, Instant expected) { + assertEquals(input.truncatedTo(unit), expected); + } + + @DataProvider(name="truncatedToInvalid") + Object[][] data_truncatedToInvalid() { + return new Object[][] { + {Instant.ofEpochSecond(1, 123_456_789), NINETY_FIVE_MINS}, + {Instant.ofEpochSecond(1, 123_456_789), WEEKS}, + {Instant.ofEpochSecond(1, 123_456_789), MONTHS}, + {Instant.ofEpochSecond(1, 123_456_789), YEARS}, + }; + } + + @Test(groups={"tck"}, dataProvider="truncatedToInvalid", expectedExceptions=DateTimeException.class) + public void test_truncatedTo_invalid(Instant input, TemporalUnit unit) { + input.truncatedTo(unit); + } + + @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + public void test_truncatedTo_null() { + TEST_12345_123456789.truncatedTo(null); + } + + //----------------------------------------------------------------------- + // plus(TemporalAmount) + //----------------------------------------------------------------------- + @DataProvider(name="plusTemporalAmount") + Object[][] data_plusTemporalAmount() { + return new Object[][] { + {DAYS, MockSimplePeriod.of(1, DAYS), 86401, 0}, + {HOURS, MockSimplePeriod.of(2, HOURS), 7201, 0}, + {MINUTES, MockSimplePeriod.of(4, MINUTES), 241, 0}, + {SECONDS, MockSimplePeriod.of(5, SECONDS), 6, 0}, + {NANOS, MockSimplePeriod.of(6, NANOS), 1, 6}, + {DAYS, MockSimplePeriod.of(10, DAYS), 864001, 0}, + {HOURS, MockSimplePeriod.of(11, HOURS), 39601, 0}, + {MINUTES, MockSimplePeriod.of(12, MINUTES), 721, 0}, + {SECONDS, MockSimplePeriod.of(13, SECONDS), 14, 0}, + {NANOS, MockSimplePeriod.of(14, NANOS), 1, 14}, + {SECONDS, Duration.ofSeconds(20, 40), 21, 40}, + {NANOS, Duration.ofSeconds(30, 300), 31, 300}, + }; + } + + @Test(dataProvider="plusTemporalAmount") + public void test_plusTemporalAmount(TemporalUnit unit, TemporalAmount amount, int seconds, int nanos) { + Instant inst = Instant.ofEpochMilli(1000); + Instant actual = inst.plus(amount); + Instant expected = Instant.ofEpochSecond(seconds, nanos); + assertEquals(actual, expected, "plus(TemporalAmount) failed"); + } + + @DataProvider(name="badTemporalAmount") + Object[][] data_badPlusTemporalAmount() { + return new Object[][] { + {MockSimplePeriod.of(2, YEARS)}, + {MockSimplePeriod.of(2, MONTHS)}, + }; + } + + @Test(dataProvider="badTemporalAmount",expectedExceptions=DateTimeException.class) + public void test_badPlusTemporalAmount(TemporalAmount amount) { + Instant inst = Instant.ofEpochMilli(1000); + inst.plus(amount); + } + //----------------------------------------------------------------------- @DataProvider(name="Plus") Object[][] provider_plus() { @@ -1433,6 +1579,50 @@ public class TCKInstant extends AbstractDateTimeTest { i.minusNanos(1); } + //----------------------------------------------------------------------- + // atOffset() + //----------------------------------------------------------------------- + @Test + public void test_atOffset() { + for (int i = 0; i < (24 * 60 * 60); i++) { + Instant instant = Instant.ofEpochSecond(i); + OffsetDateTime test = instant.atOffset(ZoneOffset.ofHours(1)); + assertEquals(test.getYear(), 1970); + assertEquals(test.getMonthValue(), 1); + assertEquals(test.getDayOfMonth(), 1 + (i >= 23 * 60 * 60 ? 1 : 0)); + assertEquals(test.getHour(), ((i / (60 * 60)) + 1) % 24); + assertEquals(test.getMinute(), (i / 60) % 60); + assertEquals(test.getSecond(), i % 60); + } + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_atOffset_null() { + TEST_12345_123456789.atOffset(null); + } + + //----------------------------------------------------------------------- + // atZone() + //----------------------------------------------------------------------- + @Test + public void test_atZone() { + for (int i = 0; i < (24 * 60 * 60); i++) { + Instant instant = Instant.ofEpochSecond(i); + ZonedDateTime test = instant.atZone(ZoneOffset.ofHours(1)); + assertEquals(test.getYear(), 1970); + assertEquals(test.getMonthValue(), 1); + assertEquals(test.getDayOfMonth(), 1 + (i >= 23 * 60 * 60 ? 1 : 0)); + assertEquals(test.getHour(), ((i / (60 * 60)) + 1) % 24); + assertEquals(test.getMinute(), (i / 60) % 60); + assertEquals(test.getSecond(), i % 60); + } + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_atZone_null() { + TEST_12345_123456789.atZone(null); + } + //----------------------------------------------------------------------- // toEpochMilli() //----------------------------------------------------------------------- diff --git a/jdk/test/java/time/tck/java/time/TCKLocalDate.java b/jdk/test/java/time/tck/java/time/TCKLocalDate.java index 721da56d36b..48b69385bd0 100644 --- a/jdk/test/java/time/tck/java/time/TCKLocalDate.java +++ b/jdk/test/java/time/tck/java/time/TCKLocalDate.java @@ -80,11 +80,6 @@ import static org.testng.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import java.time.Clock; import java.time.DateTimeException; import java.time.DayOfWeek; @@ -93,24 +88,29 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; +import java.time.OffsetDateTime; +import java.time.OffsetTime; +import java.time.Period; +import java.time.Year; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; +import java.time.chrono.IsoChronology; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatters; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; -import java.time.temporal.ISOChrono; import java.time.temporal.JulianFields; -import java.time.temporal.OffsetDate; import java.time.temporal.Queries; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalAdjuster; import java.time.temporal.TemporalField; +import java.time.temporal.TemporalQuery; import java.time.temporal.TemporalUnit; -import java.time.temporal.Year; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; @@ -595,14 +595,14 @@ public class TCKLocalDate extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void factory_parse_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M d"); LocalDate test = LocalDate.parse("2010 12 3", f); assertEquals(test, LocalDate.of(2010, 12, 3)); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void factory_parse_formatter_nullText() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M d"); LocalDate.parse((String) null, f); } @@ -637,34 +637,27 @@ public class TCKLocalDate extends AbstractDateTimeTest { //----------------------------------------------------------------------- // query(TemporalQuery) //----------------------------------------------------------------------- - @Test - public void test_query_chrono() { - assertEquals(TEST_2007_07_15.query(Queries.chrono()), ISOChrono.INSTANCE); - assertEquals(Queries.chrono().queryFrom(TEST_2007_07_15), ISOChrono.INSTANCE); + @DataProvider(name="query") + Object[][] data_query() { + return new Object[][] { + {TEST_2007_07_15, Queries.chronology(), IsoChronology.INSTANCE}, + {TEST_2007_07_15, Queries.zoneId(), null}, + {TEST_2007_07_15, Queries.precision(), ChronoUnit.DAYS}, + {TEST_2007_07_15, Queries.zone(), null}, + {TEST_2007_07_15, Queries.offset(), null}, + {TEST_2007_07_15, Queries.localDate(), TEST_2007_07_15}, + {TEST_2007_07_15, Queries.localTime(), null}, + }; } - @Test - public void test_query_zoneId() { - assertEquals(TEST_2007_07_15.query(Queries.zoneId()), null); - assertEquals(Queries.zoneId().queryFrom(TEST_2007_07_15), null); + @Test(dataProvider="query") + public void test_query(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(temporal.query(query), expected); } - @Test - public void test_query_precision() { - assertEquals(TEST_2007_07_15.query(Queries.precision()), ChronoUnit.DAYS); - assertEquals(Queries.precision().queryFrom(TEST_2007_07_15), ChronoUnit.DAYS); - } - - @Test - public void test_query_offset() { - assertEquals(TEST_2007_07_15.query(Queries.offset()), null); - assertEquals(Queries.offset().queryFrom(TEST_2007_07_15), null); - } - - @Test - public void test_query_zone() { - assertEquals(TEST_2007_07_15.query(Queries.zone()), null); - assertEquals(Queries.zone().queryFrom(TEST_2007_07_15), null); + @Test(dataProvider="query") + public void test_queryFrom(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(query.queryFrom(temporal), expected); } @Test(expectedExceptions=NullPointerException.class) @@ -1628,6 +1621,117 @@ public class TCKLocalDate extends AbstractDateTimeTest { LocalDate.of(Year.MIN_VALUE, 1, 1).minusDays(Long.MAX_VALUE); } + //----------------------------------------------------------------------- + // periodUntil(ChronoLocalDate) + //----------------------------------------------------------------------- + @DataProvider(name="periodUntil") + Object[][] data_periodUntil() { + return new Object[][] { + {2010, 1, 1, 2010, 1, 1, 0, 0, 0}, + {2010, 1, 1, 2010, 1, 2, 0, 0, 1}, + {2010, 1, 1, 2010, 1, 31, 0, 0, 30}, + {2010, 1, 1, 2010, 2, 1, 0, 1, 0}, + {2010, 1, 1, 2010, 2, 28, 0, 1, 27}, + {2010, 1, 1, 2010, 3, 1, 0, 2, 0}, + {2010, 1, 1, 2010, 12, 31, 0, 11, 30}, + {2010, 1, 1, 2011, 1, 1, 1, 0, 0}, + {2010, 1, 1, 2011, 12, 31, 1, 11, 30}, + {2010, 1, 1, 2012, 1, 1, 2, 0, 0}, + + {2010, 1, 10, 2010, 1, 1, 0, 0, -9}, + {2010, 1, 10, 2010, 1, 2, 0, 0, -8}, + {2010, 1, 10, 2010, 1, 9, 0, 0, -1}, + {2010, 1, 10, 2010, 1, 10, 0, 0, 0}, + {2010, 1, 10, 2010, 1, 11, 0, 0, 1}, + {2010, 1, 10, 2010, 1, 31, 0, 0, 21}, + {2010, 1, 10, 2010, 2, 1, 0, 0, 22}, + {2010, 1, 10, 2010, 2, 9, 0, 0, 30}, + {2010, 1, 10, 2010, 2, 10, 0, 1, 0}, + {2010, 1, 10, 2010, 2, 28, 0, 1, 18}, + {2010, 1, 10, 2010, 3, 1, 0, 1, 19}, + {2010, 1, 10, 2010, 3, 9, 0, 1, 27}, + {2010, 1, 10, 2010, 3, 10, 0, 2, 0}, + {2010, 1, 10, 2010, 12, 31, 0, 11, 21}, + {2010, 1, 10, 2011, 1, 1, 0, 11, 22}, + {2010, 1, 10, 2011, 1, 9, 0, 11, 30}, + {2010, 1, 10, 2011, 1, 10, 1, 0, 0}, + + {2010, 3, 30, 2011, 5, 1, 1, 1, 1}, + {2010, 4, 30, 2011, 5, 1, 1, 0, 1}, + + {2010, 2, 28, 2012, 2, 27, 1, 11, 30}, + {2010, 2, 28, 2012, 2, 28, 2, 0, 0}, + {2010, 2, 28, 2012, 2, 29, 2, 0, 1}, + + {2012, 2, 28, 2014, 2, 27, 1, 11, 30}, + {2012, 2, 28, 2014, 2, 28, 2, 0, 0}, + {2012, 2, 28, 2014, 3, 1, 2, 0, 1}, + + {2012, 2, 29, 2014, 2, 28, 1, 11, 30}, + {2012, 2, 29, 2014, 3, 1, 2, 0, 1}, + {2012, 2, 29, 2014, 3, 2, 2, 0, 2}, + + {2012, 2, 29, 2016, 2, 28, 3, 11, 30}, + {2012, 2, 29, 2016, 2, 29, 4, 0, 0}, + {2012, 2, 29, 2016, 3, 1, 4, 0, 1}, + + {2010, 1, 1, 2009, 12, 31, 0, 0, -1}, + {2010, 1, 1, 2009, 12, 30, 0, 0, -2}, + {2010, 1, 1, 2009, 12, 2, 0, 0, -30}, + {2010, 1, 1, 2009, 12, 1, 0, -1, 0}, + {2010, 1, 1, 2009, 11, 30, 0, -1, -1}, + {2010, 1, 1, 2009, 11, 2, 0, -1, -29}, + {2010, 1, 1, 2009, 11, 1, 0, -2, 0}, + {2010, 1, 1, 2009, 1, 2, 0, -11, -30}, + {2010, 1, 1, 2009, 1, 1, -1, 0, 0}, + + {2010, 1, 15, 2010, 1, 15, 0, 0, 0}, + {2010, 1, 15, 2010, 1, 14, 0, 0, -1}, + {2010, 1, 15, 2010, 1, 1, 0, 0, -14}, + {2010, 1, 15, 2009, 12, 31, 0, 0, -15}, + {2010, 1, 15, 2009, 12, 16, 0, 0, -30}, + {2010, 1, 15, 2009, 12, 15, 0, -1, 0}, + {2010, 1, 15, 2009, 12, 14, 0, -1, -1}, + + {2010, 2, 28, 2009, 3, 1, 0, -11, -27}, + {2010, 2, 28, 2009, 2, 28, -1, 0, 0}, + {2010, 2, 28, 2009, 2, 27, -1, 0, -1}, + + {2010, 2, 28, 2008, 2, 29, -1, -11, -28}, + {2010, 2, 28, 2008, 2, 28, -2, 0, 0}, + {2010, 2, 28, 2008, 2, 27, -2, 0, -1}, + + {2012, 2, 29, 2009, 3, 1, -2, -11, -28}, + {2012, 2, 29, 2009, 2, 28, -3, 0, -1}, + {2012, 2, 29, 2009, 2, 27, -3, 0, -2}, + + {2012, 2, 29, 2008, 3, 1, -3, -11, -28}, + {2012, 2, 29, 2008, 2, 29, -4, 0, 0}, + {2012, 2, 29, 2008, 2, 28, -4, 0, -1}, + }; + } + + @Test(dataProvider="periodUntil") + public void test_periodUntil_LocalDate(int y1, int m1, int d1, int y2, int m2, int d2, int ye, int me, int de) { + LocalDate start = LocalDate.of(y1, m1, d1); + LocalDate end = LocalDate.of(y2, m2, d2); + Period test = start.periodUntil(end); + assertEquals(test.getYears(), ye); + assertEquals(test.getMonths(), me); + assertEquals(test.getDays(), de); + } + + @Test + public void test_periodUntil_LocalDate_max() { + int years = Math.toIntExact((long) Year.MAX_VALUE - (long) Year.MIN_VALUE); + assertEquals(LocalDate.MIN.periodUntil(LocalDate.MAX), Period.of(years, 11, 30)); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_periodUntil_LocalDate_null() { + TEST_2007_07_15.periodUntil(null); + } + //----------------------------------------------------------------------- // atTime() //----------------------------------------------------------------------- @@ -1770,40 +1874,54 @@ public class TCKLocalDate extends AbstractDateTimeTest { t.atTime(11, 30, 40, 1000000000); } - //----------------------------------------------------------------------- - // atOffset() //----------------------------------------------------------------------- @Test(groups={"tck"}) - public void test_atOffset() { + public void test_atTime_OffsetTime() { LocalDate t = LocalDate.of(2008, 6, 30); - assertEquals(t.atOffset(OFFSET_PTWO), OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PTWO)); + assertEquals(t.atTime(OffsetTime.of(11, 30, 0, 0, OFFSET_PONE)), OffsetDateTime.of(2008, 6, 30, 11, 30, 0, 0, OFFSET_PONE)); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_atOffset_nullZoneOffset() { + public void test_atTime_OffsetTime_null() { LocalDate t = LocalDate.of(2008, 6, 30); - t.atOffset((ZoneOffset) null); + t.atTime((OffsetTime) null); } //----------------------------------------------------------------------- // atStartOfDay() //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_atStartOfDay() { - LocalDate t = LocalDate.of(2008, 6, 30); - assertEquals(t.atStartOfDay(ZONE_PARIS), - ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 0, 0), ZONE_PARIS)); + @DataProvider(name="atStartOfDay") + Object[][] data_atStartOfDay() { + return new Object[][] { + {LocalDate.of(2008, 6, 30), LocalDateTime.of(2008, 6, 30, 0, 0)}, + {LocalDate.of(-12, 6, 30), LocalDateTime.of(-12, 6, 30, 0, 0)}, + }; } - @Test(groups={"tck"}) - public void test_atStartOfDay_dstGap() { - LocalDate t = LocalDate.of(2007, 4, 1); - assertEquals(t.atStartOfDay(ZONE_GAZA), - ZonedDateTime.of(LocalDateTime.of(2007, 4, 1, 1, 0), ZONE_GAZA)); + @Test(dataProvider="atStartOfDay") + public void test_atStartOfDay(LocalDate test, LocalDateTime expected) { + assertEquals(test.atStartOfDay(), expected); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_atStartOfDay_nullTimeZone() { + //----------------------------------------------------------------------- + // atStartOfDay(ZoneId) + //----------------------------------------------------------------------- + @DataProvider(name="atStartOfDayZoneId") + Object[][] data_atStartOfDayZoneId() { + return new Object[][] { + {LocalDate.of(2008, 6, 30), ZONE_PARIS, ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 0, 0), ZONE_PARIS)}, + {LocalDate.of(2008, 6, 30), OFFSET_PONE, ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 0, 0), OFFSET_PONE)}, + {LocalDate.of(2007, 4, 1), ZONE_GAZA, ZonedDateTime.of(LocalDateTime.of(2007, 4, 1, 1, 0), ZONE_GAZA)}, + }; + } + + @Test(dataProvider="atStartOfDayZoneId") + public void test_atStartOfDay_ZoneId(LocalDate test, ZoneId zone, ZonedDateTime expected) { + assertEquals(test.atStartOfDay(zone), expected); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_atStartOfDay_ZoneId_null() { LocalDate t = LocalDate.of(2008, 6, 30); t.atStartOfDay((ZoneId) null); } @@ -2005,7 +2123,7 @@ public class TCKLocalDate extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_toString_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M d"); String t = LocalDate.of(2010, 12, 3).toString(f); assertEquals(t, "2010 12 3"); } diff --git a/jdk/test/java/time/tck/java/time/TCKLocalDateTime.java b/jdk/test/java/time/tck/java/time/TCKLocalDateTime.java index 1fa08f3c93e..9b95fcd51b7 100644 --- a/jdk/test/java/time/tck/java/time/TCKLocalDateTime.java +++ b/jdk/test/java/time/tck/java/time/TCKLocalDateTime.java @@ -88,8 +88,10 @@ import static java.time.temporal.ChronoField.SECOND_OF_MINUTE; import static java.time.temporal.ChronoField.YEAR; import static java.time.temporal.ChronoField.YEAR_OF_ERA; import static java.time.temporal.ChronoUnit.DAYS; +import static java.time.temporal.ChronoUnit.MONTHS; import static java.time.temporal.ChronoUnit.NANOS; import static java.time.temporal.ChronoUnit.SECONDS; +import static java.time.temporal.ChronoUnit.YEARS; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertSame; @@ -97,12 +99,6 @@ import static org.testng.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - import java.time.Clock; import java.time.DateTimeException; import java.time.DayOfWeek; @@ -111,33 +107,33 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; -import java.time.Period; +import java.time.OffsetDateTime; +import java.time.Year; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; +import java.time.chrono.IsoChronology; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatters; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; -import java.time.temporal.ISOChrono; import java.time.temporal.JulianFields; -import java.time.temporal.OffsetDateTime; import java.time.temporal.Queries; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; -import java.time.temporal.TemporalAdder; import java.time.temporal.TemporalAdjuster; +import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalField; import java.time.temporal.TemporalQuery; -import java.time.temporal.TemporalSubtractor; import java.time.temporal.TemporalUnit; -import java.time.temporal.Year; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import test.java.time.MockSimplePeriod; /** * Test LocalDateTime. @@ -280,12 +276,12 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { public void now() { LocalDateTime expected = LocalDateTime.now(Clock.systemDefaultZone()); LocalDateTime test = LocalDateTime.now(); - long diff = Math.abs(test.getTime().toNanoOfDay() - expected.getTime().toNanoOfDay()); + long diff = Math.abs(test.toLocalTime().toNanoOfDay() - expected.toLocalTime().toNanoOfDay()); if (diff >= 100000000) { // may be date change expected = LocalDateTime.now(Clock.systemDefaultZone()); test = LocalDateTime.now(); - diff = Math.abs(test.getTime().toNanoOfDay() - expected.getTime().toNanoOfDay()); + diff = Math.abs(test.toLocalTime().toNanoOfDay() - expected.toLocalTime().toNanoOfDay()); } assertTrue(diff < 100000000); // less than 0.1 secs } @@ -364,7 +360,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { assertEquals(test.getMonth(), Month.DECEMBER); assertEquals(test.getDayOfMonth(), 31); expected = expected.minusSeconds(1); - assertEquals(test.getTime(), expected); + assertEquals(test.toLocalTime(), expected); } } @@ -915,14 +911,14 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void factory_parse_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d H m s"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M d H m s"); LocalDateTime test = LocalDateTime.parse("2010 12 3 11 30 45", f); assertEquals(test, LocalDateTime.of(2010, 12, 3, 11, 30, 45)); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void factory_parse_formatter_nullText() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d H m s"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M d H m s"); LocalDateTime.parse((String) null, f); } @@ -971,34 +967,27 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- // query(TemporalQuery) //----------------------------------------------------------------------- - @Test - public void test_query_chrono() { - assertEquals(TEST_2007_07_15_12_30_40_987654321.query(Queries.chrono()), ISOChrono.INSTANCE); - assertEquals(Queries.chrono().queryFrom(TEST_2007_07_15_12_30_40_987654321), ISOChrono.INSTANCE); + @DataProvider(name="query") + Object[][] data_query() { + return new Object[][] { + {TEST_2007_07_15_12_30_40_987654321, Queries.chronology(), IsoChronology.INSTANCE}, + {TEST_2007_07_15_12_30_40_987654321, Queries.zoneId(), null}, + {TEST_2007_07_15_12_30_40_987654321, Queries.precision(), ChronoUnit.NANOS}, + {TEST_2007_07_15_12_30_40_987654321, Queries.zone(), null}, + {TEST_2007_07_15_12_30_40_987654321, Queries.offset(), null}, + {TEST_2007_07_15_12_30_40_987654321, Queries.localDate(), LocalDate.of(2007, 7, 15)}, + {TEST_2007_07_15_12_30_40_987654321, Queries.localTime(), LocalTime.of(12, 30, 40, 987654321)}, + }; } - @Test - public void test_query_zoneId() { - assertEquals(TEST_2007_07_15_12_30_40_987654321.query(Queries.zoneId()), null); - assertEquals(Queries.zoneId().queryFrom(TEST_2007_07_15_12_30_40_987654321), null); + @Test(dataProvider="query") + public void test_query(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(temporal.query(query), expected); } - @Test - public void test_query_precision() { - assertEquals(TEST_2007_07_15_12_30_40_987654321.query(Queries.precision()), NANOS); - assertEquals(Queries.precision().queryFrom(TEST_2007_07_15_12_30_40_987654321), NANOS); - } - - @Test - public void test_query_offset() { - assertEquals(TEST_2007_07_15_12_30_40_987654321.query(Queries.offset()), null); - assertEquals(Queries.offset().queryFrom(TEST_2007_07_15_12_30_40_987654321), null); - } - - @Test - public void test_query_zone() { - assertEquals(TEST_2007_07_15_12_30_40_987654321.query(Queries.zone()), null); - assertEquals(Queries.zone().queryFrom(TEST_2007_07_15_12_30_40_987654321), null); + @Test(dataProvider="query") + public void test_queryFrom(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(query.queryFrom(temporal), expected); } @Test(expectedExceptions=NullPointerException.class) @@ -1065,7 +1054,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(dataProvider="sampleTimes", groups={"tck"}) public void test_get_times(int h, int m, int s, int ns) { - LocalDateTime a = LocalDateTime.of(TEST_2007_07_15_12_30_40_987654321.getDate(), LocalTime.of(h, m, s, ns)); + LocalDateTime a = LocalDateTime.of(TEST_2007_07_15_12_30_40_987654321.toLocalDate(), LocalTime.of(h, m, s, ns)); assertEquals(a.getHour(), h); assertEquals(a.getMinute(), m); assertEquals(a.getSecond(), s); @@ -1082,7 +1071,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { int length = month.length(false); for (int i = 1; i <= length; i++) { LocalDateTime d = LocalDateTime.of(LocalDate.of(2007, month, i), - TEST_2007_07_15_12_30_40_987654321.getTime()); + TEST_2007_07_15_12_30_40_987654321.toLocalTime()); assertSame(d.getDayOfWeek(), dow); dow = dow.plus(1); } @@ -1297,54 +1286,39 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { } //----------------------------------------------------------------------- - // plus(adjuster) + // plus(TemporalAmount) //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_plus_adjuster() { - Period p = Period.ofTime(0, 0, 62, 3); - LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.plus(p); - assertEquals(t, LocalDateTime.of(2007, 7, 15, 12, 31, 42, 987654324)); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_plus_adjuster_null() { - TEST_2007_07_15_12_30_40_987654321.plus((TemporalAdder) null); - } - - //----------------------------------------------------------------------- - // plus(Period) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_plus_Period_positiveMonths() { - MockSimplePeriod period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); + @Test + public void test_plus_TemporalAmount_positiveMonths() { + MockSimplePeriod period = MockSimplePeriod.of(7, MONTHS); LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.plus(period); assertEquals(t, LocalDateTime.of(2008, 2, 15, 12, 30, 40, 987654321)); } - @Test(groups={"tck"}) - public void test_plus_Period_negativeDays() { - MockSimplePeriod period = MockSimplePeriod.of(-25, ChronoUnit.DAYS); + @Test + public void test_plus_TemporalAmount_negativeDays() { + MockSimplePeriod period = MockSimplePeriod.of(-25, DAYS); LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.plus(period); assertEquals(t, LocalDateTime.of(2007, 6, 20, 12, 30, 40, 987654321)); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_plus_Period_null() { - TEST_2007_07_15_12_30_40_987654321.plus((MockSimplePeriod) null); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_plus_Period_invalidTooLarge() { - MockSimplePeriod period = MockSimplePeriod.of(1, ChronoUnit.YEARS); + @Test(expectedExceptions=DateTimeException.class) + public void test_plus_TemporalAmount_invalidTooLarge() { + MockSimplePeriod period = MockSimplePeriod.of(1, YEARS); LocalDateTime.of(Year.MAX_VALUE, 1, 1, 0, 0).plus(period); } - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_plus_Period_invalidTooSmall() { - MockSimplePeriod period = MockSimplePeriod.of(-1, ChronoUnit.YEARS); + @Test(expectedExceptions=DateTimeException.class) + public void test_plus_TemporalAmount_invalidTooSmall() { + MockSimplePeriod period = MockSimplePeriod.of(-1, YEARS); LocalDateTime.of(Year.MIN_VALUE, 1, 1, 0, 0).plus(period); } + @Test(expectedExceptions=NullPointerException.class) + public void test_plus_TemporalAmount_null() { + TEST_2007_07_15_12_30_40_987654321.plus((TemporalAmount) null); + } + //----------------------------------------------------------------------- // plus(long,TemporalUnit) //----------------------------------------------------------------------- @@ -1697,7 +1671,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_plusHours_one() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); - LocalDate d = t.getDate(); + LocalDate d = t.toLocalDate(); for (int i = 0; i < 50; i++) { t = t.plusHours(1); @@ -1706,7 +1680,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { d = d.plusDays(1); } - assertEquals(t.getDate(), d); + assertEquals(t.toLocalDate(), d); assertEquals(t.getHour(), (i + 1) % 24); } } @@ -1714,7 +1688,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_plusHours_fromZero() { LocalDateTime base = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); - LocalDate d = base.getDate().minusDays(3); + LocalDate d = base.toLocalDate().minusDays(3); LocalTime t = LocalTime.of(21, 0); for (int i = -50; i < 50; i++) { @@ -1725,15 +1699,15 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { d = d.plusDays(1); } - assertEquals(dt.getDate(), d); - assertEquals(dt.getTime(), t); + assertEquals(dt.toLocalDate(), d); + assertEquals(dt.toLocalTime(), t); } } @Test(groups={"tck"}) public void test_plusHours_fromOne() { LocalDateTime base = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(1, 0)); - LocalDate d = base.getDate().minusDays(3); + LocalDate d = base.toLocalDate().minusDays(3); LocalTime t = LocalTime.of(22, 0); for (int i = -50; i < 50; i++) { @@ -1745,8 +1719,8 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { d = d.plusDays(1); } - assertEquals(dt.getDate(), d); - assertEquals(dt.getTime(), t); + assertEquals(dt.toLocalDate(), d); + assertEquals(dt.toLocalTime(), t); } } @@ -1756,7 +1730,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_plusMinutes_one() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); - LocalDate d = t.getDate(); + LocalDate d = t.toLocalDate(); int hour = 0; int min = 0; @@ -1769,7 +1743,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { min = 0; } - assertEquals(t.getDate(), d); + assertEquals(t.toLocalDate(), d); assertEquals(t.getHour(), hour); assertEquals(t.getMinute(), min); } @@ -1778,7 +1752,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_plusMinutes_fromZero() { LocalDateTime base = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); - LocalDate d = base.getDate().minusDays(1); + LocalDate d = base.toLocalDate().minusDays(1); LocalTime t = LocalTime.of(22, 49); for (int i = -70; i < 70; i++) { @@ -1789,15 +1763,15 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { d = d.plusDays(1); } - assertEquals(dt.getDate(), d, String.valueOf(i)); - assertEquals(dt.getTime(), t, String.valueOf(i)); + assertEquals(dt.toLocalDate(), d, String.valueOf(i)); + assertEquals(dt.toLocalTime(), t, String.valueOf(i)); } } @Test(groups={"tck"}) public void test_plusMinutes_noChange_oneDay() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.plusMinutes(24 * 60); - assertEquals(t.getDate(), TEST_2007_07_15_12_30_40_987654321.getDate().plusDays(1)); + assertEquals(t.toLocalDate(), TEST_2007_07_15_12_30_40_987654321.toLocalDate().plusDays(1)); } //----------------------------------------------------------------------- @@ -1806,7 +1780,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_plusSeconds_one() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); - LocalDate d = t.getDate(); + LocalDate d = t.toLocalDate(); int hour = 0; int min = 0; @@ -1824,7 +1798,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { min = 0; } - assertEquals(t.getDate(), d); + assertEquals(t.toLocalDate(), d); assertEquals(t.getHour(), hour); assertEquals(t.getMinute(), min); assertEquals(t.getSecond(), sec); @@ -1837,7 +1811,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { int delta = 30; int i = -3660; - LocalDate date = TEST_2007_07_15_12_30_40_987654321.getDate().minusDays(1); + LocalDate date = TEST_2007_07_15_12_30_40_987654321.toLocalDate().minusDays(1); int hour = 22; int min = 59; int sec = 0; @@ -1883,7 +1857,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { LocalDateTime base = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); LocalDateTime t = base.plusSeconds(seconds); - assertEquals(date, t.getDate()); + assertEquals(date, t.toLocalDate()); assertEquals(hour, t.getHour()); assertEquals(min, t.getMinute()); assertEquals(sec, t.getSecond()); @@ -1892,7 +1866,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_plusSeconds_noChange_oneDay() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.plusSeconds(24 * 60 * 60); - assertEquals(t.getDate(), TEST_2007_07_15_12_30_40_987654321.getDate().plusDays(1)); + assertEquals(t.toLocalDate(), TEST_2007_07_15_12_30_40_987654321.toLocalDate().plusDays(1)); } //----------------------------------------------------------------------- @@ -1901,7 +1875,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_plusNanos_halfABillion() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); - LocalDate d = t.getDate(); + LocalDate d = t.toLocalDate(); int hour = 0; int min = 0; @@ -1924,7 +1898,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { min = 0; } - assertEquals(t.getDate(), d, String.valueOf(i)); + assertEquals(t.toLocalDate(), d, String.valueOf(i)); assertEquals(t.getHour(), hour); assertEquals(t.getMinute(), min); assertEquals(t.getSecond(), sec); @@ -1938,7 +1912,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { long delta = 7500000000L; long i = -3660 * 1000000000L; - LocalDate date = TEST_2007_07_15_12_30_40_987654321.getDate().minusDays(1); + LocalDate date = TEST_2007_07_15_12_30_40_987654321.toLocalDate().minusDays(1); int hour = 22; int min = 59; int sec = 0; @@ -1987,7 +1961,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { LocalDateTime base = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); LocalDateTime t = base.plusNanos(nanoseconds); - assertEquals(date, t.getDate()); + assertEquals(date, t.toLocalDate()); assertEquals(hour, t.getHour()); assertEquals(min, t.getMinute()); assertEquals(sec, t.getSecond()); @@ -1997,58 +1971,43 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_plusNanos_noChange_oneDay() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.plusNanos(24 * 60 * 60 * 1000000000L); - assertEquals(t.getDate(), TEST_2007_07_15_12_30_40_987654321.getDate().plusDays(1)); + assertEquals(t.toLocalDate(), TEST_2007_07_15_12_30_40_987654321.toLocalDate().plusDays(1)); } //----------------------------------------------------------------------- - // minus(adjuster) + // minus(TemporalAmount) //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_minus_adjuster() { - Period p = Period.ofTime(0, 0, 62, 3); - LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.minus(p); - assertEquals(t, LocalDateTime.of(2007, 7, 15, 12, 29, 38, 987654318)); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_minus_adjuster_null() { - TEST_2007_07_15_12_30_40_987654321.minus((TemporalSubtractor) null); - } - - //----------------------------------------------------------------------- - // minus(Period) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_minus_Period_positiveMonths() { - MockSimplePeriod period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); + @Test + public void test_minus_TemporalAmount_positiveMonths() { + MockSimplePeriod period = MockSimplePeriod.of(7, MONTHS); LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.minus(period); assertEquals(t, LocalDateTime.of(2006, 12, 15, 12, 30, 40, 987654321)); } - @Test(groups={"tck"}) - public void test_minus_Period_negativeDays() { - MockSimplePeriod period = MockSimplePeriod.of(-25, ChronoUnit.DAYS); + @Test + public void test_minus_TemporalAmount_negativeDays() { + MockSimplePeriod period = MockSimplePeriod.of(-25, DAYS); LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.minus(period); assertEquals(t, LocalDateTime.of(2007, 8, 9, 12, 30, 40, 987654321)); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_minus_Period_null() { - TEST_2007_07_15_12_30_40_987654321.minus((MockSimplePeriod) null); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_minus_Period_invalidTooLarge() { - MockSimplePeriod period = MockSimplePeriod.of(-1, ChronoUnit.YEARS); + @Test(expectedExceptions=DateTimeException.class) + public void test_minus_TemporalAmount_invalidTooLarge() { + MockSimplePeriod period = MockSimplePeriod.of(-1, YEARS); LocalDateTime.of(Year.MAX_VALUE, 1, 1, 0, 0).minus(period); } - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_minus_Period_invalidTooSmall() { - MockSimplePeriod period = MockSimplePeriod.of(1, ChronoUnit.YEARS); + @Test(expectedExceptions=DateTimeException.class) + public void test_minus_TemporalAmount_invalidTooSmall() { + MockSimplePeriod period = MockSimplePeriod.of(1, YEARS); LocalDateTime.of(Year.MIN_VALUE, 1, 1, 0, 0).minus(period); } + @Test(expectedExceptions=NullPointerException.class) + public void test_minus_TemporalAmount_null() { + TEST_2007_07_15_12_30_40_987654321.minus((TemporalAmount) null); + } + //----------------------------------------------------------------------- // minus(long,TemporalUnit) //----------------------------------------------------------------------- @@ -2401,7 +2360,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_minusHours_one() { LocalDateTime t =TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); - LocalDate d = t.getDate(); + LocalDate d = t.toLocalDate(); for (int i = 0; i < 50; i++) { t = t.minusHours(1); @@ -2410,7 +2369,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { d = d.minusDays(1); } - assertEquals(t.getDate(), d); + assertEquals(t.toLocalDate(), d); assertEquals(t.getHour(), (((-i + 23) % 24) + 24) % 24); } } @@ -2418,7 +2377,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_minusHours_fromZero() { LocalDateTime base = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); - LocalDate d = base.getDate().plusDays(2); + LocalDate d = base.toLocalDate().plusDays(2); LocalTime t = LocalTime.of(3, 0); for (int i = -50; i < 50; i++) { @@ -2429,15 +2388,15 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { d = d.minusDays(1); } - assertEquals(dt.getDate(), d, String.valueOf(i)); - assertEquals(dt.getTime(), t); + assertEquals(dt.toLocalDate(), d, String.valueOf(i)); + assertEquals(dt.toLocalTime(), t); } } @Test(groups={"tck"}) public void test_minusHours_fromOne() { LocalDateTime base = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(1, 0)); - LocalDate d = base.getDate().plusDays(2); + LocalDate d = base.toLocalDate().plusDays(2); LocalTime t = LocalTime.of(4, 0); for (int i = -50; i < 50; i++) { @@ -2449,8 +2408,8 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { d = d.minusDays(1); } - assertEquals(dt.getDate(), d, String.valueOf(i)); - assertEquals(dt.getTime(), t); + assertEquals(dt.toLocalDate(), d, String.valueOf(i)); + assertEquals(dt.toLocalTime(), t); } } @@ -2460,7 +2419,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_minusMinutes_one() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); - LocalDate d = t.getDate().minusDays(1); + LocalDate d = t.toLocalDate().minusDays(1); int hour = 0; int min = 0; @@ -2476,7 +2435,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { hour = 23; } } - assertEquals(t.getDate(), d); + assertEquals(t.toLocalDate(), d); assertEquals(t.getHour(), hour); assertEquals(t.getMinute(), min); } @@ -2485,7 +2444,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_minusMinutes_fromZero() { LocalDateTime base = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); - LocalDate d = base.getDate().minusDays(1); + LocalDate d = base.toLocalDate().minusDays(1); LocalTime t = LocalTime.of(22, 49); for (int i = 70; i > -70; i--) { @@ -2496,15 +2455,15 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { d = d.plusDays(1); } - assertEquals(dt.getDate(), d); - assertEquals(dt.getTime(), t); + assertEquals(dt.toLocalDate(), d); + assertEquals(dt.toLocalTime(), t); } } @Test(groups={"tck"}) public void test_minusMinutes_noChange_oneDay() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.minusMinutes(24 * 60); - assertEquals(t.getDate(), TEST_2007_07_15_12_30_40_987654321.getDate().minusDays(1)); + assertEquals(t.toLocalDate(), TEST_2007_07_15_12_30_40_987654321.toLocalDate().minusDays(1)); } //----------------------------------------------------------------------- @@ -2513,7 +2472,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_minusSeconds_one() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); - LocalDate d = t.getDate().minusDays(1); + LocalDate d = t.toLocalDate().minusDays(1); int hour = 0; int min = 0; @@ -2536,7 +2495,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { } } - assertEquals(t.getDate(), d); + assertEquals(t.toLocalDate(), d); assertEquals(t.getHour(), hour); assertEquals(t.getMinute(), min); assertEquals(t.getSecond(), sec); @@ -2549,7 +2508,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { int delta = 30; int i = 3660; - LocalDate date = TEST_2007_07_15_12_30_40_987654321.getDate().minusDays(1); + LocalDate date = TEST_2007_07_15_12_30_40_987654321.toLocalDate().minusDays(1); int hour = 22; int min = 59; int sec = 0; @@ -2595,7 +2554,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { LocalDateTime base = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); LocalDateTime t = base.minusSeconds(seconds); - assertEquals(date, t.getDate()); + assertEquals(date, t.toLocalDate()); assertEquals(hour, t.getHour()); assertEquals(min, t.getMinute()); assertEquals(sec, t.getSecond()); @@ -2607,7 +2566,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_minusNanos_halfABillion() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); - LocalDate d = t.getDate().minusDays(1); + LocalDate d = t.toLocalDate().minusDays(1); int hour = 0; int min = 0; @@ -2637,7 +2596,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { } } - assertEquals(t.getDate(), d); + assertEquals(t.toLocalDate(), d); assertEquals(t.getHour(), hour); assertEquals(t.getMinute(), min); assertEquals(t.getSecond(), sec); @@ -2651,7 +2610,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { long delta = 7500000000L; long i = 3660 * 1000000000L; - LocalDate date = TEST_2007_07_15_12_30_40_987654321.getDate().minusDays(1); + LocalDate date = TEST_2007_07_15_12_30_40_987654321.toLocalDate().minusDays(1); int hour = 22; int min = 59; int sec = 0; @@ -2700,7 +2659,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { LocalDateTime base = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.MIDNIGHT); LocalDateTime t = base.minusNanos(nanoseconds); - assertEquals(date, t.getDate()); + assertEquals(date, t.toLocalDate()); assertEquals(hour, t.getHour()); assertEquals(min, t.getMinute()); assertEquals(sec, t.getSecond()); @@ -3032,7 +2991,7 @@ public class TCKLocalDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_toString_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d H m s"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M d H m s"); String t = LocalDateTime.of(2010, 12, 3, 11, 30, 45).toString(f); assertEquals(t, "2010 12 3 11 30 45"); } diff --git a/jdk/test/java/time/tck/java/time/TCKLocalTime.java b/jdk/test/java/time/tck/java/time/TCKLocalTime.java index 1cc5486c7e2..9b4d65f4938 100644 --- a/jdk/test/java/time/tck/java/time/TCKLocalTime.java +++ b/jdk/test/java/time/tck/java/time/TCKLocalTime.java @@ -92,42 +92,39 @@ import static org.testng.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; -import java.io.IOException; +import java.time.Clock; +import java.time.DateTimeException; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.OffsetTime; +import java.time.Period; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoField; +import java.time.temporal.ChronoUnit; +import java.time.temporal.JulianFields; +import java.time.temporal.Queries; +import java.time.temporal.Temporal; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalAdjuster; +import java.time.temporal.TemporalAmount; +import java.time.temporal.TemporalField; +import java.time.temporal.TemporalQuery; +import java.time.temporal.TemporalUnit; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import java.util.Iterator; import java.util.List; -import java.time.Clock; -import java.time.DateTimeException; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.Period; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatters; -import java.time.format.DateTimeParseException; -import java.time.temporal.ChronoField; -import java.time.temporal.ChronoUnit; -import java.time.temporal.JulianFields; -import java.time.temporal.OffsetTime; -import java.time.temporal.Queries; -import java.time.temporal.Temporal; -import java.time.temporal.TemporalAccessor; -import java.time.temporal.TemporalAdder; -import java.time.temporal.TemporalAdjuster; -import java.time.temporal.TemporalField; -import java.time.temporal.TemporalSubtractor; -import java.time.temporal.TemporalUnit; - import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import test.java.time.MockSimplePeriod; /** * Test LocalTime. @@ -504,35 +501,6 @@ public class TCKLocalTime extends AbstractDateTimeTest { LocalTime.ofSecondOfDay(24 * 60 * 60); } - //----------------------------------------------------------------------- - // ofSecondOfDay(long, int) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void factory_ofSecondOfDay_long_int() { - LocalTime localTime = LocalTime.ofSecondOfDay(2 * 60 * 60 + 17 * 60 + 23, 987); - check(localTime, 2, 17, 23, 987); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void factory_ofSecondOfDay_long_int_tooLowSecs() { - LocalTime.ofSecondOfDay(-1, 0); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void factory_ofSecondOfDay_long_int_tooHighSecs() { - LocalTime.ofSecondOfDay(24 * 60 * 60, 0); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void factory_ofSecondOfDay_long_int_tooLowNanos() { - LocalTime.ofSecondOfDay(0, -1); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void factory_ofSecondOfDay_long_int_tooHighNanos() { - LocalTime.ofSecondOfDay(0, 1000000000); - } - //----------------------------------------------------------------------- // ofNanoOfDay(long) //----------------------------------------------------------------------- @@ -631,14 +599,14 @@ public class TCKLocalTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void factory_parse_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("H m s"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("H m s"); LocalTime test = LocalTime.parse("14 30 40", f); assertEquals(test, LocalTime.of(14, 30, 40)); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void factory_parse_formatter_nullText() { - DateTimeFormatter f = DateTimeFormatters.pattern("H m s"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("H m s"); LocalTime.parse((String) null, f); } @@ -685,34 +653,27 @@ public class TCKLocalTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- // query(TemporalQuery) //----------------------------------------------------------------------- - @Test - public void test_query_chrono() { - assertEquals(TEST_12_30_40_987654321.query(Queries.chrono()), null); - assertEquals(Queries.chrono().queryFrom(TEST_12_30_40_987654321), null); + @DataProvider(name="query") + Object[][] data_query() { + return new Object[][] { + {TEST_12_30_40_987654321, Queries.chronology(), null}, + {TEST_12_30_40_987654321, Queries.zoneId(), null}, + {TEST_12_30_40_987654321, Queries.precision(), ChronoUnit.NANOS}, + {TEST_12_30_40_987654321, Queries.zone(), null}, + {TEST_12_30_40_987654321, Queries.offset(), null}, + {TEST_12_30_40_987654321, Queries.localDate(), null}, + {TEST_12_30_40_987654321, Queries.localTime(), TEST_12_30_40_987654321}, + }; } - @Test - public void test_query_zoneId() { - assertEquals(TEST_12_30_40_987654321.query(Queries.zoneId()), null); - assertEquals(Queries.zoneId().queryFrom(TEST_12_30_40_987654321), null); + @Test(dataProvider="query") + public void test_query(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(temporal.query(query), expected); } - @Test - public void test_query_precision() { - assertEquals(TEST_12_30_40_987654321.query(Queries.precision()), NANOS); - assertEquals(Queries.precision().queryFrom(TEST_12_30_40_987654321), NANOS); - } - - @Test - public void test_query_offset() { - assertEquals(TEST_12_30_40_987654321.query(Queries.offset()), null); - assertEquals(Queries.offset().queryFrom(TEST_12_30_40_987654321), null); - } - - @Test - public void test_query_zone() { - assertEquals(TEST_12_30_40_987654321.query(Queries.zone()), null); - assertEquals(Queries.zone().queryFrom(TEST_12_30_40_987654321), null); + @Test(dataProvider="query") + public void test_queryFrom(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(query.queryFrom(temporal), expected); } @Test(expectedExceptions=NullPointerException.class) @@ -942,6 +903,60 @@ public class TCKLocalTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- // truncated(TemporalUnit) //----------------------------------------------------------------------- + TemporalUnit NINETY_MINS = new TemporalUnit() { + @Override + public String getName() { + return "NinetyMins"; + } + @Override + public Duration getDuration() { + return Duration.ofMinutes(90); + } + @Override + public boolean isDurationEstimated() { + return false; + } + @Override + public boolean isSupportedBy(Temporal temporal) { + return false; + } + @Override + public R addTo(R temporal, long amount) { + throw new UnsupportedOperationException(); + } + @Override + public long between(Temporal temporal1, Temporal temporal2) { + throw new UnsupportedOperationException(); + } + }; + + TemporalUnit NINETY_FIVE_MINS = new TemporalUnit() { + @Override + public String getName() { + return "NinetyFiveMins"; + } + @Override + public Duration getDuration() { + return Duration.ofMinutes(95); + } + @Override + public boolean isDurationEstimated() { + return false; + } + @Override + public boolean isSupportedBy(Temporal temporal) { + return false; + } + @Override + public R addTo(R temporal, long amount) { + throw new UnsupportedOperationException(); + } + @Override + public long between(Temporal temporal1, Temporal temporal2) { + throw new UnsupportedOperationException(); + } + }; + @DataProvider(name="truncatedToValid") Object[][] data_truncatedToValid() { return new Object[][] { @@ -952,6 +967,10 @@ public class TCKLocalTime extends AbstractDateTimeTest { {LocalTime.of(1, 2, 3, 123_456_789), MINUTES, LocalTime.of(1, 2)}, {LocalTime.of(1, 2, 3, 123_456_789), HOURS, LocalTime.of(1, 0)}, {LocalTime.of(1, 2, 3, 123_456_789), DAYS, LocalTime.MIDNIGHT}, + + {LocalTime.of(1, 1, 1, 123_456_789), NINETY_MINS, LocalTime.of(0, 0)}, + {LocalTime.of(2, 1, 1, 123_456_789), NINETY_MINS, LocalTime.of(1, 30)}, + {LocalTime.of(3, 1, 1, 123_456_789), NINETY_MINS, LocalTime.of(3, 0)}, }; } @@ -963,6 +982,7 @@ public class TCKLocalTime extends AbstractDateTimeTest { @DataProvider(name="truncatedToInvalid") Object[][] data_truncatedToInvalid() { return new Object[][] { + {LocalTime.of(1, 2, 3, 123_456_789), NINETY_FIVE_MINS}, {LocalTime.of(1, 2, 3, 123_456_789), WEEKS}, {LocalTime.of(1, 2, 3, 123_456_789), MONTHS}, {LocalTime.of(1, 2, 3, 123_456_789), YEARS}, @@ -980,45 +1000,45 @@ public class TCKLocalTime extends AbstractDateTimeTest { } //----------------------------------------------------------------------- - // plus(PlusAdjuster) + // plus(TemporalAmount) //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_plus_Adjuster_positiveHours() { - TemporalAdder period = MockSimplePeriod.of(7, ChronoUnit.HOURS); + @Test + public void test_plus_TemporalAmount_positiveHours() { + TemporalAmount period = MockSimplePeriod.of(7, ChronoUnit.HOURS); LocalTime t = TEST_12_30_40_987654321.plus(period); assertEquals(t, LocalTime.of(19, 30, 40, 987654321)); } - @Test(groups={"tck"}) - public void test_plus_Adjuster_negativeMinutes() { - TemporalAdder period = MockSimplePeriod.of(-25, ChronoUnit.MINUTES); + @Test + public void test_plus_TemporalAmount_negativeMinutes() { + TemporalAmount period = MockSimplePeriod.of(-25, ChronoUnit.MINUTES); LocalTime t = TEST_12_30_40_987654321.plus(period); assertEquals(t, LocalTime.of(12, 5, 40, 987654321)); } - @Test(groups={"tck"}) - public void test_plus_Adjuster_zero() { - TemporalAdder period = Period.ZERO; + @Test + public void test_plus_TemporalAmount_zero() { + TemporalAmount period = Period.ZERO; LocalTime t = TEST_12_30_40_987654321.plus(period); assertEquals(t, TEST_12_30_40_987654321); } - @Test(groups={"tck"}) - public void test_plus_Adjuster_wrap() { - TemporalAdder p = Period.ofTime(1, 0, 0); + @Test + public void test_plus_TemporalAmount_wrap() { + TemporalAmount p = MockSimplePeriod.of(1, HOURS); LocalTime t = LocalTime.of(23, 30).plus(p); assertEquals(t, LocalTime.of(0, 30)); } - @Test(groups={"tck"}, expectedExceptions=DateTimeException.class) - public void test_plus_Adjuster_dateNotAllowed() { - TemporalAdder period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); + @Test(expectedExceptions=DateTimeException.class) + public void test_plus_TemporalAmount_dateNotAllowed() { + TemporalAmount period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); TEST_12_30_40_987654321.plus(period); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_plus_Adjuster_null() { - TEST_12_30_40_987654321.plus((TemporalAdder) null); + @Test(expectedExceptions=NullPointerException.class) + public void test_plus_TemporalAmount_null() { + TEST_12_30_40_987654321.plus((TemporalAmount) null); } //----------------------------------------------------------------------- @@ -1067,41 +1087,6 @@ public class TCKLocalTime extends AbstractDateTimeTest { TEST_12_30_40_987654321.plus(1, (TemporalUnit) null); } - //----------------------------------------------------------------------- - // plus(adjuster) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_plus_adjuster() { - Period p = Period.ofTime(0, 0, 62, 3); - LocalTime t = TEST_12_30_40_987654321.plus(p); - assertEquals(t, LocalTime.of(12, 31, 42, 987654324)); - } - - @Test(groups={"tck"}) - public void test_plus_adjuster_big() { - Period p = Period.ofTime(0, 0, 0, Long.MAX_VALUE); - LocalTime t = TEST_12_30_40_987654321.plus(p); - assertEquals(t, TEST_12_30_40_987654321.plusNanos(Long.MAX_VALUE)); - } - - @Test(groups={"tck"}) - public void test_plus_adjuster_zero_equal() { - LocalTime t = TEST_12_30_40_987654321.plus(Period.ZERO); - assertEquals(t, TEST_12_30_40_987654321); - } - - @Test(groups={"tck"}) - public void test_plus_adjuster_wrap() { - Period p = Period.ofTime(1, 0, 0); - LocalTime t = LocalTime.of(23, 30).plus(p); - assertEquals(t, LocalTime.of(0, 30)); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_plus_adjuster_null() { - TEST_12_30_40_987654321.plus((TemporalAdder) null); - } - //----------------------------------------------------------------------- // plusHours() //----------------------------------------------------------------------- @@ -1449,59 +1434,45 @@ public class TCKLocalTime extends AbstractDateTimeTest { } //----------------------------------------------------------------------- - // minus(MinusAdjuster) + // minus(TemporalAmount) //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_minus_Adjuster() { - TemporalSubtractor p = Period.ofTime(0, 0, 62, 3); - LocalTime t = TEST_12_30_40_987654321.minus(p); - assertEquals(t, LocalTime.of(12, 29, 38, 987654318)); - } - - @Test(groups={"tck"}) - public void test_minus_Adjuster_positiveHours() { - TemporalSubtractor period = MockSimplePeriod.of(7, ChronoUnit.HOURS); + @Test + public void test_minus_TemporalAmount_positiveHours() { + TemporalAmount period = MockSimplePeriod.of(7, ChronoUnit.HOURS); LocalTime t = TEST_12_30_40_987654321.minus(period); assertEquals(t, LocalTime.of(5, 30, 40, 987654321)); } - @Test(groups={"tck"}) - public void test_minus_Adjuster_negativeMinutes() { - TemporalSubtractor period = MockSimplePeriod.of(-25, ChronoUnit.MINUTES); + @Test + public void test_minus_TemporalAmount_negativeMinutes() { + TemporalAmount period = MockSimplePeriod.of(-25, ChronoUnit.MINUTES); LocalTime t = TEST_12_30_40_987654321.minus(period); assertEquals(t, LocalTime.of(12, 55, 40, 987654321)); } - @Test(groups={"tck"}) - public void test_minus_Adjuster_big1() { - TemporalSubtractor p = Period.ofTime(0, 0, 0, Long.MAX_VALUE); - LocalTime t = TEST_12_30_40_987654321.minus(p); - assertEquals(t, TEST_12_30_40_987654321.minusNanos(Long.MAX_VALUE)); - } - - @Test(groups={"tck"}) - public void test_minus_Adjuster_zero() { - TemporalSubtractor p = Period.ZERO; - LocalTime t = TEST_12_30_40_987654321.minus(p); + @Test + public void test_minus_TemporalAmount_zero() { + TemporalAmount period = Period.ZERO; + LocalTime t = TEST_12_30_40_987654321.minus(period); assertEquals(t, TEST_12_30_40_987654321); } - @Test(groups={"tck"}) - public void test_minus_Adjuster_wrap() { - TemporalSubtractor p = Period.ofTime(1, 0, 0); + @Test + public void test_minus_TemporalAmount_wrap() { + TemporalAmount p = MockSimplePeriod.of(1, HOURS); LocalTime t = LocalTime.of(0, 30).minus(p); assertEquals(t, LocalTime.of(23, 30)); } - @Test(groups={"tck"}, expectedExceptions=DateTimeException.class) - public void test_minus_Adjuster_dateNotAllowed() { - TemporalSubtractor period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); + @Test(expectedExceptions=DateTimeException.class) + public void test_minus_TemporalAmount_dateNotAllowed() { + TemporalAmount period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); TEST_12_30_40_987654321.minus(period); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_minus_Adjuster_null() { - TEST_12_30_40_987654321.minus((TemporalSubtractor) null); + @Test(expectedExceptions=NullPointerException.class) + public void test_minus_TemporalAmount_null() { + TEST_12_30_40_987654321.minus((TemporalAmount) null); } //----------------------------------------------------------------------- @@ -2213,7 +2184,7 @@ public class TCKLocalTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_toString_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("H m s"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("H m s"); String t = LocalTime.of(11, 30, 45).toString(f); assertEquals(t, "11 30 45"); } diff --git a/jdk/test/java/time/tck/java/time/TCKMonth.java b/jdk/test/java/time/tck/java/time/TCKMonth.java index 6f6170d06f8..c5160c1c286 100644 --- a/jdk/test/java/time/tck/java/time/TCKMonth.java +++ b/jdk/test/java/time/tck/java/time/TCKMonth.java @@ -62,23 +62,23 @@ package tck.java.time; import static java.time.temporal.ChronoField.MONTH_OF_YEAR; import static org.testng.Assert.assertEquals; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - import java.time.DateTimeException; import java.time.LocalDate; import java.time.LocalTime; import java.time.Month; +import java.time.chrono.IsoChronology; import java.time.format.TextStyle; import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; -import java.time.temporal.ISOChrono; import java.time.temporal.JulianFields; import java.time.temporal.Queries; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; +import java.time.temporal.TemporalQuery; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -167,34 +167,27 @@ public class TCKMonth extends AbstractDateTimeTest { //----------------------------------------------------------------------- // query(TemporalQuery) //----------------------------------------------------------------------- - @Test - public void test_query_chrono() { - assertEquals(Month.JUNE.query(Queries.chrono()), ISOChrono.INSTANCE); - assertEquals(Queries.chrono().queryFrom(Month.JUNE), ISOChrono.INSTANCE); + @DataProvider(name="query") + Object[][] data_query() { + return new Object[][] { + {Month.JUNE, Queries.chronology(), IsoChronology.INSTANCE}, + {Month.JUNE, Queries.zoneId(), null}, + {Month.JUNE, Queries.precision(), ChronoUnit.MONTHS}, + {Month.JUNE, Queries.zone(), null}, + {Month.JUNE, Queries.offset(), null}, + {Month.JUNE, Queries.localDate(), null}, + {Month.JUNE, Queries.localTime(), null}, + }; } - @Test - public void test_query_zoneId() { - assertEquals(Month.JUNE.query(Queries.zoneId()), null); - assertEquals(Queries.zoneId().queryFrom(Month.JUNE), null); + @Test(dataProvider="query") + public void test_query(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(temporal.query(query), expected); } - @Test - public void test_query_precision() { - assertEquals(Month.JUNE.query(Queries.precision()), ChronoUnit.MONTHS); - assertEquals(Queries.precision().queryFrom(Month.JUNE), ChronoUnit.MONTHS); - } - - @Test - public void test_query_offset() { - assertEquals(Month.JUNE.query(Queries.offset()), null); - assertEquals(Queries.offset().queryFrom(Month.JUNE), null); - } - - @Test - public void test_query_zone() { - assertEquals(Month.JUNE.query(Queries.zone()), null); - assertEquals(Queries.zone().queryFrom(Month.JUNE), null); + @Test(dataProvider="query") + public void test_queryFrom(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(query.queryFrom(temporal), expected); } @Test(expectedExceptions=NullPointerException.class) @@ -207,17 +200,17 @@ public class TCKMonth extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_getText() { - assertEquals(Month.JANUARY.getText(TextStyle.SHORT, Locale.US), "Jan"); + assertEquals(Month.JANUARY.getDisplayName(TextStyle.SHORT, Locale.US), "Jan"); } @Test(expectedExceptions = NullPointerException.class, groups={"tck"}) public void test_getText_nullStyle() { - Month.JANUARY.getText(null, Locale.US); + Month.JANUARY.getDisplayName(null, Locale.US); } @Test(expectedExceptions = NullPointerException.class, groups={"tck"}) public void test_getText_nullLocale() { - Month.JANUARY.getText(TextStyle.FULL, null); + Month.JANUARY.getDisplayName(TextStyle.FULL, null); } //----------------------------------------------------------------------- diff --git a/jdk/test/java/time/tck/java/time/temporal/TCKMonthDay.java b/jdk/test/java/time/tck/java/time/TCKMonthDay.java similarity index 93% rename from jdk/test/java/time/tck/java/time/temporal/TCKMonthDay.java rename to jdk/test/java/time/tck/java/time/TCKMonthDay.java index 774777cab03..1a80e8ce303 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TCKMonthDay.java +++ b/jdk/test/java/time/tck/java/time/TCKMonthDay.java @@ -57,7 +57,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.temporal; +package tck.java.time; import static java.time.temporal.ChronoField.DAY_OF_MONTH; import static java.time.temporal.ChronoField.MONTH_OF_YEAR; @@ -68,12 +68,6 @@ import static org.testng.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - import java.time.Clock; import java.time.DateTimeException; import java.time.Instant; @@ -81,22 +75,28 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; +import java.time.MonthDay; +import java.time.YearMonth; import java.time.ZoneId; import java.time.ZoneOffset; +import java.time.chrono.IsoChronology; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatters; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoField; import java.time.temporal.JulianFields; -import java.time.temporal.MonthDay; +import java.time.temporal.Queries; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; -import java.time.temporal.YearMonth; +import java.time.temporal.TemporalQuery; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import tck.java.time.AbstractDateTimeTest; /** * Test MonthDay. @@ -147,7 +147,7 @@ public class TCKMonthDay extends AbstractDateTimeTest { public void test_serialization_format() throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (DataOutputStream dos = new DataOutputStream(baos) ) { - dos.writeByte(6); + dos.writeByte(13); // java.time.temporal.Ser.MONTH_DAY_TYPE dos.writeByte(9); dos.writeByte(16); } @@ -372,14 +372,14 @@ public class TCKMonthDay extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void factory_parse_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("M d"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("M d"); MonthDay test = MonthDay.parse("12 3", f); assertEquals(test, MonthDay.of(12, 3)); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void factory_parse_formatter_nullText() { - DateTimeFormatter f = DateTimeFormatters.pattern("M d"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("M d"); MonthDay.parse((String) null, f); } @@ -403,6 +403,37 @@ public class TCKMonthDay extends AbstractDateTimeTest { assertEquals(TEST_07_15.getLong(ChronoField.MONTH_OF_YEAR), 7); } + //----------------------------------------------------------------------- + // query(TemporalQuery) + //----------------------------------------------------------------------- + @DataProvider(name="query") + Object[][] data_query() { + return new Object[][] { + {TEST_07_15, Queries.chronology(), IsoChronology.INSTANCE}, + {TEST_07_15, Queries.zoneId(), null}, + {TEST_07_15, Queries.precision(), null}, + {TEST_07_15, Queries.zone(), null}, + {TEST_07_15, Queries.offset(), null}, + {TEST_07_15, Queries.localDate(), null}, + {TEST_07_15, Queries.localTime(), null}, + }; + } + + @Test(dataProvider="query") + public void test_query(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(temporal.query(query), expected); + } + + @Test(dataProvider="query") + public void test_queryFrom(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(query.queryFrom(temporal), expected); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_query_null() { + TEST_07_15.query(null); + } + //----------------------------------------------------------------------- // get*() //----------------------------------------------------------------------- @@ -419,10 +450,11 @@ public class TCKMonthDay extends AbstractDateTimeTest { }; } - @Test(dataProvider="sampleDates", groups={"tck"}) + @Test(dataProvider="sampleDates") public void test_get(int m, int d) { MonthDay a = MonthDay.of(m, d); assertEquals(a.getMonth(), Month.of(m)); + assertEquals(a.getMonthValue(), m); assertEquals(a.getDayOfMonth(), d); } @@ -743,7 +775,7 @@ public class TCKMonthDay extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_toString_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("M d"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("M d"); String t = MonthDay.of(12, 3).toString(f); assertEquals(t, "12 3"); } diff --git a/jdk/test/java/time/tck/java/time/temporal/TCKOffsetDateTime.java b/jdk/test/java/time/tck/java/time/TCKOffsetDateTime.java similarity index 77% rename from jdk/test/java/time/tck/java/time/temporal/TCKOffsetDateTime.java rename to jdk/test/java/time/tck/java/time/TCKOffsetDateTime.java index 01d72a4a661..ee0832e7ff0 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TCKOffsetDateTime.java +++ b/jdk/test/java/time/tck/java/time/TCKOffsetDateTime.java @@ -57,7 +57,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.temporal; +package tck.java.time; import static java.time.Month.DECEMBER; import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH; @@ -98,13 +98,8 @@ import static org.testng.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; -import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import java.time.Clock; import java.time.DateTimeException; import java.time.Duration; @@ -113,31 +108,31 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; +import java.time.OffsetDateTime; +import java.time.OffsetTime; +import java.time.Year; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; +import java.time.chrono.IsoChronology; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatters; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; -import java.time.temporal.ISOChrono; import java.time.temporal.JulianFields; -import java.time.temporal.OffsetDate; -import java.time.temporal.OffsetDateTime; -import java.time.temporal.OffsetTime; import java.time.temporal.Queries; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalAdjuster; import java.time.temporal.TemporalField; import java.time.temporal.TemporalQuery; -import java.time.temporal.Year; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import tck.java.time.AbstractDateTimeTest; import test.java.time.MockSimplePeriod; /** @@ -225,7 +220,7 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { public void test_serialization_format() throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (DataOutputStream dos = new DataOutputStream(baos) ) { - dos.writeByte(3); + dos.writeByte(10); // java.time.Ser.OFFSET_DATE_TIME_TYPE } byte[] bytes = baos.toByteArray(); ByteArrayOutputStream baosDateTime = new ByteArrayOutputStream(); @@ -270,12 +265,12 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { public void now() { OffsetDateTime expected = OffsetDateTime.now(Clock.systemDefaultZone()); OffsetDateTime test = OffsetDateTime.now(); - long diff = Math.abs(test.getTime().toNanoOfDay() - expected.getTime().toNanoOfDay()); + long diff = Math.abs(test.toLocalTime().toNanoOfDay() - expected.toLocalTime().toNanoOfDay()); if (diff >= 100000000) { // may be date change expected = OffsetDateTime.now(Clock.systemDefaultZone()); test = OffsetDateTime.now(); - diff = Math.abs(test.getTime().toNanoOfDay() - expected.getTime().toNanoOfDay()); + diff = Math.abs(test.toLocalTime().toNanoOfDay() - expected.toLocalTime().toNanoOfDay()); } assertTrue(diff < 100000000); // less than 0.1 secs } @@ -328,14 +323,14 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { assertEquals(test.getMonth(), Month.DECEMBER); assertEquals(test.getDayOfMonth(), 31); expected = expected.minusSeconds(1); - assertEquals(test.getTime(), expected); + assertEquals(test.toLocalTime(), expected); assertEquals(test.getOffset(), ZoneOffset.UTC); } } @Test(groups={"tck"}) public void now_Clock_offsets() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(1970, 1, 1), LocalTime.of(12, 0), ZoneOffset.UTC); + OffsetDateTime base = OffsetDateTime.of(1970, 1, 1, 12, 0, 0, 0, ZoneOffset.UTC); for (int i = -9; i < 15; i++) { ZoneOffset offset = ZoneOffset.ofHours(i); Clock clock = Clock.fixed(base.toInstant(), offset); @@ -374,49 +369,11 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { } //----------------------------------------------------------------------- - // dateTime factories - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void factory_of_intMonthIntHM() { - OffsetDateTime test = OffsetDateTime.of(LocalDate.of(2008, Month.JUNE, 30), - LocalTime.of(11, 30), OFFSET_PONE); - check(test, 2008, 6, 30, 11, 30, 0, 0, OFFSET_PONE); - } - - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void factory_of_intMonthIntHMS() { - OffsetDateTime test = OffsetDateTime.of(LocalDate.of(2008, Month.JUNE, 30), - LocalTime.of(11, 30, 10), OFFSET_PONE); - check(test, 2008, 6, 30, 11, 30, 10, 0, OFFSET_PONE); - } - - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void factory_of_intMonthIntHMSN() { - OffsetDateTime test = OffsetDateTime.of(LocalDate.of(2008, Month.JUNE, 30), - LocalTime.of(11, 30, 10, 500), OFFSET_PONE); - check(test, 2008, 6, 30, 11, 30, 10, 500, OFFSET_PONE); - } - - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void factory_of_intsHM() { - OffsetDateTime test = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30), OFFSET_PONE); - check(test, 2008, 6, 30, 11, 30, 0, 0, OFFSET_PONE); - } - - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void factory_of_intsHMS() { - OffsetDateTime test = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 10), OFFSET_PONE); - check(test, 2008, 6, 30, 11, 30, 10, 0, OFFSET_PONE); - } - + // factories //----------------------------------------------------------------------- @Test(groups={"tck"}) public void factory_of_intsHMSN() { - OffsetDateTime test = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 10, 500), OFFSET_PONE); + OffsetDateTime test = OffsetDateTime.of(2008, 6, 30, 11, 30, 10, 500, OFFSET_PONE); check(test, 2008, 6, 30, 11, 30, 10, 500, OFFSET_PONE); } @@ -523,14 +480,14 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void factory_parse_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d H m s XXX"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M d H m s XXX"); OffsetDateTime test = OffsetDateTime.parse("2010 12 3 11 30 0 +01:00", f); assertEquals(test, OffsetDateTime.of(LocalDate.of(2010, 12, 3), LocalTime.of(11, 30), ZoneOffset.ofHours(1))); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void factory_parse_formatter_nullText() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d H m s"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M d H m s"); OffsetDateTime.parse((String) null, f); } @@ -593,7 +550,6 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { assertEquals(a.getSecond(), localDateTime.getSecond()); assertEquals(a.getNano(), localDateTime.getNano()); - assertEquals(a.toOffsetDate(), OffsetDate.of(localDate, offset)); assertEquals(a.toOffsetTime(), OffsetTime.of(localTime, offset)); assertEquals(a.toString(), localDateTime.toString() + offset.toString()); } @@ -643,34 +599,27 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- // query(TemporalQuery) //----------------------------------------------------------------------- - @Test - public void test_query_chrono() { - assertEquals(TEST_2008_6_30_11_30_59_000000500.query(Queries.chrono()), ISOChrono.INSTANCE); - assertEquals(Queries.chrono().queryFrom(TEST_2008_6_30_11_30_59_000000500), ISOChrono.INSTANCE); + @DataProvider(name="query") + Object[][] data_query() { + return new Object[][] { + {TEST_2008_6_30_11_30_59_000000500, Queries.chronology(), IsoChronology.INSTANCE}, + {TEST_2008_6_30_11_30_59_000000500, Queries.zoneId(), null}, + {TEST_2008_6_30_11_30_59_000000500, Queries.precision(), ChronoUnit.NANOS}, + {TEST_2008_6_30_11_30_59_000000500, Queries.zone(), OFFSET_PONE}, + {TEST_2008_6_30_11_30_59_000000500, Queries.offset(), OFFSET_PONE}, + {TEST_2008_6_30_11_30_59_000000500, Queries.localDate(), LocalDate.of(2008, 6, 30)}, + {TEST_2008_6_30_11_30_59_000000500, Queries.localTime(), LocalTime.of(11, 30, 59, 500)}, + }; } - @Test - public void test_query_zoneId() { - assertEquals(TEST_2008_6_30_11_30_59_000000500.query(Queries.zoneId()), null); - assertEquals(Queries.zoneId().queryFrom(TEST_2008_6_30_11_30_59_000000500), null); + @Test(dataProvider="query") + public void test_query(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(temporal.query(query), expected); } - @Test - public void test_query_precision() { - assertEquals(TEST_2008_6_30_11_30_59_000000500.query(Queries.precision()), NANOS); - assertEquals(Queries.precision().queryFrom(TEST_2008_6_30_11_30_59_000000500), NANOS); - } - - @Test - public void test_query_offset() { - assertEquals(TEST_2008_6_30_11_30_59_000000500.query(Queries.offset()), OFFSET_PONE); - assertEquals(Queries.offset().queryFrom(TEST_2008_6_30_11_30_59_000000500), OFFSET_PONE); - } - - @Test - public void test_query_zone() { - assertEquals(TEST_2008_6_30_11_30_59_000000500.query(Queries.zone()), OFFSET_PONE); - assertEquals(Queries.zone().queryFrom(TEST_2008_6_30_11_30_59_000000500), OFFSET_PONE); + @Test(dataProvider="query") + public void test_queryFrom(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(query.queryFrom(temporal), expected); } @Test(expectedExceptions=NullPointerException.class) @@ -711,12 +660,6 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { assertEquals(test, OffsetDateTime.of(LocalDate.of(2012, 9, 3), LocalTime.of(19, 15), OFFSET_PONE)); } - @Test(groups={"tck"}) - public void test_with_adjustment_OffsetDate() { - OffsetDateTime test = TEST_2008_6_30_11_30_59_000000500.with(OffsetDate.of(LocalDate.of(2012, 9, 3), OFFSET_PTWO)); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2012, 9, 3), LocalTime.of(11, 30, 59, 500), OFFSET_PTWO)); - } - @Test(groups={"tck"}) public void test_with_adjustment_OffsetTime() { OffsetDateTime test = TEST_2008_6_30_11_30_59_000000500.with(OffsetTime.of(LocalTime.of(19, 15), OFFSET_PTWO)); @@ -880,7 +823,7 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { public void test_plus_Period() { MockSimplePeriod period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); OffsetDateTime t = TEST_2008_6_30_11_30_59_000000500.plus(period); - assertEquals(t, OffsetDateTime.of(LocalDate.of(2009, 1, 30), LocalTime.of(11, 30, 59, 500), OFFSET_PONE)); + assertEquals(t, OffsetDateTime.of(2009, 1, 30, 11, 30, 59, 500, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -890,7 +833,7 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { public void test_plus_Duration() { Duration dur = Duration.ofSeconds(62, 3); OffsetDateTime t = TEST_2008_6_30_11_30_59_000000500.plus(dur); - assertEquals(t, OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 32, 1, 503), OFFSET_PONE)); + assertEquals(t, OffsetDateTime.of(2008, 6, 30, 11, 32, 1, 503, OFFSET_PONE)); } @Test(groups={"tck"}) @@ -909,9 +852,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_plusYears() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.plusYears(1); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2009, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2009, 6, 30, 11, 30, 59, 0, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -919,9 +862,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_plusMonths() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.plusMonths(1); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2008, 7, 30), LocalTime.of(11, 30, 59), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2008, 7, 30, 11, 30, 59, 0, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -929,9 +872,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_plusWeeks() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.plusWeeks(1); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2008, 7, 7), LocalTime.of(11, 30, 59), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2008, 7, 7, 11, 30, 59, 0, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -939,9 +882,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_plusDays() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.plusDays(1); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2008, 7, 1), LocalTime.of(11, 30, 59), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2008, 7, 1, 11, 30, 59, 0, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -949,9 +892,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_plusHours() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.plusHours(13); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2008, 7, 1), LocalTime.of(0, 30, 59), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2008, 7, 1, 0, 30, 59, 0, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -959,9 +902,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_plusMinutes() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.plusMinutes(30); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(12, 0, 59), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2008, 6, 30, 12, 0, 59, 0, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -969,9 +912,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_plusSeconds() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.plusSeconds(1); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 31, 0), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2008, 6, 30, 11, 31, 0, 0, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -979,9 +922,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_plusNanos() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59, 0), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.plusNanos(1); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59, 1), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 1, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -991,7 +934,7 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { public void test_minus_Period() { MockSimplePeriod period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); OffsetDateTime t = TEST_2008_6_30_11_30_59_000000500.minus(period); - assertEquals(t, OffsetDateTime.of(LocalDate.of(2007, 11, 30), LocalTime.of(11, 30, 59, 500), OFFSET_PONE)); + assertEquals(t, OffsetDateTime.of(2007, 11, 30, 11, 30, 59, 500, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -1001,7 +944,7 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { public void test_minus_Duration() { Duration dur = Duration.ofSeconds(62, 3); OffsetDateTime t = TEST_2008_6_30_11_30_59_000000500.minus(dur); - assertEquals(t, OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 29, 57, 497), OFFSET_PONE)); + assertEquals(t, OffsetDateTime.of(2008, 6, 30, 11, 29, 57, 497, OFFSET_PONE)); } @Test(groups={"tck"}) @@ -1020,9 +963,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_minusYears() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.minusYears(1); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2007, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2007, 6, 30, 11, 30, 59, 0, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -1030,9 +973,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_minusMonths() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.minusMonths(1); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2008, 5, 30), LocalTime.of(11, 30, 59), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2008, 5, 30, 11, 30, 59, 0, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -1040,9 +983,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_minusWeeks() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.minusWeeks(1); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2008, 6, 23), LocalTime.of(11, 30, 59), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2008, 6, 23, 11, 30, 59, 0, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -1050,9 +993,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_minusDays() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.minusDays(1); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2008, 6, 29), LocalTime.of(11, 30, 59), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2008, 6, 29, 11, 30, 59, 0, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -1060,9 +1003,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_minusHours() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.minusHours(13); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2008, 6, 29), LocalTime.of(22, 30, 59), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2008, 6, 29, 22, 30, 59, 0, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -1070,9 +1013,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_minusMinutes() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.minusMinutes(30); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 0, 59), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2008, 6, 30, 11, 0, 59, 0, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -1080,9 +1023,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_minusSeconds() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.minusSeconds(1); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 58), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2008, 6, 30, 11, 30, 58, 0, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -1090,9 +1033,9 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_minusNanos() { - OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59, 0), OFFSET_PONE); + OffsetDateTime base = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); OffsetDateTime test = base.minusNanos(1); - assertEquals(test, OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 58, 999999999), OFFSET_PONE)); + assertEquals(test, OffsetDateTime.of(2008, 6, 30, 11, 30, 58, 999999999, OFFSET_PONE)); } //----------------------------------------------------------------------- @@ -1100,14 +1043,14 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_atZone() { - OffsetDateTime t = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30), OFFSET_MTWO); + OffsetDateTime t = OffsetDateTime.of(2008, 6, 30, 11, 30, 0, 0, OFFSET_MTWO); assertEquals(t.atZoneSameInstant(ZONE_PARIS), - ZonedDateTime.of(LocalDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(15, 30)), ZONE_PARIS)); + ZonedDateTime.of(2008, 6, 30, 15, 30, 0, 0, ZONE_PARIS)); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_atZone_nullTimeZone() { - OffsetDateTime t = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30), OFFSET_PTWO); + OffsetDateTime t = OffsetDateTime.of(2008, 6, 30, 11, 30, 0, 0, OFFSET_PTWO); t.atZoneSameInstant((ZoneId) null); } @@ -1116,37 +1059,37 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_atZoneSimilarLocal() { - OffsetDateTime t = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30), OFFSET_MTWO); + OffsetDateTime t = OffsetDateTime.of(2008, 6, 30, 11, 30, 0, 0, OFFSET_MTWO); assertEquals(t.atZoneSimilarLocal(ZONE_PARIS), - ZonedDateTime.of(LocalDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30)), ZONE_PARIS)); + ZonedDateTime.of(2008, 6, 30, 11, 30, 0, 0, ZONE_PARIS)); } @Test(groups={"tck"}) public void test_atZoneSimilarLocal_dstGap() { - OffsetDateTime t = OffsetDateTime.of(LocalDate.of(2007, 4, 1), LocalTime.of(0, 0), OFFSET_MTWO); + OffsetDateTime t = OffsetDateTime.of(2007, 4, 1, 0, 0, 0, 0, OFFSET_MTWO); assertEquals(t.atZoneSimilarLocal(ZONE_GAZA), - ZonedDateTime.of(LocalDateTime.of(LocalDate.of(2007, 4, 1), LocalTime.of(1, 0)), ZONE_GAZA)); + ZonedDateTime.of(2007, 4, 1, 1, 0, 0, 0, ZONE_GAZA)); } @Test(groups={"tck"}) public void test_atZone_dstOverlapSummer() { - OffsetDateTime t = OffsetDateTime.of(LocalDate.of(2007, 10, 28), LocalTime.of(2, 30), OFFSET_PTWO); - assertEquals(t.atZoneSimilarLocal(ZONE_PARIS).getDateTime(), t.getDateTime()); + OffsetDateTime t = OffsetDateTime.of(2007, 10, 28, 2, 30, 0, 0, OFFSET_PTWO); + assertEquals(t.atZoneSimilarLocal(ZONE_PARIS).toLocalDateTime(), t.toLocalDateTime()); assertEquals(t.atZoneSimilarLocal(ZONE_PARIS).getOffset(), OFFSET_PTWO); assertEquals(t.atZoneSimilarLocal(ZONE_PARIS).getZone(), ZONE_PARIS); } @Test(groups={"tck"}) public void test_atZone_dstOverlapWinter() { - OffsetDateTime t = OffsetDateTime.of(LocalDate.of(2007, 10, 28), LocalTime.of(2, 30), OFFSET_PONE); - assertEquals(t.atZoneSimilarLocal(ZONE_PARIS).getDateTime(), t.getDateTime()); + OffsetDateTime t = OffsetDateTime.of(2007, 10, 28, 2, 30, 0, 0, OFFSET_PONE); + assertEquals(t.atZoneSimilarLocal(ZONE_PARIS).toLocalDateTime(), t.toLocalDateTime()); assertEquals(t.atZoneSimilarLocal(ZONE_PARIS).getOffset(), OFFSET_PONE); assertEquals(t.atZoneSimilarLocal(ZONE_PARIS).getZone(), ZONE_PARIS); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_atZoneSimilarLocal_nullTimeZone() { - OffsetDateTime t = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30), OFFSET_PTWO); + OffsetDateTime t = OffsetDateTime.of(2008, 6, 30, 11, 30, 0, 0, OFFSET_PTWO); t.atZoneSimilarLocal((ZoneId) null); } @@ -1156,7 +1099,7 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_toEpochSecond_afterEpoch() { for (int i = 0; i < 100000; i++) { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(1970, 1, 1), LocalTime.of(0, 0), ZoneOffset.UTC).plusSeconds(i); + OffsetDateTime a = OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC).plusSeconds(i); assertEquals(a.toEpochSecond(), i); } } @@ -1164,7 +1107,7 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_toEpochSecond_beforeEpoch() { for (int i = 0; i < 100000; i++) { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(1970, 1, 1), LocalTime.of(0, 0), ZoneOffset.UTC).minusSeconds(i); + OffsetDateTime a = OffsetDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC).minusSeconds(i); assertEquals(a.toEpochSecond(), -i); } } @@ -1174,8 +1117,8 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_compareTo_timeMins() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 29, 3), OFFSET_PONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 2), OFFSET_PONE); // a is before b due to time + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 11, 29, 3, 0, OFFSET_PONE); + OffsetDateTime b = OffsetDateTime.of(2008, 6, 30, 11, 30, 2, 0, OFFSET_PONE); // a is before b due to time assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1185,8 +1128,8 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_timeSecs() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 29, 2), OFFSET_PONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 29, 3), OFFSET_PONE); // a is before b due to time + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 11, 29, 2, 0, OFFSET_PONE); + OffsetDateTime b = OffsetDateTime.of(2008, 6, 30, 11, 29, 3, 0, OFFSET_PONE); // a is before b due to time assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1196,8 +1139,8 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_timeNanos() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 29, 40, 4), OFFSET_PONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 29, 40, 5), OFFSET_PONE); // a is before b due to time + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 11, 29, 40, 4, OFFSET_PONE); + OffsetDateTime b = OffsetDateTime.of(2008, 6, 30, 11, 29, 40, 5, OFFSET_PONE); // a is before b due to time assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1207,8 +1150,8 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_offset() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30), OFFSET_PTWO); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30), OFFSET_PONE); // a is before b due to offset + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 11, 30, 0, 0, OFFSET_PTWO); + OffsetDateTime b = OffsetDateTime.of(2008, 6, 30, 11, 30, 0, 0, OFFSET_PONE); // a is before b due to offset assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1218,8 +1161,8 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_offsetNanos() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 40, 6), OFFSET_PTWO); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 40, 5), OFFSET_PONE); // a is before b due to offset + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 11, 30, 40, 6, OFFSET_PTWO); + OffsetDateTime b = OffsetDateTime.of(2008, 6, 30, 11, 30, 40, 5, OFFSET_PONE); // a is before b due to offset assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1229,8 +1172,8 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_both() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 50), OFFSET_PTWO); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 20), OFFSET_PONE); // a is before b on instant scale + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 11, 50, 0, 0, OFFSET_PTWO); + OffsetDateTime b = OffsetDateTime.of(2008, 6, 30, 11, 20, 0, 0, OFFSET_PONE); // a is before b on instant scale assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1240,8 +1183,8 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_bothNanos() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 20, 40, 4), OFFSET_PTWO); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(10, 20, 40, 5), OFFSET_PONE); // a is before b on instant scale + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 11, 20, 40, 4, OFFSET_PTWO); + OffsetDateTime b = OffsetDateTime.of(2008, 6, 30, 10, 20, 40, 5, OFFSET_PONE); // a is before b on instant scale assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1251,8 +1194,8 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_hourDifference() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(10, 0), OFFSET_PONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 0), OFFSET_PTWO); // a is before b despite being same time-line time + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 10, 0, 0, 0, OFFSET_PONE); + OffsetDateTime b = OffsetDateTime.of(2008, 6, 30, 11, 0, 0, 0, OFFSET_PTWO); // a is before b despite being same time-line time assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1262,8 +1205,8 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_max() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(Year.MAX_VALUE, 12, 31), LocalTime.of(23, 59), OFFSET_MONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(Year.MAX_VALUE, 12, 31), LocalTime.of(23, 59), OFFSET_MTWO); // a is before b due to offset + OffsetDateTime a = OffsetDateTime.of(Year.MAX_VALUE, 12, 31, 23, 59, 0, 0, OFFSET_MONE); + OffsetDateTime b = OffsetDateTime.of(Year.MAX_VALUE, 12, 31, 23, 59, 0, 0, OFFSET_MTWO); // a is before b due to offset assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1272,8 +1215,8 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_min() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(Year.MIN_VALUE, 1, 1), LocalTime.of(0, 0), OFFSET_PTWO); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(Year.MIN_VALUE, 1, 1), LocalTime.of(0, 0), OFFSET_PONE); // a is before b due to offset + OffsetDateTime a = OffsetDateTime.of(Year.MIN_VALUE, 1, 1, 0, 0, 0, 0, OFFSET_PTWO); + OffsetDateTime b = OffsetDateTime.of(Year.MIN_VALUE, 1, 1, 0, 0, 0, 0, OFFSET_PONE); // a is before b due to offset assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1282,7 +1225,7 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_compareTo_null() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); a.compareTo(null); } @@ -1298,8 +1241,8 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_isBeforeIsAfterIsEqual1() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 58, 3), OFFSET_PONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59, 2), OFFSET_PONE); // a is before b due to time + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 11, 30, 58, 3, OFFSET_PONE); + OffsetDateTime b = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 2, OFFSET_PONE); // a is before b due to time assertEquals(a.isBefore(b), true); assertEquals(a.isEqual(b), false); assertEquals(a.isAfter(b), false); @@ -1320,8 +1263,8 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_isBeforeIsAfterIsEqual2() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59, 2), OFFSET_PONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59, 3), OFFSET_PONE); // a is before b due to time + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 2, OFFSET_PONE); + OffsetDateTime b = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 3, OFFSET_PONE); // a is before b due to time assertEquals(a.isBefore(b), true); assertEquals(a.isEqual(b), false); assertEquals(a.isAfter(b), false); @@ -1342,8 +1285,8 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_isBeforeIsAfterIsEqual_instantComparison() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(10, 0), OFFSET_PONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 0), OFFSET_PTWO); // a is same instant as b + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 10, 0, 0, 0, OFFSET_PONE); + OffsetDateTime b = OffsetDateTime.of(2008, 6, 30, 11, 0, 0, 0, OFFSET_PTWO); // a is same instant as b assertEquals(a.isBefore(b), false); assertEquals(a.isEqual(b), true); assertEquals(a.isAfter(b), false); @@ -1364,19 +1307,19 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_isBefore_null() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); a.isBefore(null); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_isEqual_null() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); a.isEqual(null); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_isAfter_null() { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetDateTime a = OffsetDateTime.of(2008, 6, 30, 11, 30, 59, 0, OFFSET_PONE); a.isAfter(null); } @@ -1385,49 +1328,49 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(dataProvider="sampleTimes", groups={"tck"}) public void test_equals_true(int y, int o, int d, int h, int m, int s, int n, ZoneOffset ignored) { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(y, o, d), LocalTime.of(h, m, s, n), OFFSET_PONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(y, o, d), LocalTime.of(h, m, s, n), OFFSET_PONE); + OffsetDateTime a = OffsetDateTime.of(y, o, d, h, m, s, n, OFFSET_PONE); + OffsetDateTime b = OffsetDateTime.of(y, o, d, h, m, s, n, OFFSET_PONE); assertEquals(a.equals(b), true); assertEquals(a.hashCode() == b.hashCode(), true); } @Test(dataProvider="sampleTimes", groups={"tck"}) public void test_equals_false_year_differs(int y, int o, int d, int h, int m, int s, int n, ZoneOffset ignored) { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(y, o, d), LocalTime.of(h, m, s, n), OFFSET_PONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(y + 1, o, d), LocalTime.of(h, m, s, n), OFFSET_PONE); + OffsetDateTime a = OffsetDateTime.of(y, o, d, h, m, s, n, OFFSET_PONE); + OffsetDateTime b = OffsetDateTime.of(y + 1, o, d, h, m, s, n, OFFSET_PONE); assertEquals(a.equals(b), false); } @Test(dataProvider="sampleTimes", groups={"tck"}) public void test_equals_false_hour_differs(int y, int o, int d, int h, int m, int s, int n, ZoneOffset ignored) { h = (h == 23 ? 22 : h); - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(y, o, d), LocalTime.of(h, m, s, n), OFFSET_PONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(y, o, d), LocalTime.of(h + 1, m, s, n), OFFSET_PONE); + OffsetDateTime a = OffsetDateTime.of(y, o, d, h, m, s, n, OFFSET_PONE); + OffsetDateTime b = OffsetDateTime.of(y, o, d, h + 1, m, s, n, OFFSET_PONE); assertEquals(a.equals(b), false); } @Test(dataProvider="sampleTimes", groups={"tck"}) public void test_equals_false_minute_differs(int y, int o, int d, int h, int m, int s, int n, ZoneOffset ignored) { m = (m == 59 ? 58 : m); - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(y, o, d), LocalTime.of(h, m, s, n), OFFSET_PONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(y, o, d), LocalTime.of(h, m + 1, s, n), OFFSET_PONE); + OffsetDateTime a = OffsetDateTime.of(y, o, d, h, m, s, n, OFFSET_PONE); + OffsetDateTime b = OffsetDateTime.of(y, o, d, h, m + 1, s, n, OFFSET_PONE); assertEquals(a.equals(b), false); } @Test(dataProvider="sampleTimes", groups={"tck"}) public void test_equals_false_second_differs(int y, int o, int d, int h, int m, int s, int n, ZoneOffset ignored) { s = (s == 59 ? 58 : s); - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(y, o, d), LocalTime.of(h, m, s, n), OFFSET_PONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(y, o, d), LocalTime.of(h, m, s + 1, n), OFFSET_PONE); + OffsetDateTime a = OffsetDateTime.of(y, o, d, h, m, s, n, OFFSET_PONE); + OffsetDateTime b = OffsetDateTime.of(y, o, d, h, m, s + 1, n, OFFSET_PONE); assertEquals(a.equals(b), false); } @Test(dataProvider="sampleTimes", groups={"tck"}) public void test_equals_false_nano_differs(int y, int o, int d, int h, int m, int s, int n, ZoneOffset ignored) { n = (n == 999999999 ? 999999998 : n); - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(y, o, d), LocalTime.of(h, m, s, n), OFFSET_PONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(y, o, d), LocalTime.of(h, m, s, n + 1), OFFSET_PONE); + OffsetDateTime a = OffsetDateTime.of(y, o, d, h, m, s, n, OFFSET_PONE); + OffsetDateTime b = OffsetDateTime.of(y, o, d, h, m, s, n + 1, OFFSET_PONE); assertEquals(a.equals(b), false); } @Test(dataProvider="sampleTimes", groups={"tck"}) public void test_equals_false_offset_differs(int y, int o, int d, int h, int m, int s, int n, ZoneOffset ignored) { - OffsetDateTime a = OffsetDateTime.of(LocalDate.of(y, o, d), LocalTime.of(h, m, s, n), OFFSET_PONE); - OffsetDateTime b = OffsetDateTime.of(LocalDate.of(y, o, d), LocalTime.of(h, m, s, n), OFFSET_PTWO); + OffsetDateTime a = OffsetDateTime.of(y, o, d, h, m, s, n, OFFSET_PONE); + OffsetDateTime b = OffsetDateTime.of(y, o, d, h, m, s, n, OFFSET_PTWO); assertEquals(a.equals(b), false); } @@ -1465,7 +1408,7 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { @Test(dataProvider="sampleToString", groups={"tck"}) public void test_toString(int y, int o, int d, int h, int m, int s, int n, String offsetId, String expected) { - OffsetDateTime t = OffsetDateTime.of(LocalDate.of(y, o, d), LocalTime.of(h, m, s, n), ZoneOffset.of(offsetId)); + OffsetDateTime t = OffsetDateTime.of(y, o, d, h, m, s, n, ZoneOffset.of(offsetId)); String str = t.toString(); assertEquals(str, expected); } @@ -1475,14 +1418,14 @@ public class TCKOffsetDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_toString_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d H m s"); - String t = OffsetDateTime.of(LocalDate.of(2010, 12, 3), LocalTime.of(11, 30), OFFSET_PONE).toString(f); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M d H m s"); + String t = OffsetDateTime.of(2010, 12, 3, 11, 30, 0, 0, OFFSET_PONE).toString(f); assertEquals(t, "2010 12 3 11 30 0"); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_toString_formatter_null() { - OffsetDateTime.of(LocalDate.of(2010, 12, 3), LocalTime.of(11, 30), OFFSET_PONE).toString(null); + OffsetDateTime.of(2010, 12, 3, 11, 30, 0, 0, OFFSET_PONE).toString(null); } } diff --git a/jdk/test/java/time/tck/java/time/temporal/TCKOffsetTime.java b/jdk/test/java/time/tck/java/time/TCKOffsetTime.java similarity index 79% rename from jdk/test/java/time/tck/java/time/temporal/TCKOffsetTime.java rename to jdk/test/java/time/tck/java/time/TCKOffsetTime.java index 374268589ad..83117099be2 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TCKOffsetTime.java +++ b/jdk/test/java/time/tck/java/time/TCKOffsetTime.java @@ -57,7 +57,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.temporal; +package tck.java.time; import static java.time.temporal.ChronoField.AMPM_OF_DAY; import static java.time.temporal.ChronoField.CLOCK_HOUR_OF_AMPM; @@ -84,45 +84,38 @@ import static org.testng.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; -import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import java.time.Clock; import java.time.DateTimeException; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.time.OffsetTime; import java.time.Period; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatters; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; import java.time.temporal.JulianFields; -import java.time.temporal.OffsetDate; -import java.time.temporal.OffsetDateTime; -import java.time.temporal.OffsetTime; import java.time.temporal.Queries; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; -import java.time.temporal.TemporalAdder; import java.time.temporal.TemporalAdjuster; +import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalField; import java.time.temporal.TemporalQuery; -import java.time.temporal.TemporalSubtractor; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import tck.java.time.AbstractDateTimeTest; import test.java.time.MockSimplePeriod; /** @@ -138,7 +131,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @BeforeMethod(groups={"tck","implementation"}) public void setUp() { - TEST_11_30_59_500_PONE = OffsetTime.of(LocalTime.of(11, 30, 59, 500), OFFSET_PONE); + TEST_11_30_59_500_PONE = OffsetTime.of(11, 30, 59, 500, OFFSET_PONE); } //----------------------------------------------------------------------- @@ -193,7 +186,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { public void test_serialization_format() throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (DataOutputStream dos = new DataOutputStream(baos) ) { - dos.writeByte(2); + dos.writeByte(9); // java.time.Ser.OFFSET_TIME_TYPE } byte[] bytes = baos.toByteArray(); ByteArrayOutputStream baosTime = new ByteArrayOutputStream(); @@ -211,7 +204,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { dos.writeByte(4); // quarter hours stored: 3600 / 900 } byte[] bytesOffset = baosOffset.toByteArray(); - assertSerializedBySer(OffsetTime.of(LocalTime.of(22, 17, 59, 464_000_000), ZoneOffset.ofHours(1)), bytes, + assertSerializedBySer(OffsetTime.of(22, 17, 59, 464_000_000, ZoneOffset.ofHours(1)), bytes, bytesTime, bytesOffset); } @@ -237,7 +230,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { OffsetTime expected = OffsetTime.now(Clock.systemDefaultZone()); OffsetTime test = OffsetTime.now(); - long diff = Math.abs(test.getTime().toNanoOfDay() - expected.getTime().toNanoOfDay()); + long diff = Math.abs(test.toLocalTime().toNanoOfDay() - expected.toLocalTime().toNanoOfDay()); assertTrue(diff < 100000000); // less than 0.1 secs assertEquals(test.getOffset(), nowDT.getOffset()); } @@ -302,7 +295,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { // factories //----------------------------------------------------------------------- private void check(OffsetTime test, int h, int m, int s, int n, ZoneOffset offset) { - assertEquals(test.getTime(), LocalTime.of(h, m, s, n)); + assertEquals(test.toLocalTime(), LocalTime.of(h, m, s, n)); assertEquals(test.getOffset(), offset); assertEquals(test.getHour(), h); @@ -315,24 +308,10 @@ public class TCKOffsetTime extends AbstractDateTimeTest { assertEquals(OffsetTime.of(LocalTime.of(h, m, s, n), offset), test); } - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void factory_intsHM() { - OffsetTime test = OffsetTime.of(LocalTime.of(11, 30), OFFSET_PONE); - check(test, 11, 30, 0, 0, OFFSET_PONE); - } - - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void factory_intsHMS() { - OffsetTime test = OffsetTime.of(LocalTime.of(11, 30, 10), OFFSET_PONE); - check(test, 11, 30, 10, 0, OFFSET_PONE); - } - //----------------------------------------------------------------------- @Test(groups={"tck"}) public void factory_intsHMSN() { - OffsetTime test = OffsetTime.of(LocalTime.of(11, 30, 10, 500), OFFSET_PONE); + OffsetTime test = OffsetTime.of(11, 30, 10, 500, OFFSET_PONE); check(test, 11, 30, 10, 500, OFFSET_PONE); } @@ -417,7 +396,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void factory_from_TemporalAccessor_OT() { - assertEquals(OffsetTime.from(OffsetTime.of(LocalTime.of(17, 30), OFFSET_PONE)), OffsetTime.of(LocalTime.of(17, 30), OFFSET_PONE)); + assertEquals(OffsetTime.from(OffsetTime.of(17, 30, 0, 0, OFFSET_PONE)), OffsetTime.of(17, 30, 0, 0, OFFSET_PONE)); } @Test(groups={"tck"}) @@ -487,14 +466,14 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void factory_parse_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("H m s XXX"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("H m s XXX"); OffsetTime test = OffsetTime.parse("11 30 0 +01:00", f); - assertEquals(test, OffsetTime.of(LocalTime.of(11, 30), ZoneOffset.ofHours(1))); + assertEquals(test, OffsetTime.of(11, 30, 0, 0, ZoneOffset.ofHours(1))); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void factory_parse_formatter_nullText() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d H m s"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M d H m s"); OffsetTime.parse((String) null, f); } @@ -522,7 +501,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { Constructor con = OffsetTime.class.getDeclaredConstructor(LocalTime.class, ZoneOffset.class); con.setAccessible(true); try { - con.newInstance(LocalTime.of(11, 30), null); + con.newInstance(LocalTime.of(11, 30, 0, 0), null); } catch (InvocationTargetException ex) { throw ex.getCause(); } @@ -545,7 +524,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { LocalTime localTime = LocalTime.of(h, m, s, n); OffsetTime a = OffsetTime.of(localTime, offset); - assertEquals(a.getTime(), localTime); + assertEquals(a.toLocalTime(), localTime); assertEquals(a.getOffset(), offset); assertEquals(a.toString(), localTime.toString() + offset.toString()); assertEquals(a.getHour(), localTime.getHour()); @@ -559,7 +538,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test public void test_get_TemporalField() { - OffsetTime test = OffsetTime.of(LocalTime.of(12, 30, 40, 987654321), OFFSET_PONE); + OffsetTime test = OffsetTime.of(12, 30, 40, 987654321, OFFSET_PONE); assertEquals(test.get(ChronoField.HOUR_OF_DAY), 12); assertEquals(test.get(ChronoField.MINUTE_OF_HOUR), 30); assertEquals(test.get(ChronoField.SECOND_OF_MINUTE), 40); @@ -572,7 +551,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test public void test_getLong_TemporalField() { - OffsetTime test = OffsetTime.of(LocalTime.of(12, 30, 40, 987654321), OFFSET_PONE); + OffsetTime test = OffsetTime.of(12, 30, 40, 987654321, OFFSET_PONE); assertEquals(test.getLong(ChronoField.HOUR_OF_DAY), 12); assertEquals(test.getLong(ChronoField.MINUTE_OF_HOUR), 30); assertEquals(test.getLong(ChronoField.SECOND_OF_MINUTE), 40); @@ -586,34 +565,27 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- // query(TemporalQuery) //----------------------------------------------------------------------- - @Test - public void test_query_chrono() { - assertEquals(TEST_11_30_59_500_PONE.query(Queries.chrono()), null); - assertEquals(Queries.chrono().queryFrom(TEST_11_30_59_500_PONE), null); + @DataProvider(name="query") + Object[][] data_query() { + return new Object[][] { + {TEST_11_30_59_500_PONE, Queries.chronology(), null}, + {TEST_11_30_59_500_PONE, Queries.zoneId(), null}, + {TEST_11_30_59_500_PONE, Queries.precision(), ChronoUnit.NANOS}, + {TEST_11_30_59_500_PONE, Queries.zone(), OFFSET_PONE}, + {TEST_11_30_59_500_PONE, Queries.offset(), OFFSET_PONE}, + {TEST_11_30_59_500_PONE, Queries.localDate(), null}, + {TEST_11_30_59_500_PONE, Queries.localTime(), LocalTime.of(11, 30, 59, 500)}, + }; } - @Test - public void test_query_zoneId() { - assertEquals(TEST_11_30_59_500_PONE.query(Queries.zoneId()), null); - assertEquals(Queries.zoneId().queryFrom(TEST_11_30_59_500_PONE), null); + @Test(dataProvider="query") + public void test_query(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(temporal.query(query), expected); } - @Test - public void test_query_precision() { - assertEquals(TEST_11_30_59_500_PONE.query(Queries.precision()), NANOS); - assertEquals(Queries.precision().queryFrom(TEST_11_30_59_500_PONE), NANOS); - } - - @Test - public void test_query_offset() { - assertEquals(TEST_11_30_59_500_PONE.query(Queries.offset()), OFFSET_PONE); - assertEquals(Queries.offset().queryFrom(TEST_11_30_59_500_PONE), OFFSET_PONE); - } - - @Test - public void test_query_zone() { - assertEquals(TEST_11_30_59_500_PONE.query(Queries.zone()), OFFSET_PONE); - assertEquals(Queries.zone().queryFrom(TEST_11_30_59_500_PONE), OFFSET_PONE); + @Test(dataProvider="query") + public void test_queryFrom(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(query.queryFrom(temporal), expected); } @Test(expectedExceptions=NullPointerException.class) @@ -626,22 +598,22 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_withOffsetSameLocal() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.withOffsetSameLocal(OFFSET_PTWO); - assertEquals(test.getTime(), base.getTime()); + assertEquals(test.toLocalTime(), base.toLocalTime()); assertEquals(test.getOffset(), OFFSET_PTWO); } @Test(groups={"tck"}) public void test_withOffsetSameLocal_noChange() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.withOffsetSameLocal(OFFSET_PONE); assertEquals(test, base); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_withOffsetSameLocal_null() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); base.withOffsetSameLocal(null); } @@ -650,22 +622,22 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_withOffsetSameInstant() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.withOffsetSameInstant(OFFSET_PTWO); - OffsetTime expected = OffsetTime.of(LocalTime.of(12, 30, 59), OFFSET_PTWO); + OffsetTime expected = OffsetTime.of(12, 30, 59, 0, OFFSET_PTWO); assertEquals(test, expected); } @Test(groups={"tck"}) public void test_withOffsetSameInstant_noChange() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.withOffsetSameInstant(OFFSET_PONE); assertEquals(test, base); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_withOffsetSameInstant_null() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); base.withOffsetSameInstant(null); } @@ -674,7 +646,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_with_adjustment() { - final OffsetTime sample = OffsetTime.of(LocalTime.of(23, 5), OFFSET_PONE); + final OffsetTime sample = OffsetTime.of(23, 5, 0, 0, OFFSET_PONE); TemporalAdjuster adjuster = new TemporalAdjuster() { @Override public Temporal adjustInto(Temporal dateTime) { @@ -687,19 +659,19 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_with_adjustment_LocalTime() { OffsetTime test = TEST_11_30_59_500_PONE.with(LocalTime.of(13, 30)); - assertEquals(test, OffsetTime.of(LocalTime.of(13, 30), OFFSET_PONE)); + assertEquals(test, OffsetTime.of(13, 30, 0, 0, OFFSET_PONE)); } @Test(groups={"tck"}) public void test_with_adjustment_OffsetTime() { - OffsetTime test = TEST_11_30_59_500_PONE.with(OffsetTime.of(LocalTime.of(13, 35), OFFSET_PTWO)); - assertEquals(test, OffsetTime.of(LocalTime.of(13, 35), OFFSET_PTWO)); + OffsetTime test = TEST_11_30_59_500_PONE.with(OffsetTime.of(13, 35, 0, 0, OFFSET_PTWO)); + assertEquals(test, OffsetTime.of(13, 35, 0, 0, OFFSET_PTWO)); } @Test(groups={"tck"}) public void test_with_adjustment_ZoneOffset() { OffsetTime test = TEST_11_30_59_500_PONE.with(OFFSET_PTWO); - assertEquals(test, OffsetTime.of(LocalTime.of(11, 30, 59, 500), OFFSET_PTWO)); + assertEquals(test, OffsetTime.of(11, 30, 59, 500, OFFSET_PTWO)); } @Test(groups={"tck"}) @@ -710,7 +682,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { return dateTime.with(HOUR_OF_DAY, 23); } }); - assertEquals(test, OffsetTime.of(LocalTime.of(23, 30, 59, 500), OFFSET_PONE)); + assertEquals(test, OffsetTime.of(23, 30, 59, 500, OFFSET_PONE)); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) @@ -723,15 +695,15 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_with_TemporalField() { - OffsetTime test = OffsetTime.of(LocalTime.of(12, 30, 40, 987654321), OFFSET_PONE); - assertEquals(test.with(ChronoField.HOUR_OF_DAY, 15), OffsetTime.of(LocalTime.of(15, 30, 40, 987654321), OFFSET_PONE)); - assertEquals(test.with(ChronoField.MINUTE_OF_HOUR, 50), OffsetTime.of(LocalTime.of(12, 50, 40, 987654321), OFFSET_PONE)); - assertEquals(test.with(ChronoField.SECOND_OF_MINUTE, 50), OffsetTime.of(LocalTime.of(12, 30, 50, 987654321), OFFSET_PONE)); - assertEquals(test.with(ChronoField.NANO_OF_SECOND, 12345), OffsetTime.of(LocalTime.of(12, 30, 40, 12345), OFFSET_PONE)); - assertEquals(test.with(ChronoField.HOUR_OF_AMPM, 6), OffsetTime.of(LocalTime.of(18, 30, 40, 987654321), OFFSET_PONE)); - assertEquals(test.with(ChronoField.AMPM_OF_DAY, 0), OffsetTime.of(LocalTime.of(0, 30, 40, 987654321), OFFSET_PONE)); + OffsetTime test = OffsetTime.of(12, 30, 40, 987654321, OFFSET_PONE); + assertEquals(test.with(ChronoField.HOUR_OF_DAY, 15), OffsetTime.of(15, 30, 40, 987654321, OFFSET_PONE)); + assertEquals(test.with(ChronoField.MINUTE_OF_HOUR, 50), OffsetTime.of(12, 50, 40, 987654321, OFFSET_PONE)); + assertEquals(test.with(ChronoField.SECOND_OF_MINUTE, 50), OffsetTime.of(12, 30, 50, 987654321, OFFSET_PONE)); + assertEquals(test.with(ChronoField.NANO_OF_SECOND, 12345), OffsetTime.of(12, 30, 40, 12345, OFFSET_PONE)); + assertEquals(test.with(ChronoField.HOUR_OF_AMPM, 6), OffsetTime.of(18, 30, 40, 987654321, OFFSET_PONE)); + assertEquals(test.with(ChronoField.AMPM_OF_DAY, 0), OffsetTime.of(0, 30, 40, 987654321, OFFSET_PONE)); - assertEquals(test.with(ChronoField.OFFSET_SECONDS, 7205), OffsetTime.of(LocalTime.of(12, 30, 40, 987654321), ZoneOffset.ofHoursMinutesSeconds(2, 0, 5))); + assertEquals(test.with(ChronoField.OFFSET_SECONDS, 7205), OffsetTime.of(12, 30, 40, 987654321, ZoneOffset.ofHoursMinutesSeconds(2, 0, 5))); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"} ) @@ -749,14 +721,14 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_withHour_normal() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.withHour(15); - assertEquals(test, OffsetTime.of(LocalTime.of(15, 30, 59), OFFSET_PONE)); + assertEquals(test, OffsetTime.of(15, 30, 59, 0, OFFSET_PONE)); } @Test(groups={"tck"}) public void test_withHour_noChange() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.withHour(11); assertEquals(test, base); } @@ -766,14 +738,14 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_withMinute_normal() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.withMinute(15); - assertEquals(test, OffsetTime.of(LocalTime.of(11, 15, 59), OFFSET_PONE)); + assertEquals(test, OffsetTime.of(11, 15, 59, 0, OFFSET_PONE)); } @Test(groups={"tck"}) public void test_withMinute_noChange() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.withMinute(30); assertEquals(test, base); } @@ -783,14 +755,14 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_withSecond_normal() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.withSecond(15); - assertEquals(test, OffsetTime.of(LocalTime.of(11, 30, 15), OFFSET_PONE)); + assertEquals(test, OffsetTime.of(11, 30, 15, 0, OFFSET_PONE)); } @Test(groups={"tck"}) public void test_withSecond_noChange() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.withSecond(59); assertEquals(test, base); } @@ -800,14 +772,14 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_withNanoOfSecond_normal() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59, 1), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 1, OFFSET_PONE); OffsetTime test = base.withNano(15); - assertEquals(test, OffsetTime.of(LocalTime.of(11, 30, 59, 15), OFFSET_PONE)); + assertEquals(test, OffsetTime.of(11, 30, 59, 15, OFFSET_PONE)); } @Test(groups={"tck"}) public void test_withNanoOfSecond_noChange() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59, 1), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 1, OFFSET_PONE); OffsetTime test = base.withNano(1); assertEquals(test, base); } @@ -834,7 +806,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { public void test_plus_PlusAdjuster() { MockSimplePeriod period = MockSimplePeriod.of(7, ChronoUnit.MINUTES); OffsetTime t = TEST_11_30_59_500_PONE.plus(period); - assertEquals(t, OffsetTime.of(LocalTime.of(11, 37, 59, 500), OFFSET_PONE)); + assertEquals(t, OffsetTime.of(11, 37, 59, 500, OFFSET_PONE)); } @Test(groups={"tck"}) @@ -851,7 +823,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_plus_PlusAdjuster_null() { - TEST_11_30_59_500_PONE.plus((TemporalAdder) null); + TEST_11_30_59_500_PONE.plus((TemporalAmount) null); } //----------------------------------------------------------------------- @@ -859,14 +831,14 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_plusHours() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.plusHours(13); - assertEquals(test, OffsetTime.of(LocalTime.of(0, 30, 59), OFFSET_PONE)); + assertEquals(test, OffsetTime.of(0, 30, 59, 0, OFFSET_PONE)); } @Test(groups={"tck"}) public void test_plusHours_zero() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.plusHours(0); assertEquals(test, base); } @@ -876,14 +848,14 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_plusMinutes() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.plusMinutes(30); - assertEquals(test, OffsetTime.of(LocalTime.of(12, 0, 59), OFFSET_PONE)); + assertEquals(test, OffsetTime.of(12, 0, 59, 0, OFFSET_PONE)); } @Test(groups={"tck"}) public void test_plusMinutes_zero() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.plusMinutes(0); assertEquals(test, base); } @@ -893,14 +865,14 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_plusSeconds() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.plusSeconds(1); - assertEquals(test, OffsetTime.of(LocalTime.of(11, 31, 0), OFFSET_PONE)); + assertEquals(test, OffsetTime.of(11, 31, 0, 0, OFFSET_PONE)); } @Test(groups={"tck"}) public void test_plusSeconds_zero() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.plusSeconds(0); assertEquals(test, base); } @@ -910,14 +882,14 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_plusNanos() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59, 0), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.plusNanos(1); - assertEquals(test, OffsetTime.of(LocalTime.of(11, 30, 59, 1), OFFSET_PONE)); + assertEquals(test, OffsetTime.of(11, 30, 59, 1, OFFSET_PONE)); } @Test(groups={"tck"}) public void test_plusNanos_zero() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.plusNanos(0); assertEquals(test, base); } @@ -929,7 +901,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { public void test_minus_MinusAdjuster() { MockSimplePeriod period = MockSimplePeriod.of(7, ChronoUnit.MINUTES); OffsetTime t = TEST_11_30_59_500_PONE.minus(period); - assertEquals(t, OffsetTime.of(LocalTime.of(11, 23, 59, 500), OFFSET_PONE)); + assertEquals(t, OffsetTime.of(11, 23, 59, 500, OFFSET_PONE)); } @Test(groups={"tck"}) @@ -946,7 +918,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_minus_MinusAdjuster_null() { - TEST_11_30_59_500_PONE.minus((TemporalSubtractor) null); + TEST_11_30_59_500_PONE.minus((TemporalAmount) null); } //----------------------------------------------------------------------- @@ -954,14 +926,14 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_minusHours() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.minusHours(-13); - assertEquals(test, OffsetTime.of(LocalTime.of(0, 30, 59), OFFSET_PONE)); + assertEquals(test, OffsetTime.of(0, 30, 59, 0, OFFSET_PONE)); } @Test(groups={"tck"}) public void test_minusHours_zero() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.minusHours(0); assertEquals(test, base); } @@ -971,14 +943,14 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_minusMinutes() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.minusMinutes(50); - assertEquals(test, OffsetTime.of(LocalTime.of(10, 40, 59), OFFSET_PONE)); + assertEquals(test, OffsetTime.of(10, 40, 59, 0, OFFSET_PONE)); } @Test(groups={"tck"}) public void test_minusMinutes_zero() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.minusMinutes(0); assertEquals(test, base); } @@ -988,14 +960,14 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_minusSeconds() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.minusSeconds(60); - assertEquals(test, OffsetTime.of(LocalTime.of(11, 29, 59), OFFSET_PONE)); + assertEquals(test, OffsetTime.of(11, 29, 59, 0, OFFSET_PONE)); } @Test(groups={"tck"}) public void test_minusSeconds_zero() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.minusSeconds(0); assertEquals(test, base); } @@ -1005,14 +977,14 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_minusNanos() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59, 0), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.minusNanos(1); - assertEquals(test, OffsetTime.of(LocalTime.of(11, 30, 58, 999999999), OFFSET_PONE)); + assertEquals(test, OffsetTime.of(11, 30, 58, 999999999, OFFSET_PONE)); } @Test(groups={"tck"}) public void test_minusNanos_zero() { - OffsetTime base = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime base = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); OffsetTime test = base.minusNanos(0); assertEquals(test, base); } @@ -1022,8 +994,8 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_compareTo_time() { - OffsetTime a = OffsetTime.of(LocalTime.of(11, 29), OFFSET_PONE); - OffsetTime b = OffsetTime.of(LocalTime.of(11, 30), OFFSET_PONE); // a is before b due to time + OffsetTime a = OffsetTime.of(11, 29, 0, 0, OFFSET_PONE); + OffsetTime b = OffsetTime.of(11, 30, 0, 0, OFFSET_PONE); // a is before b due to time assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1033,8 +1005,8 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_offset() { - OffsetTime a = OffsetTime.of(LocalTime.of(11, 30), OFFSET_PTWO); - OffsetTime b = OffsetTime.of(LocalTime.of(11, 30), OFFSET_PONE); // a is before b due to offset + OffsetTime a = OffsetTime.of(11, 30, 0, 0, OFFSET_PTWO); + OffsetTime b = OffsetTime.of(11, 30, 0, 0, OFFSET_PONE); // a is before b due to offset assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1044,8 +1016,8 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_both() { - OffsetTime a = OffsetTime.of(LocalTime.of(11, 50), OFFSET_PTWO); - OffsetTime b = OffsetTime.of(LocalTime.of(11, 20), OFFSET_PONE); // a is before b on instant scale + OffsetTime a = OffsetTime.of(11, 50, 0, 0, OFFSET_PTWO); + OffsetTime b = OffsetTime.of(11, 20, 0, 0, OFFSET_PONE); // a is before b on instant scale assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1055,8 +1027,8 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_bothNearStartOfDay() { - OffsetTime a = OffsetTime.of(LocalTime.of(0, 10), OFFSET_PONE); - OffsetTime b = OffsetTime.of(LocalTime.of(2, 30), OFFSET_PTWO); // a is before b on instant scale + OffsetTime a = OffsetTime.of(0, 10, 0, 0, OFFSET_PONE); + OffsetTime b = OffsetTime.of(2, 30, 0, 0, OFFSET_PTWO); // a is before b on instant scale assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1066,8 +1038,8 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_hourDifference() { - OffsetTime a = OffsetTime.of(LocalTime.of(10, 0), OFFSET_PONE); - OffsetTime b = OffsetTime.of(LocalTime.of(11, 0), OFFSET_PTWO); // a is before b despite being same time-line time + OffsetTime a = OffsetTime.of(10, 0, 0, 0, OFFSET_PONE); + OffsetTime b = OffsetTime.of(11, 0, 0, 0, OFFSET_PTWO); // a is before b despite being same time-line time assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1077,7 +1049,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_compareTo_null() { - OffsetTime a = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime a = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); a.compareTo(null); } @@ -1089,7 +1061,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { } private Instant convertInstant(OffsetTime ot) { - return DATE.atTime(ot.getTime()).toInstant(ot.getOffset()); + return DATE.atTime(ot.toLocalTime()).toInstant(ot.getOffset()); } //----------------------------------------------------------------------- @@ -1097,8 +1069,8 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_isBeforeIsAfterIsEqual1() { - OffsetTime a = OffsetTime.of(LocalTime.of(11, 30, 58), OFFSET_PONE); - OffsetTime b = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); // a is before b due to time + OffsetTime a = OffsetTime.of(11, 30, 58, 0, OFFSET_PONE); + OffsetTime b = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); // a is before b due to time assertEquals(a.isBefore(b), true); assertEquals(a.isEqual(b), false); assertEquals(a.isAfter(b), false); @@ -1119,8 +1091,8 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_isBeforeIsAfterIsEqual1nanos() { - OffsetTime a = OffsetTime.of(LocalTime.of(11, 30, 59, 3), OFFSET_PONE); - OffsetTime b = OffsetTime.of(LocalTime.of(11, 30, 59, 4), OFFSET_PONE); // a is before b due to time + OffsetTime a = OffsetTime.of(11, 30, 59, 3, OFFSET_PONE); + OffsetTime b = OffsetTime.of(11, 30, 59, 4, OFFSET_PONE); // a is before b due to time assertEquals(a.isBefore(b), true); assertEquals(a.isEqual(b), false); assertEquals(a.isAfter(b), false); @@ -1141,8 +1113,8 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_isBeforeIsAfterIsEqual2() { - OffsetTime a = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PTWO); - OffsetTime b = OffsetTime.of(LocalTime.of(11, 30, 58), OFFSET_PONE); // a is before b due to offset + OffsetTime a = OffsetTime.of(11, 30, 59, 0, OFFSET_PTWO); + OffsetTime b = OffsetTime.of(11, 30, 58, 0, OFFSET_PONE); // a is before b due to offset assertEquals(a.isBefore(b), true); assertEquals(a.isEqual(b), false); assertEquals(a.isAfter(b), false); @@ -1163,8 +1135,8 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_isBeforeIsAfterIsEqual2nanos() { - OffsetTime a = OffsetTime.of(LocalTime.of(11, 30, 59, 4), ZoneOffset.ofTotalSeconds(OFFSET_PONE.getTotalSeconds() + 1)); - OffsetTime b = OffsetTime.of(LocalTime.of(11, 30, 59, 3), OFFSET_PONE); // a is before b due to offset + OffsetTime a = OffsetTime.of(11, 30, 59, 4, ZoneOffset.ofTotalSeconds(OFFSET_PONE.getTotalSeconds() + 1)); + OffsetTime b = OffsetTime.of(11, 30, 59, 3, OFFSET_PONE); // a is before b due to offset assertEquals(a.isBefore(b), true); assertEquals(a.isEqual(b), false); assertEquals(a.isAfter(b), false); @@ -1185,8 +1157,8 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_isBeforeIsAfterIsEqual_instantComparison() { - OffsetTime a = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PTWO); - OffsetTime b = OffsetTime.of(LocalTime.of(10, 30, 59), OFFSET_PONE); // a is same instant as b + OffsetTime a = OffsetTime.of(11, 30, 59, 0, OFFSET_PTWO); + OffsetTime b = OffsetTime.of(10, 30, 59, 0, OFFSET_PONE); // a is same instant as b assertEquals(a.isBefore(b), false); assertEquals(a.isEqual(b), true); assertEquals(a.isAfter(b), false); @@ -1207,19 +1179,19 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_isBefore_null() { - OffsetTime a = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime a = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); a.isBefore(null); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_isAfter_null() { - OffsetTime a = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime a = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); a.isAfter(null); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_isEqual_null() { - OffsetTime a = OffsetTime.of(LocalTime.of(11, 30, 59), OFFSET_PONE); + OffsetTime a = OffsetTime.of(11, 30, 59, 0, OFFSET_PONE); a.isEqual(null); } @@ -1228,43 +1200,43 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(dataProvider="sampleTimes", groups={"tck"}) public void test_equals_true(int h, int m, int s, int n, ZoneOffset ignored) { - OffsetTime a = OffsetTime.of(LocalTime.of(h, m, s, n), OFFSET_PONE); - OffsetTime b = OffsetTime.of(LocalTime.of(h, m, s, n), OFFSET_PONE); + OffsetTime a = OffsetTime.of(h, m, s, n, OFFSET_PONE); + OffsetTime b = OffsetTime.of(h, m, s, n, OFFSET_PONE); assertEquals(a.equals(b), true); assertEquals(a.hashCode() == b.hashCode(), true); } @Test(dataProvider="sampleTimes", groups={"tck"}) public void test_equals_false_hour_differs(int h, int m, int s, int n, ZoneOffset ignored) { h = (h == 23 ? 22 : h); - OffsetTime a = OffsetTime.of(LocalTime.of(h, m, s, n), OFFSET_PONE); - OffsetTime b = OffsetTime.of(LocalTime.of(h + 1, m, s, n), OFFSET_PONE); + OffsetTime a = OffsetTime.of(h, m, s, n, OFFSET_PONE); + OffsetTime b = OffsetTime.of(h + 1, m, s, n, OFFSET_PONE); assertEquals(a.equals(b), false); } @Test(dataProvider="sampleTimes", groups={"tck"}) public void test_equals_false_minute_differs(int h, int m, int s, int n, ZoneOffset ignored) { m = (m == 59 ? 58 : m); - OffsetTime a = OffsetTime.of(LocalTime.of(h, m, s, n), OFFSET_PONE); - OffsetTime b = OffsetTime.of(LocalTime.of(h, m + 1, s, n), OFFSET_PONE); + OffsetTime a = OffsetTime.of(h, m, s, n, OFFSET_PONE); + OffsetTime b = OffsetTime.of(h, m + 1, s, n, OFFSET_PONE); assertEquals(a.equals(b), false); } @Test(dataProvider="sampleTimes", groups={"tck"}) public void test_equals_false_second_differs(int h, int m, int s, int n, ZoneOffset ignored) { s = (s == 59 ? 58 : s); - OffsetTime a = OffsetTime.of(LocalTime.of(h, m, s, n), OFFSET_PONE); - OffsetTime b = OffsetTime.of(LocalTime.of(h, m, s + 1, n), OFFSET_PONE); + OffsetTime a = OffsetTime.of(h, m, s, n, OFFSET_PONE); + OffsetTime b = OffsetTime.of(h, m, s + 1, n, OFFSET_PONE); assertEquals(a.equals(b), false); } @Test(dataProvider="sampleTimes", groups={"tck"}) public void test_equals_false_nano_differs(int h, int m, int s, int n, ZoneOffset ignored) { n = (n == 999999999 ? 999999998 : n); - OffsetTime a = OffsetTime.of(LocalTime.of(h, m, s, n), OFFSET_PONE); - OffsetTime b = OffsetTime.of(LocalTime.of(h, m, s, n + 1), OFFSET_PONE); + OffsetTime a = OffsetTime.of(h, m, s, n, OFFSET_PONE); + OffsetTime b = OffsetTime.of(h, m, s, n + 1, OFFSET_PONE); assertEquals(a.equals(b), false); } @Test(dataProvider="sampleTimes", groups={"tck"}) public void test_equals_false_offset_differs(int h, int m, int s, int n, ZoneOffset ignored) { - OffsetTime a = OffsetTime.of(LocalTime.of(h, m, s, n), OFFSET_PONE); - OffsetTime b = OffsetTime.of(LocalTime.of(h, m, s, n), OFFSET_PTWO); + OffsetTime a = OffsetTime.of(h, m, s, n, OFFSET_PONE); + OffsetTime b = OffsetTime.of(h, m, s, n, OFFSET_PTWO); assertEquals(a.equals(b), false); } @@ -1302,7 +1274,7 @@ public class TCKOffsetTime extends AbstractDateTimeTest { @Test(dataProvider="sampleToString", groups={"tck"}) public void test_toString(int h, int m, int s, int n, String offsetId, String expected) { - OffsetTime t = OffsetTime.of(LocalTime.of(h, m, s, n), ZoneOffset.of(offsetId)); + OffsetTime t = OffsetTime.of(h, m, s, n, ZoneOffset.of(offsetId)); String str = t.toString(); assertEquals(str, expected); } @@ -1312,14 +1284,14 @@ public class TCKOffsetTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_toString_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("H m s"); - String t = OffsetTime.of(LocalTime.of(11, 30), OFFSET_PONE).toString(f); + DateTimeFormatter f = DateTimeFormatter.ofPattern("H m s"); + String t = OffsetTime.of(11, 30, 0, 0, OFFSET_PONE).toString(f); assertEquals(t, "11 30 0"); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_toString_formatter_null() { - OffsetTime.of(LocalTime.of(11, 30), OFFSET_PONE).toString(null); + OffsetTime.of(11, 30, 0, 0, OFFSET_PONE).toString(null); } } diff --git a/jdk/test/java/time/tck/java/time/TCKPeriod.java b/jdk/test/java/time/tck/java/time/TCKPeriod.java new file mode 100644 index 00000000000..7399b50054e --- /dev/null +++ b/jdk/test/java/time/tck/java/time/TCKPeriod.java @@ -0,0 +1,906 @@ +/* + * Copyright (c) 2012, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of JSR-310 nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package tck.java.time; + +import static org.testng.Assert.assertEquals; + +import java.time.DateTimeException; +import java.time.LocalDate; +import java.time.Period; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoUnit; +import java.time.temporal.TemporalUnit; +import java.util.List; +import java.util.Locale; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * Test Period. + */ +@Test +public class TCKPeriod extends AbstractTCKTest { + + //----------------------------------------------------------------------- + @Test + public void test_serialization() throws Exception { + assertSerializable(Period.ZERO); + assertSerializable(Period.ofDays(1)); + assertSerializable(Period.of(1, 2, 3)); + } + + //----------------------------------------------------------------------- + // ofYears(int) + //----------------------------------------------------------------------- + @Test + public void factory_ofYears_int() { + assertPeriod(Period.ofYears(0), 0, 0, 0); + assertPeriod(Period.ofYears(1), 1, 0, 0); + assertPeriod(Period.ofYears(234), 234, 0, 0); + assertPeriod(Period.ofYears(-100), -100, 0, 0); + assertPeriod(Period.ofYears(Integer.MAX_VALUE), Integer.MAX_VALUE, 0, 0); + assertPeriod(Period.ofYears(Integer.MIN_VALUE), Integer.MIN_VALUE, 0, 0); + } + + //----------------------------------------------------------------------- + // ofMonths(int) + //----------------------------------------------------------------------- + @Test + public void factory_ofMonths_int() { + assertPeriod(Period.ofMonths(0), 0, 0, 0); + assertPeriod(Period.ofMonths(1), 0, 1, 0); + assertPeriod(Period.ofMonths(234), 0, 234, 0); + assertPeriod(Period.ofMonths(-100), 0, -100, 0); + assertPeriod(Period.ofMonths(Integer.MAX_VALUE), 0, Integer.MAX_VALUE, 0); + assertPeriod(Period.ofMonths(Integer.MIN_VALUE), 0, Integer.MIN_VALUE, 0); + } + + //----------------------------------------------------------------------- + // ofDays(int) + //----------------------------------------------------------------------- + @Test + public void factory_ofDay_int() { + assertPeriod(Period.ofDays(0), 0, 0, 0); + assertPeriod(Period.ofDays(1), 0, 0, 1); + assertPeriod(Period.ofDays(234), 0, 0, 234); + assertPeriod(Period.ofDays(-100), 0, 0, -100); + assertPeriod(Period.ofDays(Integer.MAX_VALUE), 0, 0, Integer.MAX_VALUE); + assertPeriod(Period.ofDays(Integer.MIN_VALUE), 0, 0, Integer.MIN_VALUE); + } + + //----------------------------------------------------------------------- + // of(int3) + //----------------------------------------------------------------------- + @Test + public void factory_of_ints() { + assertPeriod(Period.of(1, 2, 3), 1, 2, 3); + assertPeriod(Period.of(0, 2, 3), 0, 2, 3); + assertPeriod(Period.of(1, 0, 0), 1, 0, 0); + assertPeriod(Period.of(0, 0, 0), 0, 0, 0); + assertPeriod(Period.of(-1, -2, -3), -1, -2, -3); + } + + //----------------------------------------------------------------------- + // parse(String) + //----------------------------------------------------------------------- + @DataProvider(name="parseSuccess") + Object[][] data_factory_parseSuccess() { + return new Object[][] { + {"P1Y", Period.ofYears(1)}, + {"P12Y", Period.ofYears(12)}, + {"P987654321Y", Period.ofYears(987654321)}, + {"P+1Y", Period.ofYears(1)}, + {"P+12Y", Period.ofYears(12)}, + {"P+987654321Y", Period.ofYears(987654321)}, + {"P+0Y", Period.ofYears(0)}, + {"P0Y", Period.ofYears(0)}, + {"P-0Y", Period.ofYears(0)}, + {"P-25Y", Period.ofYears(-25)}, + {"P-987654321Y", Period.ofYears(-987654321)}, + {"P" + Integer.MAX_VALUE + "Y", Period.ofYears(Integer.MAX_VALUE)}, + {"P" + Integer.MIN_VALUE + "Y", Period.ofYears(Integer.MIN_VALUE)}, + + {"P1M", Period.ofMonths(1)}, + {"P12M", Period.ofMonths(12)}, + {"P987654321M", Period.ofMonths(987654321)}, + {"P+1M", Period.ofMonths(1)}, + {"P+12M", Period.ofMonths(12)}, + {"P+987654321M", Period.ofMonths(987654321)}, + {"P+0M", Period.ofMonths(0)}, + {"P0M", Period.ofMonths(0)}, + {"P-0M", Period.ofMonths(0)}, + {"P-25M", Period.ofMonths(-25)}, + {"P-987654321M", Period.ofMonths(-987654321)}, + {"P" + Integer.MAX_VALUE + "M", Period.ofMonths(Integer.MAX_VALUE)}, + {"P" + Integer.MIN_VALUE + "M", Period.ofMonths(Integer.MIN_VALUE)}, + + {"P1D", Period.ofDays(1)}, + {"P12D", Period.ofDays(12)}, + {"P987654321D", Period.ofDays(987654321)}, + {"P+1D", Period.ofDays(1)}, + {"P+12D", Period.ofDays(12)}, + {"P+987654321D", Period.ofDays(987654321)}, + {"P+0D", Period.ofDays(0)}, + {"P0D", Period.ofDays(0)}, + {"P-0D", Period.ofDays(0)}, + {"P-25D", Period.ofDays(-25)}, + {"P-987654321D", Period.ofDays(-987654321)}, + {"P" + Integer.MAX_VALUE + "D", Period.ofDays(Integer.MAX_VALUE)}, + {"P" + Integer.MIN_VALUE + "D", Period.ofDays(Integer.MIN_VALUE)}, + + {"P0Y0M0D", Period.of(0, 0, 0)}, + {"P2Y0M0D", Period.of(2, 0, 0)}, + {"P0Y3M0D", Period.of(0, 3, 0)}, + {"P0Y0M4D", Period.of(0, 0, 4)}, + {"P2Y3M25D", Period.of(2, 3, 25)}, + {"P-2Y3M25D", Period.of(-2, 3, 25)}, + {"P2Y-3M25D", Period.of(2, -3, 25)}, + {"P2Y3M-25D", Period.of(2, 3, -25)}, + {"P-2Y-3M-25D", Period.of(-2, -3, -25)}, + }; + } + + @Test(dataProvider="parseSuccess") + public void factory_parse(String text, Period expected) { + Period p = Period.parse(text); + assertEquals(p, expected); + } + + @Test(dataProvider="parseSuccess") + public void factory_parse_plus(String text, Period expected) { + Period p = Period.parse("+" + text); + assertEquals(p, expected); + } + + @Test(dataProvider="parseSuccess") + public void factory_parse_minus(String text, Period expected) { + Period p = null; + try { + p = Period.parse("-" + text); + } catch (DateTimeParseException ex) { + assertEquals(expected.getYears() == Integer.MIN_VALUE || + expected.getMonths() == Integer.MIN_VALUE || + expected.getDays() == Integer.MIN_VALUE, true); + return; + } + // not inside try/catch or it breaks test + assertEquals(p, expected.negated()); + } + + @Test(dataProvider="parseSuccess") + public void factory_parse_lowerCase(String text, Period expected) { + Period p = Period.parse(text.toLowerCase(Locale.ENGLISH)); + assertEquals(p, expected); + } + + @DataProvider(name="parseFailure") + Object[][] data_parseFailure() { + return new Object[][] { + {""}, + {"PTD"}, + {"AT0D"}, + {"PA0D"}, + {"PT0A"}, + + {"PT+D"}, + {"PT-D"}, + {"PT.D"}, + {"PTAD"}, + + {"PT+0D"}, + {"PT-0D"}, + {"PT+1D"}, + {"PT-.D"}, + + {"P1Y1MT1D"}, + {"P1YMD"}, + {"P1Y2Y"}, + {"PT1M+3S"}, + + {"PT1S1"}, + {"PT1S."}, + {"PT1SA"}, + {"PT1M1"}, + {"PT1M."}, + {"PT1MA"}, + + {"P"+ (((long) Integer.MAX_VALUE) + 1) + "Y"}, + {"P"+ (((long) Integer.MAX_VALUE) + 1) + "M"}, + {"P"+ (((long) Integer.MAX_VALUE) + 1) + "D"}, + {"P"+ (((long) Integer.MIN_VALUE) - 1) + "Y"}, + {"P"+ (((long) Integer.MIN_VALUE) - 1) + "M"}, + {"P"+ (((long) Integer.MIN_VALUE) - 1) + "D"}, + + {"Rubbish"}, + }; + } + + @Test(dataProvider="parseFailure", expectedExceptions=DateTimeParseException.class) + public void factory_parseFailures(String text) { + try { + Period.parse(text); + } catch (DateTimeParseException ex) { + assertEquals(ex.getParsedString(), text); + throw ex; + } + } + + @Test(expectedExceptions=NullPointerException.class) + public void factory_parse_null() { + Period.parse(null); + } + + //----------------------------------------------------------------------- + // between(LocalDate,LocalDate) + //----------------------------------------------------------------------- + @DataProvider(name="between") + Object[][] data_between() { + return new Object[][] { + {2010, 1, 1, 2010, 1, 1, 0, 0, 0}, + {2010, 1, 1, 2010, 1, 2, 0, 0, 1}, + {2010, 1, 1, 2010, 1, 31, 0, 0, 30}, + {2010, 1, 1, 2010, 2, 1, 0, 1, 0}, + {2010, 1, 1, 2010, 2, 28, 0, 1, 27}, + {2010, 1, 1, 2010, 3, 1, 0, 2, 0}, + {2010, 1, 1, 2010, 12, 31, 0, 11, 30}, + {2010, 1, 1, 2011, 1, 1, 1, 0, 0}, + {2010, 1, 1, 2011, 12, 31, 1, 11, 30}, + {2010, 1, 1, 2012, 1, 1, 2, 0, 0}, + + {2010, 1, 10, 2010, 1, 1, 0, 0, -9}, + {2010, 1, 10, 2010, 1, 2, 0, 0, -8}, + {2010, 1, 10, 2010, 1, 9, 0, 0, -1}, + {2010, 1, 10, 2010, 1, 10, 0, 0, 0}, + {2010, 1, 10, 2010, 1, 11, 0, 0, 1}, + {2010, 1, 10, 2010, 1, 31, 0, 0, 21}, + {2010, 1, 10, 2010, 2, 1, 0, 0, 22}, + {2010, 1, 10, 2010, 2, 9, 0, 0, 30}, + {2010, 1, 10, 2010, 2, 10, 0, 1, 0}, + {2010, 1, 10, 2010, 2, 28, 0, 1, 18}, + {2010, 1, 10, 2010, 3, 1, 0, 1, 19}, + {2010, 1, 10, 2010, 3, 9, 0, 1, 27}, + {2010, 1, 10, 2010, 3, 10, 0, 2, 0}, + {2010, 1, 10, 2010, 12, 31, 0, 11, 21}, + {2010, 1, 10, 2011, 1, 1, 0, 11, 22}, + {2010, 1, 10, 2011, 1, 9, 0, 11, 30}, + {2010, 1, 10, 2011, 1, 10, 1, 0, 0}, + + {2010, 3, 30, 2011, 5, 1, 1, 1, 1}, + {2010, 4, 30, 2011, 5, 1, 1, 0, 1}, + + {2010, 2, 28, 2012, 2, 27, 1, 11, 30}, + {2010, 2, 28, 2012, 2, 28, 2, 0, 0}, + {2010, 2, 28, 2012, 2, 29, 2, 0, 1}, + + {2012, 2, 28, 2014, 2, 27, 1, 11, 30}, + {2012, 2, 28, 2014, 2, 28, 2, 0, 0}, + {2012, 2, 28, 2014, 3, 1, 2, 0, 1}, + + {2012, 2, 29, 2014, 2, 28, 1, 11, 30}, + {2012, 2, 29, 2014, 3, 1, 2, 0, 1}, + {2012, 2, 29, 2014, 3, 2, 2, 0, 2}, + + {2012, 2, 29, 2016, 2, 28, 3, 11, 30}, + {2012, 2, 29, 2016, 2, 29, 4, 0, 0}, + {2012, 2, 29, 2016, 3, 1, 4, 0, 1}, + + {2010, 1, 1, 2009, 12, 31, 0, 0, -1}, + {2010, 1, 1, 2009, 12, 30, 0, 0, -2}, + {2010, 1, 1, 2009, 12, 2, 0, 0, -30}, + {2010, 1, 1, 2009, 12, 1, 0, -1, 0}, + {2010, 1, 1, 2009, 11, 30, 0, -1, -1}, + {2010, 1, 1, 2009, 11, 2, 0, -1, -29}, + {2010, 1, 1, 2009, 11, 1, 0, -2, 0}, + {2010, 1, 1, 2009, 1, 2, 0, -11, -30}, + {2010, 1, 1, 2009, 1, 1, -1, 0, 0}, + + {2010, 1, 15, 2010, 1, 15, 0, 0, 0}, + {2010, 1, 15, 2010, 1, 14, 0, 0, -1}, + {2010, 1, 15, 2010, 1, 1, 0, 0, -14}, + {2010, 1, 15, 2009, 12, 31, 0, 0, -15}, + {2010, 1, 15, 2009, 12, 16, 0, 0, -30}, + {2010, 1, 15, 2009, 12, 15, 0, -1, 0}, + {2010, 1, 15, 2009, 12, 14, 0, -1, -1}, + + {2010, 2, 28, 2009, 3, 1, 0, -11, -27}, + {2010, 2, 28, 2009, 2, 28, -1, 0, 0}, + {2010, 2, 28, 2009, 2, 27, -1, 0, -1}, + + {2010, 2, 28, 2008, 2, 29, -1, -11, -28}, + {2010, 2, 28, 2008, 2, 28, -2, 0, 0}, + {2010, 2, 28, 2008, 2, 27, -2, 0, -1}, + + {2012, 2, 29, 2009, 3, 1, -2, -11, -28}, + {2012, 2, 29, 2009, 2, 28, -3, 0, -1}, + {2012, 2, 29, 2009, 2, 27, -3, 0, -2}, + + {2012, 2, 29, 2008, 3, 1, -3, -11, -28}, + {2012, 2, 29, 2008, 2, 29, -4, 0, 0}, + {2012, 2, 29, 2008, 2, 28, -4, 0, -1}, + }; + } + + @Test(dataProvider="between") + public void factory_between_LocalDate(int y1, int m1, int d1, int y2, int m2, int d2, int ye, int me, int de) { + LocalDate start = LocalDate.of(y1, m1, d1); + LocalDate end = LocalDate.of(y2, m2, d2); + Period test = Period.between(start, end); + assertPeriod(test, ye, me, de); + //assertEquals(start.plus(test), end); + } + + @Test(expectedExceptions=NullPointerException.class) + public void factory_between_LocalDate_nullFirst() { + Period.between((LocalDate) null, LocalDate.of(2010, 1, 1)); + } + + @Test(expectedExceptions=NullPointerException.class) + public void factory_between_LocalDate_nullSecond() { + Period.between(LocalDate.of(2010, 1, 1), (LocalDate) null); + } + + //----------------------------------------------------------------------- + // isZero() + //----------------------------------------------------------------------- + @Test + public void test_isZero() { + assertEquals(Period.of(0, 0, 0).isZero(), true); + assertEquals(Period.of(1, 2, 3).isZero(), false); + assertEquals(Period.of(1, 0, 0).isZero(), false); + assertEquals(Period.of(0, 2, 0).isZero(), false); + assertEquals(Period.of(0, 0, 3).isZero(), false); + } + + //----------------------------------------------------------------------- + // isNegative() + //----------------------------------------------------------------------- + @Test + public void test_isPositive() { + assertEquals(Period.of(0, 0, 0).isNegative(), false); + assertEquals(Period.of(1, 2, 3).isNegative(), false); + assertEquals(Period.of(1, 0, 0).isNegative(), false); + assertEquals(Period.of(0, 2, 0).isNegative(), false); + assertEquals(Period.of(0, 0, 3).isNegative(), false); + + assertEquals(Period.of(-1, -2, -3).isNegative(), true); + assertEquals(Period.of(-1, -2, 3).isNegative(), true); + assertEquals(Period.of(1, -2, -3).isNegative(), true); + assertEquals(Period.of(-1, 2, -3).isNegative(), true); + assertEquals(Period.of(-1, 2, 3).isNegative(), true); + assertEquals(Period.of(1, -2, 3).isNegative(), true); + assertEquals(Period.of(1, 2, -3).isNegative(), true); + } + + //----------------------------------------------------------------------- + // withYears() + //----------------------------------------------------------------------- + @Test + public void test_withYears() { + assertPeriod(Period.of(1, 2, 3).withYears(1), 1, 2, 3); + assertPeriod(Period.of(1, 2, 3).withYears(10), 10, 2, 3); + assertPeriod(Period.of(1, 2, 3).withYears(-10), -10, 2, 3); + assertPeriod(Period.of(-1, -2, -3).withYears(10), 10, -2, -3); + assertPeriod(Period.of(1, 2, 3).withYears(0), 0, 2, 3); + } + + //----------------------------------------------------------------------- + // withMonths() + //----------------------------------------------------------------------- + @Test + public void test_withMonths() { + assertPeriod(Period.of(1, 2, 3).withMonths(2), 1, 2, 3); + assertPeriod(Period.of(1, 2, 3).withMonths(10), 1, 10, 3); + assertPeriod(Period.of(1, 2, 3).withMonths(-10), 1, -10, 3); + assertPeriod(Period.of(-1, -2, -3).withMonths(10), -1, 10, -3); + assertPeriod(Period.of(1, 2, 3).withMonths(0), 1, 0, 3); + } + + //----------------------------------------------------------------------- + // withDays() + //----------------------------------------------------------------------- + @Test + public void test_withDays() { + assertPeriod(Period.of(1, 2, 3).withDays(3), 1, 2, 3); + assertPeriod(Period.of(1, 2, 3).withDays(10), 1, 2, 10); + assertPeriod(Period.of(1, 2, 3).withDays(-10), 1, 2, -10); + assertPeriod(Period.of(-1, -2, -3).withDays(10), -1, -2, 10); + assertPeriod(Period.of(1, 2, 3).withDays(0), 1, 2, 0); + } + + //----------------------------------------------------------------------- + // plusYears() + //----------------------------------------------------------------------- + @Test + public void test_plusYears() { + assertPeriod(Period.of(1, 2, 3).plusYears(0), 1, 2, 3); + assertPeriod(Period.of(1, 2, 3).plusYears(10), 11, 2, 3); + assertPeriod(Period.of(1, 2, 3).plusYears(-10), -9, 2, 3); + assertPeriod(Period.of(1, 2, 3).plusYears(-1), 0, 2, 3); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void test_plusYears_overflowTooBig() { + Period test = Period.ofYears(Integer.MAX_VALUE); + test.plusYears(1); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void test_plusYears_overflowTooSmall() { + Period test = Period.ofYears(Integer.MIN_VALUE); + test.plusYears(-1); + } + + //----------------------------------------------------------------------- + // plusMonths() + //----------------------------------------------------------------------- + @Test + public void test_plusMonths() { + assertPeriod(Period.of(1, 2, 3).plusMonths(0), 1, 2, 3); + assertPeriod(Period.of(1, 2, 3).plusMonths(10), 1, 12, 3); + assertPeriod(Period.of(1, 2, 3).plusMonths(-10), 1, -8, 3); + assertPeriod(Period.of(1, 2, 3).plusMonths(-2), 1, 0, 3); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void test_plusMonths_overflowTooBig() { + Period test = Period.ofMonths(Integer.MAX_VALUE); + test.plusMonths(1); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void test_plusMonths_overflowTooSmall() { + Period test = Period.ofMonths(Integer.MIN_VALUE); + test.plusMonths(-1); + } + + //----------------------------------------------------------------------- + // plusDays() + //----------------------------------------------------------------------- + @Test + public void test_plusDays() { + assertPeriod(Period.of(1, 2, 3).plusDays(0), 1, 2, 3); + assertPeriod(Period.of(1, 2, 3).plusDays(10), 1, 2, 13); + assertPeriod(Period.of(1, 2, 3).plusDays(-10), 1, 2, -7); + assertPeriod(Period.of(1, 2, 3).plusDays(-3), 1, 2, 0); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void test_plusDays_overflowTooBig() { + Period test = Period.ofDays(Integer.MAX_VALUE); + test.plusDays(1); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void test_plusDays_overflowTooSmall() { + Period test = Period.ofDays(Integer.MIN_VALUE); + test.plusDays(-1); + } + + //----------------------------------------------------------------------- + // multipliedBy() + //----------------------------------------------------------------------- + @Test + public void test_multipliedBy() { + Period test = Period.of(1, 2, 3); + assertPeriod(test.multipliedBy(0), 0, 0, 0); + assertPeriod(test.multipliedBy(1), 1, 2, 3); + assertPeriod(test.multipliedBy(2), 2, 4, 6); + assertPeriod(test.multipliedBy(-3), -3, -6, -9); + } + + @Test + public void test_multipliedBy_zeroBase() { + assertPeriod(Period.ZERO.multipliedBy(2), 0, 0, 0); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void test_multipliedBy_overflowTooBig() { + Period test = Period.ofYears(Integer.MAX_VALUE / 2 + 1); + test.multipliedBy(2); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void test_multipliedBy_overflowTooSmall() { + Period test = Period.ofYears(Integer.MIN_VALUE / 2 - 1); + test.multipliedBy(2); + } + + //----------------------------------------------------------------------- + // negated() + //----------------------------------------------------------------------- + @Test + public void test_negated() { + assertPeriod(Period.of(0, 0, 0).negated(), 0 ,0, 0); + assertPeriod(Period.of(1, 2, 3).negated(), -1, -2, -3); + assertPeriod(Period.of(-1, -2, -3).negated(), 1, 2, 3); + assertPeriod(Period.of(-1, 2, -3).negated(), 1, -2, 3); + assertPeriod(Period.of(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE).negated(), + -Integer.MAX_VALUE, -Integer.MAX_VALUE, -Integer.MAX_VALUE); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void test_negated_overflow_years() { + Period.ofYears(Integer.MIN_VALUE).negated(); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void test_negated_overflow_months() { + Period.ofMonths(Integer.MIN_VALUE).negated(); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void test_negated_overflow_days() { + Period.ofDays(Integer.MIN_VALUE).negated(); + } + + //----------------------------------------------------------------------- + // normalized() + //----------------------------------------------------------------------- + @DataProvider(name="normalized") + Object[][] data_normalized() { + return new Object[][] { + {0, 0, 0, 0}, + {1, 0, 1, 0}, + {-1, 0, -1, 0}, + + {1, 1, 1, 1}, + {1, 2, 1, 2}, + {1, 11, 1, 11}, + {1, 12, 2, 0}, + {1, 13, 2, 1}, + {1, 23, 2, 11}, + {1, 24, 3, 0}, + {1, 25, 3, 1}, + + {1, -1, 0, 11}, + {1, -2, 0, 10}, + {1, -11, 0, 1}, + {1, -12, 0, 0}, + {1, -13, 0, -1}, + {1, -23, 0, -11}, + {1, -24, -1, 0}, + {1, -25, -1, -1}, + {1, -35, -1, -11}, + {1, -36, -2, 0}, + {1, -37, -2, -1}, + + {-1, 1, 0, -11}, + {-1, 11, 0, -1}, + {-1, 12, 0, 0}, + {-1, 13, 0, 1}, + {-1, 23, 0, 11}, + {-1, 24, 1, 0}, + {-1, 25, 1, 1}, + + {-1, -1, -1, -1}, + {-1, -11, -1, -11}, + {-1, -12, -2, 0}, + {-1, -13, -2, -1}, + }; + } + + @Test(dataProvider="normalized") + public void test_normalized(int inputYears, int inputMonths, int expectedYears, int expectedMonths) { + assertPeriod(Period.of(inputYears, inputMonths, 0).normalized(), expectedYears, expectedMonths, 0); + } + + @Test(dataProvider="normalized") + public void test_normalized_daysUnaffected(int inputYears, int inputMonths, int expectedYears, int expectedMonths) { + assertPeriod(Period.of(inputYears, inputMonths, 5).normalized(), expectedYears, expectedMonths, 5); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void test_normalized_min() { + Period base = Period.of(Integer.MIN_VALUE, -12, 0); + base.normalized(); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void test_normalized_max() { + Period base = Period.of(Integer.MAX_VALUE, 12, 0); + base.normalized(); + } + + //----------------------------------------------------------------------- + // addTo() + //----------------------------------------------------------------------- + @DataProvider(name="addTo") + Object[][] data_addTo() { + return new Object[][] { + {pymd(0, 0, 0), date(2012, 6, 30), date(2012, 6, 30)}, + + {pymd(1, 0, 0), date(2012, 6, 10), date(2013, 6, 10)}, + {pymd(0, 1, 0), date(2012, 6, 10), date(2012, 7, 10)}, + {pymd(0, 0, 1), date(2012, 6, 10), date(2012, 6, 11)}, + + {pymd(-1, 0, 0), date(2012, 6, 10), date(2011, 6, 10)}, + {pymd(0, -1, 0), date(2012, 6, 10), date(2012, 5, 10)}, + {pymd(0, 0, -1), date(2012, 6, 10), date(2012, 6, 9)}, + + {pymd(1, 2, 3), date(2012, 6, 27), date(2013, 8, 30)}, + {pymd(1, 2, 3), date(2012, 6, 28), date(2013, 8, 31)}, + {pymd(1, 2, 3), date(2012, 6, 29), date(2013, 9, 1)}, + {pymd(1, 2, 3), date(2012, 6, 30), date(2013, 9, 2)}, + {pymd(1, 2, 3), date(2012, 7, 1), date(2013, 9, 4)}, + + {pymd(1, 0, 0), date(2011, 2, 28), date(2012, 2, 28)}, + {pymd(4, 0, 0), date(2011, 2, 28), date(2015, 2, 28)}, + {pymd(1, 0, 0), date(2012, 2, 29), date(2013, 2, 28)}, + {pymd(4, 0, 0), date(2012, 2, 29), date(2016, 2, 29)}, + + {pymd(1, 1, 0), date(2011, 1, 29), date(2012, 2, 29)}, + {pymd(1, 2, 0), date(2012, 2, 29), date(2013, 4, 29)}, + }; + } + + @Test(dataProvider="addTo") + public void test_addTo(Period period, LocalDate baseDate, LocalDate expected) { + assertEquals(period.addTo(baseDate), expected); + } + + @Test(dataProvider="addTo") + public void test_addTo_usingLocalDatePlus(Period period, LocalDate baseDate, LocalDate expected) { + assertEquals(baseDate.plus(period), expected); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_addTo_nullZero() { + Period.ZERO.addTo(null); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_addTo_nullNonZero() { + Period.ofDays(2).addTo(null); + } + + //----------------------------------------------------------------------- + // subtractFrom() + //----------------------------------------------------------------------- + @DataProvider(name="subtractFrom") + Object[][] data_subtractFrom() { + return new Object[][] { + {pymd(0, 0, 0), date(2012, 6, 30), date(2012, 6, 30)}, + + {pymd(1, 0, 0), date(2012, 6, 10), date(2011, 6, 10)}, + {pymd(0, 1, 0), date(2012, 6, 10), date(2012, 5, 10)}, + {pymd(0, 0, 1), date(2012, 6, 10), date(2012, 6, 9)}, + + {pymd(-1, 0, 0), date(2012, 6, 10), date(2013, 6, 10)}, + {pymd(0, -1, 0), date(2012, 6, 10), date(2012, 7, 10)}, + {pymd(0, 0, -1), date(2012, 6, 10), date(2012, 6, 11)}, + + {pymd(1, 2, 3), date(2012, 8, 30), date(2011, 6, 27)}, + {pymd(1, 2, 3), date(2012, 8, 31), date(2011, 6, 27)}, + {pymd(1, 2, 3), date(2012, 9, 1), date(2011, 6, 28)}, + {pymd(1, 2, 3), date(2012, 9, 2), date(2011, 6, 29)}, + {pymd(1, 2, 3), date(2012, 9, 3), date(2011, 6, 30)}, + {pymd(1, 2, 3), date(2012, 9, 4), date(2011, 7, 1)}, + + {pymd(1, 0, 0), date(2011, 2, 28), date(2010, 2, 28)}, + {pymd(4, 0, 0), date(2011, 2, 28), date(2007, 2, 28)}, + {pymd(1, 0, 0), date(2012, 2, 29), date(2011, 2, 28)}, + {pymd(4, 0, 0), date(2012, 2, 29), date(2008, 2, 29)}, + + {pymd(1, 1, 0), date(2013, 3, 29), date(2012, 2, 29)}, + {pymd(1, 2, 0), date(2012, 2, 29), date(2010, 12, 29)}, + }; + } + + @Test(dataProvider="subtractFrom") + public void test_subtractFrom(Period period, LocalDate baseDate, LocalDate expected) { + assertEquals(period.subtractFrom(baseDate), expected); + } + + @Test(dataProvider="subtractFrom") + public void test_subtractFrom_usingLocalDateMinus(Period period, LocalDate baseDate, LocalDate expected) { + assertEquals(baseDate.minus(period), expected); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_subtractFrom_nullZero() { + Period.ZERO.subtractFrom(null); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_subtractFrom_nullNonZero() { + Period.ofDays(2).subtractFrom(null); + } + + //----------------------------------------------------------------------- + // get units + //----------------------------------------------------------------------- + @Test + public void test_Period_getUnits() { + Period period = Period.of(2012, 1, 1); + List units = period.getUnits(); + assertEquals(units.size(), 3, "Period.getUnits should return 3 units"); + assertEquals(units.get(0), ChronoUnit.YEARS, "Period.getUnits contains ChronoUnit.YEARS"); + assertEquals(units.get(1), ChronoUnit.MONTHS, "Period.getUnits contains ChronoUnit.MONTHS"); + assertEquals(units.get(2), ChronoUnit.DAYS, "Period.getUnits contains ChronoUnit.DAYS"); + } + + + @DataProvider(name="GoodTemporalUnit") + Object[][] data_goodTemporalUnit() { + return new Object[][] { + {2, ChronoUnit.DAYS}, + {2, ChronoUnit.MONTHS}, + {2, ChronoUnit.YEARS}, + }; + } + + @Test(dataProvider="GoodTemporalUnit") + public void test_good_getUnit(long amount, TemporalUnit unit) { + Period period = Period.of(2, 2, 2); + long actual = period.get(unit); + assertEquals(actual, amount, "Value of unit: " + unit); + } + + @DataProvider(name="BadTemporalUnit") + Object[][] data_badTemporalUnit() { + return new Object[][] { + {ChronoUnit.MICROS}, + {ChronoUnit.MILLIS}, + {ChronoUnit.HALF_DAYS}, + {ChronoUnit.DECADES}, + {ChronoUnit.CENTURIES}, + {ChronoUnit.MILLENNIA}, + }; + } + + @Test(dataProvider="BadTemporalUnit", expectedExceptions=DateTimeException.class) + public void test_bad_getUnit(TemporalUnit unit) { + Period period = Period.of(2, 2, 2); + period.get(unit); + } + + //----------------------------------------------------------------------- + // equals() / hashCode() + //----------------------------------------------------------------------- + public void test_equals() { + assertEquals(Period.of(1, 0, 0).equals(Period.ofYears(1)), true); + assertEquals(Period.of(0, 1, 0).equals(Period.ofMonths(1)), true); + assertEquals(Period.of(0, 0, 1).equals(Period.ofDays(1)), true); + assertEquals(Period.of(1, 2, 3).equals(Period.of(1, 2, 3)), true); + + assertEquals(Period.ofYears(1).equals(Period.ofYears(1)), true); + assertEquals(Period.ofYears(1).equals(Period.ofYears(2)), false); + + assertEquals(Period.ofMonths(1).equals(Period.ofMonths(1)), true); + assertEquals(Period.ofMonths(1).equals(Period.ofMonths(2)), false); + + assertEquals(Period.ofDays(1).equals(Period.ofDays(1)), true); + assertEquals(Period.ofDays(1).equals(Period.ofDays(2)), false); + + assertEquals(Period.of(1, 2, 3).equals(Period.of(0, 2, 3)), false); + assertEquals(Period.of(1, 2, 3).equals(Period.of(1, 0, 3)), false); + assertEquals(Period.of(1, 2, 3).equals(Period.of(1, 2, 0)), false); + } + + public void test_equals_self() { + Period test = Period.of(1, 2, 3); + assertEquals(test.equals(test), true); + } + + public void test_equals_null() { + Period test = Period.of(1, 2, 3); + assertEquals(test.equals(null), false); + } + + public void test_equals_otherClass() { + Period test = Period.of(1, 2, 3); + assertEquals(test.equals(""), false); + } + + //----------------------------------------------------------------------- + public void test_hashCode() { + Period test5 = Period.ofDays(5); + Period test6 = Period.ofDays(6); + Period test5M = Period.ofMonths(5); + Period test5Y = Period.ofYears(5); + assertEquals(test5.hashCode() == test5.hashCode(), true); + assertEquals(test5.hashCode() == test6.hashCode(), false); + } + + //----------------------------------------------------------------------- + // toString() + //----------------------------------------------------------------------- + @DataProvider(name="toStringAndParse") + Object[][] data_toString() { + return new Object[][] { + {Period.ZERO, "P0D"}, + {Period.ofDays(0), "P0D"}, + {Period.ofYears(1), "P1Y"}, + {Period.ofMonths(1), "P1M"}, + {Period.ofDays(1), "P1D"}, + {Period.of(1, 2, 0), "P1Y2M"}, + {Period.of(0, 2, 3), "P2M3D"}, + {Period.of(1, 2, 3), "P1Y2M3D"}, + }; + } + + @Test(dataProvider="toStringAndParse") + public void test_toString(Period input, String expected) { + assertEquals(input.toString(), expected); + } + + @Test(dataProvider="toStringAndParse") + public void test_parse(Period test, String expected) { + assertEquals(Period.parse(expected), test); + } + + //----------------------------------------------------------------------- + private void assertPeriod(Period test, int y, int m, int d) { + assertEquals(test.getYears(), y, "years"); + assertEquals(test.getMonths(), m, "months"); + assertEquals(test.getDays(), d, "days"); + assertEquals(test.toTotalMonths(), y * 12L + m, "totalMonths"); + } + + private static Period pymd(int y, int m, int d) { + return Period.of(y, m, d); + } + + private static LocalDate date(int y, int m, int d) { + return LocalDate.of(y, m, d); + } + +} diff --git a/jdk/test/java/time/tck/java/time/temporal/TCKYear.java b/jdk/test/java/time/tck/java/time/TCKYear.java similarity index 89% rename from jdk/test/java/time/tck/java/time/temporal/TCKYear.java rename to jdk/test/java/time/tck/java/time/TCKYear.java index 5464c6b4241..3f0e653f8cf 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TCKYear.java +++ b/jdk/test/java/time/tck/java/time/TCKYear.java @@ -57,7 +57,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.temporal; +package tck.java.time; import static java.time.temporal.ChronoField.ERA; import static java.time.temporal.ChronoField.YEAR; @@ -67,36 +67,36 @@ import static org.testng.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import java.time.Clock; import java.time.DateTimeException; import java.time.Instant; import java.time.LocalDate; import java.time.LocalTime; import java.time.Month; +import java.time.MonthDay; +import java.time.OffsetDateTime; +import java.time.Year; +import java.time.YearMonth; import java.time.ZoneId; import java.time.ZoneOffset; +import java.time.chrono.IsoChronology; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatters; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoField; +import java.time.temporal.ChronoUnit; import java.time.temporal.JulianFields; -import java.time.temporal.MonthDay; -import java.time.temporal.OffsetDateTime; +import java.time.temporal.Queries; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; -import java.time.temporal.Year; -import java.time.temporal.YearMonth; +import java.time.temporal.TemporalQuery; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import tck.java.time.AbstractDateTimeTest; /** * Test Year. @@ -149,7 +149,7 @@ public class TCKYear extends AbstractDateTimeTest { public void test_serialization_format() throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (DataOutputStream dos = new DataOutputStream(baos) ) { - dos.writeByte(4); + dos.writeByte(11); // java.time.temporal.Ser.YEAR_TYPE dos.writeInt(2012); } byte[] bytes = baos.toByteArray(); @@ -317,14 +317,14 @@ public class TCKYear extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void factory_parse_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("y"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y"); Year test = Year.parse("2010", f); assertEquals(test, Year.of(2010)); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void factory_parse_formatter_nullText() { - DateTimeFormatter f = DateTimeFormatters.pattern("y"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y"); Year.parse((String) null, f); } @@ -350,6 +350,37 @@ public class TCKYear extends AbstractDateTimeTest { assertEquals(TEST_2008.getLong(ChronoField.ERA), 1); } + //----------------------------------------------------------------------- + // query(TemporalQuery) + //----------------------------------------------------------------------- + @DataProvider(name="query") + Object[][] data_query() { + return new Object[][] { + {TEST_2008, Queries.chronology(), IsoChronology.INSTANCE}, + {TEST_2008, Queries.zoneId(), null}, + {TEST_2008, Queries.precision(), ChronoUnit.YEARS}, + {TEST_2008, Queries.zone(), null}, + {TEST_2008, Queries.offset(), null}, + {TEST_2008, Queries.localDate(), null}, + {TEST_2008, Queries.localTime(), null}, + }; + } + + @Test(dataProvider="query") + public void test_query(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(temporal.query(query), expected); + } + + @Test(dataProvider="query") + public void test_queryFrom(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(query.queryFrom(temporal), expected); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_query_null() { + TEST_2008.query(null); + } + //----------------------------------------------------------------------- // isLeap() //----------------------------------------------------------------------- @@ -555,45 +586,35 @@ public class TCKYear extends AbstractDateTimeTest { } //----------------------------------------------------------------------- - // isValidMonthDay(Month) + // isValidMonthDay(MonthDay) //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_isValidMonthDay_june() { - Year test = Year.of(2007); - MonthDay monthDay = MonthDay.of(6, 30); - assertEquals(test.isValidMonthDay(monthDay), true); + @DataProvider(name="isValidMonthDay") + Object[][] data_isValidMonthDay() { + return new Object[][] { + {Year.of(2007), MonthDay.of(6, 30), true}, + {Year.of(2008), MonthDay.of(2, 28), true}, + {Year.of(2008), MonthDay.of(2, 29), true}, + {Year.of(2009), MonthDay.of(2, 28), true}, + {Year.of(2009), MonthDay.of(2, 29), false}, + {Year.of(2009), null, false}, + }; } - @Test(groups={"tck"}) - public void test_isValidMonthDay_febNonLeap() { - Year test = Year.of(2007); - MonthDay monthDay = MonthDay.of(2, 29); - assertEquals(test.isValidMonthDay(monthDay), false); - } - - @Test(groups={"tck"}) - public void test_isValidMonthDay_febLeap() { - Year test = Year.of(2008); - MonthDay monthDay = MonthDay.of(2, 29); - assertEquals(test.isValidMonthDay(monthDay), true); - } - - @Test(groups={"tck"}) - public void test_isValidMonthDay_null() { - Year test = Year.of(2008); - assertEquals(test.isValidMonthDay(null), false); + @Test(dataProvider="isValidMonthDay") + public void test_isValidMonthDay(Year year, MonthDay monthDay, boolean expected) { + assertEquals(year.isValidMonthDay(monthDay), expected); } //----------------------------------------------------------------------- // atMonth(Month) //----------------------------------------------------------------------- - @Test(groups={"tck"}) + @Test public void test_atMonth() { Year test = Year.of(2008); assertEquals(test.atMonth(Month.JUNE), YearMonth.of(2008, 6)); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_atMonth_nullMonth() { Year test = Year.of(2008); test.atMonth((Month) null); @@ -602,13 +623,13 @@ public class TCKYear extends AbstractDateTimeTest { //----------------------------------------------------------------------- // atMonth(int) //----------------------------------------------------------------------- - @Test(groups={"tck"}) + @Test public void test_atMonth_int() { Year test = Year.of(2008); assertEquals(test.atMonth(6), YearMonth.of(2008, 6)); } - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) + @Test(expectedExceptions=DateTimeException.class) public void test_atMonth_int_invalidMonth() { Year test = Year.of(2008); test.atMonth(13); @@ -617,24 +638,26 @@ public class TCKYear extends AbstractDateTimeTest { //----------------------------------------------------------------------- // atMonthDay(Month) //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_atMonthDay() { - Year test = Year.of(2008); - assertEquals(test.atMonthDay(MonthDay.of(6, 30)), LocalDate.of(2008, 6, 30)); + @DataProvider(name="atMonthDay") + Object[][] data_atMonthDay() { + return new Object[][] { + {Year.of(2008), MonthDay.of(6, 30), LocalDate.of(2008, 6, 30)}, + {Year.of(2008), MonthDay.of(2, 29), LocalDate.of(2008, 2, 29)}, + {Year.of(2009), MonthDay.of(2, 29), LocalDate.of(2009, 2, 28)}, + }; } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(dataProvider="atMonthDay") + public void test_atMonthDay(Year year, MonthDay monthDay, LocalDate expected) { + assertEquals(year.atMonthDay(monthDay), expected); + } + + @Test(expectedExceptions=NullPointerException.class) public void test_atMonthDay_nullMonthDay() { Year test = Year.of(2008); test.atMonthDay((MonthDay) null); } - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_atMonthDay_invalidMonthDay() { - Year test = Year.of(2008); - test.atMonthDay(MonthDay.of(6, 31)); - } - //----------------------------------------------------------------------- // atDay(int) //----------------------------------------------------------------------- @@ -768,7 +791,7 @@ public class TCKYear extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_toString_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("y"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y"); String t = Year.of(2010).toString(f); assertEquals(t, "2010"); } diff --git a/jdk/test/java/time/tck/java/time/temporal/TCKYearMonth.java b/jdk/test/java/time/tck/java/time/TCKYearMonth.java similarity index 89% rename from jdk/test/java/time/tck/java/time/temporal/TCKYearMonth.java rename to jdk/test/java/time/tck/java/time/TCKYearMonth.java index 25d57f1a22b..3369daccca2 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TCKYearMonth.java +++ b/jdk/test/java/time/tck/java/time/TCKYearMonth.java @@ -57,7 +57,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.temporal; +package tck.java.time; import static java.time.temporal.ChronoField.EPOCH_MONTH; import static java.time.temporal.ChronoField.ERA; @@ -71,12 +71,6 @@ import static org.testng.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - import java.time.Clock; import java.time.DateTimeException; import java.time.Instant; @@ -84,22 +78,29 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; +import java.time.Year; +import java.time.YearMonth; import java.time.ZoneId; import java.time.ZoneOffset; +import java.time.chrono.IsoChronology; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatters; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoField; +import java.time.temporal.ChronoUnit; import java.time.temporal.JulianFields; +import java.time.temporal.Queries; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; -import java.time.temporal.Year; -import java.time.temporal.YearMonth; +import java.time.temporal.TemporalQuery; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import tck.java.time.AbstractDateTimeTest; /** * Test YearMonth. @@ -153,7 +154,7 @@ public class TCKYearMonth extends AbstractDateTimeTest { public void test_serialization_format() throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (DataOutputStream dos = new DataOutputStream(baos) ) { - dos.writeByte(5); + dos.writeByte(12); // java.time.temporal.Ser.YEAR_MONTH_TYPE dos.writeInt(2012); dos.writeByte(9); } @@ -378,14 +379,14 @@ public class TCKYearMonth extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void factory_parse_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M"); YearMonth test = YearMonth.parse("2010 12", f); assertEquals(test, YearMonth.of(2010, 12)); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void factory_parse_formatter_nullText() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M"); YearMonth.parse((String) null, f); } @@ -414,6 +415,37 @@ public class TCKYearMonth extends AbstractDateTimeTest { assertEquals(TEST_2008_06.getLong(ChronoField.EPOCH_MONTH), (2008 - 1970) * 12 + 6 - 1); } + //----------------------------------------------------------------------- + // query(TemporalQuery) + //----------------------------------------------------------------------- + @DataProvider(name="query") + Object[][] data_query() { + return new Object[][] { + {TEST_2008_06, Queries.chronology(), IsoChronology.INSTANCE}, + {TEST_2008_06, Queries.zoneId(), null}, + {TEST_2008_06, Queries.precision(), ChronoUnit.MONTHS}, + {TEST_2008_06, Queries.zone(), null}, + {TEST_2008_06, Queries.offset(), null}, + {TEST_2008_06, Queries.localDate(), null}, + {TEST_2008_06, Queries.localTime(), null}, + }; + } + + @Test(dataProvider="query") + public void test_query(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(temporal.query(query), expected); + } + + @Test(dataProvider="query") + public void test_queryFrom(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(query.queryFrom(temporal), expected); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_query_null() { + TEST_2008_06.query(null); + } + //----------------------------------------------------------------------- // get*() //----------------------------------------------------------------------- @@ -427,6 +459,14 @@ public class TCKYearMonth extends AbstractDateTimeTest { }; } + @Test(dataProvider="sampleDates") + public void test_get(int y, int m) { + YearMonth a = YearMonth.of(y, m); + assertEquals(a.getYear(), y); + assertEquals(a.getMonth(), Month.of(m)); + assertEquals(a.getMonthValue(), m); + } + //----------------------------------------------------------------------- // with(Year) //----------------------------------------------------------------------- @@ -870,16 +910,66 @@ public class TCKYearMonth extends AbstractDateTimeTest { //----------------------------------------------------------------------- // atDay(int) //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_atDay_int() { - YearMonth test = YearMonth.of(2008, 6); - assertEquals(test.atDay(30), LocalDate.of(2008, 6, 30)); + @DataProvider(name="atDay") + Object[][] data_atDay() { + return new Object[][] { + {YearMonth.of(2008, 6), 8, LocalDate.of(2008, 6, 8)}, + + {YearMonth.of(2008, 1), 31, LocalDate.of(2008, 1, 31)}, + {YearMonth.of(2008, 2), 29, LocalDate.of(2008, 2, 29)}, + {YearMonth.of(2008, 3), 31, LocalDate.of(2008, 3, 31)}, + {YearMonth.of(2008, 4), 30, LocalDate.of(2008, 4, 30)}, + + {YearMonth.of(2009, 1), 32, null}, + {YearMonth.of(2009, 1), 0, null}, + {YearMonth.of(2009, 2), 29, null}, + {YearMonth.of(2009, 2), 30, null}, + {YearMonth.of(2009, 2), 31, null}, + {YearMonth.of(2009, 4), 31, null}, + }; } - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_atDay_int_invalidDay() { - YearMonth test = YearMonth.of(2008, 6); - test.atDay(31); + @Test(dataProvider="atDay") + public void test_atDay(YearMonth test, int day, LocalDate expected) { + if (expected != null) { + assertEquals(test.atDay(day), expected); + } else { + try { + test.atDay(day); + fail(); + } catch (DateTimeException ex) { + // expected + } + } + } + + //----------------------------------------------------------------------- + // atEndOfMonth() + //----------------------------------------------------------------------- + @DataProvider(name="atEndOfMonth") + Object[][] data_atEndOfMonth() { + return new Object[][] { + {YearMonth.of(2008, 1), LocalDate.of(2008, 1, 31)}, + {YearMonth.of(2008, 2), LocalDate.of(2008, 2, 29)}, + {YearMonth.of(2008, 3), LocalDate.of(2008, 3, 31)}, + {YearMonth.of(2008, 4), LocalDate.of(2008, 4, 30)}, + {YearMonth.of(2008, 5), LocalDate.of(2008, 5, 31)}, + {YearMonth.of(2008, 6), LocalDate.of(2008, 6, 30)}, + {YearMonth.of(2008, 12), LocalDate.of(2008, 12, 31)}, + + {YearMonth.of(2009, 1), LocalDate.of(2009, 1, 31)}, + {YearMonth.of(2009, 2), LocalDate.of(2009, 2, 28)}, + {YearMonth.of(2009, 3), LocalDate.of(2009, 3, 31)}, + {YearMonth.of(2009, 4), LocalDate.of(2009, 4, 30)}, + {YearMonth.of(2009, 5), LocalDate.of(2009, 5, 31)}, + {YearMonth.of(2009, 6), LocalDate.of(2009, 6, 30)}, + {YearMonth.of(2009, 12), LocalDate.of(2009, 12, 31)}, + }; + } + + @Test(dataProvider="atEndOfMonth") + public void test_atEndOfMonth(YearMonth test, LocalDate expected) { + assertEquals(test.atEndOfMonth(), expected); } //----------------------------------------------------------------------- @@ -1033,7 +1123,7 @@ public class TCKYearMonth extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_toString_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M"); String t = YearMonth.of(2010, 12).toString(f); assertEquals(t, "2010 12"); } diff --git a/jdk/test/java/time/tck/java/time/TCKZoneId.java b/jdk/test/java/time/tck/java/time/TCKZoneId.java index adc2bb6ee2f..bc6944a8854 100644 --- a/jdk/test/java/time/tck/java/time/TCKZoneId.java +++ b/jdk/test/java/time/tck/java/time/TCKZoneId.java @@ -59,11 +59,30 @@ */ package tck.java.time; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; + +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; import java.io.DataOutputStream; - +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectStreamConstants; +import java.lang.reflect.Field; +import java.time.DateTimeException; +import java.time.LocalTime; import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.temporal.Queries; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalField; +import java.time.temporal.TemporalQuery; +import java.time.zone.ZoneRulesException; +import java.util.HashMap; +import java.util.Map; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** @@ -76,6 +95,7 @@ public class TCKZoneId extends AbstractTCKTest { @Test public void test_serialization() throws Exception { assertSerializable(ZoneId.of("Europe/London")); + assertSerializable(ZoneId.of("America/Chicago")); } @Test @@ -89,4 +109,484 @@ public class TCKZoneId extends AbstractTCKTest { assertSerializedBySer(ZoneId.of("Europe/London"), bytes); } + @Test + public void test_deserialization_lenient_characters() throws Exception { + // an ID can be loaded without validation during deserialization + String id = "QWERTYUIOPASDFGHJKLZXCVBNM~/._+-"; + ZoneId deser = deserialize(id); + // getting the ID and string are OK + assertEquals(deser.getId(), id); + assertEquals(deser.toString(), id); + // getting the rules is not + try { + deser.getRules(); + fail(); + } catch (ZoneRulesException ex) { + // expected + } + } + + @Test(expectedExceptions=DateTimeException.class) + public void test_deserialization_lenient_badCharacters() throws Exception { + // an ID can be loaded without validation during deserialization + // but there is a check to ensure the ID format is valid + deserialize("|!?"); + } + + @Test(dataProvider="offsetBasedValid", expectedExceptions=DateTimeException.class) + public void test_deserialization_lenient_offsetNotAllowed_noPrefix(String input, String resolvedId) throws Exception { + // an ID can be loaded without validation during deserialization + // but there is a check to ensure the ID format is valid + deserialize(input); + } + + @Test(dataProvider="offsetBasedValid", expectedExceptions=DateTimeException.class) + public void test_deserialization_lenient_offsetNotAllowed_prefixUTC(String input, String resolvedId) throws Exception { + // an ID can be loaded without validation during deserialization + // but there is a check to ensure the ID format is valid + deserialize("UTC" + input); + } + + @Test(dataProvider="offsetBasedValid", expectedExceptions=DateTimeException.class) + public void test_deserialization_lenient_offsetNotAllowed_prefixGMT(String input, String resolvedId) throws Exception { + // an ID can be loaded without validation during deserialization + // but there is a check to ensure the ID format is valid + deserialize("GMT" + input); + } + + @Test(dataProvider="offsetBasedValid", expectedExceptions=DateTimeException.class) + public void test_deserialization_lenient_offsetNotAllowed_prefixUT(String input, String resolvedId) throws Exception { + // an ID can be loaded without validation during deserialization + // but there is a check to ensure the ID format is valid + deserialize("UT" + input); + } + + private ZoneId deserialize(String id) throws Exception { + String serClass = ZoneId.class.getPackage().getName() + ".Ser"; + Class serCls = Class.forName(serClass); + Field field = serCls.getDeclaredField("serialVersionUID"); + field.setAccessible(true); + long serVer = (Long) field.get(null); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (DataOutputStream dos = new DataOutputStream(baos)) { + dos.writeShort(ObjectStreamConstants.STREAM_MAGIC); + dos.writeShort(ObjectStreamConstants.STREAM_VERSION); + dos.writeByte(ObjectStreamConstants.TC_OBJECT); + dos.writeByte(ObjectStreamConstants.TC_CLASSDESC); + dos.writeUTF(serClass); + dos.writeLong(serVer); + dos.writeByte(ObjectStreamConstants.SC_EXTERNALIZABLE | ObjectStreamConstants.SC_BLOCK_DATA); + dos.writeShort(0); // number of fields + dos.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA); // end of classdesc + dos.writeByte(ObjectStreamConstants.TC_NULL); // no superclasses + dos.writeByte(ObjectStreamConstants.TC_BLOCKDATA); + dos.writeByte(1 + 2 + id.length()); // length of data (1 byte + 2 bytes UTF length + 32 bytes UTF) + dos.writeByte(7); // ZoneId + dos.writeUTF(id); + dos.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA); // end of blockdata + } + ZoneId deser = null; + try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) { + deser = (ZoneId) ois.readObject(); + } + return deser; + } + + //----------------------------------------------------------------------- + // OLD_IDS_PRE_2005 + //----------------------------------------------------------------------- + public void test_constant_OLD_IDS_PRE_2005() { + Map ids = ZoneId.OLD_IDS_PRE_2005; + assertEquals(ids.get("EST"), "America/New_York"); + assertEquals(ids.get("MST"), "America/Denver"); + assertEquals(ids.get("HST"), "Pacific/Honolulu"); + assertEquals(ids.get("ACT"), "Australia/Darwin"); + assertEquals(ids.get("AET"), "Australia/Sydney"); + assertEquals(ids.get("AGT"), "America/Argentina/Buenos_Aires"); + assertEquals(ids.get("ART"), "Africa/Cairo"); + assertEquals(ids.get("AST"), "America/Anchorage"); + assertEquals(ids.get("BET"), "America/Sao_Paulo"); + assertEquals(ids.get("BST"), "Asia/Dhaka"); + assertEquals(ids.get("CAT"), "Africa/Harare"); + assertEquals(ids.get("CNT"), "America/St_Johns"); + assertEquals(ids.get("CST"), "America/Chicago"); + assertEquals(ids.get("CTT"), "Asia/Shanghai"); + assertEquals(ids.get("EAT"), "Africa/Addis_Ababa"); + assertEquals(ids.get("ECT"), "Europe/Paris"); + assertEquals(ids.get("IET"), "America/Indiana/Indianapolis"); + assertEquals(ids.get("IST"), "Asia/Kolkata"); + assertEquals(ids.get("JST"), "Asia/Tokyo"); + assertEquals(ids.get("MIT"), "Pacific/Apia"); + assertEquals(ids.get("NET"), "Asia/Yerevan"); + assertEquals(ids.get("NST"), "Pacific/Auckland"); + assertEquals(ids.get("PLT"), "Asia/Karachi"); + assertEquals(ids.get("PNT"), "America/Phoenix"); + assertEquals(ids.get("PRT"), "America/Puerto_Rico"); + assertEquals(ids.get("PST"), "America/Los_Angeles"); + assertEquals(ids.get("SST"), "Pacific/Guadalcanal"); + assertEquals(ids.get("VST"), "Asia/Ho_Chi_Minh"); + } + + @Test(expectedExceptions=UnsupportedOperationException.class) + public void test_constant_OLD_IDS_PRE_2005_immutable() { + Map ids = ZoneId.OLD_IDS_PRE_2005; + ids.clear(); + } + + //----------------------------------------------------------------------- + // OLD_IDS_POST_2005 + //----------------------------------------------------------------------- + public void test_constant_OLD_IDS_POST_2005() { + Map ids = ZoneId.OLD_IDS_POST_2005; + assertEquals(ids.get("EST"), "-05:00"); + assertEquals(ids.get("MST"), "-07:00"); + assertEquals(ids.get("HST"), "-10:00"); + assertEquals(ids.get("ACT"), "Australia/Darwin"); + assertEquals(ids.get("AET"), "Australia/Sydney"); + assertEquals(ids.get("AGT"), "America/Argentina/Buenos_Aires"); + assertEquals(ids.get("ART"), "Africa/Cairo"); + assertEquals(ids.get("AST"), "America/Anchorage"); + assertEquals(ids.get("BET"), "America/Sao_Paulo"); + assertEquals(ids.get("BST"), "Asia/Dhaka"); + assertEquals(ids.get("CAT"), "Africa/Harare"); + assertEquals(ids.get("CNT"), "America/St_Johns"); + assertEquals(ids.get("CST"), "America/Chicago"); + assertEquals(ids.get("CTT"), "Asia/Shanghai"); + assertEquals(ids.get("EAT"), "Africa/Addis_Ababa"); + assertEquals(ids.get("ECT"), "Europe/Paris"); + assertEquals(ids.get("IET"), "America/Indiana/Indianapolis"); + assertEquals(ids.get("IST"), "Asia/Kolkata"); + assertEquals(ids.get("JST"), "Asia/Tokyo"); + assertEquals(ids.get("MIT"), "Pacific/Apia"); + assertEquals(ids.get("NET"), "Asia/Yerevan"); + assertEquals(ids.get("NST"), "Pacific/Auckland"); + assertEquals(ids.get("PLT"), "Asia/Karachi"); + assertEquals(ids.get("PNT"), "America/Phoenix"); + assertEquals(ids.get("PRT"), "America/Puerto_Rico"); + assertEquals(ids.get("PST"), "America/Los_Angeles"); + assertEquals(ids.get("SST"), "Pacific/Guadalcanal"); + assertEquals(ids.get("VST"), "Asia/Ho_Chi_Minh"); + } + + @Test(expectedExceptions=UnsupportedOperationException.class) + public void test_constant_OLD_IDS_POST_2005_immutable() { + Map ids = ZoneId.OLD_IDS_POST_2005; + ids.clear(); + } + + //----------------------------------------------------------------------- + // mapped factory + //----------------------------------------------------------------------- + @Test + public void test_of_string_Map() { + Map map = new HashMap<>(); + map.put("LONDON", "Europe/London"); + map.put("PARIS", "Europe/Paris"); + ZoneId test = ZoneId.of("LONDON", map); + assertEquals(test.getId(), "Europe/London"); + } + + @Test + public void test_of_string_Map_lookThrough() { + Map map = new HashMap<>(); + map.put("LONDON", "Europe/London"); + map.put("PARIS", "Europe/Paris"); + ZoneId test = ZoneId.of("Europe/Madrid", map); + assertEquals(test.getId(), "Europe/Madrid"); + } + + @Test + public void test_of_string_Map_emptyMap() { + Map map = new HashMap<>(); + ZoneId test = ZoneId.of("Europe/Madrid", map); + assertEquals(test.getId(), "Europe/Madrid"); + } + + @Test(expectedExceptions=DateTimeException.class) + public void test_of_string_Map_badFormat() { + Map map = new HashMap<>(); + ZoneId.of("Not known", map); + } + + @Test(expectedExceptions=ZoneRulesException.class) + public void test_of_string_Map_unknown() { + Map map = new HashMap<>(); + ZoneId.of("Unknown", map); + } + + //----------------------------------------------------------------------- + // regular factory + //----------------------------------------------------------------------- + @DataProvider(name="offsetBasedZero") + Object[][] data_offsetBasedZero() { + return new Object[][] { + {""}, {"0"}, + {"+00"},{"+0000"},{"+00:00"},{"+000000"},{"+00:00:00"}, + {"-00"},{"-0000"},{"-00:00"},{"-000000"},{"-00:00:00"}, + }; + } + + @Test(dataProvider="offsetBasedZero") + public void factory_of_String_offsetBasedZero_noPrefix(String id) { + if (id.length() > 0 && id.equals("0") == false) { + ZoneId test = ZoneId.of(id); + assertEquals(test, ZoneOffset.UTC); + } + } + + @Test(dataProvider="offsetBasedZero") + public void factory_of_String_offsetBasedZero_prefixUTC(String id) { + ZoneId test = ZoneId.of("UTC" + id); + assertEquals(test, ZoneOffset.UTC); + } + + @Test(dataProvider="offsetBasedZero") + public void factory_of_String_offsetBasedZero_prefixGMT(String id) { + ZoneId test = ZoneId.of("GMT" + id); + assertEquals(test, ZoneOffset.UTC); + } + + @Test(dataProvider="offsetBasedZero") + public void factory_of_String_offsetBasedZero_prefixUT(String id) { + ZoneId test = ZoneId.of("UT" + id); + assertEquals(test, ZoneOffset.UTC); + } + + @Test + public void factory_of_String_offsetBasedZero_z() { + ZoneId test = ZoneId.of("Z"); + assertEquals(test, ZoneOffset.UTC); + } + + //----------------------------------------------------------------------- + @DataProvider(name="offsetBasedValid") + Object[][] data_offsetBasedValid() { + return new Object[][] { + {"+0", "Z"}, + {"+5", "+05:00"}, + {"+01", "+01:00"}, + {"+0100", "+01:00"},{"+01:00", "+01:00"}, + {"+010000", "+01:00"},{"+01:00:00", "+01:00"}, + {"+12", "+12:00"}, + {"+1234", "+12:34"},{"+12:34", "+12:34"}, + {"+123456", "+12:34:56"},{"+12:34:56", "+12:34:56"}, + {"-02", "-02:00"}, + {"-5", "-05:00"}, + {"-0200", "-02:00"},{"-02:00", "-02:00"}, + {"-020000", "-02:00"},{"-02:00:00", "-02:00"}, + }; + } + + @Test(dataProvider="offsetBasedValid") + public void factory_of_String_offsetBasedValid_noPrefix(String input, String id) { + ZoneId test = ZoneId.of(input); + assertEquals(test.getId(), id); + assertEquals(test, ZoneOffset.of(id)); + } + + @Test(dataProvider="offsetBasedValid") + public void factory_of_String_offsetBasedValid_prefixUTC(String input, String id) { + ZoneId test = ZoneId.of("UTC" + input); + assertEquals(test.getId(), id); + assertEquals(test, ZoneOffset.of(id)); + } + + @Test(dataProvider="offsetBasedValid") + public void factory_of_String_offsetBasedValid_prefixGMT(String input, String id) { + ZoneId test = ZoneId.of("GMT" + input); + assertEquals(test.getId(), id); + assertEquals(test, ZoneOffset.of(id)); + } + + @Test(dataProvider="offsetBasedValid") + public void factory_of_String_offsetBasedValid_prefixUT(String input, String id) { + ZoneId test = ZoneId.of("UT" + input); + assertEquals(test.getId(), id); + assertEquals(test, ZoneOffset.of(id)); + } + + //----------------------------------------------------------------------- + @DataProvider(name="offsetBasedInvalid") + Object[][] data_offsetBasedInvalid() { + return new Object[][] { + {"A"}, {"B"}, {"C"}, {"D"}, {"E"}, {"F"}, {"G"}, {"H"}, {"I"}, {"J"}, {"K"}, {"L"}, {"M"}, + {"N"}, {"O"}, {"P"}, {"Q"}, {"R"}, {"S"}, {"T"}, {"U"}, {"V"}, {"W"}, {"X"}, {"Y"}, {"Z"}, + {"+0:00"}, {"+00:0"}, {"+0:0"}, + {"+000"}, {"+00000"}, + {"+0:00:00"}, {"+00:0:00"}, {"+00:00:0"}, {"+0:0:0"}, {"+0:0:00"}, {"+00:0:0"}, {"+0:00:0"}, + {"+01_00"}, {"+01;00"}, {"+01@00"}, {"+01:AA"}, + {"+19"}, {"+19:00"}, {"+18:01"}, {"+18:00:01"}, {"+1801"}, {"+180001"}, + {"-0:00"}, {"-00:0"}, {"-0:0"}, + {"-000"}, {"-00000"}, + {"-0:00:00"}, {"-00:0:00"}, {"-00:00:0"}, {"-0:0:0"}, {"-0:0:00"}, {"-00:0:0"}, {"-0:00:0"}, + {"-19"}, {"-19:00"}, {"-18:01"}, {"-18:00:01"}, {"-1801"}, {"-180001"}, + {"-01_00"}, {"-01;00"}, {"-01@00"}, {"-01:AA"}, + {"@01:00"}, + }; + } + + @Test(dataProvider="offsetBasedInvalid", expectedExceptions=DateTimeException.class) + public void factory_of_String_offsetBasedInvalid_noPrefix(String id) { + if (id.equals("Z")) { + throw new DateTimeException("Fake exception: Z alone is valid, not invalid"); + } + ZoneId.of(id); + } + + @Test(dataProvider="offsetBasedInvalid", expectedExceptions=DateTimeException.class) + public void factory_of_String_offsetBasedInvalid_prefixUTC(String id) { + ZoneId.of("UTC" + id); + } + + @Test(dataProvider="offsetBasedInvalid", expectedExceptions=DateTimeException.class) + public void factory_of_String_offsetBasedInvalid_prefixGMT(String id) { + ZoneId.of("GMT" + id); + } + + @Test(dataProvider="offsetBasedInvalid", expectedExceptions=DateTimeException.class) + public void factory_of_String_offsetBasedInvalid_prefixUT(String id) { + if (id.equals("C")) { + throw new DateTimeException("Fake exception: UT + C = UTC, thus it is valid, not invalid"); + } + ZoneId.of("UT" + id); + } + + //----------------------------------------------------------------------- + @DataProvider(name="regionBasedInvalid") + Object[][] data_regionBasedInvalid() { + // \u00ef is a random unicode character + return new Object[][] { + {""}, {":"}, {"#"}, + {"\u00ef"}, {"`"}, {"!"}, {"\""}, {"\u00ef"}, {"$"}, {"^"}, {"&"}, {"*"}, {"("}, {")"}, {"="}, + {"\\"}, {"|"}, {","}, {"<"}, {">"}, {"?"}, {";"}, {"'"}, {"["}, {"]"}, {"{"}, {"}"}, + {"\u00ef:A"}, {"`:A"}, {"!:A"}, {"\":A"}, {"\u00ef:A"}, {"$:A"}, {"^:A"}, {"&:A"}, {"*:A"}, {"(:A"}, {"):A"}, {"=:A"}, {"+:A"}, + {"\\:A"}, {"|:A"}, {",:A"}, {"<:A"}, {">:A"}, {"?:A"}, {";:A"}, {"::A"}, {"':A"}, {"@:A"}, {"~:A"}, {"[:A"}, {"]:A"}, {"{:A"}, {"}:A"}, + {"A:B#\u00ef"}, {"A:B#`"}, {"A:B#!"}, {"A:B#\""}, {"A:B#\u00ef"}, {"A:B#$"}, {"A:B#^"}, {"A:B#&"}, {"A:B#*"}, + {"A:B#("}, {"A:B#)"}, {"A:B#="}, {"A:B#+"}, + {"A:B#\\"}, {"A:B#|"}, {"A:B#,"}, {"A:B#<"}, {"A:B#>"}, {"A:B#?"}, {"A:B#;"}, {"A:B#:"}, + {"A:B#'"}, {"A:B#@"}, {"A:B#~"}, {"A:B#["}, {"A:B#]"}, {"A:B#{"}, {"A:B#}"}, + }; + } + + @Test(dataProvider="regionBasedInvalid", expectedExceptions=DateTimeException.class) + public void factory_of_String_regionBasedInvalid(String id) { + ZoneId.of(id); + } + + //----------------------------------------------------------------------- + @Test + public void factory_of_String_region_EuropeLondon() { + ZoneId test = ZoneId.of("Europe/London"); + assertEquals(test.getId(), "Europe/London"); + assertEquals(test.getRules().isFixedOffset(), false); + } + + //----------------------------------------------------------------------- + @Test(expectedExceptions=NullPointerException.class) + public void factory_of_String_null() { + ZoneId.of(null); + } + + @Test(expectedExceptions=DateTimeException.class) + public void factory_of_String_badFormat() { + ZoneId.of("Unknown rule"); + } + + @Test(expectedExceptions=ZoneRulesException.class) + public void factory_of_String_unknown() { + ZoneId.of("Unknown"); + } + + //----------------------------------------------------------------------- + // from(TemporalAccessor) + //----------------------------------------------------------------------- + @Test + public void factory_from_TemporalAccessor_zoneId() { + TemporalAccessor mock = new TemporalAccessor() { + @Override + public boolean isSupported(TemporalField field) { + return false; + } + @Override + public long getLong(TemporalField field) { + throw new DateTimeException("Mock"); + } + @SuppressWarnings("unchecked") + @Override + public R query(TemporalQuery query) { + if (query == Queries.zoneId()) { + return (R) ZoneId.of("Europe/Paris"); + } + return TemporalAccessor.super.query(query); + } + }; + assertEquals(ZoneId.from(mock), ZoneId.of("Europe/Paris")); + } + + @Test + public void factory_from_TemporalAccessor_offset() { + ZoneOffset offset = ZoneOffset.ofHours(1); + assertEquals(ZoneId.from(offset), offset); + } + + @Test(expectedExceptions=DateTimeException.class) + public void factory_from_TemporalAccessor_invalid_noDerive() { + ZoneId.from(LocalTime.of(12, 30)); + } + + @Test(expectedExceptions=NullPointerException.class) + public void factory_from_TemporalAccessor_null() { + ZoneId.from(null); + } + + //----------------------------------------------------------------------- + // equals() / hashCode() + //----------------------------------------------------------------------- + @Test + public void test_equals() { + ZoneId test1 = ZoneId.of("Europe/London"); + ZoneId test2 = ZoneId.of("Europe/Paris"); + ZoneId test2b = ZoneId.of("Europe/Paris"); + assertEquals(test1.equals(test2), false); + assertEquals(test2.equals(test1), false); + + assertEquals(test1.equals(test1), true); + assertEquals(test2.equals(test2), true); + assertEquals(test2.equals(test2b), true); + + assertEquals(test1.hashCode() == test1.hashCode(), true); + assertEquals(test2.hashCode() == test2.hashCode(), true); + assertEquals(test2.hashCode() == test2b.hashCode(), true); + } + + @Test + public void test_equals_null() { + assertEquals(ZoneId.of("Europe/London").equals(null), false); + } + + @Test + public void test_equals_notEqualWrongType() { + assertEquals(ZoneId.of("Europe/London").equals("Europe/London"), false); + } + + //----------------------------------------------------------------------- + // toString() + //----------------------------------------------------------------------- + @DataProvider(name="toString") + Object[][] data_toString() { + return new Object[][] { + {"Europe/London", "Europe/London"}, + {"Europe/Paris", "Europe/Paris"}, + {"Europe/Berlin", "Europe/Berlin"}, + {"UTC", "Z"}, + {"UTC+01:00", "+01:00"}, + }; + } + + @Test(dataProvider="toString") + public void test_toString(String id, String expected) { + ZoneId test = ZoneId.of(id); + assertEquals(test.toString(), expected); + } + } diff --git a/jdk/test/java/time/tck/java/time/TCKZoneOffset.java b/jdk/test/java/time/tck/java/time/TCKZoneOffset.java index 4cfd40d9115..c8fb56bf63b 100644 --- a/jdk/test/java/time/tck/java/time/TCKZoneOffset.java +++ b/jdk/test/java/time/tck/java/time/TCKZoneOffset.java @@ -67,10 +67,6 @@ import static org.testng.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import java.time.DateTimeException; import java.time.Duration; import java.time.Instant; @@ -81,11 +77,15 @@ import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.temporal.ChronoField; import java.time.temporal.JulianFields; -import java.time.temporal.OffsetDate; import java.time.temporal.Queries; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; +import java.time.temporal.TemporalQuery; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** @@ -480,7 +480,6 @@ public class TCKZoneOffset extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_factory_CalendricalObject() { - assertEquals(ZoneOffset.from(OffsetDate.of(LocalDate.of(2012, 5, 2), ZoneOffset.ofHours(6))), ZoneOffset.ofHours(6)); assertEquals(ZoneOffset.from(ZonedDateTime.of(LocalDateTime.of(LocalDate.of(2007, 7, 15), LocalTime.of(17, 30)), ZoneOffset.ofHours(2))), ZoneOffset.ofHours(2)); } @@ -560,44 +559,32 @@ public class TCKZoneOffset extends AbstractDateTimeTest { //----------------------------------------------------------------------- // query(TemporalQuery) //----------------------------------------------------------------------- - @Test - public void test_query_chrono() { - ZoneOffset test = ZoneOffset.ofHoursMinutes(1, 30); - assertEquals(test.query(Queries.chrono()), null); - assertEquals(Queries.chrono().queryFrom(test), null); + @DataProvider(name="query") + Object[][] data_query() { + return new Object[][] { + {ZoneOffset.UTC, Queries.chronology(), null}, + {ZoneOffset.UTC, Queries.zoneId(), null}, + {ZoneOffset.UTC, Queries.precision(), null}, + {ZoneOffset.UTC, Queries.zone(), ZoneOffset.UTC}, + {ZoneOffset.UTC, Queries.offset(), ZoneOffset.UTC}, + {ZoneOffset.UTC, Queries.localDate(), null}, + {ZoneOffset.UTC, Queries.localTime(), null}, + }; } - @Test - public void test_query_zoneId() { - ZoneOffset test = ZoneOffset.ofHoursMinutes(1, 30); - assertEquals(test.query(Queries.zoneId()), null); - assertEquals(Queries.zoneId().queryFrom(test), null); + @Test(dataProvider="query") + public void test_query(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(temporal.query(query), expected); } - @Test - public void test_query_precision() { - ZoneOffset test = ZoneOffset.ofHoursMinutes(1, 30); - assertEquals(test.query(Queries.precision()), null); - assertEquals(Queries.precision().queryFrom(test), null); - } - - @Test - public void test_query_offset() { - ZoneOffset test = ZoneOffset.ofHoursMinutes(1, 30); - assertEquals(test.query(Queries.offset()), test); - assertEquals(Queries.offset().queryFrom(test), test); - } - - @Test - public void test_query_zone() { - ZoneOffset test = ZoneOffset.ofHoursMinutes(1, 30); - assertEquals(test.query(Queries.zone()), test); - assertEquals(Queries.zone().queryFrom(test), test); + @Test(dataProvider="query") + public void test_queryFrom(TemporalAccessor temporal, TemporalQuery query, T expected) { + assertEquals(query.queryFrom(temporal), expected); } @Test(expectedExceptions=NullPointerException.class) public void test_query_null() { - ZoneOffset.ofHoursMinutes(1, 30).query(null); + ZoneOffset.UTC.query(null); } //----------------------------------------------------------------------- diff --git a/jdk/test/java/time/tck/java/time/TCKZonedDateTime.java b/jdk/test/java/time/tck/java/time/TCKZonedDateTime.java index df18b4f246f..9841fc8e849 100644 --- a/jdk/test/java/time/tck/java/time/TCKZonedDateTime.java +++ b/jdk/test/java/time/tck/java/time/TCKZonedDateTime.java @@ -60,7 +60,6 @@ package tck.java.time; import java.time.*; -import test.java.time.MockSimplePeriod; import static java.time.Month.JANUARY; import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH; @@ -111,21 +110,21 @@ import java.util.List; import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; import java.time.temporal.Queries; -import java.time.temporal.TemporalSubtractor; -import java.time.temporal.TemporalAdder; +import java.time.temporal.TemporalAmount; +import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalAdjuster; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalQuery; import java.time.temporal.TemporalField; -import java.time.temporal.ISOChrono; +import java.time.chrono.IsoChronology; import java.time.temporal.JulianFields; import test.java.time.temporal.MockFieldNoValue; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatters; +import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; -import java.time.temporal.OffsetDateTime; -import java.time.temporal.Year; +import java.time.OffsetDateTime; +import java.time.Year; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; @@ -272,12 +271,12 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { public void now() { ZonedDateTime expected = ZonedDateTime.now(Clock.systemDefaultZone()); ZonedDateTime test = ZonedDateTime.now(); - long diff = Math.abs(test.getTime().toNanoOfDay() - expected.getTime().toNanoOfDay()); + long diff = Math.abs(test.toLocalTime().toNanoOfDay() - expected.toLocalTime().toNanoOfDay()); if (diff >= 100000000) { // may be date change expected = ZonedDateTime.now(Clock.systemDefaultZone()); test = ZonedDateTime.now(); - diff = Math.abs(test.getTime().toNanoOfDay() - expected.getTime().toNanoOfDay()); + diff = Math.abs(test.toLocalTime().toNanoOfDay() - expected.toLocalTime().toNanoOfDay()); } assertTrue(diff < 100000000); // less than 0.1 secs } @@ -354,7 +353,7 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { assertEquals(test.getMonth(), Month.DECEMBER); assertEquals(test.getDayOfMonth(), 31); expected = expected.minusSeconds(1); - assertEquals(test.getTime(), expected); + assertEquals(test.toLocalTime(), expected); assertEquals(test.getOffset(), ZoneOffset.UTC); assertEquals(test.getZone(), ZoneOffset.UTC); } @@ -391,11 +390,45 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { assertEquals(test.getZone(), zone); } + //----------------------------------------------------------------------- + // of(LocalDate, LocalTime, ZoneId) + //----------------------------------------------------------------------- + @Test(groups={"tck"}) + public void factory_of_LocalDateLocalTime() { + ZonedDateTime test = ZonedDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 10, 500), ZONE_PARIS); + check(test, 2008, 6, 30, 11, 30, 10, 500, OFFSET_0200, ZONE_PARIS); + } + + @Test(groups={"tck"}) + public void factory_of_LocalDateLocalTime_inGap() { + ZonedDateTime test = ZonedDateTime.of(TEST_PARIS_GAP_2008_03_30_02_30.toLocalDate(), TEST_PARIS_GAP_2008_03_30_02_30.toLocalTime(), ZONE_PARIS); + check(test, 2008, 3, 30, 3, 30, 0, 0, OFFSET_0200, ZONE_PARIS); // one hour later in summer offset + } + + @Test(groups={"tck"}) + public void factory_of_LocalDateLocalTime_inOverlap() { + ZonedDateTime test = ZonedDateTime.of(TEST_PARIS_OVERLAP_2008_10_26_02_30.toLocalDate(), TEST_PARIS_OVERLAP_2008_10_26_02_30.toLocalTime(), ZONE_PARIS); + check(test, 2008, 10, 26, 2, 30, 0, 0, OFFSET_0200, ZONE_PARIS); // same time in summer offset + } + + @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + public void factory_of_LocalDateLocalTime_nullDate() { + ZonedDateTime.of((LocalDate) null, LocalTime.of(11, 30, 10, 500), ZONE_PARIS); + } + + @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + public void factory_of_LocalDateLocalTime_nullTime() { + ZonedDateTime.of(LocalDate.of(2008, 6, 30), (LocalTime) null, ZONE_PARIS); + } + + @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + public void factory_of_LocalDateLocalTime_nullZone() { + ZonedDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 10, 500), null); + } + //----------------------------------------------------------------------- // of(LocalDateTime, ZoneId) //----------------------------------------------------------------------- - // TODO: tests of overlap/gap - @Test(groups={"tck"}) public void factory_of_LocalDateTime() { LocalDateTime base = LocalDateTime.of(2008, 6, 30, 11, 30, 10, 500); @@ -403,6 +436,18 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { check(test, 2008, 6, 30, 11, 30, 10, 500, OFFSET_0200, ZONE_PARIS); } + @Test(groups={"tck"}) + public void factory_of_LocalDateTime_inGap() { + ZonedDateTime test = ZonedDateTime.of(TEST_PARIS_GAP_2008_03_30_02_30, ZONE_PARIS); + check(test, 2008, 3, 30, 3, 30, 0, 0, OFFSET_0200, ZONE_PARIS); // one hour later in summer offset + } + + @Test(groups={"tck"}) + public void factory_of_LocalDateTime_inOverlap() { + ZonedDateTime test = ZonedDateTime.of(TEST_PARIS_OVERLAP_2008_10_26_02_30, ZONE_PARIS); + check(test, 2008, 10, 26, 2, 30, 0, 0, OFFSET_0200, ZONE_PARIS); // same time in summer offset + } + @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void factory_of_LocalDateTime_nullDateTime() { ZonedDateTime.of((LocalDateTime) null, ZONE_PARIS); @@ -414,6 +459,15 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { ZonedDateTime.of(base, null); } + //----------------------------------------------------------------------- + // of(int..., ZoneId) + //----------------------------------------------------------------------- + @Test(groups={"tck"}) + public void factory_of_ints() { + ZonedDateTime test = ZonedDateTime.of(2008, 6, 30, 11, 30, 10, 500, ZONE_PARIS); + check(test, 2008, 6, 30, 11, 30, 10, 500, OFFSET_0200, ZONE_PARIS); + } + //----------------------------------------------------------------------- // ofInstant(Instant, ZoneId) //----------------------------------------------------------------------- @@ -662,11 +716,11 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { assertEquals(ZonedDateTime.from(new TemporalAccessor() { @Override public boolean isSupported(TemporalField field) { - return TEST_DATE_TIME_PARIS.getDateTime().isSupported(field); + return TEST_DATE_TIME_PARIS.toLocalDateTime().isSupported(field); } @Override public long getLong(TemporalField field) { - return TEST_DATE_TIME_PARIS.getDateTime().getLong(field); + return TEST_DATE_TIME_PARIS.toLocalDateTime().getLong(field); } @SuppressWarnings("unchecked") @Override @@ -716,7 +770,7 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- // parse() //----------------------------------------------------------------------- - @Test(dataProvider="sampleToString", groups={"tck"}) + @Test(dataProvider="sampleToString") public void test_parse(int y, int month, int d, int h, int m, int s, int n, String zoneId, String text) { ZonedDateTime t = ZonedDateTime.parse(text); assertEquals(t.getYear(), y); @@ -729,6 +783,37 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { assertEquals(t.getZone().getId(), zoneId); } + @DataProvider(name="parseAdditional") + Object[][] data_parseAdditional() { + return new Object[][] { + {"2012-06-30T12:30:40Z[GMT]", 2012, 6, 30, 12, 30, 40, 0, "Z"}, + {"2012-06-30T12:30:40Z[UT]", 2012, 6, 30, 12, 30, 40, 0, "Z"}, + {"2012-06-30T12:30:40Z[UTC]", 2012, 6, 30, 12, 30, 40, 0, "Z"}, + {"2012-06-30T12:30:40+01:00[+01:00]", 2012, 6, 30, 12, 30, 40, 0, "+01:00"}, + {"2012-06-30T12:30:40+01:00[GMT+01:00]", 2012, 6, 30, 12, 30, 40, 0, "+01:00"}, + {"2012-06-30T12:30:40+01:00[UT+01:00]", 2012, 6, 30, 12, 30, 40, 0, "+01:00"}, + {"2012-06-30T12:30:40+01:00[UTC+01:00]", 2012, 6, 30, 12, 30, 40, 0, "+01:00"}, + {"2012-06-30T12:30:40-01:00[-01:00]", 2012, 6, 30, 12, 30, 40, 0, "-01:00"}, + {"2012-06-30T12:30:40-01:00[GMT-01:00]", 2012, 6, 30, 12, 30, 40, 0, "-01:00"}, + {"2012-06-30T12:30:40-01:00[UT-01:00]", 2012, 6, 30, 12, 30, 40, 0, "-01:00"}, + {"2012-06-30T12:30:40-01:00[UTC-01:00]", 2012, 6, 30, 12, 30, 40, 0, "-01:00"}, + {"2012-06-30T12:30:40+01:00[Europe/London]", 2012, 6, 30, 12, 30, 40, 0, "Europe/London"}, + }; + } + + @Test(dataProvider="parseAdditional") + public void test_parseAdditional(String text, int y, int month, int d, int h, int m, int s, int n, String zoneId) { + ZonedDateTime t = ZonedDateTime.parse(text); + assertEquals(t.getYear(), y); + assertEquals(t.getMonth().getValue(), month); + assertEquals(t.getDayOfMonth(), d); + assertEquals(t.getHour(), h); + assertEquals(t.getMinute(), m); + assertEquals(t.getSecond(), s); + assertEquals(t.getNano(), n); + assertEquals(t.getZone().getId(), zoneId); + } + @Test(expectedExceptions=DateTimeParseException.class, groups={"tck"}) public void factory_parse_illegalValue() { ZonedDateTime.parse("2008-06-32T11:15+01:00[Europe/Paris]"); @@ -749,14 +834,14 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void factory_parse_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d H m s I"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M d H m s VV"); ZonedDateTime test = ZonedDateTime.parse("2010 12 3 11 30 0 Europe/London", f); assertEquals(test, ZonedDateTime.of(LocalDateTime.of(2010, 12, 3, 11, 30), ZoneId.of("Europe/London"))); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void factory_parse_formatter_nullText() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d H m s"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M d H m s"); ZonedDateTime.parse((String) null, f); } @@ -799,9 +884,9 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { assertEquals(a.getSecond(), localTime.getSecond()); assertEquals(a.getNano(), localTime.getNano()); - assertEquals(a.getDate(), localDate); - assertEquals(a.getTime(), localTime); - assertEquals(a.getDateTime(), localDateTime); + assertEquals(a.toLocalDate(), localDate); + assertEquals(a.toLocalTime(), localTime); + assertEquals(a.toLocalDateTime(), localDateTime); if (zone instanceof ZoneOffset) { assertEquals(a.toString(), localDateTime.toString() + offset.toString()); } else { @@ -856,8 +941,8 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test public void test_query_chrono() { - assertEquals(TEST_DATE_TIME.query(Queries.chrono()), ISOChrono.INSTANCE); - assertEquals(Queries.chrono().queryFrom(TEST_DATE_TIME), ISOChrono.INSTANCE); + assertEquals(TEST_DATE_TIME.query(Queries.chronology()), IsoChronology.INSTANCE); + assertEquals(Queries.chronology().queryFrom(TEST_DATE_TIME), IsoChronology.INSTANCE); } @Test @@ -904,7 +989,7 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { ZonedDateTime base = ZonedDateTime.ofStrict(TEST_PARIS_OVERLAP_2008_10_26_02_30, OFFSET_0100, ZONE_PARIS); ZonedDateTime test = base.withEarlierOffsetAtOverlap(); assertEquals(test.getOffset(), OFFSET_0200); // offset changed to earlier - assertEquals(test.getDateTime(), base.getDateTime()); // date-time not changed + assertEquals(test.toLocalDateTime(), base.toLocalDateTime()); // date-time not changed } @Test(groups={"tck"}) @@ -929,7 +1014,7 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { ZonedDateTime base = ZonedDateTime.ofStrict(TEST_PARIS_OVERLAP_2008_10_26_02_30, OFFSET_0200, ZONE_PARIS); ZonedDateTime test = base.withLaterOffsetAtOverlap(); assertEquals(test.getOffset(), OFFSET_0100); // offset changed to later - assertEquals(test.getDateTime(), base.getDateTime()); // date-time not changed + assertEquals(test.toLocalDateTime(), base.toLocalDateTime()); // date-time not changed } @Test(groups={"tck"}) @@ -947,10 +1032,10 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { LocalDateTime ldt = LocalDateTime.of(2008, 6, 30, 23, 30, 59, 0); ZonedDateTime base = ZonedDateTime.of(ldt, ZONE_0100); ZonedDateTime test = base.withZoneSameLocal(ZONE_0200); - assertEquals(test.getDateTime(), base.getDateTime()); + assertEquals(test.toLocalDateTime(), base.toLocalDateTime()); } - @Test(groups={"implementation"}) + @Test(groups={"tck","implementation"}) public void test_withZoneSameLocal_noChange() { LocalDateTime ldt = LocalDateTime.of(2008, 6, 30, 23, 30, 59, 0); ZonedDateTime base = ZonedDateTime.of(ldt, ZONE_0100); @@ -1357,25 +1442,25 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { } //----------------------------------------------------------------------- - // plus(adjuster) + // plus(TemporalAmount) //----------------------------------------------------------------------- @Test(groups={"tck"}, dataProvider="plusDays") - public void test_plus_adjuster_Period_days(ZonedDateTime base, long amount, ZonedDateTime expected) { - assertEquals(base.plus(Period.of(amount, DAYS)), expected); + public void test_plus_TemporalAmount_Period_days(ZonedDateTime base, int amount, ZonedDateTime expected) { + assertEquals(base.plus(Period.ofDays(amount)), expected); } @Test(groups={"tck"}, dataProvider="plusTime") - public void test_plus_adjuster_Period_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { - assertEquals(base.plus(Period.of(amount, HOURS)), expected); + public void test_plus_TemporalAmount_Period_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { + assertEquals(base.plus(MockSimplePeriod.of(amount, HOURS)), expected); } @Test(groups={"tck"}, dataProvider="plusTime") - public void test_plus_adjuster_Duration_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { + public void test_plus_TemporalAmount_Duration_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { assertEquals(base.plus(Duration.ofHours(amount)), expected); } @Test(groups={"tck"}) - public void test_plus_adjuster() { + public void test_plus_TemporalAmount() { MockSimplePeriod period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); ZonedDateTime t = ZonedDateTime.of(LocalDateTime.of(2008, 6, 1, 12, 30, 59, 500), ZONE_0100); ZonedDateTime expected = ZonedDateTime.of(LocalDateTime.of(2009, 1, 1, 12, 30, 59, 500), ZONE_0100); @@ -1383,7 +1468,7 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { } @Test(groups={"tck"}) - public void test_plus_adjuster_Duration() { + public void test_plus_TemporalAmount_Duration() { Duration duration = Duration.ofSeconds(4L * 60 * 60 + 5L * 60 + 6L); ZonedDateTime t = ZonedDateTime.of(LocalDateTime.of(2008, 6, 1, 12, 30, 59, 500), ZONE_0100); ZonedDateTime expected = ZonedDateTime.of(LocalDateTime.of(2008, 6, 1, 16, 36, 5, 500), ZONE_0100); @@ -1391,20 +1476,20 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { } @Test(groups={"tck"}) - public void test_plus_adjuster_Period_zero() { + public void test_plus_TemporalAmount_Period_zero() { ZonedDateTime t = TEST_DATE_TIME.plus(MockSimplePeriod.ZERO_DAYS); assertEquals(t, TEST_DATE_TIME); } @Test(groups={"tck"}) - public void test_plus_adjuster_Duration_zero() { + public void test_plus_TemporalAmount_Duration_zero() { ZonedDateTime t = TEST_DATE_TIME.plus(Duration.ZERO); assertEquals(t, TEST_DATE_TIME); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_plus_adjuster_null() { - TEST_DATE_TIME.plus((TemporalAdder) null); + public void test_plus_TemporalAmount_null() { + TEST_DATE_TIME.plus((TemporalAmount) null); } //----------------------------------------------------------------------- @@ -1562,25 +1647,25 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { } //----------------------------------------------------------------------- - // minus(adjuster) + // minus(TemporalAmount) //----------------------------------------------------------------------- @Test(groups={"tck"}, dataProvider="plusDays") - public void test_minus_adjuster_Period_days(ZonedDateTime base, long amount, ZonedDateTime expected) { - assertEquals(base.minus(Period.of(-amount, DAYS)), expected); + public void test_minus_TemporalAmount_Period_days(ZonedDateTime base, int amount, ZonedDateTime expected) { + assertEquals(base.minus(Period.ofDays(-amount)), expected); } @Test(groups={"tck"}, dataProvider="plusTime") - public void test_minus_adjuster_Period_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { - assertEquals(base.minus(Period.of(-amount, HOURS)), expected); + public void test_minus_TemporalAmount_Period_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { + assertEquals(base.minus(MockSimplePeriod.of(-amount, HOURS)), expected); } @Test(groups={"tck"}, dataProvider="plusTime") - public void test_minus_adjuster_Duration_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { + public void test_minus_TemporalAmount_Duration_hours(ZonedDateTime base, long amount, ZonedDateTime expected) { assertEquals(base.minus(Duration.ofHours(-amount)), expected); } @Test(groups={"tck"}) - public void test_minus_adjuster() { + public void test_minus_TemporalAmount() { MockSimplePeriod period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); ZonedDateTime t = ZonedDateTime.of(LocalDateTime.of(2008, 6, 1, 12, 30, 59, 500), ZONE_0100); ZonedDateTime expected = ZonedDateTime.of(LocalDateTime.of(2007, 11, 1, 12, 30, 59, 500), ZONE_0100); @@ -1588,7 +1673,7 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { } @Test(groups={"tck"}) - public void test_minus_adjuster_Duration() { + public void test_minus_TemporalAmount_Duration() { Duration duration = Duration.ofSeconds(4L * 60 * 60 + 5L * 60 + 6L); ZonedDateTime t = ZonedDateTime.of(LocalDateTime.of(2008, 6, 1, 12, 30, 59, 500), ZONE_0100); ZonedDateTime expected = ZonedDateTime.of(LocalDateTime.of(2008, 6, 1, 8, 25, 53, 500), ZONE_0100); @@ -1596,20 +1681,20 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { } @Test(groups={"tck"}) - public void test_minus_adjuster_Period_zero() { + public void test_minus_TemporalAmount_Period_zero() { ZonedDateTime t = TEST_DATE_TIME.minus(MockSimplePeriod.ZERO_DAYS); assertEquals(t, TEST_DATE_TIME); } @Test(groups={"tck"}) - public void test_minus_adjuster_Duration_zero() { + public void test_minus_TemporalAmount_Duration_zero() { ZonedDateTime t = TEST_DATE_TIME.minus(Duration.ZERO); assertEquals(t, TEST_DATE_TIME); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_minus_adjuster_null() { - TEST_DATE_TIME.minus((TemporalSubtractor) null); + public void test_minus_TemporalAmount_null() { + TEST_DATE_TIME.minus((TemporalAmount) null); } //----------------------------------------------------------------------- @@ -1818,7 +1903,7 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_toOffsetDateTime() { - assertEquals(TEST_DATE_TIME.toOffsetDateTime(), OffsetDateTime.of(TEST_DATE_TIME.getDateTime(), TEST_DATE_TIME.getOffset())); + assertEquals(TEST_DATE_TIME.toOffsetDateTime(), OffsetDateTime.of(TEST_DATE_TIME.toLocalDateTime(), TEST_DATE_TIME.getOffset())); } //----------------------------------------------------------------------- @@ -1908,8 +1993,8 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_compareTo_time1() { - ZonedDateTime a = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30, 39), ZONE_0100); - ZonedDateTime b = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30, 41), ZONE_0100); // a is before b due to time + ZonedDateTime a = ZonedDateTime.of(2008, 6, 30, 11, 30, 39, 0, ZONE_0100); + ZonedDateTime b = ZonedDateTime.of(2008, 6, 30, 11, 30, 41, 0, ZONE_0100); // a is before b due to time assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1918,8 +2003,8 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_time2() { - ZonedDateTime a = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30, 40, 4), ZONE_0100); - ZonedDateTime b = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30, 40, 5), ZONE_0100); // a is before b due to time + ZonedDateTime a = ZonedDateTime.of(2008, 6, 30, 11, 30, 40, 4, ZONE_0100); + ZonedDateTime b = ZonedDateTime.of(2008, 6, 30, 11, 30, 40, 5, ZONE_0100); // a is before b due to time assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1928,8 +2013,8 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_offset1() { - ZonedDateTime a = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30, 41), ZONE_0200); - ZonedDateTime b = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30, 39), ZONE_0100); // a is before b due to offset + ZonedDateTime a = ZonedDateTime.of(2008, 6, 30, 11, 30, 41, 0, ZONE_0200); + ZonedDateTime b = ZonedDateTime.of(2008, 6, 30, 11, 30, 39, 0, ZONE_0100); // a is before b due to offset assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1938,8 +2023,8 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_offset2() { - ZonedDateTime a = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30, 40, 5), ZoneId.of("UTC+01:01")); - ZonedDateTime b = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30, 40, 4), ZONE_0100); // a is before b due to offset + ZonedDateTime a = ZonedDateTime.of(2008, 6, 30, 11, 30, 40, 5, ZoneId.of("UTC+01:01")); + ZonedDateTime b = ZonedDateTime.of(2008, 6, 30, 11, 30, 40, 4, ZONE_0100); // a is before b due to offset assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1948,8 +2033,8 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_both() { - ZonedDateTime a = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 50), ZONE_0200); - ZonedDateTime b = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 20), ZONE_0100); // a is before b on instant scale + ZonedDateTime a = ZonedDateTime.of(2008, 6, 30, 11, 50, 0, 0, ZONE_0200); + ZonedDateTime b = ZonedDateTime.of(2008, 6, 30, 11, 20, 0, 0, ZONE_0100); // a is before b on instant scale assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1958,8 +2043,8 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_bothNanos() { - ZonedDateTime a = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 20, 40, 5), ZONE_0200); - ZonedDateTime b = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 10, 20, 40, 6), ZONE_0100); // a is before b on instant scale + ZonedDateTime a = ZonedDateTime.of(2008, 6, 30, 11, 20, 40, 5, ZONE_0200); + ZonedDateTime b = ZonedDateTime.of(2008, 6, 30, 10, 20, 40, 6, ZONE_0100); // a is before b on instant scale assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1968,8 +2053,8 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { @Test(groups={"tck"}) public void test_compareTo_hourDifference() { - ZonedDateTime a = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 10, 0), ZONE_0100); - ZonedDateTime b = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 0), ZONE_0200); // a is before b despite being same time-line time + ZonedDateTime a = ZonedDateTime.of(2008, 6, 30, 10, 0, 0, 0, ZONE_0100); + ZonedDateTime b = ZonedDateTime.of(2008, 6, 30, 11, 0, 0, 0, ZONE_0200); // a is before b despite being same time-line time assertEquals(a.compareTo(b) < 0, true); assertEquals(b.compareTo(a) > 0, true); assertEquals(a.compareTo(a) == 0, true); @@ -1978,8 +2063,7 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_compareTo_null() { - LocalDateTime ldt = LocalDateTime.of(2008, 6, 30, 23, 30, 59, 0); - ZonedDateTime a = ZonedDateTime.of(ldt, ZONE_0100); + ZonedDateTime a = ZonedDateTime.of(2008, 6, 30, 23, 30, 59, 0, ZONE_0100); a.compareTo(null); } @@ -1997,8 +2081,8 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { @Test(dataProvider="IsBefore", groups={"tck"}) public void test_isBefore(int hour1, int minute1, ZoneId zone1, int hour2, int minute2, ZoneId zone2, boolean expected) { - ZonedDateTime a = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, hour1, minute1), zone1); - ZonedDateTime b = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, hour2, minute2), zone2); + ZonedDateTime a = ZonedDateTime.of(2008, 6, 30, hour1, minute1, 0, 0, zone1); + ZonedDateTime b = ZonedDateTime.of(2008, 6, 30, hour2, minute2, 0, 0, zone2); assertEquals(a.isBefore(b), expected); assertEquals(b.isBefore(a), false); assertEquals(a.isBefore(a), false); @@ -2007,8 +2091,7 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_isBefore_null() { - LocalDateTime ldt = LocalDateTime.of(2008, 6, 30, 23, 30, 59, 0); - ZonedDateTime a = ZonedDateTime.of(ldt, ZONE_0100); + ZonedDateTime a = ZonedDateTime.of(2008, 6, 30, 23, 30, 59, 0, ZONE_0100); a.isBefore(null); } @@ -2026,8 +2109,8 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { @Test(dataProvider="IsAfter", groups={"tck"}) public void test_isAfter(int hour1, int minute1, ZoneId zone1, int hour2, int minute2, ZoneId zone2, boolean expected) { - ZonedDateTime a = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, hour1, minute1), zone1); - ZonedDateTime b = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, hour2, minute2), zone2); + ZonedDateTime a = ZonedDateTime.of(2008, 6, 30, hour1, minute1, 0, 0, zone1); + ZonedDateTime b = ZonedDateTime.of(2008, 6, 30, hour2, minute2, 0, 0, zone2); assertEquals(a.isAfter(b), expected); assertEquals(b.isAfter(a), false); assertEquals(a.isAfter(a), false); @@ -2036,8 +2119,7 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_isAfter_null() { - LocalDateTime ldt = LocalDateTime.of(2008, 6, 30, 23, 30, 59, 0); - ZonedDateTime a = ZonedDateTime.of(ldt, ZONE_0100); + ZonedDateTime a = ZonedDateTime.of(2008, 6, 30, 23, 30, 59, 0, ZONE_0100); a.isAfter(null); } @@ -2134,7 +2216,7 @@ public class TCKZonedDateTime extends AbstractDateTimeTest { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_toString_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d H m s"); + DateTimeFormatter f = DateTimeFormatter.ofPattern("y M d H m s"); String t = ZonedDateTime.of(dateTime(2010, 12, 3, 11, 30), ZONE_PARIS).toString(f); assertEquals(t, "2010 12 3 11 30 0"); } diff --git a/jdk/test/java/time/tck/java/time/temporal/TestChrono.java b/jdk/test/java/time/tck/java/time/TestChronology.java similarity index 76% rename from jdk/test/java/time/tck/java/time/temporal/TestChrono.java rename to jdk/test/java/time/tck/java/time/TestChronology.java index cd30519dd04..b186cd315eb 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TestChrono.java +++ b/jdk/test/java/time/tck/java/time/TestChronology.java @@ -57,7 +57,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.temporal; +package tck.java.time; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; @@ -71,36 +71,23 @@ import java.io.ObjectOutputStream; import java.util.Locale; import java.util.Set; -import java.time.temporal.Chrono; +import java.time.chrono.Chronology; import java.time.temporal.ChronoField; -import java.time.calendar.HijrahChrono; -import java.time.calendar.JapaneseChrono; -import java.time.calendar.MinguoChrono; -import java.time.calendar.ThaiBuddhistChrono; -import java.time.temporal.ChronoLocalDate; -import java.time.temporal.ISOChrono; +import java.time.chrono.HijrahChronology; +import java.time.chrono.JapaneseChronology; +import java.time.chrono.MinguoChronology; +import java.time.chrono.ThaiBuddhistChronology; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.IsoChronology; -import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** - * Test Chrono class. + * Test Chronology class. */ @Test -public class TestChrono { - - @BeforeMethod(groups="tck") - public void setUp() { - // Ensure each of the classes are initialized (until initialization is fixed) - Chrono c; - c = HijrahChrono.INSTANCE; - c = ISOChrono.INSTANCE; - c = JapaneseChrono.INSTANCE; - c = MinguoChrono.INSTANCE; - c = ThaiBuddhistChrono.INSTANCE; - c.toString(); // avoids variable being marked as unused - } +public class TestChronology { //----------------------------------------------------------------------- // regular data factory for names and descriptions of available calendars @@ -118,7 +105,7 @@ public class TestChrono { @Test(dataProvider = "calendars") public void test_getters(String chronoId, String calendarSystemType, String description) { - Chrono chrono = Chrono.of(chronoId); + Chronology chrono = Chronology.of(chronoId); assertNotNull(chrono, "Required calendar not found by ID: " + chronoId); assertEquals(chrono.getId(), chronoId); assertEquals(chrono.getCalendarType(), calendarSystemType); @@ -126,23 +113,23 @@ public class TestChrono { @Test(dataProvider = "calendars") public void test_required_calendars(String chronoId, String calendarSystemType, String description) { - Chrono chrono = Chrono.of(chronoId); + Chronology chrono = Chronology.of(chronoId); assertNotNull(chrono, "Required calendar not found by ID: " + chronoId); - chrono = Chrono.of(calendarSystemType); + chrono = Chronology.of(calendarSystemType); assertNotNull(chrono, "Required calendar not found by type: " + chronoId); - Set> cals = Chrono.getAvailableChronologies(); + Set cals = Chronology.getAvailableChronologies(); assertTrue(cals.contains(chrono), "Required calendar not found in set of available calendars"); } @Test(groups="tck") public void test_calendar_list() { - Set> chronos = Chrono.getAvailableChronologies(); + Set chronos = Chronology.getAvailableChronologies(); assertNotNull(chronos, "Required list of calendars must be non-null"); - for (Chrono chrono : chronos) { - Chrono lookup = Chrono.of(chrono.getId()); + for (Chronology chrono : chronos) { + Chronology lookup = Chronology.of(chrono.getId()); assertNotNull(lookup, "Required calendar not found: " + chrono); } - assertEquals(chronos.size() >= data_of_calendars().length, true, "Chrono.getAvailableChronologies().size = " + chronos.size() + assertEquals(chronos.size() >= data_of_calendars().length, true, "Chronology.getAvailableChronologies().size = " + chronos.size() + ", expected >= " + data_of_calendars().length); } @@ -151,7 +138,7 @@ public class TestChrono { */ @Test(dataProvider = "calendars", groups="tck") public void test_epoch(String name, String alias, String description) { - Chrono chrono = Chrono.of(name); // a chronology. In practice this is rarely hardcoded + Chronology chrono = Chronology.of(name); // a chronology. In practice this is rarely hardcoded ChronoLocalDate date1 = chrono.dateNow(); long epoch1 = date1.getLong(ChronoField.EPOCH_DAY); ChronoLocalDate date2 = date1.with(ChronoField.EPOCH_DAY, epoch1); @@ -166,41 +153,40 @@ public class TestChrono { @DataProvider(name = "calendarsystemtype") Object[][] data_CalendarType() { return new Object[][] { - {HijrahChrono.INSTANCE, "islamicc"}, - {ISOChrono.INSTANCE, "iso8601"}, - {JapaneseChrono.INSTANCE, "japanese"}, - {MinguoChrono.INSTANCE, "roc"}, - {ThaiBuddhistChrono.INSTANCE, "buddhist"}, + {HijrahChronology.INSTANCE, "islamicc"}, + {IsoChronology.INSTANCE, "iso8601"}, + {JapaneseChronology.INSTANCE, "japanese"}, + {MinguoChronology.INSTANCE, "roc"}, + {ThaiBuddhistChronology.INSTANCE, "buddhist"}, }; } @Test(dataProvider = "calendarsystemtype", groups="tck") - public void test_getCalendarType(Chrono chrono, String calendarType) { + public void test_getCalendarType(Chronology chrono, String calendarType) { assertEquals(chrono.getCalendarType(), calendarType); } @Test(dataProvider = "calendarsystemtype", groups="tck") - public void test_lookupLocale(Chrono chrono, String calendarType) { + public void test_lookupLocale(Chronology chrono, String calendarType) { Locale locale = new Locale.Builder().setLanguage("en").setRegion("CA").setUnicodeLocaleKeyword("ca", calendarType).build(); - assertEquals(Chrono.ofLocale(locale), chrono); + assertEquals(Chronology.ofLocale(locale), chrono); } //----------------------------------------------------------------------- // serialization; serialize and check each calendar system //----------------------------------------------------------------------- - @Test(groups={"implementation"}, dataProvider = "calendarsystemtype") - public > void test_chronoSerializationSingleton(C chrono, String calendarType) throws Exception { - C orginal = chrono; + @Test(groups={"tck","implementation"}, dataProvider = "calendarsystemtype") + public void test_chronoSerializationSingleton(Chronology chrono, String calendarType) throws Exception { + Chronology orginal = chrono; ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject(orginal); out.close(); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream in = new ObjectInputStream(bais); - @SuppressWarnings("unchecked") - C ser = (C) in.readObject(); - assertSame(ser, chrono, "Deserialized Chrono is not the singleton serialized"); + Chronology ser = (Chronology) in.readObject(); + assertSame(ser, chrono, "Deserialized Chronology is not the singleton serialized"); } } diff --git a/jdk/test/java/time/tck/java/time/temporal/TestISOChrono.java b/jdk/test/java/time/tck/java/time/TestIsoChronology.java similarity index 70% rename from jdk/test/java/time/tck/java/time/temporal/TestISOChrono.java rename to jdk/test/java/time/tck/java/time/TestIsoChronology.java index 634fab301e5..aa42e4a0ca0 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TestISOChrono.java +++ b/jdk/test/java/time/tck/java/time/TestIsoChronology.java @@ -57,13 +57,13 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.temporal; +package tck.java.time; +import static java.time.chrono.IsoChronology.ERA_BCE; +import static java.time.chrono.IsoChronology.ERA_CE; import static java.time.temporal.ChronoField.ERA; import static java.time.temporal.ChronoField.YEAR; import static java.time.temporal.ChronoField.YEAR_OF_ERA; -import static java.time.temporal.ISOChrono.ERA_BCE; -import static java.time.temporal.ISOChrono.ERA_CE; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; @@ -73,13 +73,13 @@ import java.time.DateTimeException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.Month; -import java.time.temporal.Chrono; -import java.time.temporal.ChronoField; -import java.time.temporal.ChronoLocalDate; import java.time.temporal.Adjusters; -import java.time.calendar.HijrahChrono; -import java.time.temporal.Era; -import java.time.temporal.ISOChrono; +import java.time.temporal.ChronoField; +import java.time.chrono.HijrahChronology; +import java.time.chrono.Chronology; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.Era; +import java.time.chrono.IsoChronology; import org.testng.Assert; import org.testng.annotations.DataProvider; @@ -89,15 +89,15 @@ import org.testng.annotations.Test; * Test. */ @Test -public class TestISOChrono { +public class TestIsoChronology { //----------------------------------------------------------------------- - // Chrono.ofName("ISO") Lookup by name + // Chronology.ofName("ISO") Lookup by name //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_chrono_byName() { - Chrono c = ISOChrono.INSTANCE; - Chrono test = Chrono.of("ISO"); + Chronology c = IsoChronology.INSTANCE; + Chronology test = Chronology.of("ISO"); Assert.assertNotNull(test, "The ISO calendar could not be found byName"); Assert.assertEquals(test.getId(), "ISO", "ID mismatch"); Assert.assertEquals(test.getCalendarType(), "iso8601", "Type mismatch"); @@ -109,7 +109,7 @@ public class TestISOChrono { //----------------------------------------------------------------------- @Test(groups="tck") public void instanceNotNull() { - assertNotNull(ISOChrono.INSTANCE); + assertNotNull(IsoChronology.INSTANCE); } //----------------------------------------------------------------------- @@ -117,8 +117,8 @@ public class TestISOChrono { //----------------------------------------------------------------------- @Test(groups="tck") public void test_eraOf() { - assertEquals(ISOChrono.INSTANCE.eraOf(0), ERA_BCE); - assertEquals(ISOChrono.INSTANCE.eraOf(1), ERA_CE); + assertEquals(IsoChronology.INSTANCE.eraOf(0), ERA_BCE); + assertEquals(IsoChronology.INSTANCE.eraOf(1), ERA_CE); } //----------------------------------------------------------------------- @@ -127,31 +127,31 @@ public class TestISOChrono { @DataProvider(name="samples") Object[][] data_samples() { return new Object[][] { - {ISOChrono.INSTANCE.date(1, 7, 8), LocalDate.of(1, 7, 8)}, - {ISOChrono.INSTANCE.date(1, 7, 20), LocalDate.of(1, 7, 20)}, - {ISOChrono.INSTANCE.date(1, 7, 21), LocalDate.of(1, 7, 21)}, + {IsoChronology.INSTANCE.date(1, 7, 8), LocalDate.of(1, 7, 8)}, + {IsoChronology.INSTANCE.date(1, 7, 20), LocalDate.of(1, 7, 20)}, + {IsoChronology.INSTANCE.date(1, 7, 21), LocalDate.of(1, 7, 21)}, - {ISOChrono.INSTANCE.date(2, 7, 8), LocalDate.of(2, 7, 8)}, - {ISOChrono.INSTANCE.date(3, 6, 27), LocalDate.of(3, 6, 27)}, - {ISOChrono.INSTANCE.date(3, 5, 23), LocalDate.of(3, 5, 23)}, - {ISOChrono.INSTANCE.date(4, 6, 16), LocalDate.of(4, 6, 16)}, - {ISOChrono.INSTANCE.date(4, 7, 3), LocalDate.of(4, 7, 3)}, - {ISOChrono.INSTANCE.date(4, 7, 4), LocalDate.of(4, 7, 4)}, - {ISOChrono.INSTANCE.date(5, 1, 1), LocalDate.of(5, 1, 1)}, - {ISOChrono.INSTANCE.date(1727, 3, 3), LocalDate.of(1727, 3, 3)}, - {ISOChrono.INSTANCE.date(1728, 10, 28), LocalDate.of(1728, 10, 28)}, - {ISOChrono.INSTANCE.date(2012, 10, 29), LocalDate.of(2012, 10, 29)}, + {IsoChronology.INSTANCE.date(2, 7, 8), LocalDate.of(2, 7, 8)}, + {IsoChronology.INSTANCE.date(3, 6, 27), LocalDate.of(3, 6, 27)}, + {IsoChronology.INSTANCE.date(3, 5, 23), LocalDate.of(3, 5, 23)}, + {IsoChronology.INSTANCE.date(4, 6, 16), LocalDate.of(4, 6, 16)}, + {IsoChronology.INSTANCE.date(4, 7, 3), LocalDate.of(4, 7, 3)}, + {IsoChronology.INSTANCE.date(4, 7, 4), LocalDate.of(4, 7, 4)}, + {IsoChronology.INSTANCE.date(5, 1, 1), LocalDate.of(5, 1, 1)}, + {IsoChronology.INSTANCE.date(1727, 3, 3), LocalDate.of(1727, 3, 3)}, + {IsoChronology.INSTANCE.date(1728, 10, 28), LocalDate.of(1728, 10, 28)}, + {IsoChronology.INSTANCE.date(2012, 10, 29), LocalDate.of(2012, 10, 29)}, }; } @Test(dataProvider="samples", groups={"tck"}) - public void test_toLocalDate(ChronoLocalDate isoDate, LocalDate iso) { + public void test_toLocalDate(LocalDate isoDate, LocalDate iso) { assertEquals(LocalDate.from(isoDate), iso); } @Test(dataProvider="samples", groups={"tck"}) - public void test_fromCalendrical(ChronoLocalDate isoDate, LocalDate iso) { - assertEquals(ISOChrono.INSTANCE.date(iso), isoDate); + public void test_fromCalendrical(LocalDate isoDate, LocalDate iso) { + assertEquals(IsoChronology.INSTANCE.date(iso), isoDate); } @DataProvider(name="badDates") @@ -176,7 +176,7 @@ public class TestISOChrono { @Test(dataProvider="badDates", groups={"tck"}, expectedExceptions=DateTimeException.class) public void test_badDates(int year, int month, int dom) { - ISOChrono.INSTANCE.date(year, month, dom); + IsoChronology.INSTANCE.date(year, month, dom); } @Test(groups="tck") @@ -184,7 +184,7 @@ public class TestISOChrono { int year = 5; int month = 5; int dayOfMonth = 5; - ChronoLocalDate test = ISOChrono.INSTANCE.date(ERA_BCE, year, month, dayOfMonth); + LocalDate test = IsoChronology.INSTANCE.date(ERA_BCE, year, month, dayOfMonth); assertEquals(test.getEra(), ERA_BCE); assertEquals(test.get(ChronoField.YEAR_OF_ERA), year); assertEquals(test.get(ChronoField.MONTH_OF_YEAR), month); @@ -198,7 +198,7 @@ public class TestISOChrono { @SuppressWarnings({ "unchecked", "rawtypes" }) @Test(expectedExceptions=DateTimeException.class, groups="tck") public void test_date_withEra_withWrongEra() { - ISOChrono.INSTANCE.date((Era) HijrahChrono.ERA_AH, 1, 1, 1); + IsoChronology.INSTANCE.date((Era) HijrahChronology.ERA_AH, 1, 1, 1); } //----------------------------------------------------------------------- @@ -206,16 +206,16 @@ public class TestISOChrono { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_adjust1() { - ChronoLocalDate base = ISOChrono.INSTANCE.date(1728, 10, 28); - ChronoLocalDate test = base.with(Adjusters.lastDayOfMonth()); - assertEquals(test, ISOChrono.INSTANCE.date(1728, 10, 31)); + LocalDate base = IsoChronology.INSTANCE.date(1728, 10, 28); + LocalDate test = base.with(Adjusters.lastDayOfMonth()); + assertEquals(test, IsoChronology.INSTANCE.date(1728, 10, 31)); } @Test(groups={"tck"}) public void test_adjust2() { - ChronoLocalDate base = ISOChrono.INSTANCE.date(1728, 12, 2); - ChronoLocalDate test = base.with(Adjusters.lastDayOfMonth()); - assertEquals(test, ISOChrono.INSTANCE.date(1728, 12, 31)); + LocalDate base = IsoChronology.INSTANCE.date(1728, 12, 2); + LocalDate test = base.with(Adjusters.lastDayOfMonth()); + assertEquals(test, IsoChronology.INSTANCE.date(1728, 12, 31)); } //----------------------------------------------------------------------- @@ -223,15 +223,15 @@ public class TestISOChrono { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_adjust_toLocalDate() { - ChronoLocalDate isoDate = ISOChrono.INSTANCE.date(1726, 1, 4); - ChronoLocalDate test = isoDate.with(LocalDate.of(2012, 7, 6)); - assertEquals(test, ISOChrono.INSTANCE.date(2012, 7, 6)); + LocalDate isoDate = IsoChronology.INSTANCE.date(1726, 1, 4); + LocalDate test = isoDate.with(LocalDate.of(2012, 7, 6)); + assertEquals(test, IsoChronology.INSTANCE.date(2012, 7, 6)); } @Test(groups={"tck"}) public void test_adjust_toMonth() { - ChronoLocalDate isoDate = ISOChrono.INSTANCE.date(1726, 1, 4); - assertEquals(ISOChrono.INSTANCE.date(1726, 4, 4), isoDate.with(Month.APRIL)); + LocalDate isoDate = IsoChronology.INSTANCE.date(1726, 1, 4); + assertEquals(IsoChronology.INSTANCE.date(1726, 4, 4), isoDate.with(Month.APRIL)); } //----------------------------------------------------------------------- @@ -239,14 +239,14 @@ public class TestISOChrono { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_LocalDate_adjustToISODate() { - ChronoLocalDate isoDate = ISOChrono.INSTANCE.date(1728, 10, 29); + LocalDate isoDate = IsoChronology.INSTANCE.date(1728, 10, 29); LocalDate test = LocalDate.MIN.with(isoDate); assertEquals(test, LocalDate.of(1728, 10, 29)); } @Test(groups={"tck"}) public void test_LocalDateTime_adjustToISODate() { - ChronoLocalDate isoDate = ISOChrono.INSTANCE.date(1728, 10, 29); + LocalDate isoDate = IsoChronology.INSTANCE.date(1728, 10, 29); LocalDateTime test = LocalDateTime.MIN.with(isoDate); assertEquals(test, LocalDateTime.of(1728, 10, 29, 0, 0)); } @@ -268,7 +268,7 @@ public class TestISOChrono { @Test(dataProvider="leapYears", groups="tck") public void test_isLeapYear(int year, boolean isLeapYear) { - assertEquals(ISOChrono.INSTANCE.isLeapYear(year), isLeapYear); + assertEquals(IsoChronology.INSTANCE.isLeapYear(year), isLeapYear); } //----------------------------------------------------------------------- @@ -276,7 +276,7 @@ public class TestISOChrono { //----------------------------------------------------------------------- @Test(groups="tck") public void test_now() { - assertEquals(LocalDate.from(ISOChrono.INSTANCE.dateNow()), LocalDate.now()); + assertEquals(LocalDate.from(IsoChronology.INSTANCE.dateNow()), LocalDate.now()); } //----------------------------------------------------------------------- @@ -285,16 +285,16 @@ public class TestISOChrono { @DataProvider(name="toString") Object[][] data_toString() { return new Object[][] { - {ISOChrono.INSTANCE.date(1, 1, 1), "0001-01-01"}, - {ISOChrono.INSTANCE.date(1728, 10, 28), "1728-10-28"}, - {ISOChrono.INSTANCE.date(1728, 10, 29), "1728-10-29"}, - {ISOChrono.INSTANCE.date(1727, 12, 5), "1727-12-05"}, - {ISOChrono.INSTANCE.date(1727, 12, 6), "1727-12-06"}, + {IsoChronology.INSTANCE.date(1, 1, 1), "0001-01-01"}, + {IsoChronology.INSTANCE.date(1728, 10, 28), "1728-10-28"}, + {IsoChronology.INSTANCE.date(1728, 10, 29), "1728-10-29"}, + {IsoChronology.INSTANCE.date(1727, 12, 5), "1727-12-05"}, + {IsoChronology.INSTANCE.date(1727, 12, 6), "1727-12-06"}, }; } @Test(dataProvider="toString", groups={"tck"}) - public void test_toString(ChronoLocalDate isoDate, String expected) { + public void test_toString(LocalDate isoDate, String expected) { assertEquals(isoDate.toString(), expected); } @@ -303,12 +303,12 @@ public class TestISOChrono { //----------------------------------------------------------------------- @Test(groups="tck") public void test_equals_true() { - assertTrue(ISOChrono.INSTANCE.equals(ISOChrono.INSTANCE)); + assertTrue(IsoChronology.INSTANCE.equals(IsoChronology.INSTANCE)); } @Test(groups="tck") public void test_equals_false() { - assertFalse(ISOChrono.INSTANCE.equals(HijrahChrono.INSTANCE)); + assertFalse(IsoChronology.INSTANCE.equals(HijrahChronology.INSTANCE)); } } diff --git a/jdk/test/java/time/tck/java/time/calendar/TestJapaneseChrono.java b/jdk/test/java/time/tck/java/time/calendar/TestJapaneseChrono.java deleted file mode 100644 index 614a3ff0b0a..00000000000 --- a/jdk/test/java/time/tck/java/time/calendar/TestJapaneseChrono.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (c) 2012, 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 - * 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. - */ - -/* - * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of JSR-310 nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package tck.java.time.calendar; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -import java.util.List; - -import java.time.DateTimeException; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.Month; -import java.time.calendar.JapaneseChrono; -import java.time.temporal.Adjusters; -import java.time.temporal.Chrono; -import java.time.temporal.ChronoLocalDate; -import java.time.temporal.Era; -import java.time.temporal.ISOChrono; - -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -/** - * Test. - */ -@Test -public class TestJapaneseChrono { - - //----------------------------------------------------------------------- - // Chrono.ofName("Japanese") Lookup by name - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_chrono_byName() { - Chrono c = JapaneseChrono.INSTANCE; - Chrono test = Chrono.of("Japanese"); - Assert.assertNotNull(test, "The Japanese calendar could not be found byName"); - Assert.assertEquals(test.getId(), "Japanese", "ID mismatch"); - Assert.assertEquals(test.getCalendarType(), "japanese", "Type mismatch"); - Assert.assertEquals(test, c); - } - - //----------------------------------------------------------------------- - // creation, toLocalDate() - //----------------------------------------------------------------------- - @DataProvider(name="samples") - Object[][] data_samples() { - return new Object[][] { - {JapaneseChrono.INSTANCE.date(1, 1, 1), LocalDate.of(1, 1, 1)}, - {JapaneseChrono.INSTANCE.date(1, 1, 2), LocalDate.of(1, 1, 2)}, - {JapaneseChrono.INSTANCE.date(1, 1, 3), LocalDate.of(1, 1, 3)}, - - {JapaneseChrono.INSTANCE.date(2, 1, 1), LocalDate.of(2, 1, 1)}, - {JapaneseChrono.INSTANCE.date(3, 1, 1), LocalDate.of(3, 1, 1)}, - {JapaneseChrono.INSTANCE.date(3, 12, 6), LocalDate.of(3, 12, 6)}, - {JapaneseChrono.INSTANCE.date(4, 1, 1), LocalDate.of(4, 1, 1)}, - {JapaneseChrono.INSTANCE.date(4, 7, 3), LocalDate.of(4, 7, 3)}, - {JapaneseChrono.INSTANCE.date(4, 7, 4), LocalDate.of(4, 7, 4)}, - {JapaneseChrono.INSTANCE.date(5, 1, 1), LocalDate.of(5, 1, 1)}, - {JapaneseChrono.INSTANCE.date(1662, 3, 3), LocalDate.of(1662, 3, 3)}, - {JapaneseChrono.INSTANCE.date(1728, 10, 28), LocalDate.of(1728, 10, 28)}, - {JapaneseChrono.INSTANCE.date(1728, 10, 29), LocalDate.of(1728, 10, 29)}, - }; - } - - @Test(dataProvider="samples", groups={"tck"}) - public void test_toLocalDate(ChronoLocalDate jdate, LocalDate iso) { - assertEquals(LocalDate.from(jdate), iso); - } - - @Test(dataProvider="samples", groups={"tck"}) - public void test_fromCalendrical(ChronoLocalDate jdate, LocalDate iso) { - assertEquals(JapaneseChrono.INSTANCE.date(iso), jdate); - } - - @DataProvider(name="badDates") - Object[][] data_badDates() { - return new Object[][] { - {1728, 0, 0}, - - {1728, -1, 1}, - {1728, 0, 1}, - {1728, 14, 1}, - {1728, 15, 1}, - - {1728, 1, -1}, - {1728, 1, 0}, - {1728, 1, 32}, - - {1728, 12, -1}, - {1728, 12, 0}, - {1728, 12, 32}, - }; - } - - @Test(dataProvider="badDates", groups={"tck"}, expectedExceptions=DateTimeException.class) - public void test_badDates(int year, int month, int dom) { - JapaneseChrono.INSTANCE.date(year, month, dom); - } - - //----------------------------------------------------------------------- - // with(WithAdjuster) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_adjust1() { - ChronoLocalDate base = JapaneseChrono.INSTANCE.date(1728, 10, 29); - ChronoLocalDate test = base.with(Adjusters.lastDayOfMonth()); - assertEquals(test, JapaneseChrono.INSTANCE.date(1728, 10, 31)); - } - - @Test(groups={"tck"}) - public void test_adjust2() { - ChronoLocalDate base = JapaneseChrono.INSTANCE.date(1728, 12, 2); - ChronoLocalDate test = base.with(Adjusters.lastDayOfMonth()); - assertEquals(test, JapaneseChrono.INSTANCE.date(1728, 12, 31)); - } - - //----------------------------------------------------------------------- - // JapaneseDate.with(Local*) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_adjust_toLocalDate() { - ChronoLocalDate jdate = JapaneseChrono.INSTANCE.date(1726, 1, 4); - ChronoLocalDate test = jdate.with(LocalDate.of(2012, 7, 6)); - assertEquals(test, JapaneseChrono.INSTANCE.date(2012, 7, 6)); - } - - @Test(groups={"tck"}, expectedExceptions=DateTimeException.class) - public void test_adjust_toMonth() { - ChronoLocalDate jdate = JapaneseChrono.INSTANCE.date(1726, 1, 4); - jdate.with(Month.APRIL); - } - - //----------------------------------------------------------------------- - // LocalDate.with(JapaneseDate) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_LocalDate_adjustToJapaneseDate() { - ChronoLocalDate jdate = JapaneseChrono.INSTANCE.date(1728, 10, 29); - LocalDate test = LocalDate.MIN.with(jdate); - assertEquals(test, LocalDate.of(1728, 10, 29)); - } - - @Test(groups={"tck"}) - public void test_LocalDateTime_adjustToJapaneseDate() { - ChronoLocalDate jdate = JapaneseChrono.INSTANCE.date(1728, 10, 29); - LocalDateTime test = LocalDateTime.MIN.with(jdate); - assertEquals(test, LocalDateTime.of(1728, 10, 29, 0, 0)); - } - - //----------------------------------------------------------------------- - // Check Japanese Eras - //----------------------------------------------------------------------- - @DataProvider(name="japaneseEras") - Object[][] data_japanseseEras() { - return new Object[][] { - { JapaneseChrono.ERA_SEIREKI, -999, "Seireki"}, - { JapaneseChrono.ERA_MEIJI, -1, "Meiji"}, - { JapaneseChrono.ERA_TAISHO, 0, "Taisho"}, - { JapaneseChrono.ERA_SHOWA, 1, "Showa"}, - { JapaneseChrono.ERA_HEISEI, 2, "Heisei"}, - }; - } - - @Test(groups={"tck"}, dataProvider="japaneseEras") - public void test_Japanese_Eras(Era era, int eraValue, String name) { - assertEquals(era.getValue(), eraValue, "EraValue"); - assertEquals(era.toString(), name, "Era Name"); - assertEquals(era, JapaneseChrono.INSTANCE.eraOf(eraValue), "JapaneseChrono.eraOf()"); - List> eras = JapaneseChrono.INSTANCE.eras(); - assertTrue(eras.contains(era), "Era is not present in JapaneseChrono.INSTANCE.eras()"); - } - - @Test(groups="tck") - public void test_Japanese_badEras() { - int badEras[] = {-1000, -998, -997, -2, 3, 4, 1000}; - for (int badEra : badEras) { - try { - Era era = JapaneseChrono.INSTANCE.eraOf(badEra); - fail("JapaneseChrono.eraOf returned " + era + " + for invalid eraValue " + badEra); - } catch (DateTimeException ex) { - // ignore expected exception - } - } - } - - //----------------------------------------------------------------------- - // toString() - //----------------------------------------------------------------------- - @DataProvider(name="toString") - Object[][] data_toString() { - return new Object[][] { - {JapaneseChrono.INSTANCE.date(0001, 1, 1), "Japanese 0001-01-01"}, - {JapaneseChrono.INSTANCE.date(1728, 10, 28), "Japanese 1728-10-28"}, - {JapaneseChrono.INSTANCE.date(1728, 10, 29), "Japanese 1728-10-29"}, - {JapaneseChrono.INSTANCE.date(1727, 12, 5), "Japanese 1727-12-05"}, - {JapaneseChrono.INSTANCE.date(1727, 12, 6), "Japanese 1727-12-06"}, - {JapaneseChrono.INSTANCE.date(1868, 9, 8), "Japanese Meiji 1-09-08"}, - {JapaneseChrono.INSTANCE.date(1912, 7, 29), "Japanese Meiji 45-07-29"}, - {JapaneseChrono.INSTANCE.date(1912, 7, 30), "Japanese Taisho 1-07-30"}, - {JapaneseChrono.INSTANCE.date(1926, 12, 24), "Japanese Taisho 15-12-24"}, - {JapaneseChrono.INSTANCE.date(1926, 12, 25), "Japanese Showa 1-12-25"}, - {JapaneseChrono.INSTANCE.date(1989, 1, 7), "Japanese Showa 64-01-07"}, - {JapaneseChrono.INSTANCE.date(1989, 1, 8), "Japanese Heisei 1-01-08"}, - {JapaneseChrono.INSTANCE.date(2012, 12, 6), "Japanese Heisei 24-12-06"}, - }; - } - - @Test(dataProvider="toString", groups={"tck"}) - public void test_toString(ChronoLocalDate jdate, String expected) { - assertEquals(jdate.toString(), expected); - } - - //----------------------------------------------------------------------- - // equals() - //----------------------------------------------------------------------- - @Test(groups="tck") - public void test_equals_true() { - assertTrue(JapaneseChrono.INSTANCE.equals(JapaneseChrono.INSTANCE)); - } - - @Test(groups="tck") - public void test_equals_false() { - assertFalse(JapaneseChrono.INSTANCE.equals(ISOChrono.INSTANCE)); - } - -} diff --git a/jdk/test/java/time/tck/java/time/calendar/TestThaiBuddhistChrono.java b/jdk/test/java/time/tck/java/time/calendar/TestThaiBuddhistChrono.java deleted file mode 100644 index 4d20f570be8..00000000000 --- a/jdk/test/java/time/tck/java/time/calendar/TestThaiBuddhistChrono.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (c) 2012, 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 - * 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. - */ - -/* - * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of JSR-310 nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package tck.java.time.calendar; - -import static java.time.temporal.ChronoField.DAY_OF_MONTH; -import static java.time.temporal.ChronoField.DAY_OF_YEAR; -import static java.time.temporal.ChronoField.MONTH_OF_YEAR; -import static java.time.temporal.ChronoField.YEAR; -import static java.time.temporal.ChronoField.YEAR_OF_ERA; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; - -import java.time.DateTimeException; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.Month; -import java.time.calendar.ThaiBuddhistChrono; -import java.time.temporal.Chrono; -import java.time.temporal.ChronoField; -import java.time.temporal.ChronoLocalDate; -import java.time.temporal.Adjusters; -import java.time.temporal.ValueRange; -import java.time.temporal.ISOChrono; - -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -/** - * Test. - */ -@Test -public class TestThaiBuddhistChrono { - - private static final int YDIFF = 543; - - //----------------------------------------------------------------------- - // Chrono.ofName("ThaiBuddhist") Lookup by name - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_chrono_byName() { - Chrono c = ThaiBuddhistChrono.INSTANCE; - Chrono test = Chrono.of("ThaiBuddhist"); - Assert.assertNotNull(test, "The ThaiBuddhist calendar could not be found byName"); - Assert.assertEquals(test.getId(), "ThaiBuddhist", "ID mismatch"); - Assert.assertEquals(test.getCalendarType(), "buddhist", "Type mismatch"); - Assert.assertEquals(test, c); - } - - //----------------------------------------------------------------------- - // creation, toLocalDate() - //----------------------------------------------------------------------- - @DataProvider(name="samples") - Object[][] data_samples() { - return new Object[][] { - {ThaiBuddhistChrono.INSTANCE.date(1 + YDIFF, 1, 1), LocalDate.of(1, 1, 1)}, - {ThaiBuddhistChrono.INSTANCE.date(1 + YDIFF, 1, 2), LocalDate.of(1, 1, 2)}, - {ThaiBuddhistChrono.INSTANCE.date(1 + YDIFF, 1, 3), LocalDate.of(1, 1, 3)}, - - {ThaiBuddhistChrono.INSTANCE.date(2 + YDIFF, 1, 1), LocalDate.of(2, 1, 1)}, - {ThaiBuddhistChrono.INSTANCE.date(3 + YDIFF, 1, 1), LocalDate.of(3, 1, 1)}, - {ThaiBuddhistChrono.INSTANCE.date(3 + YDIFF, 12, 6), LocalDate.of(3, 12, 6)}, - {ThaiBuddhistChrono.INSTANCE.date(4 + YDIFF, 1, 1), LocalDate.of(4, 1, 1)}, - {ThaiBuddhistChrono.INSTANCE.date(4 + YDIFF, 7, 3), LocalDate.of(4, 7, 3)}, - {ThaiBuddhistChrono.INSTANCE.date(4 + YDIFF, 7, 4), LocalDate.of(4, 7, 4)}, - {ThaiBuddhistChrono.INSTANCE.date(5 + YDIFF, 1, 1), LocalDate.of(5, 1, 1)}, - {ThaiBuddhistChrono.INSTANCE.date(1662 + YDIFF, 3, 3), LocalDate.of(1662, 3, 3)}, - {ThaiBuddhistChrono.INSTANCE.date(1728 + YDIFF, 10, 28), LocalDate.of(1728, 10, 28)}, - {ThaiBuddhistChrono.INSTANCE.date(1728 + YDIFF, 10, 29), LocalDate.of(1728, 10, 29)}, - {ThaiBuddhistChrono.INSTANCE.date(2555, 8, 29), LocalDate.of(2012, 8, 29)}, - }; - } - - @Test(dataProvider="samples", groups={"tck"}) - public void test_toLocalDate(ChronoLocalDate jdate, LocalDate iso) { - assertEquals(LocalDate.from(jdate), iso); - } - - @Test(dataProvider="samples", groups={"tck"}) - public void test_fromCalendrical(ChronoLocalDate jdate, LocalDate iso) { - assertEquals(ThaiBuddhistChrono.INSTANCE.date(iso), jdate); - } - - @DataProvider(name="badDates") - Object[][] data_badDates() { - return new Object[][] { - {1728, 0, 0}, - - {1728, -1, 1}, - {1728, 0, 1}, - {1728, 14, 1}, - {1728, 15, 1}, - - {1728, 1, -1}, - {1728, 1, 0}, - {1728, 1, 32}, - - {1728, 12, -1}, - {1728, 12, 0}, - {1728, 12, 32}, - }; - } - - @Test(dataProvider="badDates", groups={"tck"}, expectedExceptions=DateTimeException.class) - public void test_badDates(int year, int month, int dom) { - ThaiBuddhistChrono.INSTANCE.date(year, month, dom); - } - - //----------------------------------------------------------------------- - // with(WithAdjuster) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_adjust1() { - ChronoLocalDate base = ThaiBuddhistChrono.INSTANCE.date(1728, 10, 29); - ChronoLocalDate test = base.with(Adjusters.lastDayOfMonth()); - assertEquals(test, ThaiBuddhistChrono.INSTANCE.date(1728, 10, 31)); - } - - @Test(groups={"tck"}) - public void test_adjust2() { - ChronoLocalDate base = ThaiBuddhistChrono.INSTANCE.date(1728, 12, 2); - ChronoLocalDate test = base.with(Adjusters.lastDayOfMonth()); - assertEquals(test, ThaiBuddhistChrono.INSTANCE.date(1728, 12, 31)); - } - - //----------------------------------------------------------------------- - // withYear() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_withYear_BE() { - ChronoLocalDate base = ThaiBuddhistChrono.INSTANCE.date(2555, 8, 29); - ChronoLocalDate test = base.with(YEAR, 2554); - assertEquals(test, ThaiBuddhistChrono.INSTANCE.date(2554, 8, 29)); - } - - @Test(groups={"tck"}) - public void test_withYear_BBE() { - ChronoLocalDate base = ThaiBuddhistChrono.INSTANCE.date(-2554, 8, 29); - ChronoLocalDate test = base.with(YEAR_OF_ERA, 2554); - assertEquals(test, ThaiBuddhistChrono.INSTANCE.date(-2553, 8, 29)); - } - - //----------------------------------------------------------------------- - // withEra() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_withEra_BE() { - ChronoLocalDate base = ThaiBuddhistChrono.INSTANCE.date(2555, 8, 29); - ChronoLocalDate test = base.with(ChronoField.ERA, ThaiBuddhistChrono.ERA_BE.getValue()); - assertEquals(test, ThaiBuddhistChrono.INSTANCE.date(2555, 8, 29)); - } - - @Test(groups={"tck"}) - public void test_withEra_BBE() { - ChronoLocalDate base = ThaiBuddhistChrono.INSTANCE.date(-2554, 8, 29); - ChronoLocalDate test = base.with(ChronoField.ERA, ThaiBuddhistChrono.ERA_BEFORE_BE.getValue()); - assertEquals(test, ThaiBuddhistChrono.INSTANCE.date(-2554, 8, 29)); - } - - @Test(groups={"tck"}) - public void test_withEra_swap() { - ChronoLocalDate base = ThaiBuddhistChrono.INSTANCE.date(-2554, 8, 29); - ChronoLocalDate test = base.with(ChronoField.ERA, ThaiBuddhistChrono.ERA_BE.getValue()); - assertEquals(test, ThaiBuddhistChrono.INSTANCE.date(2555, 8, 29)); - } - - //----------------------------------------------------------------------- - // BuddhistDate.with(Local*) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_adjust_toLocalDate() { - ChronoLocalDate jdate = ThaiBuddhistChrono.INSTANCE.date(1726, 1, 4); - ChronoLocalDate test = jdate.with(LocalDate.of(2012, 7, 6)); - assertEquals(test, ThaiBuddhistChrono.INSTANCE.date(2555, 7, 6)); - } - - @Test(groups={"tck"}, expectedExceptions=DateTimeException.class) - public void test_adjust_toMonth() { - ChronoLocalDate jdate = ThaiBuddhistChrono.INSTANCE.date(1726, 1, 4); - jdate.with(Month.APRIL); - } - - //----------------------------------------------------------------------- - // LocalDate.with(BuddhistDate) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_LocalDate_adjustToBuddhistDate() { - ChronoLocalDate jdate = ThaiBuddhistChrono.INSTANCE.date(2555, 10, 29); - LocalDate test = LocalDate.MIN.with(jdate); - assertEquals(test, LocalDate.of(2012, 10, 29)); - } - - @Test(groups={"tck"}) - public void test_LocalDateTime_adjustToBuddhistDate() { - ChronoLocalDate jdate = ThaiBuddhistChrono.INSTANCE.date(2555, 10, 29); - LocalDateTime test = LocalDateTime.MIN.with(jdate); - assertEquals(test, LocalDateTime.of(2012, 10, 29, 0, 0)); - } - - //----------------------------------------------------------------------- - // toString() - //----------------------------------------------------------------------- - @DataProvider(name="toString") - Object[][] data_toString() { - return new Object[][] { - {ThaiBuddhistChrono.INSTANCE.date(544, 1, 1), "ThaiBuddhist BE 544-01-01"}, - {ThaiBuddhistChrono.INSTANCE.date(2271, 10, 28), "ThaiBuddhist BE 2271-10-28"}, - {ThaiBuddhistChrono.INSTANCE.date(2271, 10, 29), "ThaiBuddhist BE 2271-10-29"}, - {ThaiBuddhistChrono.INSTANCE.date(2270, 12, 5), "ThaiBuddhist BE 2270-12-05"}, - {ThaiBuddhistChrono.INSTANCE.date(2270, 12, 6), "ThaiBuddhist BE 2270-12-06"}, - }; - } - - @Test(dataProvider="toString", groups={"tck"}) - public void test_toString(ChronoLocalDate jdate, String expected) { - assertEquals(jdate.toString(), expected); - } - - //----------------------------------------------------------------------- - // chronology range(ChronoField) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_Chrono_range() { - long minYear = LocalDate.MIN.getYear() + YDIFF; - long maxYear = LocalDate.MAX.getYear() + YDIFF; - assertEquals(ThaiBuddhistChrono.INSTANCE.range(YEAR), ValueRange.of(minYear, maxYear)); - assertEquals(ThaiBuddhistChrono.INSTANCE.range(YEAR_OF_ERA), ValueRange.of(1, -minYear + 1, maxYear)); - - assertEquals(ThaiBuddhistChrono.INSTANCE.range(DAY_OF_MONTH), DAY_OF_MONTH.range()); - assertEquals(ThaiBuddhistChrono.INSTANCE.range(DAY_OF_YEAR), DAY_OF_YEAR.range()); - assertEquals(ThaiBuddhistChrono.INSTANCE.range(MONTH_OF_YEAR), MONTH_OF_YEAR.range()); - } - - //----------------------------------------------------------------------- - // equals() - //----------------------------------------------------------------------- - @Test(groups="tck") - public void test_equals_true() { - assertTrue(ThaiBuddhistChrono.INSTANCE.equals(ThaiBuddhistChrono.INSTANCE)); - } - - @Test(groups="tck") - public void test_equals_false() { - assertFalse(ThaiBuddhistChrono.INSTANCE.equals(ISOChrono.INSTANCE)); - } - -} diff --git a/jdk/test/java/time/tck/java/time/calendar/CopticChrono.java b/jdk/test/java/time/tck/java/time/chrono/CopticChronology.java similarity index 87% rename from jdk/test/java/time/tck/java/time/calendar/CopticChrono.java rename to jdk/test/java/time/tck/java/time/chrono/CopticChronology.java index c3dc941e491..5c55d7593cc 100644 --- a/jdk/test/java/time/tck/java/time/calendar/CopticChrono.java +++ b/jdk/test/java/time/tck/java/time/chrono/CopticChronology.java @@ -54,7 +54,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.calendar; +package tck.java.time.chrono; import static java.time.temporal.ChronoField.EPOCH_DAY; @@ -67,9 +67,9 @@ import java.time.DateTimeException; import java.time.temporal.ChronoField; import java.time.temporal.TemporalAccessor; import java.time.temporal.ValueRange; -import java.time.temporal.Chrono; -import java.time.temporal.ChronoLocalDate; -import java.time.temporal.Era; +import java.time.chrono.Chronology; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.Era; /** * The Coptic calendar system. @@ -96,22 +96,22 @@ import java.time.temporal.Era; *

    Implementation notes

    * This class is immutable and thread-safe. */ -public final class CopticChrono extends Chrono implements Serializable { +public final class CopticChronology extends Chronology implements Serializable { /** * Singleton instance of the Coptic chronology. */ - public static final CopticChrono INSTANCE = new CopticChrono(); + public static final CopticChronology INSTANCE = new CopticChronology(); /** * The singleton instance for the era BEFORE_AM. * This has the numeric value of {@code 0}. */ - public static final Era ERA_BEFORE_AM = CopticEra.BEFORE_AM; + public static final Era ERA_BEFORE_AM = CopticEra.BEFORE_AM; /** * The singleton instance for the era AM - 'Era of the Martyrs'. * This has the numeric value of {@code 1}. */ - public static final Era ERA_AM = CopticEra.AM; + public static final Era ERA_AM = CopticEra.AM; /** * Serialization version. @@ -137,7 +137,7 @@ public final class CopticChrono extends Chrono implements Serializ /** * Public Constructor to be instantiated by the ServiceLoader */ - public CopticChrono() { + public CopticChronology() { } /** @@ -153,8 +153,8 @@ public final class CopticChrono extends Chrono implements Serializ /** * Gets the ID of the chronology - 'Coptic'. *

    - * The ID uniquely identifies the {@code Chrono}. - * It can be used to lookup the {@code Chrono} using {@link #of(String)}. + * The ID uniquely identifies the {@code Chronology}. + * It can be used to lookup the {@code Chronology} using {@link #of(String)}. * * @return the chronology ID - 'Coptic' * @see #getCalendarType() @@ -169,7 +169,7 @@ public final class CopticChrono extends Chrono implements Serializ *

    * The calendar type is an identifier defined by the * Unicode Locale Data Markup Language (LDML) specification. - * It can be used to lookup the {@code Chrono} using {@link #of(String)}. + * It can be used to lookup the {@code Chronology} using {@link #of(String)}. * It can also be used as part of a locale, accessible via * {@link Locale#getUnicodeLocaleType(String)} with the key 'ca'. * @@ -183,17 +183,17 @@ public final class CopticChrono extends Chrono implements Serializ //----------------------------------------------------------------------- @Override - public ChronoLocalDate date(int prolepticYear, int month, int dayOfMonth) { + public CopticDate date(int prolepticYear, int month, int dayOfMonth) { return new CopticDate(prolepticYear, month, dayOfMonth); } @Override - public ChronoLocalDate dateYearDay(int prolepticYear, int dayOfYear) { + public CopticDate dateYearDay(int prolepticYear, int dayOfYear) { return new CopticDate(prolepticYear, (dayOfYear - 1) / 30 + 1, (dayOfYear - 1) % 30 + 1); } @Override - public ChronoLocalDate date(TemporalAccessor dateTime) { + public CopticDate date(TemporalAccessor dateTime) { if (dateTime instanceof CopticDate) { return (CopticDate) dateTime; } @@ -217,7 +217,7 @@ public final class CopticChrono extends Chrono implements Serializ } @Override - public int prolepticYear(Era era, int yearOfEra) { + public int prolepticYear(Era era, int yearOfEra) { if (era instanceof CopticEra == false) { throw new DateTimeException("Era must be CopticEra"); } @@ -225,13 +225,13 @@ public final class CopticChrono extends Chrono implements Serializ } @Override - public Era eraOf(int eraValue) { + public Era eraOf(int eraValue) { return CopticEra.of(eraValue); } @Override - public List> eras() { - return Arrays.>asList(CopticEra.values()); + public List eras() { + return Arrays.asList(CopticEra.values()); } //----------------------------------------------------------------------- diff --git a/jdk/test/java/time/tck/java/time/calendar/CopticDate.java b/jdk/test/java/time/tck/java/time/chrono/CopticDate.java similarity index 87% rename from jdk/test/java/time/tck/java/time/calendar/CopticDate.java rename to jdk/test/java/time/tck/java/time/chrono/CopticDate.java index 30f1664dd0e..d8447eb660f 100644 --- a/jdk/test/java/time/tck/java/time/calendar/CopticDate.java +++ b/jdk/test/java/time/tck/java/time/chrono/CopticDate.java @@ -53,7 +53,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.calendar; +package tck.java.time.chrono; import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH; import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR; @@ -67,29 +67,26 @@ import java.io.Serializable; import java.time.DateTimeException; import java.time.LocalDate; +import java.time.Period; +import java.time.chrono.ChronoLocalDate; import java.time.temporal.ChronoField; -import java.time.temporal.ChronoLocalDate; import java.time.temporal.ChronoUnit; -import java.time.temporal.Era; import java.time.temporal.Temporal; -import java.time.temporal.TemporalAdjuster; -import java.time.temporal.TemporalAdder; -import java.time.temporal.TemporalSubtractor; import java.time.temporal.TemporalField; import java.time.temporal.TemporalUnit; import java.time.temporal.ValueRange; -import java.time.temporal.Year; +import java.time.Year; /** * A date in the Coptic calendar system. *

    - * This implements {@code ChronoLocalDate} for the {@link CopticChrono Coptic calendar}. + * This implements {@code ChronoLocalDate} for the {@link CopticChronology Coptic calendar}. * *

    Implementation notes

    * This class is immutable and thread-safe. */ -final class CopticDate - implements ChronoLocalDate, Serializable { +public final class CopticDate + implements ChronoLocalDate, Serializable { /** * Serialization version. @@ -133,7 +130,7 @@ final class CopticDate private static CopticDate resolvePreviousValid(int prolepticYear, int month, int day) { if (month == 13 && day > 5) { - day = CopticChrono.INSTANCE.isLeapYear(prolepticYear) ? 6 : 5; + day = CopticChronology.INSTANCE.isLeapYear(prolepticYear) ? 6 : 5; } return new CopticDate(prolepticYear, month, day); } @@ -148,12 +145,12 @@ final class CopticDate * @throws DateTimeException if the date is invalid */ CopticDate(int prolepticYear, int month, int dayOfMonth) { - CopticChrono.MOY_RANGE.checkValidValue(month, MONTH_OF_YEAR); + CopticChronology.MOY_RANGE.checkValidValue(month, MONTH_OF_YEAR); ValueRange range; if (month == 13) { - range = CopticChrono.INSTANCE.isLeapYear(prolepticYear) ? CopticChrono.DOM_RANGE_LEAP : CopticChrono.DOM_RANGE_NONLEAP; + range = CopticChronology.INSTANCE.isLeapYear(prolepticYear) ? CopticChronology.DOM_RANGE_LEAP : CopticChronology.DOM_RANGE_NONLEAP; } else { - range = CopticChrono.DOM_RANGE; + range = CopticChronology.DOM_RANGE; } range.checkValidValue(dayOfMonth, DAY_OF_MONTH); @@ -174,8 +171,8 @@ final class CopticDate //----------------------------------------------------------------------- @Override - public CopticChrono getChrono() { - return CopticChrono.INSTANCE; + public CopticChronology getChronology() { + return CopticChronology.INSTANCE; } //----------------------------------------------------------------------- @@ -202,11 +199,11 @@ final class CopticDate case YEAR_OF_ERA: return (prolepticYear <= 0 ? ValueRange.of(1, Year.MAX_VALUE + 1) : ValueRange.of(1, Year.MAX_VALUE)); // TODO } - return getChrono().range(f); + return getChronology().range(f); } throw new DateTimeException("Unsupported field: " + field.getName()); } - return field.doRange(this); + return field.rangeRefinedBy(this); } @Override @@ -228,7 +225,7 @@ final class CopticDate } throw new DateTimeException("Unsupported field: " + field.getName()); } - return field.doGet(this); + return field.getFrom(this); } @Override @@ -253,7 +250,7 @@ final class CopticDate } throw new DateTimeException("Unsupported field: " + field.getName()); } - return field.doWith(this, newValue); + return field.adjustInto(this, newValue); } //----------------------------------------------------------------------- @@ -272,7 +269,7 @@ final class CopticDate } throw new DateTimeException(unit.getName() + " not valid for CopticDate"); } - return unit.doPlus(this, amountToAdd); + return unit.addTo(this, amountToAdd); } //----------------------------------------------------------------------- @@ -304,13 +301,32 @@ final class CopticDate throw new DateTimeException("Unable to calculate period between objects of two different types"); } ChronoLocalDate end = (ChronoLocalDate) endDateTime; - if (getChrono().equals(end.getChrono()) == false) { + if (getChronology().equals(end.getChronology()) == false) { throw new DateTimeException("Unable to calculate period between two different chronologies"); } if (unit instanceof ChronoUnit) { return LocalDate.from(this).periodUntil(end, unit); // TODO: this is wrong } - return unit.between(this, endDateTime).getAmount(); + return unit.between(this, endDateTime); + } + + @Override + public Period periodUntil(ChronoLocalDate endDate) { + // TODO: untested + CopticDate end = (CopticDate) getChronology().date(endDate); + long totalMonths = (end.prolepticYear - this.prolepticYear) * 13 + (end.month - this.month); // safe + int days = end.day - this.day; + if (totalMonths > 0 && days < 0) { + totalMonths--; + CopticDate calcDate = this.plusMonths(totalMonths); + days = (int) (end.toEpochDay() - calcDate.toEpochDay()); // safe + } else if (totalMonths < 0 && days > 0) { + totalMonths++; + days -= end.lengthOfMonth(); + } + long years = totalMonths / 13; // safe + int months = (int) (totalMonths % 13); // safe + return Period.of(Math.toIntExact(years), months, days); } //----------------------------------------------------------------------- @@ -328,7 +344,7 @@ final class CopticDate long moy = getLong(MONTH_OF_YEAR); long dom = getLong(DAY_OF_MONTH); StringBuilder buf = new StringBuilder(30); - buf.append(getChrono().toString()) + buf.append(getChronology().toString()) .append(" ") .append(getEra()) .append(" ") diff --git a/jdk/test/java/time/tck/java/time/calendar/CopticEra.java b/jdk/test/java/time/tck/java/time/chrono/CopticEra.java similarity index 63% rename from jdk/test/java/time/tck/java/time/calendar/CopticEra.java rename to jdk/test/java/time/tck/java/time/chrono/CopticEra.java index 2526530ed3b..cfe4bdc9b34 100644 --- a/jdk/test/java/time/tck/java/time/calendar/CopticEra.java +++ b/jdk/test/java/time/tck/java/time/chrono/CopticEra.java @@ -53,23 +53,11 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.calendar; +package tck.java.time.chrono; -import static java.time.temporal.ChronoField.ERA; - -import java.util.Locale; import java.time.DateTimeException; -import java.time.temporal.ChronoField; -import java.time.temporal.Queries; -import java.time.temporal.Temporal; -import java.time.temporal.TemporalField; -import java.time.temporal.TemporalQuery; -import java.time.temporal.ValueRange; -import java.time.temporal.ChronoLocalDate; -import java.time.temporal.Era; -import java.time.format.DateTimeFormatterBuilder; -import java.time.format.TextStyle; +import java.time.chrono.Era; /** * An era in the Coptic calendar system. @@ -83,7 +71,7 @@ import java.time.format.TextStyle; *

    Implementation notes

    * This is an immutable and thread-safe enum. */ -enum CopticEra implements Era { +enum CopticEra implements Era { /** * The singleton instance for the era BEFORE_AM, 'Before Era of the Martyrs'. @@ -131,80 +119,20 @@ enum CopticEra implements Era { } @Override - public CopticChrono getChrono() { - return CopticChrono.INSTANCE; + public CopticChronology getChronology() { + return CopticChronology.INSTANCE; } // JDK8 default methods: //----------------------------------------------------------------------- @Override - public ChronoLocalDate date(int year, int month, int day) { - return getChrono().date(this, year, month, day); + public CopticDate date(int year, int month, int day) { + return (CopticDate)(getChronology().date(this, year, month, day)); } @Override - public ChronoLocalDate dateYearDay(int year, int dayOfYear) { - return getChrono().dateYearDay(this, year, dayOfYear); - } - - //----------------------------------------------------------------------- - @Override - public boolean isSupported(TemporalField field) { - if (field instanceof ChronoField) { - return field == ERA; - } - return field != null && field.doIsSupported(this); - } - - @Override - public ValueRange range(TemporalField field) { - if (field == ERA) { - return field.range(); - } else if (field instanceof ChronoField) { - throw new DateTimeException("Unsupported field: " + field.getName()); - } - return field.doRange(this); - } - - @Override - public int get(TemporalField field) { - if (field == ERA) { - return getValue(); - } - return range(field).checkValidIntValue(getLong(field), field); - } - - @Override - public long getLong(TemporalField field) { - if (field == ERA) { - return getValue(); - } else if (field instanceof ChronoField) { - throw new DateTimeException("Unsupported field: " + field.getName()); - } - return field.doGet(this); - } - - //------------------------------------------------------------------------- - @Override - public Temporal adjustInto(Temporal dateTime) { - return dateTime.with(ERA, getValue()); - } - - @SuppressWarnings("unchecked") - @Override - public R query(TemporalQuery query) { - if (query == Queries.zoneId()) { - return null; - } else if (query == Queries.chrono()) { - return (R) getChrono(); - } - return query.queryFrom(this); - } - - //----------------------------------------------------------------------- - @Override - public String getText(TextStyle style, Locale locale) { - return new DateTimeFormatterBuilder().appendText(ERA, style).toFormatter(locale).print(this); + public CopticDate dateYearDay(int year, int dayOfYear) { + return (CopticDate)(getChronology().dateYearDay(this, year, dayOfYear)); } } diff --git a/jdk/test/java/time/tck/java/time/chrono/TCKChronology.java b/jdk/test/java/time/tck/java/time/chrono/TCKChronology.java new file mode 100644 index 00000000000..c1a43093733 --- /dev/null +++ b/jdk/test/java/time/tck/java/time/chrono/TCKChronology.java @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2012, 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 + * 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. + */ + +/* + * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of JSR-310 nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package tck.java.time.chrono; + +import static org.testng.Assert.assertEquals; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.Chronology; +import java.time.chrono.Era; +import java.time.chrono.IsoChronology; +import java.time.temporal.ChronoField; +import java.time.temporal.Queries; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalField; +import java.time.temporal.TemporalQuery; +import java.time.temporal.ValueRange; +import java.util.List; + +import org.testng.annotations.Test; + +/** + * Test. + */ +@Test +public class TCKChronology { + // Can only work with IsoChronology here + // others may be in separate module + + @Test + public void factory_from_TemporalAccessor_dateWithChronlogy() { + assertEquals(Chronology.from(LocalDate.of(2012, 6, 30)), IsoChronology.INSTANCE); + } + + @Test + public void factory_from_TemporalAccessor_chronology() { + assertEquals(Chronology.from(new TemporalAccessor() { + @Override + public boolean isSupported(TemporalField field) { + throw new UnsupportedOperationException(); + } + @Override + public long getLong(TemporalField field) { + throw new UnsupportedOperationException(); + } + @SuppressWarnings("unchecked") + @Override + public R query(TemporalQuery query) { + if (query == Queries.chronology()) { + return (R) IsoChronology.INSTANCE; + } + throw new UnsupportedOperationException(); + } + }), IsoChronology.INSTANCE); + } + + @Test + public void factory_from_TemporalAccessor_noChronology() { + assertEquals(Chronology.from(new TemporalAccessor() { + @Override + public boolean isSupported(TemporalField field) { + throw new UnsupportedOperationException(); + } + + @Override + public long getLong(TemporalField field) { + throw new UnsupportedOperationException(); + } + + @Override + public R query(TemporalQuery query) { + if (query == Queries.chronology()) { + return null; + } + throw new UnsupportedOperationException(); + } + }), IsoChronology.INSTANCE); + } + + @Test(expectedExceptions=NullPointerException.class) + public void factory_from_TemporalAccessor_null() { + Chronology.from(null); + } + + //----------------------------------------------------------------------- + @Test + public void test_date_TemporalAccessor() { + assertEquals(IsoChronology.INSTANCE.date(new TemporalAccessor() { + @Override + public boolean isSupported(TemporalField field) { + if (field == ChronoField.EPOCH_DAY) { + return true; + } + throw new UnsupportedOperationException(); + } + + @Override + public long getLong(TemporalField field) { + if (field == ChronoField.EPOCH_DAY) { + return LocalDate.of(2012, 6, 30).toEpochDay(); + } + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unchecked") + @Override + public R query(TemporalQuery query) { + if (query == Queries.localDate()) { + return (R) LocalDate.of(2012, 6, 30); + } + throw new UnsupportedOperationException(); + } + }), LocalDate.of(2012, 6, 30)); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_date_TemporalAccessor_null() { + IsoChronology.INSTANCE.date(null); + } + + //----------------------------------------------------------------------- + @Test + public void test_localDateTime_TemporalAccessor() { + assertEquals(IsoChronology.INSTANCE.localDateTime(new TemporalAccessor() { + @Override + public boolean isSupported(TemporalField field) { + if (field == ChronoField.EPOCH_DAY || field == ChronoField.NANO_OF_DAY) { + return true; + } + throw new UnsupportedOperationException(); + } + + @Override + public long getLong(TemporalField field) { + if (field == ChronoField.EPOCH_DAY) { + return LocalDate.of(2012, 6, 30).toEpochDay(); + } + if (field == ChronoField.NANO_OF_DAY) { + return LocalTime.of(12, 30, 40).toNanoOfDay(); + } + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unchecked") + @Override + public R query(TemporalQuery query) { + if (query == Queries.localDate()) { + return (R) LocalDate.of(2012, 6, 30); + } + if (query == Queries.localTime()) { + return (R) LocalTime.of(12, 30, 40); + } + throw new UnsupportedOperationException(); + } + }), LocalDateTime.of(2012, 6, 30, 12, 30, 40)); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_localDateTime_TemporalAccessor_null() { + IsoChronology.INSTANCE.localDateTime(null); + } + + //----------------------------------------------------------------------- + @Test + public void test_zonedDateTime_TemporalAccessor() { + assertEquals(IsoChronology.INSTANCE.zonedDateTime(new TemporalAccessor() { + @Override + public boolean isSupported(TemporalField field) { + if (field == ChronoField.EPOCH_DAY || field == ChronoField.NANO_OF_DAY || + field == ChronoField.INSTANT_SECONDS || field == ChronoField.NANO_OF_SECOND) { + return true; + } + throw new UnsupportedOperationException(); + } + + @Override + public long getLong(TemporalField field) { + if (field == ChronoField.INSTANT_SECONDS) { + return ZonedDateTime.of(2012, 6, 30, 12, 30, 40, 0, ZoneId.of("Europe/London")).toEpochSecond(); + } + if (field == ChronoField.NANO_OF_SECOND) { + return 0; + } + if (field == ChronoField.EPOCH_DAY) { + return LocalDate.of(2012, 6, 30).toEpochDay(); + } + if (field == ChronoField.NANO_OF_DAY) { + return LocalTime.of(12, 30, 40).toNanoOfDay(); + } + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unchecked") + @Override + public R query(TemporalQuery query) { + if (query == Queries.localDate()) { + return (R) LocalDate.of(2012, 6, 30); + } + if (query == Queries.localTime()) { + return (R) LocalTime.of(12, 30, 40); + } + if (query == Queries.zoneId() || query == Queries.zone()) { + return (R) ZoneId.of("Europe/London"); + } + throw new UnsupportedOperationException(); + } + }), ZonedDateTime.of(2012, 6, 30, 12, 30, 40, 0, ZoneId.of("Europe/London"))); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_zonedDateTime_TemporalAccessor_null() { + IsoChronology.INSTANCE.zonedDateTime(null); + } + +} diff --git a/jdk/test/java/time/tck/java/time/calendar/TestServiceLoader.java b/jdk/test/java/time/tck/java/time/chrono/TCKTestServiceLoader.java similarity index 73% rename from jdk/test/java/time/tck/java/time/calendar/TestServiceLoader.java rename to jdk/test/java/time/tck/java/time/chrono/TCKTestServiceLoader.java index b7381b77c84..0236656aad6 100644 --- a/jdk/test/java/time/tck/java/time/calendar/TestServiceLoader.java +++ b/jdk/test/java/time/tck/java/time/chrono/TCKTestServiceLoader.java @@ -56,51 +56,29 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.calendar; +package tck.java.time.chrono; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.fail; -import static org.testng.Assert.assertSame; -import static org.testng.Assert.assertTrue; -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.ServiceLoader; import java.time.LocalDate; -import java.time.temporal.Chrono; -import java.time.temporal.ChronoLocalDate; -import java.time.temporal.ISOChrono; -import java.time.DateTimeException; +import java.time.chrono.Chronology; +import java.time.chrono.ChronoLocalDate; -import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * Tests that a custom Chronology is available via the ServiceLoader. - * The CopticChrono is configured via META-INF/services/java.time.temporal.Chrono. + * The CopticChronology is configured via META-INF/services/java.time.chrono.Chronology. */ @Test -public class TestServiceLoader { +public class TCKTestServiceLoader { @Test(groups={"tck"}) public void test_CopticServiceLoader() { - Chrono chrono = Chrono.of("Coptic"); - ChronoLocalDate copticDate = chrono.date(1729, 4, 27); + Chronology chrono = Chronology.of("Coptic"); + ChronoLocalDate copticDate = chrono.date(1729, 4, 27); LocalDate ld = LocalDate.from(copticDate); assertEquals(ld, LocalDate.of(2013, 1, 5), "CopticDate does not match LocalDate"); } - @Test(groups="implementation") - public void test_copticServiceLoader() { - Map chronos = new HashMap<>(); - ServiceLoader loader = ServiceLoader.load(Chrono.class, null); - for (Chrono chrono : loader) { - chronos.put(chrono.getId(), chrono); - } - assertNotNull(chronos.get("Coptic"), "CopticChrono not found"); - } - } diff --git a/jdk/test/java/time/tck/java/time/calendar/TestChronoLocalDate.java b/jdk/test/java/time/tck/java/time/chrono/TestChronoLocalDate.java similarity index 84% rename from jdk/test/java/time/tck/java/time/calendar/TestChronoLocalDate.java rename to jdk/test/java/time/tck/java/time/chrono/TestChronoLocalDate.java index 67175c0b06c..51674e27f90 100644 --- a/jdk/test/java/time/tck/java/time/calendar/TestChronoLocalDate.java +++ b/jdk/test/java/time/tck/java/time/chrono/TestChronoLocalDate.java @@ -54,7 +54,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.calendar; +package tck.java.time.chrono; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -63,29 +63,25 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.util.ArrayList; -import java.util.List; - import java.time.Duration; import java.time.LocalDate; -import java.time.calendar.HijrahChrono; -import java.time.calendar.JapaneseChrono; -import java.time.calendar.MinguoChrono; -import java.time.calendar.ThaiBuddhistChrono; -import java.time.temporal.Chrono; -import java.time.temporal.ChronoLocalDate; +import java.time.chrono.HijrahChronology; +import java.time.chrono.JapaneseChronology; +import java.time.chrono.MinguoChronology; +import java.time.chrono.ThaiBuddhistChronology; +import java.time.chrono.Chronology; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.IsoChronology; import java.time.temporal.ChronoUnit; -import java.time.temporal.SimplePeriod; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; -import java.time.format.DateTimeBuilder; -import java.time.temporal.TemporalAdder; import java.time.temporal.TemporalAdjuster; +import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalField; -import java.time.temporal.TemporalSubtractor; -import java.time.temporal.ValueRange; import java.time.temporal.TemporalUnit; -import java.time.temporal.ISOChrono; +import java.time.temporal.ValueRange; +import java.util.ArrayList; +import java.util.List; import org.testng.Assert; import org.testng.annotations.DataProvider; @@ -101,21 +97,21 @@ public class TestChronoLocalDate { // regular data factory for names and descriptions of available calendars //----------------------------------------------------------------------- @DataProvider(name = "calendars") - Chrono[][] data_of_calendars() { - return new Chrono[][]{ - {HijrahChrono.INSTANCE}, - {ISOChrono.INSTANCE}, - {JapaneseChrono.INSTANCE}, - {MinguoChrono.INSTANCE}, - {ThaiBuddhistChrono.INSTANCE}}; + Chronology[][] data_of_calendars() { + return new Chronology[][]{ + {HijrahChronology.INSTANCE}, + {IsoChronology.INSTANCE}, + {JapaneseChronology.INSTANCE}, + {MinguoChronology.INSTANCE}, + {ThaiBuddhistChronology.INSTANCE}}; } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badWithAdjusterChrono(Chrono chrono) { + public void test_badWithAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDate date = chrono.date(refDate); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDate date2 = chrono2.date(refDate); TemporalAdjuster adjuster = new FixedAdjuster(date2); if (chrono != chrono2) { @@ -134,13 +130,13 @@ public class TestChronoLocalDate { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badPlusAdjusterChrono(Chrono chrono) { + public void test_badPlusAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDate date = chrono.date(refDate); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDate date2 = chrono2.date(refDate); - TemporalAdder adjuster = new FixedAdjuster(date2); + TemporalAmount adjuster = new FixedAdjuster(date2); if (chrono != chrono2) { try { date.plus(adjuster); @@ -157,13 +153,13 @@ public class TestChronoLocalDate { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badMinusAdjusterChrono(Chrono chrono) { + public void test_badMinusAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDate date = chrono.date(refDate); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDate date2 = chrono2.date(refDate); - TemporalSubtractor adjuster = new FixedAdjuster(date2); + TemporalAmount adjuster = new FixedAdjuster(date2); if (chrono != chrono2) { try { date.minus(adjuster); @@ -180,11 +176,11 @@ public class TestChronoLocalDate { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badPlusTemporalUnitChrono(Chrono chrono) { + public void test_badPlusTemporalUnitChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDate date = chrono.date(refDate); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDate date2 = chrono2.date(refDate); TemporalUnit adjuster = new FixedTemporalUnit(date2); if (chrono != chrono2) { @@ -204,11 +200,11 @@ public class TestChronoLocalDate { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badMinusTemporalUnitChrono(Chrono chrono) { + public void test_badMinusTemporalUnitChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDate date = chrono.date(refDate); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDate date2 = chrono2.date(refDate); TemporalUnit adjuster = new FixedTemporalUnit(date2); if (chrono != chrono2) { @@ -228,11 +224,11 @@ public class TestChronoLocalDate { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badTemporalFieldChrono(Chrono chrono) { + public void test_badTemporalFieldChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDate date = chrono.date(refDate); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDate date2 = chrono2.date(refDate); TemporalField adjuster = new FixedTemporalField(date2); if (chrono != chrono2) { @@ -255,8 +251,8 @@ public class TestChronoLocalDate { // isBefore, isAfter, isEqual, DATE_COMPARATOR //----------------------------------------------------------------------- @Test(groups={"tck"}, dataProvider="calendars") - public void test_date_comparisons(Chrono chrono) { - List> dates = new ArrayList<>(); + public void test_date_comparisons(Chronology chrono) { + List dates = new ArrayList<>(); ChronoLocalDate date = chrono.date(LocalDate.of(1900, 1, 1)); @@ -278,9 +274,9 @@ public class TestChronoLocalDate { dates.add(date.plus(1000, ChronoUnit.YEARS)); // Check these dates against the corresponding dates for every calendar - for (Chrono[] clist : data_of_calendars()) { + for (Chronology[] clist : data_of_calendars()) { List> otherDates = new ArrayList<>(); - Chrono chrono2 = clist[0]; + Chronology chrono2 = clist[0]; for (ChronoLocalDate d : dates) { otherDates.add(chrono2.date(d)); } @@ -316,9 +312,9 @@ public class TestChronoLocalDate { // Test Serialization of Calendars //----------------------------------------------------------------------- @Test( groups={"tck"}, dataProvider="calendars") - public > void test_ChronoSerialization(C chrono) throws Exception { + public void test_ChronoSerialization(Chronology chrono) throws Exception { LocalDate ref = LocalDate.of(1900, 1, 5); - ChronoLocalDate orginal = chrono.date(ref); + ChronoLocalDate orginal = chrono.date(ref); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject(orginal); @@ -326,7 +322,7 @@ public class TestChronoLocalDate { ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream in = new ObjectInputStream(bais); @SuppressWarnings("unchecked") - ChronoLocalDate ser = (ChronoLocalDate) in.readObject(); + ChronoLocalDate ser = (ChronoLocalDate) in.readObject(); assertEquals(ser, orginal, "deserialized date is wrong"); } @@ -334,7 +330,7 @@ public class TestChronoLocalDate { * FixedAdjusted returns a fixed Temporal in all adjustments. * Construct an adjuster with the Temporal that should be returned from adjust. */ - static class FixedAdjuster implements TemporalAdjuster, TemporalAdder, TemporalSubtractor { + static class FixedAdjuster implements TemporalAdjuster, TemporalAmount { private Temporal datetime; FixedAdjuster(Temporal datetime) { @@ -356,6 +352,15 @@ public class TestChronoLocalDate { return datetime; } + @Override + public long get(TemporalUnit unit) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List getUnits() { + throw new UnsupportedOperationException("Not supported yet."); + } } /** @@ -385,18 +390,18 @@ public class TestChronoLocalDate { } @Override - public boolean isSupported(Temporal temporal) { + public boolean isSupportedBy(Temporal temporal) { throw new UnsupportedOperationException("Not supported yet."); } @SuppressWarnings("unchecked") @Override - public R doPlus(R dateTime, long periodToAdd) { + public R addTo(R temporal, long amount) { return (R) this.temporal; } @Override - public SimplePeriod between(R dateTime1, R dateTime2) { + public long between(Temporal temporal1, Temporal temporal2) { throw new UnsupportedOperationException("Not supported yet."); } } @@ -432,30 +437,24 @@ public class TestChronoLocalDate { } @Override - public boolean doIsSupported(TemporalAccessor temporal) { + public boolean isSupportedBy(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public ValueRange doRange(TemporalAccessor temporal) { + public ValueRange rangeRefinedBy(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public long doGet(TemporalAccessor temporal) { + public long getFrom(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @SuppressWarnings("unchecked") @Override - public R doWith(R temporal, long newValue) { + public R adjustInto(R temporal, long newValue) { return (R) this.temporal; } - - @Override - public boolean resolve(DateTimeBuilder builder, long value) { - throw new UnsupportedOperationException("Not supported yet."); - } - } } diff --git a/jdk/test/java/time/tck/java/time/calendar/TestChronoLocalDateTime.java b/jdk/test/java/time/tck/java/time/chrono/TestChronoLocalDateTime.java similarity index 85% rename from jdk/test/java/time/tck/java/time/calendar/TestChronoLocalDateTime.java rename to jdk/test/java/time/tck/java/time/chrono/TestChronoLocalDateTime.java index e514fb82e02..fd72237b8b7 100644 --- a/jdk/test/java/time/tck/java/time/calendar/TestChronoLocalDateTime.java +++ b/jdk/test/java/time/tck/java/time/chrono/TestChronoLocalDateTime.java @@ -54,7 +54,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.calendar; +package tck.java.time.chrono; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -63,31 +63,28 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.util.ArrayList; -import java.util.List; - import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.calendar.HijrahChrono; -import java.time.calendar.JapaneseChrono; -import java.time.calendar.MinguoChrono; -import java.time.calendar.ThaiBuddhistChrono; -import java.time.temporal.Chrono; -import java.time.temporal.ChronoLocalDateTime; +import java.time.chrono.HijrahChronology; +import java.time.chrono.JapaneseChronology; +import java.time.chrono.MinguoChronology; +import java.time.chrono.ThaiBuddhistChronology; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.ChronoLocalDateTime; +import java.time.chrono.Chronology; +import java.time.chrono.IsoChronology; import java.time.temporal.ChronoUnit; -import java.time.temporal.SimplePeriod; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; -import java.time.format.DateTimeBuilder; -import java.time.temporal.TemporalAdder; import java.time.temporal.TemporalAdjuster; +import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalField; -import java.time.temporal.TemporalSubtractor; -import java.time.temporal.ValueRange; -import java.time.temporal.ISOChrono; import java.time.temporal.TemporalUnit; +import java.time.temporal.ValueRange; +import java.util.ArrayList; +import java.util.List; import org.testng.Assert; import org.testng.annotations.DataProvider; @@ -102,21 +99,21 @@ public class TestChronoLocalDateTime { // regular data factory for names and descriptions of available calendars //----------------------------------------------------------------------- @DataProvider(name = "calendars") - Chrono[][] data_of_calendars() { - return new Chrono[][]{ - {HijrahChrono.INSTANCE}, - {ISOChrono.INSTANCE}, - {JapaneseChrono.INSTANCE}, - {MinguoChrono.INSTANCE}, - {ThaiBuddhistChrono.INSTANCE}}; + Chronology[][] data_of_calendars() { + return new Chronology[][]{ + {HijrahChronology.INSTANCE}, + {IsoChronology.INSTANCE}, + {JapaneseChronology.INSTANCE}, + {MinguoChronology.INSTANCE}, + {ThaiBuddhistChronology.INSTANCE}}; } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badWithAdjusterChrono(Chrono chrono) { + public void test_badWithAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDateTime cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON); TemporalAdjuster adjuster = new FixedAdjuster(cdt2); if (chrono != chrono2) { @@ -136,13 +133,13 @@ public class TestChronoLocalDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badPlusAdjusterChrono(Chrono chrono) { + public void test_badPlusAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDateTime cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON); - TemporalAdder adjuster = new FixedAdjuster(cdt2); + TemporalAmount adjuster = new FixedAdjuster(cdt2); if (chrono != chrono2) { try { ChronoLocalDateTime notreached = cdt.plus(adjuster); @@ -160,13 +157,13 @@ public class TestChronoLocalDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badMinusAdjusterChrono(Chrono chrono) { + public void test_badMinusAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDateTime cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON); - TemporalSubtractor adjuster = new FixedAdjuster(cdt2); + TemporalAmount adjuster = new FixedAdjuster(cdt2); if (chrono != chrono2) { try { ChronoLocalDateTime notreached = cdt.minus(adjuster); @@ -184,11 +181,11 @@ public class TestChronoLocalDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badPlusTemporalUnitChrono(Chrono chrono) { + public void test_badPlusTemporalUnitChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDateTime cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON); TemporalUnit adjuster = new FixedTemporalUnit(cdt2); if (chrono != chrono2) { @@ -208,11 +205,11 @@ public class TestChronoLocalDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badMinusTemporalUnitChrono(Chrono chrono) { + public void test_badMinusTemporalUnitChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDateTime cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON); TemporalUnit adjuster = new FixedTemporalUnit(cdt2); if (chrono != chrono2) { @@ -232,11 +229,11 @@ public class TestChronoLocalDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badTemporalFieldChrono(Chrono chrono) { + public void test_badTemporalFieldChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDateTime cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON); TemporalField adjuster = new FixedTemporalField(cdt2); if (chrono != chrono2) { @@ -259,7 +256,7 @@ public class TestChronoLocalDateTime { // isBefore, isAfter, isEqual //----------------------------------------------------------------------- @Test(groups={"tck"}, dataProvider="calendars") - public void test_datetime_comparisons(Chrono chrono) { + public void test_datetime_comparisons(Chronology chrono) { List> dates = new ArrayList<>(); ChronoLocalDateTime date = chrono.date(LocalDate.of(1900, 1, 1)).atTime(LocalTime.MIN); @@ -286,11 +283,11 @@ public class TestChronoLocalDateTime { dates.add(date.plus(100, ChronoUnit.YEARS)); // Check these dates against the corresponding dates for every calendar - for (Chrono[] clist : data_of_calendars()) { + for (Chronology[] clist : data_of_calendars()) { List> otherDates = new ArrayList<>(); - Chrono chrono2 = clist[0]; + Chronology chrono2 = clist[0]; for (ChronoLocalDateTime d : dates) { - otherDates.add(chrono2.date(d).atTime(d.getTime())); + otherDates.add(chrono2.date(d).atTime(d.toLocalTime())); } // Now compare the sequence of original dates with the sequence of converted dates @@ -324,16 +321,16 @@ public class TestChronoLocalDateTime { // Test Serialization of ISO via chrono API //----------------------------------------------------------------------- @Test( groups={"tck"}, dataProvider="calendars") - public > void test_ChronoLocalDateTimeSerialization(C chrono) throws Exception { + public void test_ChronoLocalDateTimeSerialization(Chronology chrono) throws Exception { LocalDateTime ref = LocalDate.of(2000, 1, 5).atTime(12, 1, 2, 3); - ChronoLocalDateTime orginal = chrono.date(ref).atTime(ref.getTime()); + ChronoLocalDateTime orginal = chrono.date(ref).atTime(ref.toLocalTime()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject(orginal); out.close(); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream in = new ObjectInputStream(bais); - ChronoLocalDateTime ser = (ChronoLocalDateTime) in.readObject(); + ChronoLocalDateTime ser = (ChronoLocalDateTime) in.readObject(); assertEquals(ser, orginal, "deserialized date is wrong"); } @@ -342,7 +339,7 @@ public class TestChronoLocalDateTime { * FixedAdjusted returns a fixed Temporal in all adjustments. * Construct an adjuster with the Temporal that should be returned from adjust. */ - static class FixedAdjuster implements TemporalAdjuster, TemporalAdder, TemporalSubtractor { + static class FixedAdjuster implements TemporalAdjuster, TemporalAmount { private Temporal datetime; FixedAdjuster(Temporal datetime) { @@ -364,6 +361,16 @@ public class TestChronoLocalDateTime { return datetime; } + @Override + public long get(TemporalUnit unit) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List getUnits() { + throw new UnsupportedOperationException("Not supported yet."); + } + } /** @@ -393,18 +400,18 @@ public class TestChronoLocalDateTime { } @Override - public boolean isSupported(Temporal temporal) { + public boolean isSupportedBy(Temporal temporal) { throw new UnsupportedOperationException("Not supported yet."); } @SuppressWarnings("unchecked") @Override - public R doPlus(R dateTime, long periodToAdd) { + public R addTo(R temporal, long amount) { return (R) this.temporal; } @Override - public SimplePeriod between(R dateTime1, R dateTime2) { + public long between(Temporal temporal1, Temporal temporal2) { throw new UnsupportedOperationException("Not supported yet."); } } @@ -440,30 +447,24 @@ public class TestChronoLocalDateTime { } @Override - public boolean doIsSupported(TemporalAccessor temporal) { + public boolean isSupportedBy(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public ValueRange doRange(TemporalAccessor temporal) { + public ValueRange rangeRefinedBy(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public long doGet(TemporalAccessor temporal) { + public long getFrom(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @SuppressWarnings("unchecked") @Override - public R doWith(R temporal, long newValue) { + public R adjustInto(R temporal, long newValue) { return (R) this.temporal; } - - @Override - public boolean resolve(DateTimeBuilder builder, long value) { - throw new UnsupportedOperationException("Not supported yet."); - } - } } diff --git a/jdk/test/java/time/tck/java/time/calendar/TestHijrahChrono.java b/jdk/test/java/time/tck/java/time/chrono/TestHijrahChronology.java similarity index 71% rename from jdk/test/java/time/tck/java/time/calendar/TestHijrahChrono.java rename to jdk/test/java/time/tck/java/time/chrono/TestHijrahChronology.java index 3157e822f09..1938c5e9849 100644 --- a/jdk/test/java/time/tck/java/time/calendar/TestHijrahChrono.java +++ b/jdk/test/java/time/tck/java/time/chrono/TestHijrahChronology.java @@ -54,7 +54,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.calendar; +package tck.java.time.chrono; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -64,11 +64,12 @@ import java.time.DateTimeException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.Month; -import java.time.calendar.HijrahChrono; -import java.time.temporal.ChronoLocalDate; +import java.time.chrono.HijrahChronology; +import java.time.chrono.HijrahDate; +import java.time.chrono.ChronoLocalDate; import java.time.temporal.Adjusters; -import java.time.temporal.Chrono; -import java.time.temporal.ISOChrono; +import java.time.chrono.Chronology; +import java.time.chrono.IsoChronology; import org.testng.Assert; import org.testng.annotations.DataProvider; @@ -78,15 +79,15 @@ import org.testng.annotations.Test; * Test. */ @Test -public class TestHijrahChrono { +public class TestHijrahChronology { //----------------------------------------------------------------------- - // Chrono.ofName("Hijrah") Lookup by name + // Chronology.ofName("Hijrah") Lookup by name //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_chrono_byName() { - Chrono c = HijrahChrono.INSTANCE; - Chrono test = Chrono.of("Hijrah"); + Chronology c = HijrahChronology.INSTANCE; + Chronology test = Chronology.of("Hijrah"); Assert.assertNotNull(test, "The Hijrah calendar could not be found byName"); Assert.assertEquals(test.getId(), "Hijrah", "ID mismatch"); Assert.assertEquals(test.getCalendarType(), "islamicc", "Type mismatch"); @@ -99,20 +100,20 @@ public class TestHijrahChrono { @DataProvider(name="samples") Object[][] data_samples() { return new Object[][] { - {HijrahChrono.INSTANCE.date(1, 1, 1), LocalDate.of(622, 7, 19)}, - {HijrahChrono.INSTANCE.date(1, 1, 2), LocalDate.of(622, 7, 20)}, - {HijrahChrono.INSTANCE.date(1, 1, 3), LocalDate.of(622, 7, 21)}, + {HijrahChronology.INSTANCE.date(1, 1, 1), LocalDate.of(622, 7, 19)}, + {HijrahChronology.INSTANCE.date(1, 1, 2), LocalDate.of(622, 7, 20)}, + {HijrahChronology.INSTANCE.date(1, 1, 3), LocalDate.of(622, 7, 21)}, - {HijrahChrono.INSTANCE.date(2, 1, 1), LocalDate.of(623, 7, 8)}, - {HijrahChrono.INSTANCE.date(3, 1, 1), LocalDate.of(624, 6, 27)}, - {HijrahChrono.INSTANCE.date(3, 12, 6), LocalDate.of(625, 5, 23)}, - {HijrahChrono.INSTANCE.date(4, 1, 1), LocalDate.of(625, 6, 16)}, - {HijrahChrono.INSTANCE.date(4, 7, 3), LocalDate.of(625, 12, 12)}, - {HijrahChrono.INSTANCE.date(4, 7, 4), LocalDate.of(625, 12, 13)}, - {HijrahChrono.INSTANCE.date(5, 1, 1), LocalDate.of(626, 6, 5)}, - {HijrahChrono.INSTANCE.date(1662, 3, 3), LocalDate.of(2234, 4, 3)}, - {HijrahChrono.INSTANCE.date(1728, 10, 28), LocalDate.of(2298, 12, 03)}, - {HijrahChrono.INSTANCE.date(1728, 10, 29), LocalDate.of(2298, 12, 04)}, + {HijrahChronology.INSTANCE.date(2, 1, 1), LocalDate.of(623, 7, 8)}, + {HijrahChronology.INSTANCE.date(3, 1, 1), LocalDate.of(624, 6, 27)}, + {HijrahChronology.INSTANCE.date(3, 12, 6), LocalDate.of(625, 5, 23)}, + {HijrahChronology.INSTANCE.date(4, 1, 1), LocalDate.of(625, 6, 16)}, + {HijrahChronology.INSTANCE.date(4, 7, 3), LocalDate.of(625, 12, 12)}, + {HijrahChronology.INSTANCE.date(4, 7, 4), LocalDate.of(625, 12, 13)}, + {HijrahChronology.INSTANCE.date(5, 1, 1), LocalDate.of(626, 6, 5)}, + {HijrahChronology.INSTANCE.date(1662, 3, 3), LocalDate.of(2234, 4, 3)}, + {HijrahChronology.INSTANCE.date(1728, 10, 28), LocalDate.of(2298, 12, 03)}, + {HijrahChronology.INSTANCE.date(1728, 10, 29), LocalDate.of(2298, 12, 04)}, }; } @@ -123,7 +124,7 @@ public class TestHijrahChrono { @Test(dataProvider="samples", groups={"tck"}) public void test_fromCalendrical(ChronoLocalDate hijrahDate, LocalDate iso) { - assertEquals(HijrahChrono.INSTANCE.date(iso), hijrahDate); + assertEquals(HijrahChronology.INSTANCE.date(iso), hijrahDate); } @DataProvider(name="badDates") @@ -148,7 +149,7 @@ public class TestHijrahChrono { @Test(dataProvider="badDates", groups={"tck"}, expectedExceptions=DateTimeException.class) public void test_badDates(int year, int month, int dom) { - HijrahChrono.INSTANCE.date(year, month, dom); + HijrahChronology.INSTANCE.date(year, month, dom); } //----------------------------------------------------------------------- @@ -156,16 +157,16 @@ public class TestHijrahChrono { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_adjust1() { - ChronoLocalDate base = HijrahChrono.INSTANCE.date(1728, 10, 28); + ChronoLocalDate base = HijrahChronology.INSTANCE.date(1728, 10, 28); ChronoLocalDate test = base.with(Adjusters.lastDayOfMonth()); - assertEquals(test, HijrahChrono.INSTANCE.date(1728, 10, 29)); + assertEquals(test, HijrahChronology.INSTANCE.date(1728, 10, 29)); } @Test(groups={"tck"}) public void test_adjust2() { - ChronoLocalDate base = HijrahChrono.INSTANCE.date(1728, 12, 2); + ChronoLocalDate base = HijrahChronology.INSTANCE.date(1728, 12, 2); ChronoLocalDate test = base.with(Adjusters.lastDayOfMonth()); - assertEquals(test, HijrahChrono.INSTANCE.date(1728, 12, 30)); + assertEquals(test, HijrahChronology.INSTANCE.date(1728, 12, 30)); } //----------------------------------------------------------------------- @@ -173,14 +174,14 @@ public class TestHijrahChrono { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_adjust_toLocalDate() { - ChronoLocalDate hijrahDate = HijrahChrono.INSTANCE.date(1726, 1, 4); + ChronoLocalDate hijrahDate = HijrahChronology.INSTANCE.date(1726, 1, 4); ChronoLocalDate test = hijrahDate.with(LocalDate.of(2012, 7, 6)); - assertEquals(test, HijrahChrono.INSTANCE.date(1433, 8, 16)); + assertEquals(test, HijrahChronology.INSTANCE.date(1433, 8, 16)); } @Test(groups={"tck"}, expectedExceptions=DateTimeException.class) public void test_adjust_toMonth() { - ChronoLocalDate hijrahDate = HijrahChrono.INSTANCE.date(1726, 1, 4); + ChronoLocalDate hijrahDate = HijrahChronology.INSTANCE.date(1726, 1, 4); hijrahDate.with(Month.APRIL); } @@ -189,14 +190,14 @@ public class TestHijrahChrono { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_LocalDate_adjustToHijrahDate() { - ChronoLocalDate hijrahDate = HijrahChrono.INSTANCE.date(1728, 10, 29); + ChronoLocalDate hijrahDate = HijrahChronology.INSTANCE.date(1728, 10, 29); LocalDate test = LocalDate.MIN.with(hijrahDate); assertEquals(test, LocalDate.of(2298, 12, 4)); } @Test(groups={"tck"}) public void test_LocalDateTime_adjustToHijrahDate() { - ChronoLocalDate hijrahDate = HijrahChrono.INSTANCE.date(1728, 10, 29); + ChronoLocalDate hijrahDate = HijrahChronology.INSTANCE.date(1728, 10, 29); LocalDateTime test = LocalDateTime.MIN.with(hijrahDate); assertEquals(test, LocalDateTime.of(2298, 12, 4, 0, 0)); } @@ -207,11 +208,11 @@ public class TestHijrahChrono { @DataProvider(name="toString") Object[][] data_toString() { return new Object[][] { - {HijrahChrono.INSTANCE.date(1, 1, 1), "Hijrah AH 1-01-01"}, - {HijrahChrono.INSTANCE.date(1728, 10, 28), "Hijrah AH 1728-10-28"}, - {HijrahChrono.INSTANCE.date(1728, 10, 29), "Hijrah AH 1728-10-29"}, - {HijrahChrono.INSTANCE.date(1727, 12, 5), "Hijrah AH 1727-12-05"}, - {HijrahChrono.INSTANCE.date(1727, 12, 6), "Hijrah AH 1727-12-06"}, + {HijrahChronology.INSTANCE.date(1, 1, 1), "Hijrah AH 1-01-01"}, + {HijrahChronology.INSTANCE.date(1728, 10, 28), "Hijrah AH 1728-10-28"}, + {HijrahChronology.INSTANCE.date(1728, 10, 29), "Hijrah AH 1728-10-29"}, + {HijrahChronology.INSTANCE.date(1727, 12, 5), "Hijrah AH 1727-12-05"}, + {HijrahChronology.INSTANCE.date(1727, 12, 6), "Hijrah AH 1727-12-06"}, }; } @@ -225,12 +226,12 @@ public class TestHijrahChrono { //----------------------------------------------------------------------- @Test(groups="tck") public void test_equals_true() { - assertTrue(HijrahChrono.INSTANCE.equals(HijrahChrono.INSTANCE)); + assertTrue(HijrahChronology.INSTANCE.equals(HijrahChronology.INSTANCE)); } @Test(groups="tck") public void test_equals_false() { - assertFalse(HijrahChrono.INSTANCE.equals(ISOChrono.INSTANCE)); + assertFalse(HijrahChronology.INSTANCE.equals(IsoChronology.INSTANCE)); } } diff --git a/jdk/test/java/time/tck/java/time/chrono/TestJapaneseChronology.java b/jdk/test/java/time/tck/java/time/chrono/TestJapaneseChronology.java new file mode 100644 index 00000000000..b3027dfb6f6 --- /dev/null +++ b/jdk/test/java/time/tck/java/time/chrono/TestJapaneseChronology.java @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2012, 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 + * 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. + */ + +/* + * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of JSR-310 nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package tck.java.time.chrono; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +import java.util.List; + +import java.time.DateTimeException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.Month; +import java.time.Year; +import java.time.chrono.JapaneseChronology; +import java.time.chrono.JapaneseDate; +import java.time.chrono.Chronology; +import java.time.chrono.Era; +import java.time.chrono.IsoChronology; +import java.time.temporal.Adjusters; +import java.util.Locale; + +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * Test. + */ +@Test +public class TestJapaneseChronology { + private static int YDIFF_HEISEI = 1988; + private static int YDIFF_MEIJI = 1867; + private static int YDIFF_SHOWA = 1925; + private static int YDIFF_TAISHO = 1911; + + //----------------------------------------------------------------------- + // Chronology.of(String) + //----------------------------------------------------------------------- + @Test + public void test_chrono_byName() { + Chronology c = JapaneseChronology.INSTANCE; + Chronology test = Chronology.of("Japanese"); + Assert.assertNotNull(test, "The Japanese calendar could not be found byName"); + Assert.assertEquals(test.getId(), "Japanese", "ID mismatch"); + Assert.assertEquals(test.getCalendarType(), "japanese", "Type mismatch"); + Assert.assertEquals(test, c); + } + + //----------------------------------------------------------------------- + // Chronology.ofLocale(Locale) + //----------------------------------------------------------------------- + @Test + public void test_chrono_byLocale_fullTag_japaneseCalendarFromJapan() { + Chronology test = Chronology.ofLocale(Locale.forLanguageTag("ja-JP-u-ca-japanese")); + Assert.assertEquals(test.getId(), "Japanese"); + Assert.assertEquals(test, JapaneseChronology.INSTANCE); + } + + @Test + public void test_chrono_byLocale_fullTag_japaneseCalendarFromElsewhere() { + Chronology test = Chronology.ofLocale(Locale.forLanguageTag("en-US-u-ca-japanese")); + Assert.assertEquals(test.getId(), "Japanese"); + Assert.assertEquals(test, JapaneseChronology.INSTANCE); + } + + @Test + public void test_chrono_byLocale_oldJP_noVariant() { + Chronology test = Chronology.ofLocale(new Locale("ja", "JP")); + Assert.assertEquals(test.getId(), "ISO"); + Assert.assertEquals(test, IsoChronology.INSTANCE); + } + + @Test + public void test_chrono_byLocale_oldJP_variant() { + Chronology test = Chronology.ofLocale(new Locale("ja", "JP", "JP")); + Assert.assertEquals(test.getId(), "Japanese"); + Assert.assertEquals(test, JapaneseChronology.INSTANCE); + } + + @Test + public void test_chrono_byLocale_iso() { + Assert.assertEquals(Chronology.ofLocale(new Locale("ja", "JP")).getId(), "ISO"); + Assert.assertEquals(Chronology.ofLocale(Locale.forLanguageTag("ja-JP")).getId(), "ISO"); + Assert.assertEquals(Chronology.ofLocale(Locale.forLanguageTag("ja-JP-JP")).getId(), "ISO"); + } + + //----------------------------------------------------------------------- + // creation, toLocalDate() + //----------------------------------------------------------------------- + @DataProvider(name="samples") + Object[][] data_samples() { + return new Object[][] { + {JapaneseChronology.INSTANCE.date(1, 1, 1), LocalDate.of(1, 1, 1)}, + {JapaneseChronology.INSTANCE.date(1, 1, 2), LocalDate.of(1, 1, 2)}, + {JapaneseChronology.INSTANCE.date(1, 1, 3), LocalDate.of(1, 1, 3)}, + + {JapaneseChronology.INSTANCE.date(2, 1, 1), LocalDate.of(2, 1, 1)}, + {JapaneseChronology.INSTANCE.date(3, 1, 1), LocalDate.of(3, 1, 1)}, + {JapaneseChronology.INSTANCE.date(3, 12, 6), LocalDate.of(3, 12, 6)}, + {JapaneseChronology.INSTANCE.date(4, 1, 1), LocalDate.of(4, 1, 1)}, + {JapaneseChronology.INSTANCE.date(4, 7, 3), LocalDate.of(4, 7, 3)}, + {JapaneseChronology.INSTANCE.date(4, 7, 4), LocalDate.of(4, 7, 4)}, + {JapaneseChronology.INSTANCE.date(5, 1, 1), LocalDate.of(5, 1, 1)}, + {JapaneseChronology.INSTANCE.date(1662, 3, 3), LocalDate.of(1662, 3, 3)}, + {JapaneseChronology.INSTANCE.date(1728, 10, 28), LocalDate.of(1728, 10, 28)}, + {JapaneseChronology.INSTANCE.date(1728, 10, 29), LocalDate.of(1728, 10, 29)}, + + {JapaneseChronology.INSTANCE.date(JapaneseChronology.ERA_HEISEI, 1996 - YDIFF_HEISEI, 2, 29), LocalDate.of(1996, 2, 29)}, + {JapaneseChronology.INSTANCE.date(JapaneseChronology.ERA_HEISEI, 2000 - YDIFF_HEISEI, 2, 29), LocalDate.of(2000, 2, 29)}, + {JapaneseChronology.INSTANCE.date(JapaneseChronology.ERA_MEIJI, 1868 - YDIFF_MEIJI, 2, 29), LocalDate.of(1868, 2, 29)}, + {JapaneseChronology.INSTANCE.date(JapaneseChronology.ERA_SHOWA, 1928 - YDIFF_SHOWA, 2, 29), LocalDate.of(1928, 2, 29)}, + {JapaneseChronology.INSTANCE.date(JapaneseChronology.ERA_TAISHO, 1912 - YDIFF_TAISHO, 2, 29), LocalDate.of(1912, 2, 29)}, + + {JapaneseChronology.INSTANCE.dateYearDay(1996, 60), LocalDate.of(1996, 2, 29)}, + {JapaneseChronology.INSTANCE.dateYearDay(1868, 60), LocalDate.of(1868, 2, 29)}, + {JapaneseChronology.INSTANCE.dateYearDay(1928, 60), LocalDate.of(1928, 2, 29)}, + {JapaneseChronology.INSTANCE.dateYearDay(1912, 60), LocalDate.of(1912, 2, 29)}, + }; + } + + @Test(dataProvider="samples", groups={"tck"}) + public void test_toLocalDate(JapaneseDate jdate, LocalDate iso) { + assertEquals(LocalDate.from(jdate), iso); + } + + @Test(dataProvider="samples", groups={"tck"}) + public void test_fromCalendrical(JapaneseDate jdate, LocalDate iso) { + assertEquals(JapaneseChronology.INSTANCE.date(iso), jdate); + } + + @DataProvider(name="badDates") + Object[][] data_badDates() { + return new Object[][] { + {1728, 0, 0}, + + {1728, -1, 1}, + {1728, 0, 1}, + {1728, 14, 1}, + {1728, 15, 1}, + + {1728, 1, -1}, + {1728, 1, 0}, + {1728, 1, 32}, + + {1728, 12, -1}, + {1728, 12, 0}, + {1728, 12, 32}, + + {1725, 2, 29}, + {500, 2, 29}, + {2100, 2, 29}, + }; + } + + @Test(dataProvider="badDates", groups={"tck"}, expectedExceptions=DateTimeException.class) + public void test_badDates(int year, int month, int dom) { + JapaneseChronology.INSTANCE.date(year, month, dom); + } + + //----------------------------------------------------------------------- + // prolepticYear() and is LeapYear() + //----------------------------------------------------------------------- + @DataProvider(name="prolepticYear") + Object[][] data_prolepticYear() { + return new Object[][] { + {2, JapaneseChronology.ERA_HEISEI, 1, 1 + YDIFF_HEISEI, false}, + {2, JapaneseChronology.ERA_HEISEI, 100, 100 + YDIFF_HEISEI, true}, + {2, JapaneseChronology.ERA_HEISEI, 0, YDIFF_HEISEI, true}, + {2, JapaneseChronology.ERA_HEISEI, -10, -10 + YDIFF_HEISEI, false}, + + {-1, JapaneseChronology.ERA_MEIJI, 1, 1 + YDIFF_MEIJI, true}, + {-1, JapaneseChronology.ERA_MEIJI, 100, 100 + YDIFF_MEIJI, false}, + {-1, JapaneseChronology.ERA_MEIJI, 0, YDIFF_MEIJI, false}, + {-1, JapaneseChronology.ERA_MEIJI, -10, -10 + YDIFF_MEIJI, false}, + + {1, JapaneseChronology.ERA_SHOWA, 1, 1 + YDIFF_SHOWA, false}, + {1, JapaneseChronology.ERA_SHOWA, 100, 100 + YDIFF_SHOWA, false}, + {1, JapaneseChronology.ERA_SHOWA, 0, YDIFF_SHOWA, false}, + {1, JapaneseChronology.ERA_SHOWA, -5, -5 + YDIFF_SHOWA, true}, + + {0, JapaneseChronology.ERA_TAISHO, 1, 1 + YDIFF_TAISHO, true}, + {0, JapaneseChronology.ERA_TAISHO, 100, 100 + YDIFF_TAISHO, false}, + {0, JapaneseChronology.ERA_TAISHO, 0, YDIFF_TAISHO, false}, + {0, JapaneseChronology.ERA_TAISHO, -10, -10 + YDIFF_TAISHO, false}, + + }; + } + + @Test(dataProvider="prolepticYear", groups={"tck"}) + public void test_prolepticYear(int eraValue, Era era, int yearOfEra, int expectedProlepticYear, boolean isLeapYear) { + Era eraObj = JapaneseChronology.INSTANCE.eraOf(eraValue) ; + assertTrue(JapaneseChronology.INSTANCE.eras().contains(eraObj)); + assertEquals(eraObj, era); + assertEquals(JapaneseChronology.INSTANCE.prolepticYear(era, yearOfEra), expectedProlepticYear); + assertEquals(JapaneseChronology.INSTANCE.isLeapYear(expectedProlepticYear), isLeapYear) ; + assertEquals(JapaneseChronology.INSTANCE.isLeapYear(expectedProlepticYear), Year.of(expectedProlepticYear).isLeap()) ; + } + + //----------------------------------------------------------------------- + // with(WithAdjuster) + //----------------------------------------------------------------------- + @Test(groups={"tck"}) + public void test_adjust1() { + JapaneseDate base = JapaneseChronology.INSTANCE.date(1728, 10, 29); + JapaneseDate test = base.with(Adjusters.lastDayOfMonth()); + assertEquals(test, JapaneseChronology.INSTANCE.date(1728, 10, 31)); + } + + @Test(groups={"tck"}) + public void test_adjust2() { + JapaneseDate base = JapaneseChronology.INSTANCE.date(1728, 12, 2); + JapaneseDate test = base.with(Adjusters.lastDayOfMonth()); + assertEquals(test, JapaneseChronology.INSTANCE.date(1728, 12, 31)); + } + + //----------------------------------------------------------------------- + // JapaneseDate.with(Local*) + //----------------------------------------------------------------------- + @Test(groups={"tck"}) + public void test_adjust_toLocalDate() { + JapaneseDate jdate = JapaneseChronology.INSTANCE.date(1726, 1, 4); + JapaneseDate test = jdate.with(LocalDate.of(2012, 7, 6)); + assertEquals(test, JapaneseChronology.INSTANCE.date(2012, 7, 6)); + } + + @Test(groups={"tck"}, expectedExceptions=DateTimeException.class) + public void test_adjust_toMonth() { + JapaneseDate jdate = JapaneseChronology.INSTANCE.date(1726, 1, 4); + jdate.with(Month.APRIL); + } + + //----------------------------------------------------------------------- + // LocalDate.with(JapaneseDate) + //----------------------------------------------------------------------- + @Test(groups={"tck"}) + public void test_LocalDate_adjustToJapaneseDate() { + JapaneseDate jdate = JapaneseChronology.INSTANCE.date(1728, 10, 29); + LocalDate test = LocalDate.MIN.with(jdate); + assertEquals(test, LocalDate.of(1728, 10, 29)); + } + + @Test(groups={"tck"}) + public void test_LocalDateTime_adjustToJapaneseDate() { + JapaneseDate jdate = JapaneseChronology.INSTANCE.date(1728, 10, 29); + LocalDateTime test = LocalDateTime.MIN.with(jdate); + assertEquals(test, LocalDateTime.of(1728, 10, 29, 0, 0)); + } + + //----------------------------------------------------------------------- + // Check Japanese Eras + //----------------------------------------------------------------------- + @DataProvider(name="japaneseEras") + Object[][] data_japanseseEras() { + return new Object[][] { + { JapaneseChronology.ERA_SEIREKI, -999, "Seireki"}, + { JapaneseChronology.ERA_MEIJI, -1, "Meiji"}, + { JapaneseChronology.ERA_TAISHO, 0, "Taisho"}, + { JapaneseChronology.ERA_SHOWA, 1, "Showa"}, + { JapaneseChronology.ERA_HEISEI, 2, "Heisei"}, + }; + } + + @Test(groups={"tck"}, dataProvider="japaneseEras") + public void test_Japanese_Eras(Era era, int eraValue, String name) { + assertEquals(era.getValue(), eraValue, "EraValue"); + assertEquals(era.toString(), name, "Era Name"); + assertEquals(era, JapaneseChronology.INSTANCE.eraOf(eraValue), "JapaneseChronology.eraOf()"); + List eras = JapaneseChronology.INSTANCE.eras(); + assertTrue(eras.contains(era), "Era is not present in JapaneseChronology.INSTANCE.eras()"); + } + + @Test(groups="tck") + public void test_Japanese_badEras() { + int badEras[] = {-1000, -998, -997, -2, 3, 4, 1000}; + for (int badEra : badEras) { + try { + Era era = JapaneseChronology.INSTANCE.eraOf(badEra); + fail("JapaneseChronology.eraOf returned " + era + " + for invalid eraValue " + badEra); + } catch (DateTimeException ex) { + // ignore expected exception + } + } + } + + //----------------------------------------------------------------------- + // toString() + //----------------------------------------------------------------------- + @DataProvider(name="toString") + Object[][] data_toString() { + return new Object[][] { + {JapaneseChronology.INSTANCE.date(0001, 1, 1), "Japanese 0001-01-01"}, + {JapaneseChronology.INSTANCE.date(1728, 10, 28), "Japanese 1728-10-28"}, + {JapaneseChronology.INSTANCE.date(1728, 10, 29), "Japanese 1728-10-29"}, + {JapaneseChronology.INSTANCE.date(1727, 12, 5), "Japanese 1727-12-05"}, + {JapaneseChronology.INSTANCE.date(1727, 12, 6), "Japanese 1727-12-06"}, + {JapaneseChronology.INSTANCE.date(1868, 9, 8), "Japanese Meiji 1-09-08"}, + {JapaneseChronology.INSTANCE.date(1912, 7, 29), "Japanese Meiji 45-07-29"}, + {JapaneseChronology.INSTANCE.date(1912, 7, 30), "Japanese Taisho 1-07-30"}, + {JapaneseChronology.INSTANCE.date(1926, 12, 24), "Japanese Taisho 15-12-24"}, + {JapaneseChronology.INSTANCE.date(1926, 12, 25), "Japanese Showa 1-12-25"}, + {JapaneseChronology.INSTANCE.date(1989, 1, 7), "Japanese Showa 64-01-07"}, + {JapaneseChronology.INSTANCE.date(1989, 1, 8), "Japanese Heisei 1-01-08"}, + {JapaneseChronology.INSTANCE.date(2012, 12, 6), "Japanese Heisei 24-12-06"}, + }; + } + + @Test(dataProvider="toString", groups={"tck"}) + public void test_toString(JapaneseDate jdate, String expected) { + assertEquals(jdate.toString(), expected); + } + + //----------------------------------------------------------------------- + // equals() + //----------------------------------------------------------------------- + @Test(groups="tck") + public void test_equals_true() { + assertTrue(JapaneseChronology.INSTANCE.equals(JapaneseChronology.INSTANCE)); + } + + @Test(groups="tck") + public void test_equals_false() { + assertFalse(JapaneseChronology.INSTANCE.equals(IsoChronology.INSTANCE)); + } + +} diff --git a/jdk/test/java/time/tck/java/time/calendar/TestMinguoChrono.java b/jdk/test/java/time/tck/java/time/chrono/TestMinguoChronology.java similarity index 52% rename from jdk/test/java/time/tck/java/time/calendar/TestMinguoChrono.java rename to jdk/test/java/time/tck/java/time/chrono/TestMinguoChronology.java index 118f7d89b70..5ea1979bcdf 100644 --- a/jdk/test/java/time/tck/java/time/calendar/TestMinguoChrono.java +++ b/jdk/test/java/time/tck/java/time/chrono/TestMinguoChronology.java @@ -54,7 +54,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package tck.java.time.calendar; +package tck.java.time.chrono; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -66,14 +66,17 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; import java.time.ZoneOffset; -import java.time.calendar.MinguoChrono; +import java.time.chrono.MinguoChronology; +import java.time.chrono.MinguoDate; import java.time.temporal.Adjusters; import java.time.temporal.ChronoUnit; -import java.time.temporal.ChronoZonedDateTime; -import java.time.temporal.Chrono; -import java.time.temporal.ChronoLocalDate; -import java.time.temporal.ChronoLocalDateTime; -import java.time.temporal.ISOChrono; +import java.time.chrono.ChronoZonedDateTime; +import java.time.chrono.Chronology; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.ChronoLocalDateTime; +import java.time.chrono.IsoChronology; +import java.time.chrono.Era; +import java.time.Year; import org.testng.Assert; import org.testng.annotations.DataProvider; @@ -83,15 +86,16 @@ import org.testng.annotations.Test; * Test. */ @Test -public class TestMinguoChrono { +public class TestMinguoChronology { + private static final int YDIFF = 1911; //----------------------------------------------------------------------- - // Chrono.ofName("Minguo") Lookup by name + // Chronology.ofName("Minguo") Lookup by name //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_chrono_byName() { - Chrono c = MinguoChrono.INSTANCE; - Chrono test = Chrono.of("Minguo"); + Chronology c = MinguoChronology.INSTANCE; + Chronology test = Chronology.of("Minguo"); Assert.assertNotNull(test, "The Minguo calendar could not be found byName"); Assert.assertEquals(test.getId(), "Minguo", "ID mismatch"); Assert.assertEquals(test.getCalendarType(), "roc", "Type mismatch"); @@ -104,40 +108,45 @@ public class TestMinguoChrono { @DataProvider(name="samples") Object[][] data_samples() { return new Object[][] { - {MinguoChrono.INSTANCE.date(1, 1, 1), LocalDate.of(1912, 1, 1)}, - {MinguoChrono.INSTANCE.date(1, 1, 2), LocalDate.of(1912, 1, 2)}, - {MinguoChrono.INSTANCE.date(1, 1, 3), LocalDate.of(1912, 1, 3)}, + {MinguoChronology.INSTANCE.date(1, 1, 1), LocalDate.of(1 + YDIFF, 1, 1)}, + {MinguoChronology.INSTANCE.date(1, 1, 2), LocalDate.of(1 + YDIFF, 1, 2)}, + {MinguoChronology.INSTANCE.date(1, 1, 3), LocalDate.of(1 + YDIFF, 1, 3)}, - {MinguoChrono.INSTANCE.date(2, 1, 1), LocalDate.of(1913, 1, 1)}, - {MinguoChrono.INSTANCE.date(3, 1, 1), LocalDate.of(1914, 1, 1)}, - {MinguoChrono.INSTANCE.date(3, 12, 6), LocalDate.of(1914, 12, 6)}, - {MinguoChrono.INSTANCE.date(4, 1, 1), LocalDate.of(1915, 1, 1)}, - {MinguoChrono.INSTANCE.date(4, 7, 3), LocalDate.of(1915, 7, 3)}, - {MinguoChrono.INSTANCE.date(4, 7, 4), LocalDate.of(1915, 7, 4)}, - {MinguoChrono.INSTANCE.date(5, 1, 1), LocalDate.of(1916, 1, 1)}, - {MinguoChrono.INSTANCE.date(100, 3, 3), LocalDate.of(2011, 3, 3)}, - {MinguoChrono.INSTANCE.date(101, 10, 28), LocalDate.of(2012, 10, 28)}, - {MinguoChrono.INSTANCE.date(101, 10, 29), LocalDate.of(2012, 10, 29)}, + {MinguoChronology.INSTANCE.date(2, 1, 1), LocalDate.of(2 + YDIFF, 1, 1)}, + {MinguoChronology.INSTANCE.date(3, 1, 1), LocalDate.of(3 + YDIFF, 1, 1)}, + {MinguoChronology.INSTANCE.date(3, 12, 6), LocalDate.of(3 + YDIFF, 12, 6)}, + {MinguoChronology.INSTANCE.date(4, 1, 1), LocalDate.of(4 + YDIFF, 1, 1)}, + {MinguoChronology.INSTANCE.date(4, 7, 3), LocalDate.of(4 + YDIFF, 7, 3)}, + {MinguoChronology.INSTANCE.date(4, 7, 4), LocalDate.of(4 + YDIFF, 7, 4)}, + {MinguoChronology.INSTANCE.date(5, 1, 1), LocalDate.of(5 + YDIFF, 1, 1)}, + {MinguoChronology.INSTANCE.date(100, 3, 3), LocalDate.of(100 + YDIFF, 3, 3)}, + {MinguoChronology.INSTANCE.date(101, 10, 28), LocalDate.of(101 + YDIFF, 10, 28)}, + {MinguoChronology.INSTANCE.date(101, 10, 29), LocalDate.of(101 + YDIFF, 10, 29)}, + + {MinguoChronology.INSTANCE.dateYearDay(1916 - YDIFF, 60), LocalDate.of(1916, 2, 29)}, + {MinguoChronology.INSTANCE.dateYearDay(1908 - YDIFF, 60), LocalDate.of(1908, 2, 29)}, + {MinguoChronology.INSTANCE.dateYearDay(2000 - YDIFF, 60), LocalDate.of(2000, 2, 29)}, + {MinguoChronology.INSTANCE.dateYearDay(2400 - YDIFF, 60), LocalDate.of(2400, 2, 29)}, }; } @Test(dataProvider="samples", groups={"tck"}) - public void test_toLocalDate(ChronoLocalDate minguo, LocalDate iso) { + public void test_toLocalDate(MinguoDate minguo, LocalDate iso) { assertEquals(LocalDate.from(minguo), iso); } @Test(dataProvider="samples", groups={"tck"}) - public void test_fromCalendrical(ChronoLocalDate minguo, LocalDate iso) { - assertEquals(MinguoChrono.INSTANCE.date(iso), minguo); + public void test_fromCalendrical(MinguoDate minguo, LocalDate iso) { + assertEquals(MinguoChronology.INSTANCE.date(iso), minguo); } @SuppressWarnings("unused") @Test(dataProvider="samples", groups={"implementation"}) - public void test_MinguoDate(ChronoLocalDate minguoDate, LocalDate iso) { - ChronoLocalDate hd = minguoDate; - ChronoLocalDateTime hdt = hd.atTime(LocalTime.NOON); + public void test_MinguoDate(MinguoDate minguoDate, LocalDate iso) { + MinguoDate hd = minguoDate; + ChronoLocalDateTime hdt = hd.atTime(LocalTime.NOON); ZoneOffset zo = ZoneOffset.ofHours(1); - ChronoZonedDateTime hzdt = hdt.atZone(zo); + ChronoZonedDateTime hzdt = hdt.atZone(zo); hdt = hdt.plus(1, ChronoUnit.YEARS); hdt = hdt.plus(1, ChronoUnit.MONTHS); hdt = hdt.plus(1, ChronoUnit.DAYS); @@ -145,19 +154,19 @@ public class TestMinguoChrono { hdt = hdt.plus(1, ChronoUnit.MINUTES); hdt = hdt.plus(1, ChronoUnit.SECONDS); hdt = hdt.plus(1, ChronoUnit.NANOS); - ChronoLocalDateTime a2 = hzdt.getDateTime(); - ChronoLocalDate a3 = a2.getDate(); - ChronoLocalDate a5 = hzdt.getDate(); + ChronoLocalDateTime a2 = hzdt.toLocalDateTime(); + MinguoDate a3 = a2.toLocalDate(); + MinguoDate a5 = hzdt.toLocalDate(); //System.out.printf(" d: %s, dt: %s; odt: %s; zodt: %s; a4: %s%n", date, hdt, hodt, hzdt, a5); } @Test() public void test_MinguoChrono() { - ChronoLocalDate h1 = MinguoChrono.ERA_ROC.date(1, 2, 3); - ChronoLocalDate h2 = h1; - ChronoLocalDateTime h3 = h2.atTime(LocalTime.NOON); + MinguoDate h1 = (MinguoDate)MinguoChronology.ERA_ROC.date(1, 2, 3); + MinguoDate h2 = h1; + ChronoLocalDateTime h3 = h2.atTime(LocalTime.NOON); @SuppressWarnings("unused") - ChronoZonedDateTime h4 = h3.atZone(ZoneOffset.UTC); + ChronoZonedDateTime h4 = h3.atZone(ZoneOffset.UTC); } @DataProvider(name="badDates") @@ -179,12 +188,56 @@ public class TestMinguoChrono { {1912, 12, -1}, {1912, 12, 0}, {1912, 12, 32}, + + {1907 - YDIFF, 2, 29}, + {100 - YDIFF, 2, 29}, + {2100 - YDIFF, 2, 29}, + {2101 - YDIFF, 2, 29}, }; } @Test(dataProvider="badDates", groups={"tck"}, expectedExceptions=DateTimeException.class) public void test_badDates(int year, int month, int dom) { - MinguoChrono.INSTANCE.date(year, month, dom); + MinguoChronology.INSTANCE.date(year, month, dom); + } + + //----------------------------------------------------------------------- + // prolepticYear() and is LeapYear() + //----------------------------------------------------------------------- + @DataProvider(name="prolepticYear") + Object[][] data_prolepticYear() { + return new Object[][] { + {1, MinguoChronology.ERA_ROC, 1912 - YDIFF, 1912 - YDIFF, true}, + {1, MinguoChronology.ERA_ROC, 1916 - YDIFF, 1916 - YDIFF, true}, + {1, MinguoChronology.ERA_ROC, 1914 - YDIFF, 1914 - YDIFF, false}, + {1, MinguoChronology.ERA_ROC, 2000 - YDIFF, 2000 - YDIFF, true}, + {1, MinguoChronology.ERA_ROC, 2100 - YDIFF, 2100 - YDIFF, false}, + {1, MinguoChronology.ERA_ROC, 0, 0, false}, + {1, MinguoChronology.ERA_ROC, 1908 - YDIFF, 1908 - YDIFF, true}, + {1, MinguoChronology.ERA_ROC, 1900 - YDIFF, 1900 - YDIFF, false}, + {1, MinguoChronology.ERA_ROC, 1600 - YDIFF, 1600 - YDIFF, true}, + + {0, MinguoChronology.ERA_BEFORE_ROC, YDIFF - 1911, 1912 - YDIFF, true}, + {0, MinguoChronology.ERA_BEFORE_ROC, YDIFF - 1915, 1916 - YDIFF, true}, + {0, MinguoChronology.ERA_BEFORE_ROC, YDIFF - 1913, 1914 - YDIFF, false}, + {0, MinguoChronology.ERA_BEFORE_ROC, YDIFF - 1999, 2000 - YDIFF, true}, + {0, MinguoChronology.ERA_BEFORE_ROC, YDIFF - 2099, 2100 - YDIFF, false}, + {0, MinguoChronology.ERA_BEFORE_ROC, 1, 0, false}, + {0, MinguoChronology.ERA_BEFORE_ROC, YDIFF - 1907, 1908 - YDIFF, true}, + {0, MinguoChronology.ERA_BEFORE_ROC, YDIFF - 1899, 1900 - YDIFF, false}, + {0, MinguoChronology.ERA_BEFORE_ROC, YDIFF - 1599, 1600 - YDIFF, true}, + + }; + } + + @Test(dataProvider="prolepticYear", groups={"tck"}) + public void test_prolepticYear(int eraValue, Era era, int yearOfEra, int expectedProlepticYear, boolean isLeapYear) { + Era eraObj = MinguoChronology.INSTANCE.eraOf(eraValue) ; + assertTrue(MinguoChronology.INSTANCE.eras().contains(eraObj)); + assertEquals(eraObj, era); + assertEquals(MinguoChronology.INSTANCE.prolepticYear(era, yearOfEra), expectedProlepticYear); + assertEquals(MinguoChronology.INSTANCE.isLeapYear(expectedProlepticYear), isLeapYear) ; + assertEquals(MinguoChronology.INSTANCE.isLeapYear(expectedProlepticYear), Year.of(expectedProlepticYear + YDIFF).isLeap()) ; } //----------------------------------------------------------------------- @@ -192,16 +245,16 @@ public class TestMinguoChrono { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_adjust1() { - ChronoLocalDate base = MinguoChrono.INSTANCE.date(2012, 10, 29); - ChronoLocalDate test = base.with(Adjusters.lastDayOfMonth()); - assertEquals(test, MinguoChrono.INSTANCE.date(2012, 10, 31)); + MinguoDate base = MinguoChronology.INSTANCE.date(2012, 10, 29); + MinguoDate test = base.with(Adjusters.lastDayOfMonth()); + assertEquals(test, MinguoChronology.INSTANCE.date(2012, 10, 31)); } @Test(groups={"tck"}) public void test_adjust2() { - ChronoLocalDate base = MinguoChrono.INSTANCE.date(1728, 12, 2); - ChronoLocalDate test = base.with(Adjusters.lastDayOfMonth()); - assertEquals(test, MinguoChrono.INSTANCE.date(1728, 12, 31)); + MinguoDate base = MinguoChronology.INSTANCE.date(1728, 12, 2); + MinguoDate test = base.with(Adjusters.lastDayOfMonth()); + assertEquals(test, MinguoChronology.INSTANCE.date(1728, 12, 31)); } //----------------------------------------------------------------------- @@ -209,14 +262,14 @@ public class TestMinguoChrono { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_adjust_toLocalDate() { - ChronoLocalDate minguo = MinguoChrono.INSTANCE.date(99, 1, 4); - ChronoLocalDate test = minguo.with(LocalDate.of(2012, 7, 6)); - assertEquals(test, MinguoChrono.INSTANCE.date(101, 7, 6)); + MinguoDate minguo = MinguoChronology.INSTANCE.date(99, 1, 4); + MinguoDate test = minguo.with(LocalDate.of(2012, 7, 6)); + assertEquals(test, MinguoChronology.INSTANCE.date(101, 7, 6)); } @Test(groups={"tck"}, expectedExceptions=DateTimeException.class) public void test_adjust_toMonth() { - ChronoLocalDate minguo = MinguoChrono.INSTANCE.date(1726, 1, 4); + MinguoDate minguo = MinguoChronology.INSTANCE.date(1726, 1, 4); minguo.with(Month.APRIL); } @@ -225,14 +278,14 @@ public class TestMinguoChrono { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_LocalDate_adjustToMinguoDate() { - ChronoLocalDate minguo = MinguoChrono.INSTANCE.date(101, 10, 29); + MinguoDate minguo = MinguoChronology.INSTANCE.date(101, 10, 29); LocalDate test = LocalDate.MIN.with(minguo); assertEquals(test, LocalDate.of(2012, 10, 29)); } @Test(groups={"tck"}) public void test_LocalDateTime_adjustToMinguoDate() { - ChronoLocalDate minguo = MinguoChrono.INSTANCE.date(101, 10, 29); + MinguoDate minguo = MinguoChronology.INSTANCE.date(101, 10, 29); LocalDateTime test = LocalDateTime.MIN.with(minguo); assertEquals(test, LocalDateTime.of(2012, 10, 29, 0, 0)); } @@ -243,16 +296,16 @@ public class TestMinguoChrono { @DataProvider(name="toString") Object[][] data_toString() { return new Object[][] { - {MinguoChrono.INSTANCE.date(1, 1, 1), "Minguo ROC 1-01-01"}, - {MinguoChrono.INSTANCE.date(1728, 10, 28), "Minguo ROC 1728-10-28"}, - {MinguoChrono.INSTANCE.date(1728, 10, 29), "Minguo ROC 1728-10-29"}, - {MinguoChrono.INSTANCE.date(1727, 12, 5), "Minguo ROC 1727-12-05"}, - {MinguoChrono.INSTANCE.date(1727, 12, 6), "Minguo ROC 1727-12-06"}, + {MinguoChronology.INSTANCE.date(1, 1, 1), "Minguo ROC 1-01-01"}, + {MinguoChronology.INSTANCE.date(1728, 10, 28), "Minguo ROC 1728-10-28"}, + {MinguoChronology.INSTANCE.date(1728, 10, 29), "Minguo ROC 1728-10-29"}, + {MinguoChronology.INSTANCE.date(1727, 12, 5), "Minguo ROC 1727-12-05"}, + {MinguoChronology.INSTANCE.date(1727, 12, 6), "Minguo ROC 1727-12-06"}, }; } @Test(dataProvider="toString", groups={"tck"}) - public void test_toString(ChronoLocalDate minguo, String expected) { + public void test_toString(MinguoDate minguo, String expected) { assertEquals(minguo.toString(), expected); } @@ -261,12 +314,12 @@ public class TestMinguoChrono { //----------------------------------------------------------------------- @Test(groups="tck") public void test_equals_true() { - assertTrue(MinguoChrono.INSTANCE.equals(MinguoChrono.INSTANCE)); + assertTrue(MinguoChronology.INSTANCE.equals(MinguoChronology.INSTANCE)); } @Test(groups="tck") public void test_equals_false() { - assertFalse(MinguoChrono.INSTANCE.equals(ISOChrono.INSTANCE)); + assertFalse(MinguoChronology.INSTANCE.equals(IsoChronology.INSTANCE)); } } diff --git a/jdk/test/java/time/tck/java/time/chrono/TestThaiBuddhistChronology.java b/jdk/test/java/time/tck/java/time/chrono/TestThaiBuddhistChronology.java new file mode 100644 index 00000000000..32eae1e073e --- /dev/null +++ b/jdk/test/java/time/tck/java/time/chrono/TestThaiBuddhistChronology.java @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2012, 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 + * 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. + */ + +/* + * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of JSR-310 nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package tck.java.time.chrono; + +import static java.time.temporal.ChronoField.DAY_OF_MONTH; +import static java.time.temporal.ChronoField.DAY_OF_YEAR; +import static java.time.temporal.ChronoField.MONTH_OF_YEAR; +import static java.time.temporal.ChronoField.YEAR; +import static java.time.temporal.ChronoField.YEAR_OF_ERA; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import java.time.DateTimeException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.Month; +import java.time.Year; +import java.time.chrono.ThaiBuddhistChronology; +import java.time.chrono.ThaiBuddhistDate; +import java.time.chrono.Chronology; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.Era; +import java.time.chrono.IsoChronology; +import java.time.temporal.Adjusters; +import java.time.temporal.ChronoField; +import java.time.temporal.ValueRange; +import java.util.Locale; + +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * Test. + */ +@Test +public class TestThaiBuddhistChronology { + + private static final int YDIFF = 543; + + //----------------------------------------------------------------------- + // Chronology.of(String) + //----------------------------------------------------------------------- + @Test + public void test_chrono_byName() { + Chronology c = ThaiBuddhistChronology.INSTANCE; + Chronology test = Chronology.of("ThaiBuddhist"); + Assert.assertNotNull(test, "The ThaiBuddhist calendar could not be found byName"); + Assert.assertEquals(test.getId(), "ThaiBuddhist", "ID mismatch"); + Assert.assertEquals(test.getCalendarType(), "buddhist", "Type mismatch"); + Assert.assertEquals(test, c); + } + + //----------------------------------------------------------------------- + // Chronology.ofLocale(Locale) + //----------------------------------------------------------------------- + @Test + public void test_chrono_byLocale_fullTag_thaiCalendarFromThai() { + Chronology test = Chronology.ofLocale(Locale.forLanguageTag("th-TH-u-ca-buddhist")); + Assert.assertEquals(test.getId(), "ThaiBuddhist"); + Assert.assertEquals(test, ThaiBuddhistChronology.INSTANCE); + } + + @Test + public void test_chrono_byLocale_fullTag_thaiCalendarFromElsewhere() { + Chronology test = Chronology.ofLocale(Locale.forLanguageTag("en-US-u-ca-buddhist")); + Assert.assertEquals(test.getId(), "ThaiBuddhist"); + Assert.assertEquals(test, ThaiBuddhistChronology.INSTANCE); + } + + @Test + public void test_chrono_byLocale_oldTH_noVariant() { // deliberately different to Calendar + Chronology test = Chronology.ofLocale(new Locale("th", "TH")); + Assert.assertEquals(test.getId(), "ISO"); + Assert.assertEquals(test, IsoChronology.INSTANCE); + } + + @Test + public void test_chrono_byLocale_oldTH_variant() { + Chronology test = Chronology.ofLocale(new Locale("th", "TH", "TH")); + Assert.assertEquals(test.getId(), "ISO"); + Assert.assertEquals(test, IsoChronology.INSTANCE); + } + + @Test + public void test_chrono_byLocale_iso() { + Assert.assertEquals(Chronology.ofLocale(new Locale("th", "TH")).getId(), "ISO"); + Assert.assertEquals(Chronology.ofLocale(Locale.forLanguageTag("th-TH")).getId(), "ISO"); + Assert.assertEquals(Chronology.ofLocale(Locale.forLanguageTag("th-TH-TH")).getId(), "ISO"); + } + + //----------------------------------------------------------------------- + // creation, toLocalDate() + //----------------------------------------------------------------------- + @DataProvider(name="samples") + Object[][] data_samples() { + return new Object[][] { + {ThaiBuddhistChronology.INSTANCE.date(1 + YDIFF, 1, 1), LocalDate.of(1, 1, 1)}, + {ThaiBuddhistChronology.INSTANCE.date(1 + YDIFF, 1, 2), LocalDate.of(1, 1, 2)}, + {ThaiBuddhistChronology.INSTANCE.date(1 + YDIFF, 1, 3), LocalDate.of(1, 1, 3)}, + + {ThaiBuddhistChronology.INSTANCE.date(2 + YDIFF, 1, 1), LocalDate.of(2, 1, 1)}, + {ThaiBuddhistChronology.INSTANCE.date(3 + YDIFF, 1, 1), LocalDate.of(3, 1, 1)}, + {ThaiBuddhistChronology.INSTANCE.date(3 + YDIFF, 12, 6), LocalDate.of(3, 12, 6)}, + {ThaiBuddhistChronology.INSTANCE.date(4 + YDIFF, 1, 1), LocalDate.of(4, 1, 1)}, + {ThaiBuddhistChronology.INSTANCE.date(4 + YDIFF, 7, 3), LocalDate.of(4, 7, 3)}, + {ThaiBuddhistChronology.INSTANCE.date(4 + YDIFF, 7, 4), LocalDate.of(4, 7, 4)}, + {ThaiBuddhistChronology.INSTANCE.date(5 + YDIFF, 1, 1), LocalDate.of(5, 1, 1)}, + {ThaiBuddhistChronology.INSTANCE.date(1662 + YDIFF, 3, 3), LocalDate.of(1662, 3, 3)}, + {ThaiBuddhistChronology.INSTANCE.date(1728 + YDIFF, 10, 28), LocalDate.of(1728, 10, 28)}, + {ThaiBuddhistChronology.INSTANCE.date(1728 + YDIFF, 10, 29), LocalDate.of(1728, 10, 29)}, + {ThaiBuddhistChronology.INSTANCE.date(2555, 8, 29), LocalDate.of(2012, 8, 29)}, + + {ThaiBuddhistChronology.INSTANCE.dateYearDay(4 + YDIFF, 60), LocalDate.of(4, 2, 29)}, + {ThaiBuddhistChronology.INSTANCE.dateYearDay(400 + YDIFF, 60), LocalDate.of(400, 2, 29)}, + {ThaiBuddhistChronology.INSTANCE.dateYearDay(2000 + YDIFF, 60), LocalDate.of(2000, 2, 29)}, + + }; + } + + @Test(dataProvider="samples", groups={"tck"}) + public void test_toLocalDate(ThaiBuddhistDate jdate, LocalDate iso) { + assertEquals(LocalDate.from(jdate), iso); + } + + @Test(dataProvider="samples", groups={"tck"}) + public void test_fromCalendrical(ThaiBuddhistDate jdate, LocalDate iso) { + assertEquals(ThaiBuddhistChronology.INSTANCE.date(iso), jdate); + } + + @DataProvider(name="badDates") + Object[][] data_badDates() { + return new Object[][] { + {1728, 0, 0}, + + {1728, -1, 1}, + {1728, 0, 1}, + {1728, 14, 1}, + {1728, 15, 1}, + + {1728, 1, -1}, + {1728, 1, 0}, + {1728, 1, 32}, + + {1728, 12, -1}, + {1728, 12, 0}, + {1728, 12, 32}, + + {3 + YDIFF, 2, 29}, + {600 + YDIFF, 2, 29}, + {1501 + YDIFF, 2, 29}, + }; + } + + @Test(dataProvider="badDates", groups={"tck"}, expectedExceptions=DateTimeException.class) + public void test_badDates(int year, int month, int dom) { + ThaiBuddhistChronology.INSTANCE.date(year, month, dom); + } + + //----------------------------------------------------------------------- + // prolepticYear() and is LeapYear() + //----------------------------------------------------------------------- + @DataProvider(name="prolepticYear") + Object[][] data_prolepticYear() { + return new Object[][] { + {1, ThaiBuddhistChronology.ERA_BE, 4 + YDIFF, 4 + YDIFF, true}, + {1, ThaiBuddhistChronology.ERA_BE, 7 + YDIFF, 7 + YDIFF, false}, + {1, ThaiBuddhistChronology.ERA_BE, 8 + YDIFF, 8 + YDIFF, true}, + {1, ThaiBuddhistChronology.ERA_BE, 1000 + YDIFF, 1000 + YDIFF, false}, + {1, ThaiBuddhistChronology.ERA_BE, 2000 + YDIFF, 2000 + YDIFF, true}, + {1, ThaiBuddhistChronology.ERA_BE, 0, 0, false}, + {1, ThaiBuddhistChronology.ERA_BE, -4 + YDIFF, -4 + YDIFF, true}, + {1, ThaiBuddhistChronology.ERA_BE, -7 + YDIFF, -7 + YDIFF, false}, + {1, ThaiBuddhistChronology.ERA_BE, -100 + YDIFF, -100 + YDIFF, false}, + {1, ThaiBuddhistChronology.ERA_BE, -800 + YDIFF, -800 + YDIFF, true}, + + {0, ThaiBuddhistChronology.ERA_BEFORE_BE, -3 - YDIFF, 4 + YDIFF, true}, + {0, ThaiBuddhistChronology.ERA_BEFORE_BE, -6 - YDIFF, 7 + YDIFF, false}, + {0, ThaiBuddhistChronology.ERA_BEFORE_BE, -7 - YDIFF, 8 + YDIFF, true}, + {0, ThaiBuddhistChronology.ERA_BEFORE_BE, -999 - YDIFF, 1000 + YDIFF, false}, + {0, ThaiBuddhistChronology.ERA_BEFORE_BE, -1999 - YDIFF, 2000 + YDIFF, true}, + {0, ThaiBuddhistChronology.ERA_BEFORE_BE, 1, 0, false}, + {0, ThaiBuddhistChronology.ERA_BEFORE_BE, 5 - YDIFF, -4 + YDIFF, true}, + {0, ThaiBuddhistChronology.ERA_BEFORE_BE, 8 - YDIFF, -7 + YDIFF, false}, + {0, ThaiBuddhistChronology.ERA_BEFORE_BE, 101 - YDIFF, -100 + YDIFF, false}, + {0, ThaiBuddhistChronology.ERA_BEFORE_BE, 801 - YDIFF, -800 + YDIFF, true}, + + }; + } + + @Test(dataProvider="prolepticYear", groups={"tck"}) + public void test_prolepticYear(int eraValue, Era era, int yearOfEra, int expectedProlepticYear, boolean isLeapYear) { + Era eraObj = ThaiBuddhistChronology.INSTANCE.eraOf(eraValue) ; + assertTrue(ThaiBuddhistChronology.INSTANCE.eras().contains(eraObj)); + assertEquals(eraObj, era); + assertEquals(ThaiBuddhistChronology.INSTANCE.prolepticYear(era, yearOfEra), expectedProlepticYear); + assertEquals(ThaiBuddhistChronology.INSTANCE.isLeapYear(expectedProlepticYear), isLeapYear) ; + assertEquals(ThaiBuddhistChronology.INSTANCE.isLeapYear(expectedProlepticYear), Year.of(expectedProlepticYear - YDIFF).isLeap()) ; + } + + //----------------------------------------------------------------------- + // with(WithAdjuster) + //----------------------------------------------------------------------- + @Test(groups={"tck"}) + public void test_adjust1() { + ThaiBuddhistDate base = ThaiBuddhistChronology.INSTANCE.date(1728, 10, 29); + ThaiBuddhistDate test = base.with(Adjusters.lastDayOfMonth()); + assertEquals(test, ThaiBuddhistChronology.INSTANCE.date(1728, 10, 31)); + } + + @Test(groups={"tck"}) + public void test_adjust2() { + ThaiBuddhistDate base = ThaiBuddhistChronology.INSTANCE.date(1728, 12, 2); + ThaiBuddhistDate test = base.with(Adjusters.lastDayOfMonth()); + assertEquals(test, ThaiBuddhistChronology.INSTANCE.date(1728, 12, 31)); + } + + //----------------------------------------------------------------------- + // withYear() + //----------------------------------------------------------------------- + @Test(groups={"tck"}) + public void test_withYear_BE() { + ThaiBuddhistDate base = ThaiBuddhistChronology.INSTANCE.date(2555, 8, 29); + ThaiBuddhistDate test = base.with(YEAR, 2554); + assertEquals(test, ThaiBuddhistChronology.INSTANCE.date(2554, 8, 29)); + } + + @Test(groups={"tck"}) + public void test_withYear_BBE() { + ThaiBuddhistDate base = ThaiBuddhistChronology.INSTANCE.date(-2554, 8, 29); + ThaiBuddhistDate test = base.with(YEAR_OF_ERA, 2554); + assertEquals(test, ThaiBuddhistChronology.INSTANCE.date(-2553, 8, 29)); + } + + //----------------------------------------------------------------------- + // withEra() + //----------------------------------------------------------------------- + @Test(groups={"tck"}) + public void test_withEra_BE() { + ThaiBuddhistDate base = ThaiBuddhistChronology.INSTANCE.date(2555, 8, 29); + ThaiBuddhistDate test = base.with(ChronoField.ERA, ThaiBuddhistChronology.ERA_BE.getValue()); + assertEquals(test, ThaiBuddhistChronology.INSTANCE.date(2555, 8, 29)); + } + + @Test(groups={"tck"}) + public void test_withEra_BBE() { + ThaiBuddhistDate base = ThaiBuddhistChronology.INSTANCE.date(-2554, 8, 29); + ThaiBuddhistDate test = base.with(ChronoField.ERA, ThaiBuddhistChronology.ERA_BEFORE_BE.getValue()); + assertEquals(test, ThaiBuddhistChronology.INSTANCE.date(-2554, 8, 29)); + } + + @Test(groups={"tck"}) + public void test_withEra_swap() { + ThaiBuddhistDate base = ThaiBuddhistChronology.INSTANCE.date(-2554, 8, 29); + ThaiBuddhistDate test = base.with(ChronoField.ERA, ThaiBuddhistChronology.ERA_BE.getValue()); + assertEquals(test, ThaiBuddhistChronology.INSTANCE.date(2555, 8, 29)); + } + + //----------------------------------------------------------------------- + // BuddhistDate.with(Local*) + //----------------------------------------------------------------------- + @Test(groups={"tck"}) + public void test_adjust_toLocalDate() { + ThaiBuddhistDate jdate = ThaiBuddhistChronology.INSTANCE.date(1726, 1, 4); + ThaiBuddhistDate test = jdate.with(LocalDate.of(2012, 7, 6)); + assertEquals(test, ThaiBuddhistChronology.INSTANCE.date(2555, 7, 6)); + } + + @Test(groups={"tck"}, expectedExceptions=DateTimeException.class) + public void test_adjust_toMonth() { + ThaiBuddhistDate jdate = ThaiBuddhistChronology.INSTANCE.date(1726, 1, 4); + jdate.with(Month.APRIL); + } + + //----------------------------------------------------------------------- + // LocalDate.with(BuddhistDate) + //----------------------------------------------------------------------- + @Test(groups={"tck"}) + public void test_LocalDate_adjustToBuddhistDate() { + ThaiBuddhistDate jdate = ThaiBuddhistChronology.INSTANCE.date(2555, 10, 29); + LocalDate test = LocalDate.MIN.with(jdate); + assertEquals(test, LocalDate.of(2012, 10, 29)); + } + + @Test(groups={"tck"}) + public void test_LocalDateTime_adjustToBuddhistDate() { + ThaiBuddhistDate jdate = ThaiBuddhistChronology.INSTANCE.date(2555, 10, 29); + LocalDateTime test = LocalDateTime.MIN.with(jdate); + assertEquals(test, LocalDateTime.of(2012, 10, 29, 0, 0)); + } + + //----------------------------------------------------------------------- + // toString() + //----------------------------------------------------------------------- + @DataProvider(name="toString") + Object[][] data_toString() { + return new Object[][] { + {ThaiBuddhistChronology.INSTANCE.date(544, 1, 1), "ThaiBuddhist BE 544-01-01"}, + {ThaiBuddhistChronology.INSTANCE.date(2271, 10, 28), "ThaiBuddhist BE 2271-10-28"}, + {ThaiBuddhistChronology.INSTANCE.date(2271, 10, 29), "ThaiBuddhist BE 2271-10-29"}, + {ThaiBuddhistChronology.INSTANCE.date(2270, 12, 5), "ThaiBuddhist BE 2270-12-05"}, + {ThaiBuddhistChronology.INSTANCE.date(2270, 12, 6), "ThaiBuddhist BE 2270-12-06"}, + }; + } + + @Test(dataProvider="toString", groups={"tck"}) + public void test_toString(ThaiBuddhistDate jdate, String expected) { + assertEquals(jdate.toString(), expected); + } + + //----------------------------------------------------------------------- + // chronology range(ChronoField) + //----------------------------------------------------------------------- + @Test(groups={"tck"}) + public void test_Chrono_range() { + long minYear = LocalDate.MIN.getYear() + YDIFF; + long maxYear = LocalDate.MAX.getYear() + YDIFF; + assertEquals(ThaiBuddhistChronology.INSTANCE.range(YEAR), ValueRange.of(minYear, maxYear)); + assertEquals(ThaiBuddhistChronology.INSTANCE.range(YEAR_OF_ERA), ValueRange.of(1, -minYear + 1, maxYear)); + + assertEquals(ThaiBuddhistChronology.INSTANCE.range(DAY_OF_MONTH), DAY_OF_MONTH.range()); + assertEquals(ThaiBuddhistChronology.INSTANCE.range(DAY_OF_YEAR), DAY_OF_YEAR.range()); + assertEquals(ThaiBuddhistChronology.INSTANCE.range(MONTH_OF_YEAR), MONTH_OF_YEAR.range()); + } + + //----------------------------------------------------------------------- + // equals() + //----------------------------------------------------------------------- + @Test(groups="tck") + public void test_equals_true() { + assertTrue(ThaiBuddhistChronology.INSTANCE.equals(ThaiBuddhistChronology.INSTANCE)); + } + + @Test(groups="tck") + public void test_equals_false() { + assertFalse(ThaiBuddhistChronology.INSTANCE.equals(IsoChronology.INSTANCE)); + } + +} diff --git a/jdk/test/java/time/test/java/time/format/TestPadParserDecorator.java b/jdk/test/java/time/tck/java/time/format/TCKChronoPrinterParser.java similarity index 50% rename from jdk/test/java/time/test/java/time/format/TestPadParserDecorator.java rename to jdk/test/java/time/tck/java/time/format/TCKChronoPrinterParser.java index 08a9e24544d..e4e74f6f351 100644 --- a/jdk/test/java/time/test/java/time/format/TestPadParserDecorator.java +++ b/jdk/test/java/time/tck/java/time/format/TCKChronoPrinterParser.java @@ -27,7 +27,7 @@ * However, the following notice accompanied the original version of this * file: * - * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos + * Copyright (c) 2010-2012, Stephen Colebourne & Michael Nascimento Santos * * All rights reserved. * @@ -57,84 +57,110 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package test.java.time.format; +package tck.java.time.format; -import java.time.format.*; - -import static java.time.temporal.ChronoField.MONTH_OF_YEAR; import static org.testng.Assert.assertEquals; import java.text.ParsePosition; -import java.time.format.DateTimeBuilder; +import java.time.chrono.Chronology; +import java.time.chrono.IsoChronology; +import java.time.chrono.JapaneseChronology; +import java.time.chrono.ThaiBuddhistChronology; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.Queries; +import java.time.temporal.TemporalAccessor; +import java.util.Locale; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** - * Test PadPrinterParserDecorator. + * Test formatter chrono. */ -@Test(groups={"implementation"}) -public class TestPadParserDecorator extends AbstractTestPrinterParser { +@Test +public class TCKChronoPrinterParser { + // this test assumes ISO, ThaiBuddhist and Japanese are available + + private DateTimeFormatterBuilder builder; + private ParsePosition pos; + + @BeforeMethod + public void setUp() { + builder = new DateTimeFormatterBuilder(); + pos = new ParsePosition(0); + } //----------------------------------------------------------------------- @Test(expectedExceptions=IndexOutOfBoundsException.class) - public void test_parse_negativePosition() throws Exception { - builder.padNext(3, '-').appendLiteral('Z'); - getFormatter().parseToBuilder("--Z", new ParsePosition(-1)); + public void test_parse_negativePosition() { + builder.appendChronologyId().toFormatter().parseUnresolved("ISO", new ParsePosition(-1)); } @Test(expectedExceptions=IndexOutOfBoundsException.class) - public void test_parse_offEndPosition() throws Exception { - builder.padNext(3, '-').appendLiteral('Z'); - getFormatter().parseToBuilder("--Z", new ParsePosition(4)); + public void test_parse_offEndPosition() { + builder.appendChronologyId().toFormatter().parseUnresolved("ISO", new ParsePosition(4)); } //----------------------------------------------------------------------- - public void test_parse() throws Exception { - ParsePosition pos = new ParsePosition(0); - builder.padNext(3, '-').appendValue(MONTH_OF_YEAR, 1, 3, SignStyle.NEVER); - DateTimeBuilder dtb = getFormatter().parseToBuilder("--2", pos); - assertEquals(pos.getIndex(), 3); - assertEquals(dtb.getFieldValueMap().size(), 1); - assertEquals(dtb.getLong(MONTH_OF_YEAR), 2L); + @DataProvider(name="parseValid") + Object[][] data_parseValid() { + return new Object[][] { + {"ISO", IsoChronology.INSTANCE}, + {"ThaiBuddhist", ThaiBuddhistChronology.INSTANCE}, + {"Japanese", JapaneseChronology.INSTANCE}, + + {"ISO2012", IsoChronology.INSTANCE}, + {"ThaiBuddhistXXX", ThaiBuddhistChronology.INSTANCE}, + {"JapaneseXXX", JapaneseChronology.INSTANCE}, + }; } - public void test_parse_noReadBeyond() throws Exception { - ParsePosition pos = new ParsePosition(0); - builder.padNext(3, '-').appendValue(MONTH_OF_YEAR, 1, 3, SignStyle.NEVER); - DateTimeBuilder dtb = getFormatter().parseToBuilder("--22", pos); - assertEquals(pos.getIndex(), 3); - assertEquals(dtb.getFieldValueMap().size(), 1); - assertEquals(dtb.getLong(MONTH_OF_YEAR), 2L); + @Test(dataProvider="parseValid") + public void test_parseValid_caseSensitive(String text, Chronology expected) { + builder.appendChronologyId(); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved(text, pos); + assertEquals(pos.getIndex(), expected.getId().length()); + assertEquals(pos.getErrorIndex(), -1); + assertEquals(parsed.query(Queries.chronology()), expected); } - public void test_parse_textLessThanPadWidth() throws Exception { - ParsePosition pos = new ParsePosition(0); - builder.padNext(3, '-').appendValue(MONTH_OF_YEAR, 1, 3, SignStyle.NEVER); - DateTimeBuilder dtb = getFormatter().parseToBuilder("-1", pos); + @Test(dataProvider="parseValid") + public void test_parseValid_caseSensitive_lowercaseRejected(String text, Chronology expected) { + builder.appendChronologyId(); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved(text.toLowerCase(Locale.ENGLISH), pos); + assertEquals(pos.getIndex(), 0); assertEquals(pos.getErrorIndex(), 0); + assertEquals(parsed, null); } - public void test_parse_decoratedErrorPassedBack() throws Exception { - ParsePosition pos = new ParsePosition(0); - builder.padNext(3, '-').appendValue(MONTH_OF_YEAR, 1, 3, SignStyle.NEVER); - DateTimeBuilder dtb = getFormatter().parseToBuilder("--A", pos); - assertEquals(pos.getErrorIndex(), 2); - } - - public void test_parse_decoratedDidNotParseToPadWidth() throws Exception { - ParsePosition pos = new ParsePosition(0); - builder.padNext(3, '-').appendValue(MONTH_OF_YEAR, 1, 3, SignStyle.NEVER); - DateTimeBuilder dtb = getFormatter().parseToBuilder("-1X", pos); - assertEquals(pos.getErrorIndex(), 0); + @Test(dataProvider="parseValid") + public void test_parseValid_caseInsensitive(String text, Chronology expected) { + builder.parseCaseInsensitive().appendChronologyId(); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved(text.toLowerCase(Locale.ENGLISH), pos); + assertEquals(pos.getIndex(), expected.getId().length()); + assertEquals(pos.getErrorIndex(), -1); + assertEquals(parsed.query(Queries.chronology()), expected); } //----------------------------------------------------------------------- - public void test_parse_decoratedStartsWithPad() throws Exception { - ParsePosition pos = new ParsePosition(0); - builder.padNext(8, '-').appendLiteral("-HELLO-"); - DateTimeBuilder dtb = getFormatter().parseToBuilder("--HELLO-", pos); - assertEquals(pos.getIndex(), 8); - assertEquals(dtb.getFieldValueMap().size(), 0); + @DataProvider(name="parseInvalid") + Object[][] data_parseInvalid() { + return new Object[][] { + {"Rubbish"}, + {"IS"}, + {"Thai"}, + {"Japan"}, + }; + } + + @Test(dataProvider="parseInvalid") + public void test_parseInvalid(String text) { + builder.appendChronologyId(); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved(text, pos); + assertEquals(pos.getIndex(), 0); + assertEquals(pos.getErrorIndex(), 0); + assertEquals(parsed, null); } } diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatter.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatter.java index e206a1f28a7..f124d7ef215 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatter.java +++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatter.java @@ -61,12 +61,13 @@ package tck.java.time.format; import static java.time.temporal.ChronoField.DAY_OF_MONTH; import static java.time.temporal.ChronoField.HOUR_OF_DAY; +import static java.time.temporal.ChronoField.MONTH_OF_YEAR; import static java.time.temporal.ChronoField.YEAR; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; -import java.io.IOException; import java.text.Format; import java.text.ParseException; import java.text.ParsePosition; @@ -80,20 +81,16 @@ import java.time.LocalTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; -import java.time.calendar.ThaiBuddhistChrono; +import java.time.chrono.ThaiBuddhistChronology; import java.time.format.DateTimeFormatSymbols; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; -import java.time.format.DateTimeFormatters; import java.time.format.DateTimeParseException; -import java.time.format.DateTimePrintException; import java.time.format.SignStyle; -import java.time.format.DateTimeBuilder; -import java.time.temporal.Chrono; -import java.time.temporal.ISOChrono; -import java.time.temporal.OffsetDate; -import java.time.temporal.OffsetDateTime; -import java.time.temporal.OffsetTime; +import java.time.chrono.Chronology; +import java.time.chrono.IsoChronology; +import java.time.OffsetDateTime; +import java.time.OffsetTime; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalQuery; @@ -101,7 +98,6 @@ import java.time.temporal.TemporalQuery; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import test.java.time.format.MockIOExceptionAppendable; /** * Test DateTimeFormatter. @@ -113,8 +109,8 @@ public class TCKDateTimeFormatter { private static final ZoneOffset OFFSET_PTHREE = ZoneOffset.ofHours(3); private static final ZoneId ZONE_PARIS = ZoneId.of("Europe/Paris"); - private static final DateTimeFormatter BASIC_FORMATTER = DateTimeFormatters.pattern("'ONE'd"); - private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatters.pattern("'ONE'yyyy MM dd"); + private static final DateTimeFormatter BASIC_FORMATTER = DateTimeFormatter.ofPattern("'ONE'd"); + private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("'ONE'yyyy MM dd"); private DateTimeFormatter fmt; @@ -141,13 +137,13 @@ public class TCKDateTimeFormatter { //----------------------------------------------------------------------- @Test - public void test_withChrono() { + public void test_withChronology() { DateTimeFormatter test = fmt; - assertEquals(test.getChrono(), null); - test = test.withChrono(ISOChrono.INSTANCE); - assertEquals(test.getChrono(), ISOChrono.INSTANCE); - test = test.withChrono(null); - assertEquals(test.getChrono(), null); + assertEquals(test.getChronology(), null); + test = test.withChronology(IsoChronology.INSTANCE); + assertEquals(test.getChronology(), IsoChronology.INSTANCE); + test = test.withChronology(null); + assertEquals(test.getChronology(), null); } //----------------------------------------------------------------------- @@ -167,11 +163,10 @@ public class TCKDateTimeFormatter { // print //----------------------------------------------------------------------- @DataProvider(name="print") - Object[][] data_print() { + Object[][] data_format() { LocalDate ld = LocalDate.of(2008, 6, 30); LocalTime lt = LocalTime.of(11, 30); LocalDateTime ldt = LocalDateTime.of(2008, 6, 30, 11, 30); - OffsetDate od = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); OffsetTime ot = OffsetTime.of(LocalTime.of(11, 30), OFFSET_PONE); OffsetDateTime odt = OffsetDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30), OFFSET_PONE); ZonedDateTime zdt = ZonedDateTime.of(LocalDateTime.of(2008, 6, 30, 11, 30), ZONE_PARIS); @@ -180,7 +175,6 @@ public class TCKDateTimeFormatter { {null, null, ld, "2008::"}, {null, null, lt, ":11:"}, {null, null, ldt, "2008:11:"}, - {null, null, od, "2008::+01:00"}, {null, null, ot, ":11:+01:00"}, {null, null, odt, "2008:11:+01:00"}, {null, null, zdt, "2008:11:+02:00Europe/Paris"}, @@ -189,7 +183,6 @@ public class TCKDateTimeFormatter { {null, ZONE_PARIS, ld, "2008::"}, {null, ZONE_PARIS, lt, ":11:"}, {null, ZONE_PARIS, ldt, "2008:11:"}, - {null, ZONE_PARIS, od, "2008::+01:00"}, {null, ZONE_PARIS, ot, ":11:+01:00"}, {null, ZONE_PARIS, odt, "2008:12:+02:00Europe/Paris"}, {null, ZONE_PARIS, zdt, "2008:11:+02:00Europe/Paris"}, @@ -198,61 +191,58 @@ public class TCKDateTimeFormatter { {null, OFFSET_PTHREE, ld, "2008::"}, {null, OFFSET_PTHREE, lt, ":11:"}, {null, OFFSET_PTHREE, ldt, "2008:11:"}, - {null, OFFSET_PTHREE, od, "2008::+01:00"}, {null, OFFSET_PTHREE, ot, ":11:+01:00"}, {null, OFFSET_PTHREE, odt, "2008:13:+03:00"}, {null, OFFSET_PTHREE, zdt, "2008:12:+03:00"}, {null, OFFSET_PTHREE, instant, "1970:04:+03:00"}, - {ThaiBuddhistChrono.INSTANCE, null, ld, "2551::"}, - {ThaiBuddhistChrono.INSTANCE, null, lt, ":11:"}, - {ThaiBuddhistChrono.INSTANCE, null, ldt, "2551:11:"}, - {ThaiBuddhistChrono.INSTANCE, null, od, "2551::+01:00"}, - {ThaiBuddhistChrono.INSTANCE, null, ot, ":11:+01:00"}, - {ThaiBuddhistChrono.INSTANCE, null, odt, "2551:11:+01:00"}, - {ThaiBuddhistChrono.INSTANCE, null, zdt, "2551:11:+02:00Europe/Paris"}, - {ThaiBuddhistChrono.INSTANCE, null, instant, "::"}, + {ThaiBuddhistChronology.INSTANCE, null, ld, "2551::"}, + {ThaiBuddhistChronology.INSTANCE, null, lt, ":11:"}, + {ThaiBuddhistChronology.INSTANCE, null, ldt, "2551:11:"}, + {ThaiBuddhistChronology.INSTANCE, null, ot, ":11:+01:00"}, + {ThaiBuddhistChronology.INSTANCE, null, odt, "2551:11:+01:00"}, + {ThaiBuddhistChronology.INSTANCE, null, zdt, "2551:11:+02:00Europe/Paris"}, + {ThaiBuddhistChronology.INSTANCE, null, instant, "::"}, - {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, ld, "2551::"}, - {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, lt, ":11:"}, - {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, ldt, "2551:11:"}, - {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, od, "2551::+01:00"}, - {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, ot, ":11:+01:00"}, - {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, odt, "2551:12:+02:00Europe/Paris"}, - {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, zdt, "2551:11:+02:00Europe/Paris"}, - {ThaiBuddhistChrono.INSTANCE, ZONE_PARIS, instant, "1970:02:+01:00Europe/Paris"}, + {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, ld, "2551::"}, + {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, lt, ":11:"}, + {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, ldt, "2551:11:"}, + {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, ot, ":11:+01:00"}, + {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, odt, "2551:12:+02:00Europe/Paris"}, + {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, zdt, "2551:11:+02:00Europe/Paris"}, + {ThaiBuddhistChronology.INSTANCE, ZONE_PARIS, instant, "1970:02:+01:00Europe/Paris"}, }; } @Test(dataProvider="print") - public void test_print_Temporal(Chrono overrideChrono, ZoneId overrideZone, Temporal temporal, String expected) { + public void test_print_Temporal(Chronology overrideChrono, ZoneId overrideZone, Temporal temporal, String expected) { DateTimeFormatter test = new DateTimeFormatterBuilder() .optionalStart().appendValue(YEAR, 4).optionalEnd() .appendLiteral(':').optionalStart().appendValue(HOUR_OF_DAY, 2).optionalEnd() .appendLiteral(':').optionalStart().appendOffsetId().optionalStart().appendZoneRegionId().optionalEnd().optionalEnd() .toFormatter(Locale.ENGLISH) - .withChrono(overrideChrono).withZone(overrideZone); - String result = test.print(temporal); + .withChronology(overrideChrono).withZone(overrideZone); + String result = test.format(temporal); assertEquals(result, expected); } @Test public void test_print_Temporal_simple() throws Exception { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); - String result = test.print(LocalDate.of(2008, 6, 30)); + String result = test.format(LocalDate.of(2008, 6, 30)); assertEquals(result, "ONE30"); } @Test(expectedExceptions=DateTimeException.class) public void test_print_Temporal_noSuchField() throws Exception { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); - test.print(LocalTime.of(11, 30)); + test.format(LocalTime.of(11, 30)); } @Test(expectedExceptions=NullPointerException.class) public void test_print_Temporal_null() throws Exception { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); - test.print((TemporalAccessor) null); + test.format((TemporalAccessor) null); } //----------------------------------------------------------------------- @@ -260,7 +250,7 @@ public class TCKDateTimeFormatter { public void test_print_TemporalAppendable() throws Exception { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); StringBuilder buf = new StringBuilder(); - test.printTo(LocalDate.of(2008, 6, 30), buf); + test.formatTo(LocalDate.of(2008, 6, 30), buf); assertEquals(buf.toString(), "ONE30"); } @@ -268,33 +258,117 @@ public class TCKDateTimeFormatter { public void test_print_TemporalAppendable_noSuchField() throws Exception { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); StringBuilder buf = new StringBuilder(); - test.printTo(LocalTime.of(11, 30), buf); + test.formatTo(LocalTime.of(11, 30), buf); } @Test(expectedExceptions=NullPointerException.class) public void test_print_TemporalAppendable_nullTemporal() throws Exception { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); StringBuilder buf = new StringBuilder(); - test.printTo((TemporalAccessor) null, buf); + test.formatTo((TemporalAccessor) null, buf); } @Test(expectedExceptions=NullPointerException.class) public void test_print_TemporalAppendable_nullAppendable() throws Exception { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); - test.printTo(LocalDate.of(2008, 6, 30), (Appendable) null); + test.formatTo(LocalDate.of(2008, 6, 30), (Appendable) null); } - @Test(expectedExceptions=IOException.class) // IOException - public void test_print_TemporalAppendable_ioError() throws Exception { + //----------------------------------------------------------------------- + // parse(CharSequence) + //----------------------------------------------------------------------- + @Test + public void test_parse_CharSequence() { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); + TemporalAccessor result = test.parse("ONE30"); + assertEquals(result.isSupported(DAY_OF_MONTH), true); + assertEquals(result.getLong(DAY_OF_MONTH), 30L); + assertEquals(result.isSupported(HOUR_OF_DAY), false); + } + + @Test + public void test_parse_CharSequence_resolved() { + DateTimeFormatter test = DateTimeFormatter.ISO_DATE; + TemporalAccessor result = test.parse("2012-06-30"); + assertEquals(result.isSupported(YEAR), true); + assertEquals(result.isSupported(MONTH_OF_YEAR), true); + assertEquals(result.isSupported(DAY_OF_MONTH), true); + assertEquals(result.isSupported(HOUR_OF_DAY), false); + assertEquals(result.getLong(YEAR), 2012L); + assertEquals(result.getLong(MONTH_OF_YEAR), 6L); + assertEquals(result.getLong(DAY_OF_MONTH), 30L); + assertEquals(result.query(LocalDate::from), LocalDate.of(2012, 6, 30)); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_parse_CharSequence_null() { + DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); + test.parse((String) null); + } + + //----------------------------------------------------------------------- + // parse(CharSequence) + //----------------------------------------------------------------------- + @Test + public void test_parse_CharSequence_ParsePosition() { + DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); + ParsePosition pos = new ParsePosition(3); + TemporalAccessor result = test.parse("XXXONE30XXX", pos); + assertEquals(pos.getIndex(), 8); + assertEquals(pos.getErrorIndex(), -1); + assertEquals(result.isSupported(DAY_OF_MONTH), true); + assertEquals(result.getLong(DAY_OF_MONTH), 30L); + assertEquals(result.isSupported(HOUR_OF_DAY), false); + } + + @Test + public void test_parse_CharSequence_ParsePosition_resolved() { + DateTimeFormatter test = DateTimeFormatter.ISO_DATE; + ParsePosition pos = new ParsePosition(3); + TemporalAccessor result = test.parse("XXX2012-06-30XXX", pos); + assertEquals(pos.getIndex(), 13); + assertEquals(pos.getErrorIndex(), -1); + assertEquals(result.isSupported(YEAR), true); + assertEquals(result.isSupported(MONTH_OF_YEAR), true); + assertEquals(result.isSupported(DAY_OF_MONTH), true); + assertEquals(result.isSupported(HOUR_OF_DAY), false); + assertEquals(result.getLong(YEAR), 2012L); + assertEquals(result.getLong(MONTH_OF_YEAR), 6L); + assertEquals(result.getLong(DAY_OF_MONTH), 30L); + assertEquals(result.query(LocalDate::from), LocalDate.of(2012, 6, 30)); + } + + @Test(expectedExceptions=DateTimeParseException.class) + public void test_parse_CharSequence_ParsePosition_parseError() { + DateTimeFormatter test = DateTimeFormatter.ISO_DATE; + ParsePosition pos = new ParsePosition(3); try { - test.printTo(LocalDate.of(2008, 6, 30), new MockIOExceptionAppendable()); - } catch (DateTimePrintException ex) { - assertEquals(ex.getCause() instanceof IOException, true); - ex.rethrowIOException(); + test.parse("XXX2012XXX", pos); + fail(); + } catch (DateTimeParseException ex) { + assertEquals(ex.getErrorIndex(), 7); + throw ex; } } + @Test(expectedExceptions=IndexOutOfBoundsException.class) + public void test_parse_CharSequence_ParsePosition_indexTooBig() { + DateTimeFormatter test = DateTimeFormatter.ISO_DATE; + test.parse("Text", new ParsePosition(5)); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_parse_CharSequence_ParsePosition_nullText() { + DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); + test.parse((CharSequence) null, new ParsePosition(0)); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_parse_CharSequence_ParsePosition_nullParsePosition() { + DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); + test.parse("Text", (ParsePosition) null); + } + //----------------------------------------------------------------------- // parse(Query) //----------------------------------------------------------------------- @@ -363,23 +437,24 @@ public class TCKDateTimeFormatter { //----------------------------------------------------------------------- @Test public void test_parseBest_firstOption() throws Exception { - DateTimeFormatter test = DateTimeFormatters.pattern("yyyy-MM-dd[ZZZ]"); - TemporalAccessor result = test.parseBest("2011-06-30+03:00", OffsetDate::from, LocalDate::from); - assertEquals(result, OffsetDate.of(LocalDate.of(2011, 6, 30), ZoneOffset.ofHours(3))); + DateTimeFormatter test = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm[XXX]"); + TemporalAccessor result = test.parseBest("2011-06-30 12:30+03:00", ZonedDateTime::from, LocalDateTime::from); + LocalDateTime ldt = LocalDateTime.of(2011, 6, 30, 12, 30); + assertEquals(result, ZonedDateTime.of(ldt, ZoneOffset.ofHours(3))); } @Test public void test_parseBest_secondOption() throws Exception { - DateTimeFormatter test = DateTimeFormatters.pattern("yyyy-MM-dd[ZZZ]"); - TemporalAccessor result = test.parseBest("2011-06-30", OffsetDate::from, LocalDate::from); + DateTimeFormatter test = DateTimeFormatter.ofPattern("yyyy-MM-dd[ HH:mm[XXX]]"); + TemporalAccessor result = test.parseBest("2011-06-30", ZonedDateTime::from, LocalDate::from); assertEquals(result, LocalDate.of(2011, 6, 30)); } @Test(expectedExceptions=DateTimeParseException.class) public void test_parseBest_String_parseError() throws Exception { - DateTimeFormatter test = DateTimeFormatters.pattern("yyyy-MM-dd[ZZZ]"); + DateTimeFormatter test = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm[XXX]"); try { - test.parseBest("2011-06-XX", OffsetDate::from, LocalDate::from); + test.parseBest("2011-06-XX", ZonedDateTime::from, LocalDateTime::from); } catch (DateTimeParseException ex) { assertEquals(ex.getMessage().contains("could not be parsed"), true); assertEquals(ex.getMessage().contains("XX"), true); @@ -393,7 +468,7 @@ public class TCKDateTimeFormatter { public void test_parseBest_String_parseErrorLongText() throws Exception { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); try { - test.parseBest("ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789", LocalDate::from, OffsetDate::from); + test.parseBest("ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789", ZonedDateTime::from, LocalDate::from); } catch (DateTimeParseException ex) { assertEquals(ex.getMessage().contains("could not be parsed"), true); assertEquals(ex.getMessage().contains("ONEXXX6789012345678901234567890123456789012345678901234567890123..."), true); @@ -407,7 +482,7 @@ public class TCKDateTimeFormatter { public void test_parseBest_String_parseIncomplete() throws Exception { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); try { - test.parseBest("ONE30SomethingElse", LocalDate::from, OffsetDate::from); + test.parseBest("ONE30SomethingElse", ZonedDateTime::from, LocalDate::from); } catch (DateTimeParseException ex) { assertEquals(ex.getMessage().contains("could not be parsed"), true); assertEquals(ex.getMessage().contains("ONE30SomethingElse"), true); @@ -420,7 +495,7 @@ public class TCKDateTimeFormatter { @Test(expectedExceptions=NullPointerException.class) public void test_parseBest_String_nullText() throws Exception { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); - test.parseBest((String) null, LocalDate::from, OffsetDate::from); + test.parseBest((String) null, ZonedDateTime::from, LocalDate::from); } @Test(expectedExceptions=NullPointerException.class) @@ -443,108 +518,65 @@ public class TCKDateTimeFormatter { //----------------------------------------------------------------------- @Test - public void test_parseToBuilder_String() throws Exception { - DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); - DateTimeBuilder result = test.parseToBuilder("ONE30"); - assertEquals(result.getFieldValueMap().size(), 1); - assertEquals(result.getFieldValue(DAY_OF_MONTH), 30L); - assertEquals(result.getCalendricalList().size(), 0); - } - - @Test - public void test_parseToBuilder_CharSequence() throws Exception { - DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); - DateTimeBuilder result = test.parseToBuilder(new StringBuilder("ONE30")); - assertEquals(result.getFieldValueMap().size(), 1); - assertEquals(result.getFieldValue(DAY_OF_MONTH), 30L); - assertEquals(result.getCalendricalList().size(), 0); - } - - @Test(expectedExceptions=DateTimeParseException.class) - public void test_parseToBuilder_String_parseError() throws Exception { - DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); - try { - test.parseToBuilder("ONEXXX"); - } catch (DateTimeParseException ex) { - assertEquals(ex.getMessage().contains("ONEXXX"), true); - assertEquals(ex.getParsedString(), "ONEXXX"); - assertEquals(ex.getErrorIndex(), 3); - throw ex; - } - } - - @Test(expectedExceptions=DateTimeParseException.class) - public void test_parseToBuilder_String_parseErrorLongText() throws Exception { - DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); - try { - test.parseToBuilder("ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789"); - } catch (DateTimeParseException ex) { - assertEquals(ex.getMessage().contains("ONEXXX6789012345678901234567890123456789012345678901234567890123..."), true); - assertEquals(ex.getParsedString(), "ONEXXX67890123456789012345678901234567890123456789012345678901234567890123456789"); - assertEquals(ex.getErrorIndex(), 3); - throw ex; - } - } - - @Test(expectedExceptions=DateTimeParseException.class) - public void test_parseToBuilder_String_parseIncomplete() throws Exception { - DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); - try { - test.parseToBuilder("ONE30SomethingElse"); - } catch (DateTimeParseException ex) { - assertEquals(ex.getMessage().contains("ONE30SomethingElse"), true); - assertEquals(ex.getParsedString(), "ONE30SomethingElse"); - assertEquals(ex.getErrorIndex(), 5); - throw ex; - } - } - - @Test(expectedExceptions=NullPointerException.class) - public void test_parseToBuilder_String_null() throws Exception { - DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); - test.parseToBuilder((String) null); - } - - //----------------------------------------------------------------------- - @Test - public void test_parseToBuilder_StringParsePosition() throws Exception { + public void test_parseUnresolved_StringParsePosition() { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); ParsePosition pos = new ParsePosition(0); - DateTimeBuilder result = test.parseToBuilder("ONE30XXX", pos); + TemporalAccessor result = test.parseUnresolved("ONE30XXX", pos); assertEquals(pos.getIndex(), 5); assertEquals(pos.getErrorIndex(), -1); - assertEquals(result.getFieldValueMap().size(), 1); - assertEquals(result.getFieldValueMap().get(DAY_OF_MONTH), Long.valueOf(30)); + assertEquals(result.getLong(DAY_OF_MONTH), 30L); } @Test - public void test_parseToBuilder_StringParsePosition_parseError() throws Exception { + public void test_parseUnresolved_StringParsePosition_parseError() { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); ParsePosition pos = new ParsePosition(0); - DateTimeBuilder result = test.parseToBuilder("ONEXXX", pos); - assertEquals(pos.getIndex(), 0); // TODO: is this right? + TemporalAccessor result = test.parseUnresolved("ONEXXX", pos); + assertEquals(pos.getIndex(), 0); assertEquals(pos.getErrorIndex(), 3); assertEquals(result, null); } - @Test(expectedExceptions=NullPointerException.class) - public void test_parseToBuilder_StringParsePosition_nullString() throws Exception { - DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); - ParsePosition pos = new ParsePosition(0); - test.parseToBuilder((String) null, pos); + @Test + public void test_parseUnresolved_StringParsePosition_duplicateFieldSameValue() { + DateTimeFormatter test = new DateTimeFormatterBuilder() + .appendValue(MONTH_OF_YEAR).appendLiteral('-').appendValue(MONTH_OF_YEAR).toFormatter(); + ParsePosition pos = new ParsePosition(3); + TemporalAccessor result = test.parseUnresolved("XXX6-6", pos); + assertEquals(pos.getIndex(), 6); + assertEquals(pos.getErrorIndex(), -1); + assertEquals(result.getLong(MONTH_OF_YEAR), 6); + } + + @Test + public void test_parseUnresolved_StringParsePosition_duplicateFieldDifferentValue() { + DateTimeFormatter test = new DateTimeFormatterBuilder() + .appendValue(MONTH_OF_YEAR).appendLiteral('-').appendValue(MONTH_OF_YEAR).toFormatter(); + ParsePosition pos = new ParsePosition(3); + TemporalAccessor result = test.parseUnresolved("XXX6-7", pos); + assertEquals(pos.getIndex(), 3); + assertEquals(pos.getErrorIndex(), 5); + assertEquals(result, null); } @Test(expectedExceptions=NullPointerException.class) - public void test_parseToBuilder_StringParsePosition_nullParsePosition() throws Exception { + public void test_parseUnresolved_StringParsePosition_nullString() { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); - test.parseToBuilder("ONE30", (ParsePosition) null); + ParsePosition pos = new ParsePosition(0); + test.parseUnresolved((String) null, pos); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_parseUnresolved_StringParsePosition_nullParsePosition() { + DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); + test.parseUnresolved("ONE30", (ParsePosition) null); } @Test(expectedExceptions=IndexOutOfBoundsException.class) - public void test_parseToBuilder_StringParsePosition_invalidPosition() throws Exception { + public void test_parseUnresolved_StringParsePosition_invalidPosition() { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); ParsePosition pos = new ParsePosition(6); - test.parseToBuilder("ONE30", pos); + test.parseUnresolved("ONE30", pos); } //----------------------------------------------------------------------- @@ -576,9 +608,9 @@ public class TCKDateTimeFormatter { public void test_toFormat_parseObject_String() throws Exception { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); Format format = test.toFormat(); - DateTimeBuilder result = (DateTimeBuilder) format.parseObject("ONE30"); - assertEquals(result.getFieldValueMap().size(), 1); - assertEquals(result.getFieldValue(DAY_OF_MONTH), 30L); + TemporalAccessor result = (TemporalAccessor) format.parseObject("ONE30"); + assertEquals(result.isSupported(DAY_OF_MONTH), true); + assertEquals(result.getLong(DAY_OF_MONTH), 30L); } @Test(expectedExceptions=ParseException.class) @@ -621,11 +653,11 @@ public class TCKDateTimeFormatter { DateTimeFormatter test = fmt.withLocale(Locale.ENGLISH).withSymbols(DateTimeFormatSymbols.STANDARD); Format format = test.toFormat(); ParsePosition pos = new ParsePosition(0); - DateTimeBuilder result = (DateTimeBuilder) format.parseObject("ONE30XXX", pos); + TemporalAccessor result = (TemporalAccessor) format.parseObject("ONE30XXX", pos); assertEquals(pos.getIndex(), 5); assertEquals(pos.getErrorIndex(), -1); - assertEquals(result.getFieldValueMap().size(), 1); - assertEquals(result.getFieldValue(DAY_OF_MONTH), 30L); + assertEquals(result.isSupported(DAY_OF_MONTH), true); + assertEquals(result.getLong(DAY_OF_MONTH), 30L); } @Test diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java index 1fe79b165eb..0cb5cb1c7a3 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java +++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java @@ -59,25 +59,24 @@ */ package tck.java.time.format; -import java.time.LocalDate; -import java.time.ZoneOffset; -import java.time.format.*; - import static java.time.temporal.ChronoField.DAY_OF_MONTH; -import static java.time.temporal.ChronoField.DAY_OF_WEEK; import static java.time.temporal.ChronoField.MINUTE_OF_HOUR; import static java.time.temporal.ChronoField.MONTH_OF_YEAR; import static java.time.temporal.ChronoField.YEAR; import static org.testng.Assert.assertEquals; -import java.text.ParsePosition; +import java.time.LocalDate; +import java.time.YearMonth; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.SignStyle; +import java.time.format.TextStyle; +import java.time.temporal.Temporal; import java.util.HashMap; import java.util.Locale; import java.util.Map; -import java.time.format.DateTimeBuilder; -import java.time.temporal.Temporal; - import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -90,238 +89,116 @@ public class TCKDateTimeFormatterBuilder { private DateTimeFormatterBuilder builder; - @BeforeMethod(groups={"tck"}) + @BeforeMethod public void setUp() { builder = new DateTimeFormatterBuilder(); } //----------------------------------------------------------------------- - @Test(groups={"tck"}) + @Test public void test_toFormatter_empty() throws Exception { DateTimeFormatter f = builder.toFormatter(); assertEquals(f.toString(), ""); } //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_parseCaseSensitive() throws Exception { - builder.parseCaseSensitive(); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "ParseCaseSensitive(true)"); - } - - @Test(groups={"tck"}) - public void test_parseCaseInsensitive() throws Exception { - builder.parseCaseInsensitive(); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "ParseCaseSensitive(false)"); - } - - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_parseStrict() throws Exception { - builder.parseStrict(); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "ParseStrict(true)"); - } - - @Test(groups={"tck"}) - public void test_parseLenient() throws Exception { - builder.parseLenient(); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "ParseStrict(false)"); - } - - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_appendValue_1arg() throws Exception { - builder.appendValue(DAY_OF_MONTH); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(DayOfMonth)"); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_appendValue_1arg_null() throws Exception { builder.appendValue(null); } //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_appendValue_2arg() throws Exception { - builder.appendValue(DAY_OF_MONTH, 3); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(DayOfMonth,3)"); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_appendValue_2arg_null() throws Exception { builder.appendValue(null, 3); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_appendValue_2arg_widthTooSmall() throws Exception { builder.appendValue(DAY_OF_MONTH, 0); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_appendValue_2arg_widthTooBig() throws Exception { builder.appendValue(DAY_OF_MONTH, 20); } //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_appendValue_3arg() throws Exception { - builder.appendValue(DAY_OF_MONTH, 2, 3, SignStyle.NORMAL); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(DayOfMonth,2,3,NORMAL)"); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_appendValue_3arg_nullField() throws Exception { builder.appendValue(null, 2, 3, SignStyle.NORMAL); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_appendValue_3arg_minWidthTooSmall() throws Exception { builder.appendValue(DAY_OF_MONTH, 0, 2, SignStyle.NORMAL); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_appendValue_3arg_minWidthTooBig() throws Exception { builder.appendValue(DAY_OF_MONTH, 20, 2, SignStyle.NORMAL); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_appendValue_3arg_maxWidthTooSmall() throws Exception { builder.appendValue(DAY_OF_MONTH, 2, 0, SignStyle.NORMAL); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_appendValue_3arg_maxWidthTooBig() throws Exception { builder.appendValue(DAY_OF_MONTH, 2, 20, SignStyle.NORMAL); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_appendValue_3arg_maxWidthMinWidth() throws Exception { builder.appendValue(DAY_OF_MONTH, 4, 2, SignStyle.NORMAL); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_appendValue_3arg_nullSignStyle() throws Exception { builder.appendValue(DAY_OF_MONTH, 2, 3, null); } //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_appendValue_subsequent2_parse3() throws Exception { - builder.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL).appendValue(DAY_OF_MONTH, 2); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear,1,2,NORMAL)Value(DayOfMonth,2)"); - DateTimeBuilder cal = f.parseToBuilder("123", new ParsePosition(0)); - assertEquals(cal.getFieldValueMap().get(MONTH_OF_YEAR), Long.valueOf(1)); - assertEquals(cal.getFieldValueMap().get(DAY_OF_MONTH), Long.valueOf(23)); - } - - @Test(groups={"tck"}) - public void test_appendValue_subsequent2_parse4() throws Exception { - builder.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL).appendValue(DAY_OF_MONTH, 2); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear,1,2,NORMAL)Value(DayOfMonth,2)"); - DateTimeBuilder cal = f.parseToBuilder("0123", new ParsePosition(0)); - assertEquals(cal.getFieldValueMap().get(MONTH_OF_YEAR), Long.valueOf(1)); - assertEquals(cal.getFieldValueMap().get(DAY_OF_MONTH), Long.valueOf(23)); - } - - @Test(groups={"tck"}) - public void test_appendValue_subsequent2_parse5() throws Exception { - builder.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL).appendValue(DAY_OF_MONTH, 2).appendLiteral('4'); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear,1,2,NORMAL)Value(DayOfMonth,2)'4'"); - DateTimeBuilder cal = f.parseToBuilder("01234", new ParsePosition(0)); - assertEquals(cal.getFieldValueMap().get(MONTH_OF_YEAR), Long.valueOf(1)); - assertEquals(cal.getFieldValueMap().get(DAY_OF_MONTH), Long.valueOf(23)); - } - - @Test(groups={"tck"}) - public void test_appendValue_subsequent3_parse6() throws Exception { - builder - .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD) - .appendValue(MONTH_OF_YEAR, 2) - .appendValue(DAY_OF_MONTH, 2); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(Year,4,10,EXCEEDS_PAD)Value(MonthOfYear,2)Value(DayOfMonth,2)"); - DateTimeBuilder cal = f.parseToBuilder("20090630", new ParsePosition(0)); - assertEquals(cal.getFieldValueMap().get(YEAR), Long.valueOf(2009)); - assertEquals(cal.getFieldValueMap().get(MONTH_OF_YEAR), Long.valueOf(6)); - assertEquals(cal.getFieldValueMap().get(DAY_OF_MONTH), Long.valueOf(30)); - } - - //----------------------------------------------------------------------- - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_appendValueReduced_null() throws Exception { builder.appendValueReduced(null, 2, 2000); } - @Test(groups={"tck"}) - public void test_appendValueReduced() throws Exception { - builder.appendValueReduced(YEAR, 2, 2000); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "ReducedValue(Year,2,2000)"); - DateTimeBuilder cal = f.parseToBuilder("12", new ParsePosition(0)); - assertEquals(cal.getFieldValueMap().get(YEAR), Long.valueOf(2012)); - } - - @Test(groups={"tck"}) - public void test_appendValueReduced_subsequent_parse() throws Exception { - builder.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL).appendValueReduced(YEAR, 2, 2000); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear,1,2,NORMAL)ReducedValue(Year,2,2000)"); - DateTimeBuilder cal = f.parseToBuilder("123", new ParsePosition(0)); - assertEquals(cal.getFieldValueMap().get(MONTH_OF_YEAR), Long.valueOf(1)); - assertEquals(cal.getFieldValueMap().get(YEAR), Long.valueOf(2023)); - } - //----------------------------------------------------------------------- //----------------------------------------------------------------------- //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_appendFraction_4arg() throws Exception { - builder.appendFraction(MINUTE_OF_HOUR, 1, 9, false); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Fraction(MinuteOfHour,1,9)"); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_appendFraction_4arg_nullRule() throws Exception { builder.appendFraction(null, 1, 9, false); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_appendFraction_4arg_invalidRuleNotFixedSet() throws Exception { builder.appendFraction(DAY_OF_MONTH, 1, 9, false); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_appendFraction_4arg_minTooSmall() throws Exception { builder.appendFraction(MINUTE_OF_HOUR, -1, 9, false); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_appendFraction_4arg_minTooBig() throws Exception { builder.appendFraction(MINUTE_OF_HOUR, 10, 9, false); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_appendFraction_4arg_maxTooSmall() throws Exception { builder.appendFraction(MINUTE_OF_HOUR, 0, -1, false); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_appendFraction_4arg_maxTooBig() throws Exception { builder.appendFraction(MINUTE_OF_HOUR, 1, 10, false); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_appendFraction_4arg_maxWidthMinWidth() throws Exception { builder.appendFraction(MINUTE_OF_HOUR, 9, 3, false); } @@ -329,63 +206,29 @@ public class TCKDateTimeFormatterBuilder { //----------------------------------------------------------------------- //----------------------------------------------------------------------- //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_appendText_1arg() throws Exception { - builder.appendText(MONTH_OF_YEAR); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Text(MonthOfYear)"); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_appendText_1arg_null() throws Exception { builder.appendText(null); } //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_appendText_2arg() throws Exception { - builder.appendText(MONTH_OF_YEAR, TextStyle.SHORT); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Text(MonthOfYear,SHORT)"); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_appendText_2arg_nullRule() throws Exception { builder.appendText(null, TextStyle.SHORT); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_appendText_2arg_nullStyle() throws Exception { builder.appendText(MONTH_OF_YEAR, (TextStyle) null); } //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_appendTextMap() throws Exception { - Map map = new HashMap(); - map.put(1L, "JNY"); - map.put(2L, "FBY"); - map.put(3L, "MCH"); - map.put(4L, "APL"); - map.put(5L, "MAY"); - map.put(6L, "JUN"); - map.put(7L, "JLY"); - map.put(8L, "AGT"); - map.put(9L, "SPT"); - map.put(10L, "OBR"); - map.put(11L, "NVR"); - map.put(12L, "DBR"); - builder.appendText(MONTH_OF_YEAR, map); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Text(MonthOfYear)"); // TODO: toString should be different? - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_appendTextMap_nullRule() throws Exception { - builder.appendText(null, new HashMap()); + builder.appendText(null, new HashMap<>()); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_appendTextMap_nullStyle() throws Exception { builder.appendText(MONTH_OF_YEAR, (Map) null); } @@ -393,13 +236,6 @@ public class TCKDateTimeFormatterBuilder { //----------------------------------------------------------------------- //----------------------------------------------------------------------- //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_appendOffsetId() throws Exception { - builder.appendOffsetId(); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Offset('Z',+HH:MM:ss)"); - } - @DataProvider(name="offsetPatterns") Object[][] data_offsetPatterns() { return new Object[][] { @@ -447,21 +283,20 @@ public class TCKDateTimeFormatterBuilder { }; } - @Test(dataProvider="offsetPatterns", groups={"tck"}) - public void test_appendOffset_print(String pattern, int h, int m, int s, String expected) throws Exception { + @Test(dataProvider="offsetPatterns") + public void test_appendOffset_format(String pattern, int h, int m, int s, String expected) throws Exception { builder.appendOffset(pattern, "Z"); DateTimeFormatter f = builder.toFormatter(); ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(h, m, s); - assertEquals(f.print(offset), expected); + assertEquals(f.format(offset), expected); } - @Test(dataProvider="offsetPatterns", groups={"tck"}) + @Test(dataProvider="offsetPatterns") public void test_appendOffset_parse(String pattern, int h, int m, int s, String expected) throws Exception { builder.appendOffset(pattern, "Z"); DateTimeFormatter f = builder.toFormatter(); - ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(h, m, s); ZoneOffset parsed = f.parse(expected, ZoneOffset::from); - assertEquals(f.print(parsed), expected); + assertEquals(f.format(parsed), expected); } @DataProvider(name="badOffsetPatterns") @@ -481,17 +316,17 @@ public class TCKDateTimeFormatterBuilder { }; } - @Test(dataProvider="badOffsetPatterns", expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(dataProvider="badOffsetPatterns", expectedExceptions=IllegalArgumentException.class) public void test_appendOffset_badPattern(String pattern) throws Exception { builder.appendOffset(pattern, "Z"); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_appendOffset_3arg_nullText() throws Exception { builder.appendOffset("+HH:MM", null); } - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_appendOffset_3arg_nullPattern() throws Exception { builder.appendOffset(null, "Z"); } @@ -499,21 +334,7 @@ public class TCKDateTimeFormatterBuilder { //----------------------------------------------------------------------- //----------------------------------------------------------------------- //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_appendZoneId() throws Exception { - builder.appendZoneId(); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "ZoneId()"); - } - - @Test(groups={"tck"}) - public void test_appendZoneText_1arg() throws Exception { - builder.appendZoneText(TextStyle.FULL); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "ZoneText(FULL)"); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) + @Test(expectedExceptions=NullPointerException.class) public void test_appendZoneText_1arg_nullText() throws Exception { builder.appendZoneText(null); } @@ -521,101 +342,43 @@ public class TCKDateTimeFormatterBuilder { //----------------------------------------------------------------------- //----------------------------------------------------------------------- //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_padNext_1arg() throws Exception { - builder.appendValue(MONTH_OF_YEAR).padNext(2).appendValue(DAY_OF_MONTH).appendValue(DAY_OF_WEEK); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear)Pad(Value(DayOfMonth),2)Value(DayOfWeek)"); + @Test + public void test_padNext_1arg() { + builder.appendValue(MONTH_OF_YEAR).appendLiteral(':').padNext(2).appendValue(DAY_OF_MONTH); + assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2: 1"); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_padNext_1arg_invalidWidth() throws Exception { builder.padNext(0); } //----------------------------------------------------------------------- - @Test(groups={"tck"}) + @Test public void test_padNext_2arg_dash() throws Exception { - builder.appendValue(MONTH_OF_YEAR).padNext(2, '-').appendValue(DAY_OF_MONTH).appendValue(DAY_OF_WEEK); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear)Pad(Value(DayOfMonth),2,'-')Value(DayOfWeek)"); + builder.appendValue(MONTH_OF_YEAR).appendLiteral(':').padNext(2, '-').appendValue(DAY_OF_MONTH); + assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2:-1"); } - @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalArgumentException.class) public void test_padNext_2arg_invalidWidth() throws Exception { builder.padNext(0, '-'); } //----------------------------------------------------------------------- - @Test(groups={"tck"}) + @Test public void test_padOptional() throws Exception { - builder.appendValue(MONTH_OF_YEAR).padNext(5).optionalStart().appendValue(DAY_OF_MONTH).optionalEnd().appendValue(DAY_OF_WEEK); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear)Pad([Value(DayOfMonth)],5)Value(DayOfWeek)"); + builder.appendValue(MONTH_OF_YEAR).appendLiteral(':') + .padNext(5).optionalStart().appendValue(DAY_OF_MONTH).optionalEnd() + .appendLiteral(':').appendValue(YEAR); + assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2: 1:2013"); + assertEquals(builder.toFormatter().format(YearMonth.of(2013, 2)), "2: :2013"); } //----------------------------------------------------------------------- //----------------------------------------------------------------------- //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_optionalStart_noEnd() throws Exception { - builder.appendValue(MONTH_OF_YEAR).optionalStart().appendValue(DAY_OF_MONTH).appendValue(DAY_OF_WEEK); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear)[Value(DayOfMonth)Value(DayOfWeek)]"); - } - - @Test(groups={"tck"}) - public void test_optionalStart2_noEnd() throws Exception { - builder.appendValue(MONTH_OF_YEAR).optionalStart().appendValue(DAY_OF_MONTH).optionalStart().appendValue(DAY_OF_WEEK); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear)[Value(DayOfMonth)[Value(DayOfWeek)]]"); - } - - @Test(groups={"tck"}) - public void test_optionalStart_doubleStart() throws Exception { - builder.appendValue(MONTH_OF_YEAR).optionalStart().optionalStart().appendValue(DAY_OF_MONTH); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear)[[Value(DayOfMonth)]]"); - } - - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_optionalEnd() throws Exception { - builder.appendValue(MONTH_OF_YEAR).optionalStart().appendValue(DAY_OF_MONTH).optionalEnd().appendValue(DAY_OF_WEEK); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear)[Value(DayOfMonth)]Value(DayOfWeek)"); - } - - @Test(groups={"tck"}) - public void test_optionalEnd2() throws Exception { - builder.appendValue(MONTH_OF_YEAR).optionalStart().appendValue(DAY_OF_MONTH) - .optionalStart().appendValue(DAY_OF_WEEK).optionalEnd().appendValue(DAY_OF_MONTH).optionalEnd(); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear)[Value(DayOfMonth)[Value(DayOfWeek)]Value(DayOfMonth)]"); - } - - @Test(groups={"tck"}) - public void test_optionalEnd_doubleStartSingleEnd() throws Exception { - builder.appendValue(MONTH_OF_YEAR).optionalStart().optionalStart().appendValue(DAY_OF_MONTH).optionalEnd(); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear)[[Value(DayOfMonth)]]"); - } - - @Test(groups={"tck"}) - public void test_optionalEnd_doubleStartDoubleEnd() throws Exception { - builder.appendValue(MONTH_OF_YEAR).optionalStart().optionalStart().appendValue(DAY_OF_MONTH).optionalEnd().optionalEnd(); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear)[[Value(DayOfMonth)]]"); - } - - @Test(groups={"tck"}) - public void test_optionalStartEnd_immediateStartEnd() throws Exception { - builder.appendValue(MONTH_OF_YEAR).optionalStart().optionalEnd().appendValue(DAY_OF_MONTH); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), "Value(MonthOfYear)Value(DayOfMonth)"); - } - - @Test(expectedExceptions=IllegalStateException.class, groups={"tck"}) + @Test(expectedExceptions=IllegalStateException.class) public void test_optionalEnd_noStart() throws Exception { builder.optionalEnd(); } @@ -626,157 +389,149 @@ public class TCKDateTimeFormatterBuilder { @DataProvider(name="validPatterns") Object[][] dataValid() { return new Object[][] { - {"'a'", "'a'"}, - {"''", "''"}, - {"'!'", "'!'"}, - {"!", "'!'"}, + {"'a'"}, + {"''"}, + {"'!'"}, + {"!"}, - {"'hello_people,][)('", "'hello_people,][)('"}, - {"'hi'", "'hi'"}, - {"'yyyy'", "'yyyy'"}, - {"''''", "''"}, - {"'o''clock'", "'o''clock'"}, + {"'hello_people,][)('"}, + {"'hi'"}, + {"'yyyy'"}, + {"''''"}, + {"'o''clock'"}, - {"G", "Value(Era)"}, - {"GG", "Value(Era,2)"}, - {"GGG", "Text(Era,SHORT)"}, - {"GGGG", "Text(Era)"}, - {"GGGGG", "Text(Era,NARROW)"}, + {"G"}, + {"GG"}, + {"GGG"}, + {"GGGG"}, + {"GGGGG"}, - {"y", "Value(Year)"}, - {"yy", "ReducedValue(Year,2,2000)"}, - {"yyy", "Value(Year,3,19,NORMAL)"}, - {"yyyy", "Value(Year,4,19,EXCEEDS_PAD)"}, - {"yyyyy", "Value(Year,5,19,EXCEEDS_PAD)"}, + {"y"}, + {"yy"}, + {"yyy"}, + {"yyyy"}, + {"yyyyy"}, -// {"Y", "Value(WeekBasedYear)"}, -// {"YY", "ReducedValue(WeekBasedYear,2,2000)"}, -// {"YYY", "Value(WeekBasedYear,3,19,NORMAL)"}, -// {"YYYY", "Value(WeekBasedYear,4,19,EXCEEDS_PAD)"}, -// {"YYYYY", "Value(WeekBasedYear,5,19,EXCEEDS_PAD)"}, + {"M"}, + {"MM"}, + {"MMM"}, + {"MMMM"}, + {"MMMMM"}, - {"M", "Value(MonthOfYear)"}, - {"MM", "Value(MonthOfYear,2)"}, - {"MMM", "Text(MonthOfYear,SHORT)"}, - {"MMMM", "Text(MonthOfYear)"}, - {"MMMMM", "Text(MonthOfYear,NARROW)"}, + {"D"}, + {"DD"}, + {"DDD"}, - {"D", "Value(DayOfYear)"}, - {"DD", "Value(DayOfYear,2)"}, - {"DDD", "Value(DayOfYear,3)"}, + {"d"}, + {"dd"}, + {"ddd"}, - {"d", "Value(DayOfMonth)"}, - {"dd", "Value(DayOfMonth,2)"}, - {"ddd", "Value(DayOfMonth,3)"}, + {"F"}, + {"FF"}, + {"FFF"}, - {"F", "Value(AlignedWeekOfMonth)"}, - {"FF", "Value(AlignedWeekOfMonth,2)"}, - {"FFF", "Value(AlignedWeekOfMonth,3)"}, + {"Q"}, + {"QQ"}, + {"QQQ"}, + {"QQQQ"}, + {"QQQQQ"}, - {"Q", "Value(QuarterOfYear)"}, - {"QQ", "Value(QuarterOfYear,2)"}, - {"QQQ", "Text(QuarterOfYear,SHORT)"}, - {"QQQQ", "Text(QuarterOfYear)"}, - {"QQQQQ", "Text(QuarterOfYear,NARROW)"}, + {"E"}, + {"EE"}, + {"EEE"}, + {"EEEE"}, + {"EEEEE"}, - {"E", "Value(DayOfWeek)"}, - {"EE", "Value(DayOfWeek,2)"}, - {"EEE", "Text(DayOfWeek,SHORT)"}, - {"EEEE", "Text(DayOfWeek)"}, - {"EEEEE", "Text(DayOfWeek,NARROW)"}, + {"a"}, + {"aa"}, + {"aaa"}, + {"aaaa"}, + {"aaaaa"}, - {"a", "Text(AmPmOfDay,SHORT)"}, - {"aa", "Text(AmPmOfDay,SHORT)"}, - {"aaa", "Text(AmPmOfDay,SHORT)"}, - {"aaaa", "Text(AmPmOfDay)"}, - {"aaaaa", "Text(AmPmOfDay,NARROW)"}, + {"H"}, + {"HH"}, + {"HHH"}, - {"H", "Value(HourOfDay)"}, - {"HH", "Value(HourOfDay,2)"}, - {"HHH", "Value(HourOfDay,3)"}, + {"K"}, + {"KK"}, + {"KKK"}, - {"K", "Value(HourOfAmPm)"}, - {"KK", "Value(HourOfAmPm,2)"}, - {"KKK", "Value(HourOfAmPm,3)"}, + {"k"}, + {"kk"}, + {"kkk"}, - {"k", "Value(ClockHourOfDay)"}, - {"kk", "Value(ClockHourOfDay,2)"}, - {"kkk", "Value(ClockHourOfDay,3)"}, + {"h"}, + {"hh"}, + {"hhh"}, - {"h", "Value(ClockHourOfAmPm)"}, - {"hh", "Value(ClockHourOfAmPm,2)"}, - {"hhh", "Value(ClockHourOfAmPm,3)"}, + {"m"}, + {"mm"}, + {"mmm"}, - {"m", "Value(MinuteOfHour)"}, - {"mm", "Value(MinuteOfHour,2)"}, - {"mmm", "Value(MinuteOfHour,3)"}, + {"s"}, + {"ss"}, + {"sss"}, - {"s", "Value(SecondOfMinute)"}, - {"ss", "Value(SecondOfMinute,2)"}, - {"sss", "Value(SecondOfMinute,3)"}, + {"S"}, + {"SS"}, + {"SSS"}, + {"SSSSSSSSS"}, - {"S", "Fraction(NanoOfSecond,1,1)"}, - {"SS", "Fraction(NanoOfSecond,2,2)"}, - {"SSS", "Fraction(NanoOfSecond,3,3)"}, - {"SSSSSSSSS", "Fraction(NanoOfSecond,9,9)"}, + {"A"}, + {"AA"}, + {"AAA"}, - {"A", "Value(MilliOfDay)"}, - {"AA", "Value(MilliOfDay,2)"}, - {"AAA", "Value(MilliOfDay,3)"}, + {"n"}, + {"nn"}, + {"nnn"}, - {"n", "Value(NanoOfSecond)"}, - {"nn", "Value(NanoOfSecond,2)"}, - {"nnn", "Value(NanoOfSecond,3)"}, + {"N"}, + {"NN"}, + {"NNN"}, - {"N", "Value(NanoOfDay)"}, - {"NN", "Value(NanoOfDay,2)"}, - {"NNN", "Value(NanoOfDay,3)"}, + {"z"}, + {"zz"}, + {"zzz"}, + {"zzzz"}, - {"z", "ZoneText(SHORT)"}, - {"zz", "ZoneText(SHORT)"}, - {"zzz", "ZoneText(SHORT)"}, - {"zzzz", "ZoneText(FULL)"}, - {"zzzzz", "ZoneText(FULL)"}, + {"VV"}, - {"I", "ZoneId()"}, - {"II", "ZoneId()"}, - {"III", "ZoneId()"}, - {"IIII", "ZoneId()"}, - {"IIIII", "ZoneId()"}, + {"Z"}, + {"ZZ"}, + {"ZZZ"}, - {"Z", "Offset('+0000',+HHMM)"}, // SimpleDateFormat compatible - {"ZZ", "Offset('+0000',+HHMM)"}, - {"ZZZ", "Offset('+00:00',+HH:MM)"}, + {"X"}, + {"XX"}, + {"XXX"}, + {"XXXX"}, + {"XXXXX"}, - {"X", "Offset('Z',+HH)"}, - {"XX", "Offset('Z',+HHMM)"}, - {"XXX", "Offset('Z',+HH:MM)"}, - {"XXXX", "Offset('Z',+HHMMss)"}, - {"XXXXX", "Offset('Z',+HH:MM:ss)"}, + {"x"}, + {"xx"}, + {"xxx"}, + {"xxxx"}, + {"xxxxx"}, - {"ppH", "Pad(Value(HourOfDay),2)"}, - {"pppDD", "Pad(Value(DayOfYear,2),3)"}, + {"ppH"}, + {"pppDD"}, - {"yyyy[-MM[-dd", "Value(Year,4,19,EXCEEDS_PAD)['-'Value(MonthOfYear,2)['-'Value(DayOfMonth,2)]]"}, - {"yyyy[-MM[-dd]]", "Value(Year,4,19,EXCEEDS_PAD)['-'Value(MonthOfYear,2)['-'Value(DayOfMonth,2)]]"}, - {"yyyy[-MM[]-dd]", "Value(Year,4,19,EXCEEDS_PAD)['-'Value(MonthOfYear,2)'-'Value(DayOfMonth,2)]"}, + {"yyyy[-MM[-dd"}, + {"yyyy[-MM[-dd]]"}, + {"yyyy[-MM[]-dd]"}, - {"yyyy-MM-dd'T'HH:mm:ss.SSS", "Value(Year,4,19,EXCEEDS_PAD)'-'Value(MonthOfYear,2)'-'Value(DayOfMonth,2)" + - "'T'Value(HourOfDay,2)':'Value(MinuteOfHour,2)':'Value(SecondOfMinute,2)'.'Fraction(NanoOfSecond,3,3)"}, + {"yyyy-MM-dd'T'HH:mm:ss.SSS"}, - {"e", "WeekBased(e1)"}, - {"w", "WeekBased(w1)"}, - {"W", "WeekBased(W1)"}, - {"WW", "WeekBased(W2)"}, + {"e"}, + {"w"}, + {"W"}, + {"WW"}, }; } - @Test(dataProvider="validPatterns", groups={"implementation"}) - public void test_appendPattern_valid(String input, String expected) throws Exception { - builder.appendPattern(input); - DateTimeFormatter f = builder.toFormatter(); - assertEquals(f.toString(), expected); + @Test(dataProvider="validPatterns") + public void test_appendPattern_valid(String input) throws Exception { + builder.appendPattern(input); // test is for no error here } //----------------------------------------------------------------------- @@ -801,6 +556,7 @@ public class TCKDateTimeFormatterBuilder { {"aaaaaa"}, {"ZZZZ"}, {"XXXXXX"}, + {"zzzzz"}, {"RO"}, @@ -821,13 +577,9 @@ public class TCKDateTimeFormatterBuilder { }; } - @Test(dataProvider="invalidPatterns", expectedExceptions=IllegalArgumentException.class, groups={"tck"}) + @Test(dataProvider="invalidPatterns", expectedExceptions=IllegalArgumentException.class) public void test_appendPattern_invalid(String input) throws Exception { - try { - builder.appendPattern(input); - } catch (IllegalArgumentException ex) { - throw ex; - } + builder.appendPattern(input); // test is for error here } //----------------------------------------------------------------------- @@ -842,10 +594,10 @@ public class TCKDateTimeFormatterBuilder { }; } - @Test(dataProvider="patternPrint", groups={"tck"}) + @Test(dataProvider="patternPrint") public void test_appendPattern_patternPrint(String input, Temporal temporal, String expected) throws Exception { DateTimeFormatter f = builder.appendPattern(input).toFormatter(Locale.UK); - String test = f.print(temporal); + String test = f.format(temporal); assertEquals(test, expected); } diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatters.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatters.java index cbb79b981b9..45548772f50 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatters.java +++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatters.java @@ -74,37 +74,33 @@ import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import java.text.ParsePosition; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; - import java.time.DateTimeException; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.Year; +import java.time.YearMonth; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; -import java.time.format.DateTimeBuilder; +import java.time.chrono.Chronology; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatters; import java.time.format.DateTimeParseException; -import java.time.format.DateTimePrintException; -import java.time.temporal.ISOFields; +import java.time.temporal.IsoFields; import java.time.temporal.Queries; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; import java.time.temporal.TemporalQuery; -import java.time.temporal.Year; -import java.time.temporal.YearMonth; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** - * Test DateTimeFormatters. + * Test DateTimeFormatter. */ @Test public class TCKDateTimeFormatters { @@ -116,7 +112,7 @@ public class TCKDateTimeFormatters { //----------------------------------------------------------------------- @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_print_nullCalendrical() { - DateTimeFormatters.isoDate().print((TemporalAccessor) null); + DateTimeFormatter.ISO_DATE.format((TemporalAccessor) null); } //----------------------------------------------------------------------- @@ -124,19 +120,19 @@ public class TCKDateTimeFormatters { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_pattern_String() { - DateTimeFormatter test = DateTimeFormatters.pattern("d MMM yyyy"); + DateTimeFormatter test = DateTimeFormatter.ofPattern("d MMM yyyy"); assertEquals(test.toString(), "Value(DayOfMonth)' 'Text(MonthOfYear,SHORT)' 'Value(Year,4,19,EXCEEDS_PAD)"); assertEquals(test.getLocale(), Locale.getDefault()); } @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) public void test_pattern_String_invalid() { - DateTimeFormatters.pattern("p"); + DateTimeFormatter.ofPattern("p"); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_pattern_String_null() { - DateTimeFormatters.pattern(null); + DateTimeFormatter.ofPattern(null); } //----------------------------------------------------------------------- @@ -144,24 +140,24 @@ public class TCKDateTimeFormatters { //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_pattern_StringLocale() { - DateTimeFormatter test = DateTimeFormatters.pattern("d MMM yyyy", Locale.UK); + DateTimeFormatter test = DateTimeFormatter.ofPattern("d MMM yyyy", Locale.UK); assertEquals(test.toString(), "Value(DayOfMonth)' 'Text(MonthOfYear,SHORT)' 'Value(Year,4,19,EXCEEDS_PAD)"); assertEquals(test.getLocale(), Locale.UK); } @Test(expectedExceptions=IllegalArgumentException.class, groups={"tck"}) public void test_pattern_StringLocale_invalid() { - DateTimeFormatters.pattern("p", Locale.UK); + DateTimeFormatter.ofPattern("p", Locale.UK); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_pattern_StringLocale_nullPattern() { - DateTimeFormatters.pattern(null, Locale.UK); + DateTimeFormatter.ofPattern(null, Locale.UK); } @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) public void test_pattern_StringLocale_nullLocale() { - DateTimeFormatters.pattern("yyyy", null); + DateTimeFormatter.ofPattern("yyyy", null); } //----------------------------------------------------------------------- @@ -193,10 +189,10 @@ public class TCKDateTimeFormatters { String expected, Class expectedEx) { TemporalAccessor test = buildAccessor(year, month, day, null, null, null, null, offsetId, zoneId); if (expectedEx == null) { - assertEquals(DateTimeFormatters.isoLocalDate().print(test), expected); + assertEquals(DateTimeFormatter.ISO_LOCAL_DATE.format(test), expected); } else { try { - DateTimeFormatters.isoLocalDate().print(test); + DateTimeFormatter.ISO_LOCAL_DATE.format(test); fail(); } catch (Exception ex) { assertTrue(expectedEx.isInstance(ex)); @@ -209,23 +205,23 @@ public class TCKDateTimeFormatters { Integer year, Integer month, Integer day, String offsetId, String zoneId, String input, Class invalid) { if (input != null) { - DateTimeBuilder expected = createDate(year, month, day); + Expected expected = createDate(year, month, day); // offset/zone not expected to be parsed - assertParseMatch(DateTimeFormatters.isoLocalDate().parseToBuilder(input, new ParsePosition(0)), expected); + assertParseMatch(DateTimeFormatter.ISO_LOCAL_DATE.parseUnresolved(input, new ParsePosition(0)), expected); } } @Test(groups={"tck"}) public void test_parse_isoLocalDate_999999999() { - DateTimeBuilder expected = createDate(999999999, 8, 6); - assertParseMatch(DateTimeFormatters.isoLocalDate().parseToBuilder("+999999999-08-06", new ParsePosition(0)), expected); + Expected expected = createDate(999999999, 8, 6); + assertParseMatch(DateTimeFormatter.ISO_LOCAL_DATE.parseUnresolved("+999999999-08-06", new ParsePosition(0)), expected); assertEquals(LocalDate.parse("+999999999-08-06"), LocalDate.of(999999999, 8, 6)); } @Test(groups={"tck"}) public void test_parse_isoLocalDate_1000000000() { - DateTimeBuilder expected = createDate(1000000000, 8, 6); - assertParseMatch(DateTimeFormatters.isoLocalDate().parseToBuilder("+1000000000-08-06", new ParsePosition(0)), expected); + Expected expected = createDate(1000000000, 8, 6); + assertParseMatch(DateTimeFormatter.ISO_LOCAL_DATE.parseUnresolved("+1000000000-08-06", new ParsePosition(0)), expected); } @Test(expectedExceptions = DateTimeException.class, groups={"tck"}) @@ -235,15 +231,15 @@ public class TCKDateTimeFormatters { @Test(groups={"tck"}) public void test_parse_isoLocalDate_M999999999() { - DateTimeBuilder expected = createDate(-999999999, 8, 6); - assertParseMatch(DateTimeFormatters.isoLocalDate().parseToBuilder("-999999999-08-06", new ParsePosition(0)), expected); + Expected expected = createDate(-999999999, 8, 6); + assertParseMatch(DateTimeFormatter.ISO_LOCAL_DATE.parseUnresolved("-999999999-08-06", new ParsePosition(0)), expected); assertEquals(LocalDate.parse("-999999999-08-06"), LocalDate.of(-999999999, 8, 6)); } @Test(groups={"tck"}) public void test_parse_isoLocalDate_M1000000000() { - DateTimeBuilder expected = createDate(-1000000000, 8, 6); - assertParseMatch(DateTimeFormatters.isoLocalDate().parseToBuilder("-1000000000-08-06", new ParsePosition(0)), expected); + Expected expected = createDate(-1000000000, 8, 6); + assertParseMatch(DateTimeFormatter.ISO_LOCAL_DATE.parseUnresolved("-1000000000-08-06", new ParsePosition(0)), expected); } @Test(expectedExceptions = DateTimeException.class, groups={"tck"}) @@ -280,10 +276,10 @@ public class TCKDateTimeFormatters { String expected, Class expectedEx) { TemporalAccessor test = buildAccessor(year, month, day, null, null, null, null, offsetId, zoneId); if (expectedEx == null) { - assertEquals(DateTimeFormatters.isoOffsetDate().print(test), expected); + assertEquals(DateTimeFormatter.ISO_OFFSET_DATE.format(test), expected); } else { try { - DateTimeFormatters.isoOffsetDate().print(test); + DateTimeFormatter.ISO_OFFSET_DATE.format(test); fail(); } catch (Exception ex) { assertTrue(expectedEx.isInstance(ex)); @@ -296,9 +292,9 @@ public class TCKDateTimeFormatters { Integer year, Integer month, Integer day, String offsetId, String zoneId, String input, Class invalid) { if (input != null) { - DateTimeBuilder expected = createDate(year, month, day); + Expected expected = createDate(year, month, day); buildCalendrical(expected, offsetId, null); // zone not expected to be parsed - assertParseMatch(DateTimeFormatters.isoOffsetDate().parseToBuilder(input, new ParsePosition(0)), expected); + assertParseMatch(DateTimeFormatter.ISO_OFFSET_DATE.parseUnresolved(input, new ParsePosition(0)), expected); } } @@ -331,10 +327,10 @@ public class TCKDateTimeFormatters { String expected, Class expectedEx) { TemporalAccessor test = buildAccessor(year, month, day, null, null, null, null, offsetId, zoneId); if (expectedEx == null) { - assertEquals(DateTimeFormatters.isoDate().print(test), expected); + assertEquals(DateTimeFormatter.ISO_DATE.format(test), expected); } else { try { - DateTimeFormatters.isoDate().print(test); + DateTimeFormatter.ISO_DATE.format(test); fail(); } catch (Exception ex) { assertTrue(expectedEx.isInstance(ex)); @@ -347,11 +343,11 @@ public class TCKDateTimeFormatters { Integer year, Integer month, Integer day, String offsetId, String zoneId, String input, Class invalid) { if (input != null) { - DateTimeBuilder expected = createDate(year, month, day); + Expected expected = createDate(year, month, day); if (offsetId != null) { - expected.addFieldValue(OFFSET_SECONDS, ZoneOffset.of(offsetId).getTotalSeconds()); + expected.add(ZoneOffset.of(offsetId)); } - assertParseMatch(DateTimeFormatters.isoDate().parseToBuilder(input, new ParsePosition(0)), expected); + assertParseMatch(DateTimeFormatter.ISO_DATE.parseUnresolved(input, new ParsePosition(0)), expected); } } @@ -396,10 +392,10 @@ public class TCKDateTimeFormatters { String expected, Class expectedEx) { TemporalAccessor test = buildAccessor(null, null, null, hour, min, sec, nano, offsetId, zoneId); if (expectedEx == null) { - assertEquals(DateTimeFormatters.isoLocalTime().print(test), expected); + assertEquals(DateTimeFormatter.ISO_LOCAL_TIME.format(test), expected); } else { try { - DateTimeFormatters.isoLocalTime().print(test); + DateTimeFormatter.ISO_LOCAL_TIME.format(test); fail(); } catch (Exception ex) { assertTrue(expectedEx.isInstance(ex)); @@ -412,9 +408,9 @@ public class TCKDateTimeFormatters { Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId, String input, Class invalid) { if (input != null) { - DateTimeBuilder expected = createTime(hour, min, sec, nano); + Expected expected = createTime(hour, min, sec, nano); // offset/zone not expected to be parsed - assertParseMatch(DateTimeFormatters.isoLocalTime().parseToBuilder(input, new ParsePosition(0)), expected); + assertParseMatch(DateTimeFormatter.ISO_LOCAL_TIME.parseUnresolved(input, new ParsePosition(0)), expected); } } @@ -459,10 +455,10 @@ public class TCKDateTimeFormatters { String expected, Class expectedEx) { TemporalAccessor test = buildAccessor(null, null, null, hour, min, sec, nano, offsetId, zoneId); if (expectedEx == null) { - assertEquals(DateTimeFormatters.isoOffsetTime().print(test), expected); + assertEquals(DateTimeFormatter.ISO_OFFSET_TIME.format(test), expected); } else { try { - DateTimeFormatters.isoOffsetTime().print(test); + DateTimeFormatter.ISO_OFFSET_TIME.format(test); fail(); } catch (Exception ex) { assertTrue(expectedEx.isInstance(ex)); @@ -475,9 +471,9 @@ public class TCKDateTimeFormatters { Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId, String input, Class invalid) { if (input != null) { - DateTimeBuilder expected = createTime(hour, min, sec, nano); + Expected expected = createTime(hour, min, sec, nano); buildCalendrical(expected, offsetId, null); // zoneId is not expected from parse - assertParseMatch(DateTimeFormatters.isoOffsetTime().parseToBuilder(input, new ParsePosition(0)), expected); + assertParseMatch(DateTimeFormatter.ISO_OFFSET_TIME.parseUnresolved(input, new ParsePosition(0)), expected); } } @@ -522,10 +518,10 @@ public class TCKDateTimeFormatters { String expected, Class expectedEx) { TemporalAccessor test = buildAccessor(null, null, null, hour, min, sec, nano, offsetId, zoneId); if (expectedEx == null) { - assertEquals(DateTimeFormatters.isoTime().print(test), expected); + assertEquals(DateTimeFormatter.ISO_TIME.format(test), expected); } else { try { - DateTimeFormatters.isoTime().print(test); + DateTimeFormatter.ISO_TIME.format(test); fail(); } catch (Exception ex) { assertTrue(expectedEx.isInstance(ex)); @@ -538,11 +534,11 @@ public class TCKDateTimeFormatters { Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId, String input, Class invalid) { if (input != null) { - DateTimeBuilder expected = createTime(hour, min, sec, nano); + Expected expected = createTime(hour, min, sec, nano); if (offsetId != null) { - expected.addFieldValue(OFFSET_SECONDS, ZoneOffset.of(offsetId).getTotalSeconds()); + expected.add(ZoneOffset.of(offsetId)); } - assertParseMatch(DateTimeFormatters.isoTime().parseToBuilder(input, new ParsePosition(0)), expected); + assertParseMatch(DateTimeFormatter.ISO_TIME.parseUnresolved(input, new ParsePosition(0)), expected); } } @@ -596,10 +592,10 @@ public class TCKDateTimeFormatters { String expected, Class expectedEx) { TemporalAccessor test = buildAccessor(year, month, day, hour, min, sec, nano, offsetId, zoneId); if (expectedEx == null) { - assertEquals(DateTimeFormatters.isoLocalDateTime().print(test), expected); + assertEquals(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(test), expected); } else { try { - DateTimeFormatters.isoLocalDateTime().print(test); + DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(test); fail(); } catch (Exception ex) { assertTrue(expectedEx.isInstance(ex)); @@ -613,8 +609,8 @@ public class TCKDateTimeFormatters { Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId, String input, Class invalid) { if (input != null) { - DateTimeBuilder expected = createDateTime(year, month, day, hour, min, sec, nano); - assertParseMatch(DateTimeFormatters.isoLocalDateTime().parseToBuilder(input, new ParsePosition(0)), expected); + Expected expected = createDateTime(year, month, day, hour, min, sec, nano); + assertParseMatch(DateTimeFormatter.ISO_LOCAL_DATE_TIME.parseUnresolved(input, new ParsePosition(0)), expected); } } @@ -668,10 +664,10 @@ public class TCKDateTimeFormatters { String expected, Class expectedEx) { TemporalAccessor test = buildAccessor(year, month, day, hour, min, sec, nano, offsetId, zoneId); if (expectedEx == null) { - assertEquals(DateTimeFormatters.isoOffsetDateTime().print(test), expected); + assertEquals(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(test), expected); } else { try { - DateTimeFormatters.isoOffsetDateTime().print(test); + DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(test); fail(); } catch (Exception ex) { assertTrue(expectedEx.isInstance(ex)); @@ -685,9 +681,9 @@ public class TCKDateTimeFormatters { Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId, String input, Class invalid) { if (input != null) { - DateTimeBuilder expected = createDateTime(year, month, day, hour, min, sec, nano); + Expected expected = createDateTime(year, month, day, hour, min, sec, nano); buildCalendrical(expected, offsetId, null); // zone not expected to be parsed - assertParseMatch(DateTimeFormatters.isoOffsetDateTime().parseToBuilder(input, new ParsePosition(0)), expected); + assertParseMatch(DateTimeFormatter.ISO_OFFSET_DATE_TIME.parseUnresolved(input, new ParsePosition(0)), expected); } } @@ -750,10 +746,10 @@ public class TCKDateTimeFormatters { String expected, Class expectedEx) { TemporalAccessor test = buildAccessor(year, month, day, hour, min, sec, nano, offsetId, zoneId); if (expectedEx == null) { - assertEquals(DateTimeFormatters.isoZonedDateTime().print(test), expected); + assertEquals(DateTimeFormatter.ISO_ZONED_DATE_TIME.format(test), expected); } else { try { - DateTimeFormatters.isoZonedDateTime().print(test); + DateTimeFormatter.ISO_ZONED_DATE_TIME.format(test); fail(test.toString()); } catch (Exception ex) { assertTrue(expectedEx.isInstance(ex)); @@ -767,13 +763,13 @@ public class TCKDateTimeFormatters { Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId, String input, Class invalid) { if (input != null) { - DateTimeBuilder expected = createDateTime(year, month, day, hour, min, sec, nano); + Expected expected = createDateTime(year, month, day, hour, min, sec, nano); if (offsetId.equals(zoneId)) { buildCalendrical(expected, offsetId, null); } else { buildCalendrical(expected, offsetId, zoneId); } - assertParseMatch(DateTimeFormatters.isoZonedDateTime().parseToBuilder(input, new ParsePosition(0)), expected); + assertParseMatch(DateTimeFormatter.ISO_ZONED_DATE_TIME.parseUnresolved(input, new ParsePosition(0)), expected); } } @@ -827,10 +823,10 @@ public class TCKDateTimeFormatters { String expected, Class expectedEx) { TemporalAccessor test = buildAccessor(year, month, day, hour, min, sec, nano, offsetId, zoneId); if (expectedEx == null) { - assertEquals(DateTimeFormatters.isoDateTime().print(test), expected); + assertEquals(DateTimeFormatter.ISO_DATE_TIME.format(test), expected); } else { try { - DateTimeFormatters.isoDateTime().print(test); + DateTimeFormatter.ISO_DATE_TIME.format(test); fail(); } catch (Exception ex) { assertTrue(expectedEx.isInstance(ex)); @@ -844,14 +840,14 @@ public class TCKDateTimeFormatters { Integer hour, Integer min, Integer sec, Integer nano, String offsetId, String zoneId, String input, Class invalid) { if (input != null) { - DateTimeBuilder expected = createDateTime(year, month, day, hour, min, sec, nano); + Expected expected = createDateTime(year, month, day, hour, min, sec, nano); if (offsetId != null) { - expected.addFieldValue(OFFSET_SECONDS, ZoneOffset.of(offsetId).getTotalSeconds()); + expected.add(ZoneOffset.of(offsetId)); if (zoneId != null) { - expected.addCalendrical(ZoneId.of(zoneId)); + expected.zone = ZoneId.of(zoneId); } } - assertParseMatch(DateTimeFormatters.isoDateTime().parseToBuilder(input, new ParsePosition(0)), expected); + assertParseMatch(DateTimeFormatter.ISO_DATE_TIME.parseUnresolved(input, new ParsePosition(0)), expected); } } @@ -861,50 +857,66 @@ public class TCKDateTimeFormatters { @Test(groups={"tck"}) public void test_print_isoOrdinalDate() { TemporalAccessor test = buildAccessor(LocalDateTime.of(2008, 6, 3, 11, 5, 30), null, null); - assertEquals(DateTimeFormatters.isoOrdinalDate().print(test), "2008-155"); + assertEquals(DateTimeFormatter.ISO_ORDINAL_DATE.format(test), "2008-155"); } @Test(groups={"tck"}) public void test_print_isoOrdinalDate_offset() { TemporalAccessor test = buildAccessor(LocalDateTime.of(2008, 6, 3, 11, 5, 30), "Z", null); - assertEquals(DateTimeFormatters.isoOrdinalDate().print(test), "2008-155Z"); + assertEquals(DateTimeFormatter.ISO_ORDINAL_DATE.format(test), "2008-155Z"); } @Test(groups={"tck"}) public void test_print_isoOrdinalDate_zoned() { TemporalAccessor test = buildAccessor(LocalDateTime.of(2008, 6, 3, 11, 5, 30), "+02:00", "Europe/Paris"); - assertEquals(DateTimeFormatters.isoOrdinalDate().print(test), "2008-155+02:00"); + assertEquals(DateTimeFormatter.ISO_ORDINAL_DATE.format(test), "2008-155+02:00"); } @Test(groups={"tck"}) public void test_print_isoOrdinalDate_zoned_largeYear() { TemporalAccessor test = buildAccessor(LocalDateTime.of(123456, 6, 3, 11, 5, 30), "Z", null); - assertEquals(DateTimeFormatters.isoOrdinalDate().print(test), "+123456-155Z"); + assertEquals(DateTimeFormatter.ISO_ORDINAL_DATE.format(test), "+123456-155Z"); } - @Test(groups={"tck"}) + @Test public void test_print_isoOrdinalDate_fields() { - TemporalAccessor test = new DateTimeBuilder(YEAR, 2008).addFieldValue(DAY_OF_YEAR, 231); - assertEquals(DateTimeFormatters.isoOrdinalDate().print(test), "2008-231"); + // mock for testing that does not fully comply with TemporalAccessor contract + TemporalAccessor test = new TemporalAccessor() { + @Override + public boolean isSupported(TemporalField field) { + return field == YEAR || field == DAY_OF_YEAR; + } + @Override + public long getLong(TemporalField field) { + if (field == YEAR) { + return 2008; + } + if (field == DAY_OF_YEAR) { + return 231; + } + throw new DateTimeException("Unsupported"); + } + }; + assertEquals(DateTimeFormatter.ISO_ORDINAL_DATE.format(test), "2008-231"); } - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) + @Test(expectedExceptions=DateTimeException.class) public void test_print_isoOrdinalDate_missingField() { TemporalAccessor test = Year.of(2008); - DateTimeFormatters.isoOrdinalDate().print(test); + DateTimeFormatter.ISO_ORDINAL_DATE.format(test); } //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_parse_isoOrdinalDate() { - DateTimeBuilder expected = new DateTimeBuilder(YEAR, 2008).addFieldValue(DAY_OF_YEAR, 123); - assertParseMatch(DateTimeFormatters.isoOrdinalDate().parseToBuilder("2008-123", new ParsePosition(0)), expected); + Expected expected = new Expected(YEAR, 2008, DAY_OF_YEAR, 123); + assertParseMatch(DateTimeFormatter.ISO_ORDINAL_DATE.parseUnresolved("2008-123", new ParsePosition(0)), expected); } @Test(groups={"tck"}) public void test_parse_isoOrdinalDate_largeYear() { - DateTimeBuilder expected = new DateTimeBuilder(YEAR, 123456).addFieldValue(DAY_OF_YEAR, 123); - assertParseMatch(DateTimeFormatters.isoOrdinalDate().parseToBuilder("+123456-123", new ParsePosition(0)), expected); + Expected expected = new Expected(YEAR, 123456, DAY_OF_YEAR, 123); + assertParseMatch(DateTimeFormatter.ISO_ORDINAL_DATE.parseUnresolved("+123456-123", new ParsePosition(0)), expected); } //----------------------------------------------------------------------- @@ -913,51 +925,51 @@ public class TCKDateTimeFormatters { @Test(groups={"tck"}) public void test_print_basicIsoDate() { TemporalAccessor test = buildAccessor(LocalDateTime.of(2008, 6, 3, 11, 5, 30), null, null); - assertEquals(DateTimeFormatters.basicIsoDate().print(test), "20080603"); + assertEquals(DateTimeFormatter.BASIC_ISO_DATE.format(test), "20080603"); } @Test(groups={"tck"}) public void test_print_basicIsoDate_offset() { TemporalAccessor test = buildAccessor(LocalDateTime.of(2008, 6, 3, 11, 5, 30), "Z", null); - assertEquals(DateTimeFormatters.basicIsoDate().print(test), "20080603Z"); + assertEquals(DateTimeFormatter.BASIC_ISO_DATE.format(test), "20080603Z"); } @Test(groups={"tck"}) public void test_print_basicIsoDate_zoned() { TemporalAccessor test = buildAccessor(LocalDateTime.of(2008, 6, 3, 11, 5, 30), "+02:00", "Europe/Paris"); - assertEquals(DateTimeFormatters.basicIsoDate().print(test), "20080603+0200"); + assertEquals(DateTimeFormatter.BASIC_ISO_DATE.format(test), "20080603+0200"); } - @Test(expectedExceptions=DateTimePrintException.class, groups={"tck"}) + @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) public void test_print_basicIsoDate_largeYear() { TemporalAccessor test = buildAccessor(LocalDateTime.of(123456, 6, 3, 11, 5, 30), "Z", null); - DateTimeFormatters.basicIsoDate().print(test); + DateTimeFormatter.BASIC_ISO_DATE.format(test); } @Test(groups={"tck"}) public void test_print_basicIsoDate_fields() { TemporalAccessor test = buildAccessor(LocalDate.of(2008, 6, 3), null, null); - assertEquals(DateTimeFormatters.basicIsoDate().print(test), "20080603"); + assertEquals(DateTimeFormatter.BASIC_ISO_DATE.format(test), "20080603"); } @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) public void test_print_basicIsoDate_missingField() { TemporalAccessor test = YearMonth.of(2008, 6); - DateTimeFormatters.basicIsoDate().print(test); + DateTimeFormatter.BASIC_ISO_DATE.format(test); } //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_parse_basicIsoDate() { LocalDate expected = LocalDate.of(2008, 6, 3); - assertEquals(DateTimeFormatters.basicIsoDate().parse("20080603", LocalDate::from), expected); + assertEquals(DateTimeFormatter.BASIC_ISO_DATE.parse("20080603", LocalDate::from), expected); } @Test(expectedExceptions=DateTimeParseException.class, groups={"tck"}) public void test_parse_basicIsoDate_largeYear() { try { LocalDate expected = LocalDate.of(123456, 6, 3); - assertEquals(DateTimeFormatters.basicIsoDate().parse("+1234560603", LocalDate::from), expected); + assertEquals(DateTimeFormatter.BASIC_ISO_DATE.parse("+1234560603", LocalDate::from), expected); } catch (DateTimeParseException ex) { assertEquals(ex.getErrorIndex(), 0); assertEquals(ex.getParsedString(), "+1234560603"); @@ -1002,40 +1014,40 @@ public class TCKDateTimeFormatters { @Test(dataProvider="weekDate", groups={"tck"}) public void test_print_isoWeekDate(TemporalAccessor test, String expected) { - assertEquals(DateTimeFormatters.isoWeekDate().print(test), expected); + assertEquals(DateTimeFormatter.ISO_WEEK_DATE.format(test), expected); } @Test(groups={"tck"}) public void test_print_isoWeekDate_zoned_largeYear() { TemporalAccessor test = buildAccessor(LocalDateTime.of(123456, 6, 3, 11, 5, 30), "Z", null); - assertEquals(DateTimeFormatters.isoWeekDate().print(test), "+123456-W23-2Z"); + assertEquals(DateTimeFormatter.ISO_WEEK_DATE.format(test), "+123456-W23-2Z"); } @Test(groups={"tck"}) public void test_print_isoWeekDate_fields() { TemporalAccessor test = buildAccessor(LocalDate.of(2004, 1, 27), null, null); - assertEquals(DateTimeFormatters.isoWeekDate().print(test), "2004-W05-2"); + assertEquals(DateTimeFormatter.ISO_WEEK_DATE.format(test), "2004-W05-2"); } @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) public void test_print_isoWeekDate_missingField() { TemporalAccessor test = YearMonth.of(2008, 6); - DateTimeFormatters.isoWeekDate().print(test); + DateTimeFormatter.ISO_WEEK_DATE.format(test); } //----------------------------------------------------------------------- @Test(groups={"tck"}) public void test_parse_weekDate() { LocalDate expected = LocalDate.of(2004, 1, 28); - assertEquals(DateTimeFormatters.isoWeekDate().parse("2004-W05-3", LocalDate::from), expected); + assertEquals(DateTimeFormatter.ISO_WEEK_DATE.parse("2004-W05-3", LocalDate::from), expected); } @Test(groups={"tck"}) public void test_parse_weekDate_largeYear() { - DateTimeBuilder builder = DateTimeFormatters.isoWeekDate().parseToBuilder("+123456-W04-5", new ParsePosition(0)); - assertEquals(builder.getFieldValue(ISOFields.WEEK_BASED_YEAR), 123456); - assertEquals(builder.getFieldValue(ISOFields.WEEK_OF_WEEK_BASED_YEAR), 4); - assertEquals(builder.getFieldValue(DAY_OF_WEEK), 5); + TemporalAccessor parsed = DateTimeFormatter.ISO_WEEK_DATE.parseUnresolved("+123456-W04-5", new ParsePosition(0)); + assertEquals(parsed.getLong(IsoFields.WEEK_BASED_YEAR), 123456L); + assertEquals(parsed.getLong(IsoFields.WEEK_OF_WEEK_BASED_YEAR), 4L); + assertEquals(parsed.getLong(DAY_OF_WEEK), 5L); } //----------------------------------------------------------------------- @@ -1054,79 +1066,79 @@ public class TCKDateTimeFormatters { @Test(groups={"tck"}, dataProvider="rfc") public void test_print_rfc1123(LocalDateTime base, String offsetId, String expected) { TemporalAccessor test = buildAccessor(base, offsetId, null); - assertEquals(DateTimeFormatters.rfc1123().print(test), expected); + assertEquals(DateTimeFormatter.RFC_1123_DATE_TIME.format(test), expected); } @Test(groups={"tck"}, dataProvider="rfc") public void test_print_rfc1123_french(LocalDateTime base, String offsetId, String expected) { TemporalAccessor test = buildAccessor(base, offsetId, null); - assertEquals(DateTimeFormatters.rfc1123().withLocale(Locale.FRENCH).print(test), expected); + assertEquals(DateTimeFormatter.RFC_1123_DATE_TIME.withLocale(Locale.FRENCH).format(test), expected); } @Test(groups={"tck"}, expectedExceptions=DateTimeException.class) public void test_print_rfc1123_missingField() { TemporalAccessor test = YearMonth.of(2008, 6); - DateTimeFormatters.rfc1123().print(test); + DateTimeFormatter.RFC_1123_DATE_TIME.format(test); } //----------------------------------------------------------------------- //----------------------------------------------------------------------- //----------------------------------------------------------------------- - private DateTimeBuilder createDate(Integer year, Integer month, Integer day) { - DateTimeBuilder test = new DateTimeBuilder(); + private Expected createDate(Integer year, Integer month, Integer day) { + Expected test = new Expected(); if (year != null) { - test.addFieldValue(YEAR, year); + test.fieldValues.put(YEAR, (long) year); } if (month != null) { - test.addFieldValue(MONTH_OF_YEAR, month); + test.fieldValues.put(MONTH_OF_YEAR, (long) month); } if (day != null) { - test.addFieldValue(DAY_OF_MONTH, day); + test.fieldValues.put(DAY_OF_MONTH, (long) day); } return test; } - private DateTimeBuilder createTime(Integer hour, Integer min, Integer sec, Integer nano) { - DateTimeBuilder test = new DateTimeBuilder(); + private Expected createTime(Integer hour, Integer min, Integer sec, Integer nano) { + Expected test = new Expected(); if (hour != null) { - test.addFieldValue(HOUR_OF_DAY, hour); + test.fieldValues.put(HOUR_OF_DAY, (long) hour); } if (min != null) { - test.addFieldValue(MINUTE_OF_HOUR, min); + test.fieldValues.put(MINUTE_OF_HOUR, (long) min); } if (sec != null) { - test.addFieldValue(SECOND_OF_MINUTE, sec); + test.fieldValues.put(SECOND_OF_MINUTE, (long) sec); } if (nano != null) { - test.addFieldValue(NANO_OF_SECOND, nano); + test.fieldValues.put(NANO_OF_SECOND, (long) nano); } return test; } - private DateTimeBuilder createDateTime( + private Expected createDateTime( Integer year, Integer month, Integer day, Integer hour, Integer min, Integer sec, Integer nano) { - DateTimeBuilder test = new DateTimeBuilder(); + Expected test = new Expected(); if (year != null) { - test.addFieldValue(YEAR, year); + test.fieldValues.put(YEAR, (long) year); } if (month != null) { - test.addFieldValue(MONTH_OF_YEAR, month); + test.fieldValues.put(MONTH_OF_YEAR, (long) month); } if (day != null) { - test.addFieldValue(DAY_OF_MONTH, day); + test.fieldValues.put(DAY_OF_MONTH, (long) day); } if (hour != null) { - test.addFieldValue(HOUR_OF_DAY, hour); + test.fieldValues.put(HOUR_OF_DAY, (long) hour); } if (min != null) { - test.addFieldValue(MINUTE_OF_HOUR, min); + test.fieldValues.put(MINUTE_OF_HOUR, (long) min); } if (sec != null) { - test.addFieldValue(SECOND_OF_MINUTE, sec); + test.fieldValues.put(SECOND_OF_MINUTE, (long) sec); } if (nano != null) { - test.addFieldValue(NANO_OF_SECOND, nano); + test.fieldValues.put(NANO_OF_SECOND, (long) nano); } return test; } @@ -1178,23 +1190,22 @@ public class TCKDateTimeFormatters { return mock; } - private void buildCalendrical(DateTimeBuilder cal, String offsetId, String zoneId) { + private void buildCalendrical(Expected expected, String offsetId, String zoneId) { if (offsetId != null) { - cal.addFieldValue(OFFSET_SECONDS, ZoneOffset.of(offsetId).getTotalSeconds()); + expected.add(ZoneOffset.of(offsetId)); } if (zoneId != null) { - cal.addCalendrical(ZoneId.of(zoneId)); + expected.zone = ZoneId.of(zoneId); } } - private void assertParseMatch(DateTimeBuilder parsed, DateTimeBuilder expected) { - Map parsedFVMap = parsed.getFieldValueMap(); - Map expectedFVMap = expected.getFieldValueMap(); - assertEquals(parsedFVMap, expectedFVMap); - - List parsedCMap = parsed.getCalendricalList(); - List expectedCMap = expected.getCalendricalList(); - assertEquals(parsedCMap, expectedCMap); + private void assertParseMatch(TemporalAccessor parsed, Expected expected) { + for (TemporalField field : expected.fieldValues.keySet()) { + assertEquals(parsed.isSupported(field), true); + parsed.getLong(field); + } + assertEquals(parsed.query(Queries.chronology()), expected.chrono); + assertEquals(parsed.query(Queries.zoneId()), expected.zone); } //------------------------------------------------------------------------- @@ -1211,8 +1222,8 @@ public class TCKDateTimeFormatters { fields.put(DAY_OF_MONTH, (long) dt.getDayOfMonth()); fields.put(DAY_OF_YEAR, (long) dt.getDayOfYear()); fields.put(DAY_OF_WEEK, (long) dt.getDayOfWeek().getValue()); - fields.put(ISOFields.WEEK_BASED_YEAR, dt.getLong(ISOFields.WEEK_BASED_YEAR)); - fields.put(ISOFields.WEEK_OF_WEEK_BASED_YEAR, dt.getLong(ISOFields.WEEK_OF_WEEK_BASED_YEAR)); + fields.put(IsoFields.WEEK_BASED_YEAR, dt.getLong(IsoFields.WEEK_BASED_YEAR)); + fields.put(IsoFields.WEEK_OF_WEEK_BASED_YEAR, dt.getLong(IsoFields.WEEK_OF_WEEK_BASED_YEAR)); } } @@ -1223,8 +1234,8 @@ public class TCKDateTimeFormatters { fields.put(DAY_OF_MONTH, (long) dt.getDayOfMonth()); fields.put(DAY_OF_YEAR, (long) dt.getDayOfYear()); fields.put(DAY_OF_WEEK, (long) dt.getDayOfWeek().getValue()); - fields.put(ISOFields.WEEK_BASED_YEAR, dt.getLong(ISOFields.WEEK_BASED_YEAR)); - fields.put(ISOFields.WEEK_OF_WEEK_BASED_YEAR, dt.getLong(ISOFields.WEEK_OF_WEEK_BASED_YEAR)); + fields.put(IsoFields.WEEK_BASED_YEAR, dt.getLong(IsoFields.WEEK_BASED_YEAR)); + fields.put(IsoFields.WEEK_OF_WEEK_BASED_YEAR, dt.getLong(IsoFields.WEEK_OF_WEEK_BASED_YEAR)); fields.put(HOUR_OF_DAY, (long) dt.getHour()); fields.put(MINUTE_OF_HOUR, (long) dt.getMinute()); fields.put(SECOND_OF_MINUTE, (long) dt.getSecond()); @@ -1273,4 +1284,22 @@ public class TCKDateTimeFormatters { } } + //----------------------------------------------------------------------- + static class Expected { + Map fieldValues = new HashMap<>(); + ZoneId zone; + Chronology chrono; + + Expected() { + } + + Expected(TemporalField field1, long value1, TemporalField field2, long value2) { + fieldValues.put(field1, value1); + fieldValues.put(field2, value2); + } + + void add(ZoneOffset offset) { + fieldValues.put(OFFSET_SECONDS, (long) offset.getTotalSeconds()); + } + } } diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimePrintException.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimePrintException.java deleted file mode 100644 index 0117629f8cb..00000000000 --- a/jdk/test/java/time/tck/java/time/format/TCKDateTimePrintException.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2012, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * - * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of JSR-310 nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package tck.java.time.format; - -import java.time.format.*; -import test.java.time.format.*; - -import static org.testng.Assert.assertEquals; - -import java.io.IOException; - -import org.testng.annotations.Test; - -/** - * Test DateTimePrintException. - */ -@Test -public class TCKDateTimePrintException { - - @Test(groups={"tck"}) - public void test_constructor_String() throws Exception { - DateTimePrintException ex = new DateTimePrintException("TEST"); - assertEquals(ex.getMessage(), "TEST"); - } - - @Test(groups={"tck"}) - public void test_constructor_StringThrowable_notIOException_equal() throws Exception { - IllegalArgumentException iaex = new IllegalArgumentException("INNER"); - DateTimePrintException ex = new DateTimePrintException("TEST", iaex); - assertEquals(ex.getMessage(), "TEST"); - assertEquals(ex.getCause(), iaex); - ex.rethrowIOException(); // no effect - } - - @Test(expectedExceptions=IOException.class, groups={"tck"}) - public void test_constructor_StringThrowable_IOException() throws Exception { - IOException ioex = new IOException("INNER"); - DateTimePrintException ex = new DateTimePrintException("TEST", ioex); - assertEquals(ex.getMessage(), "TEST"); - assertEquals(ex.getCause(), ioex); - ex.rethrowIOException(); // rethrows - } - -} diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeTextPrinting.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeTextPrinting.java index 5af0ebf41a9..d436fb41ad4 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeTextPrinting.java +++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeTextPrinting.java @@ -136,21 +136,21 @@ public class TCKDateTimeTextPrinting { } @Test(dataProvider="printText", groups={"tck"}) - public void test_appendText2arg_print(TemporalField field, TextStyle style, int value, String expected) throws Exception { + public void test_appendText2arg_format(TemporalField field, TextStyle style, int value, String expected) throws Exception { DateTimeFormatter f = builder.appendText(field, style).toFormatter(Locale.ENGLISH); LocalDateTime dt = LocalDateTime.of(2010, 1, 1, 0, 0); dt = dt.with(field, value); - String text = f.print(dt); + String text = f.format(dt); assertEquals(text, expected); } @Test(dataProvider="printText", groups={"tck"}) - public void test_appendText1arg_print(TemporalField field, TextStyle style, int value, String expected) throws Exception { + public void test_appendText1arg_format(TemporalField field, TextStyle style, int value, String expected) throws Exception { if (style == TextStyle.FULL) { DateTimeFormatter f = builder.appendText(field).toFormatter(Locale.ENGLISH); LocalDateTime dt = LocalDateTime.of(2010, 1, 1, 0, 0); dt = dt.with(field, value); - String text = f.print(dt); + String text = f.format(dt); assertEquals(text, expected); } } @@ -160,7 +160,7 @@ public class TCKDateTimeTextPrinting { public void test_print_appendText2arg_french_long() throws Exception { DateTimeFormatter f = builder.appendText(MONTH_OF_YEAR, TextStyle.FULL).toFormatter(Locale.FRENCH); LocalDateTime dt = LocalDateTime.of(2010, 1, 1, 0, 0); - String text = f.print(dt); + String text = f.format(dt); assertEquals(text, "janvier"); } @@ -168,7 +168,7 @@ public class TCKDateTimeTextPrinting { public void test_print_appendText2arg_french_short() throws Exception { DateTimeFormatter f = builder.appendText(MONTH_OF_YEAR, TextStyle.SHORT).toFormatter(Locale.FRENCH); LocalDateTime dt = LocalDateTime.of(2010, 1, 1, 0, 0); - String text = f.print(dt); + String text = f.format(dt); assertEquals(text, "janv."); } @@ -192,7 +192,7 @@ public class TCKDateTimeTextPrinting { DateTimeFormatter f = builder.toFormatter(); LocalDateTime dt = LocalDateTime.of(2010, 1, 1, 0, 0); for (Month month : Month.values()) { - assertEquals(f.print(dt.with(month)), map.get((long) month.getValue())); + assertEquals(f.format(dt.with(month)), map.get((long) month.getValue())); } } @@ -205,9 +205,9 @@ public class TCKDateTimeTextPrinting { builder.appendText(DAY_OF_MONTH, map); DateTimeFormatter f = builder.toFormatter(); LocalDateTime dt = LocalDateTime.of(2010, 1, 1, 0, 0); - assertEquals(f.print(dt.withDayOfMonth(1)), "1st"); - assertEquals(f.print(dt.withDayOfMonth(2)), "2nd"); - assertEquals(f.print(dt.withDayOfMonth(3)), "3rd"); + assertEquals(f.format(dt.withDayOfMonth(1)), "1st"); + assertEquals(f.format(dt.withDayOfMonth(2)), "2nd"); + assertEquals(f.format(dt.withDayOfMonth(3)), "3rd"); } @Test(groups={"tck"}) @@ -217,7 +217,7 @@ public class TCKDateTimeTextPrinting { builder.appendText(MONTH_OF_YEAR, map); DateTimeFormatter f = builder.toFormatter(); LocalDateTime dt = LocalDateTime.of(2010, 2, 1, 0, 0); - assertEquals(f.print(dt), "2"); + assertEquals(f.format(dt), "2"); } } diff --git a/jdk/test/java/time/tck/java/time/format/TCKLocalizedFieldParser.java b/jdk/test/java/time/tck/java/time/format/TCKLocalizedFieldParser.java index d6f5f1619bb..0d7975a8310 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKLocalizedFieldParser.java +++ b/jdk/test/java/time/tck/java/time/format/TCKLocalizedFieldParser.java @@ -59,22 +59,21 @@ */ package tck.java.time.format; -import java.time.format.*; - +import static java.time.temporal.ChronoField.MONTH_OF_YEAR; +import static java.time.temporal.ChronoField.YEAR; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.fail; import java.text.ParsePosition; -import java.time.format.DateTimeBuilder; - import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; import java.time.temporal.WeekFields; -import test.java.time.format.AbstractTestPrinterParser; - import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import test.java.time.format.AbstractTestPrinterParser; /** * Test TCKLocalizedFieldParser. @@ -114,12 +113,12 @@ public class TCKLocalizedFieldParser extends AbstractTestPrinterParser { DateTimeFormatterBuilder b = new DateTimeFormatterBuilder().appendPattern(pattern); DateTimeFormatter dtf = b.toFormatter(locale); - DateTimeBuilder dtb = dtf.parseToBuilder(text, ppos); + TemporalAccessor parsed = dtf.parseUnresolved(text, ppos); if (ppos.getErrorIndex() != -1) { assertEquals(ppos.getErrorIndex(), expectedPos); } else { assertEquals(ppos.getIndex(), expectedPos, "Incorrect ending parse position"); - long value = dtb.getLong(field); + long value = parsed.getLong(field); assertEquals(value, expectedValue, "Value incorrect for " + field); } } @@ -143,20 +142,23 @@ public class TCKLocalizedFieldParser extends AbstractTestPrinterParser { "Date: 2012, day-of-week: 6, week-of-year: 29", 0, 44, LocalDate.of(2012, 7, 20)}, }; } + @Test(dataProvider="LocalDatePatterns",groups={"tck"}) public void test_parse_textLocalDate(String pattern, String text, int pos, int expectedPos, LocalDate expectedValue) { - WeekFields weekDef = WeekFields.of(locale); ParsePosition ppos = new ParsePosition(pos); - DateTimeFormatterBuilder b - = new DateTimeFormatterBuilder().appendPattern(pattern); + DateTimeFormatterBuilder b = new DateTimeFormatterBuilder().appendPattern(pattern); DateTimeFormatter dtf = b.toFormatter(locale); - DateTimeBuilder dtb = dtf.parseToBuilder(text, ppos); + TemporalAccessor parsed = dtf.parseUnresolved(text, ppos); if (ppos.getErrorIndex() != -1) { assertEquals(ppos.getErrorIndex(), expectedPos); } else { assertEquals(ppos.getIndex(), expectedPos, "Incorrect ending parse position"); - dtb.resolve(); - LocalDate result = dtb.query(LocalDate::from); + assertEquals(parsed.isSupported(YEAR), true); + assertEquals(parsed.isSupported(WeekFields.of(locale).dayOfWeek()), true); + assertEquals(parsed.isSupported(WeekFields.of(locale).weekOfMonth()) || + parsed.isSupported(WeekFields.of(locale).weekOfYear()), true); + // ensure combination resolves into a date + LocalDate result = LocalDate.parse(text, dtf); assertEquals(result, expectedValue, "LocalDate incorrect for " + pattern); } } diff --git a/jdk/test/java/time/tck/java/time/format/TCKLocalizedFieldPrinter.java b/jdk/test/java/time/tck/java/time/format/TCKLocalizedFieldPrinter.java index dac65b6b110..3be85a9a03c 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKLocalizedFieldPrinter.java +++ b/jdk/test/java/time/tck/java/time/format/TCKLocalizedFieldPrinter.java @@ -98,7 +98,7 @@ public class TCKLocalizedFieldPrinter extends AbstractTestPrinterParser { = new DateTimeFormatterBuilder().appendPattern(pattern); LocalDate date = LocalDate.of(2012, 7, 20); - String result = b.toFormatter(locale).print(date); + String result = b.toFormatter(locale).format(date); assertEquals(result, expected, "Wrong output for pattern '" + pattern + "'."); } diff --git a/jdk/test/java/time/tck/java/time/format/TCKLocalizedPrinterParser.java b/jdk/test/java/time/tck/java/time/format/TCKLocalizedPrinterParser.java new file mode 100644 index 00000000000..cb348b264c3 --- /dev/null +++ b/jdk/test/java/time/tck/java/time/format/TCKLocalizedPrinterParser.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2012, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Copyright (c) 2010-2012, Stephen Colebourne & Michael Nascimento Santos + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of JSR-310 nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package tck.java.time.format; + +import static org.testng.Assert.assertEquals; + +import java.text.DateFormat; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.FormatStyle; +import java.time.temporal.TemporalAccessor; +import java.util.Date; +import java.util.Locale; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * Test localized behavior of formatter. + */ +@Test +public class TCKLocalizedPrinterParser { + + private DateTimeFormatterBuilder builder; + private ParsePosition pos; + + @BeforeMethod + public void setUp() { + builder = new DateTimeFormatterBuilder(); + pos = new ParsePosition(0); + } + + //----------------------------------------------------------------------- + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_parse_negativePosition() { + builder.appendLocalized(null, null); + } + + //----------------------------------------------------------------------- + @DataProvider(name="date") + Object[][] data_date() { + return new Object[][] { + {LocalDate.of(2012, 6, 30), FormatStyle.SHORT, DateFormat.SHORT, Locale.UK}, + {LocalDate.of(2012, 6, 30), FormatStyle.SHORT, DateFormat.SHORT, Locale.US}, + {LocalDate.of(2012, 6, 30), FormatStyle.SHORT, DateFormat.SHORT, Locale.FRANCE}, + {LocalDate.of(2012, 6, 30), FormatStyle.SHORT, DateFormat.SHORT, Locale.JAPAN}, + + {LocalDate.of(2012, 6, 30), FormatStyle.MEDIUM, DateFormat.MEDIUM, Locale.UK}, + {LocalDate.of(2012, 6, 30), FormatStyle.MEDIUM, DateFormat.MEDIUM, Locale.US}, + {LocalDate.of(2012, 6, 30), FormatStyle.MEDIUM, DateFormat.MEDIUM, Locale.FRANCE}, + {LocalDate.of(2012, 6, 30), FormatStyle.MEDIUM, DateFormat.MEDIUM, Locale.JAPAN}, + + {LocalDate.of(2012, 6, 30), FormatStyle.LONG, DateFormat.LONG, Locale.UK}, + {LocalDate.of(2012, 6, 30), FormatStyle.LONG, DateFormat.LONG, Locale.US}, + {LocalDate.of(2012, 6, 30), FormatStyle.LONG, DateFormat.LONG, Locale.FRANCE}, + {LocalDate.of(2012, 6, 30), FormatStyle.LONG, DateFormat.LONG, Locale.JAPAN}, + + {LocalDate.of(2012, 6, 30), FormatStyle.FULL, DateFormat.FULL, Locale.UK}, + {LocalDate.of(2012, 6, 30), FormatStyle.FULL, DateFormat.FULL, Locale.US}, + {LocalDate.of(2012, 6, 30), FormatStyle.FULL, DateFormat.FULL, Locale.FRANCE}, + {LocalDate.of(2012, 6, 30), FormatStyle.FULL, DateFormat.FULL, Locale.JAPAN}, + }; + } + + @SuppressWarnings("deprecated") + @Test(dataProvider="date") + public void test_date_print(LocalDate date, FormatStyle dateStyle, int dateStyleOld, Locale locale) { + DateFormat old = DateFormat.getDateInstance(dateStyleOld, locale); + Date oldDate = new Date(date.getYear() - 1900, date.getMonthValue() - 1, date.getDayOfMonth()); + String text = old.format(oldDate); + + DateTimeFormatter f = builder.appendLocalized(dateStyle, null).toFormatter(locale); + String formatted = f.format(date); + assertEquals(formatted, text); + } + + @SuppressWarnings("deprecated") + @Test(dataProvider="date") + public void test_date_parse(LocalDate date, FormatStyle dateStyle, int dateStyleOld, Locale locale) { + DateFormat old = DateFormat.getDateInstance(dateStyleOld, locale); + Date oldDate = new Date(date.getYear() - 1900, date.getMonthValue() - 1, date.getDayOfMonth()); + String text = old.format(oldDate); + + DateTimeFormatter f = builder.appendLocalized(dateStyle, null).toFormatter(locale); + TemporalAccessor parsed = f.parse(text, pos); + assertEquals(pos.getIndex(), text.length()); + assertEquals(pos.getErrorIndex(), -1); + assertEquals(LocalDate.from(parsed), date); + } + + //----------------------------------------------------------------------- + @DataProvider(name="time") + Object[][] data_time() { + return new Object[][] { + {LocalTime.of(11, 30), FormatStyle.SHORT, DateFormat.SHORT, Locale.UK}, + {LocalTime.of(11, 30), FormatStyle.SHORT, DateFormat.SHORT, Locale.US}, + {LocalTime.of(11, 30), FormatStyle.SHORT, DateFormat.SHORT, Locale.FRANCE}, + {LocalTime.of(11, 30), FormatStyle.SHORT, DateFormat.SHORT, Locale.JAPAN}, + + {LocalTime.of(11, 30), FormatStyle.MEDIUM, DateFormat.MEDIUM, Locale.UK}, + {LocalTime.of(11, 30), FormatStyle.MEDIUM, DateFormat.MEDIUM, Locale.US}, + {LocalTime.of(11, 30), FormatStyle.MEDIUM, DateFormat.MEDIUM, Locale.FRANCE}, + {LocalTime.of(11, 30), FormatStyle.MEDIUM, DateFormat.MEDIUM, Locale.JAPAN}, + + // these localized patterns include "z" which isn't available from LocalTime +// {LocalTime.of(11, 30), FormatStyle.LONG, DateFormat.LONG, Locale.UK}, +// {LocalTime.of(11, 30), FormatStyle.LONG, DateFormat.LONG, Locale.US}, +// {LocalTime.of(11, 30), FormatStyle.LONG, DateFormat.LONG, Locale.FRANCE}, +// {LocalTime.of(11, 30), FormatStyle.LONG, DateFormat.LONG, Locale.JAPAN}, +// +// {LocalTime.of(11, 30), FormatStyle.FULL, DateFormat.FULL, Locale.UK}, +// {LocalTime.of(11, 30), FormatStyle.FULL, DateFormat.FULL, Locale.US}, +// {LocalTime.of(11, 30), FormatStyle.FULL, DateFormat.FULL, Locale.FRANCE}, +// {LocalTime.of(11, 30), FormatStyle.FULL, DateFormat.FULL, Locale.JAPAN}, + }; + } + + @SuppressWarnings("deprecated") + @Test(dataProvider="time") + public void test_time_print(LocalTime time, FormatStyle timeStyle, int timeStyleOld, Locale locale) { + DateFormat old = DateFormat.getTimeInstance(timeStyleOld, locale); + Date oldDate = new Date(1970, 0, 0, time.getHour(), time.getMinute(), time.getSecond()); + String text = old.format(oldDate); + + DateTimeFormatter f = builder.appendLocalized(null, timeStyle).toFormatter(locale); + String formatted = f.format(time); + assertEquals(formatted, text); + } + + @SuppressWarnings("deprecated") + @Test(dataProvider="time") + public void test_time_parse(LocalTime time, FormatStyle timeStyle, int timeStyleOld, Locale locale) { + DateFormat old = DateFormat.getTimeInstance(timeStyleOld, locale); + Date oldDate = new Date(1970, 0, 0, time.getHour(), time.getMinute(), time.getSecond()); + String text = old.format(oldDate); + + DateTimeFormatter f = builder.appendLocalized(null, timeStyle).toFormatter(locale); + TemporalAccessor parsed = f.parse(text, pos); + assertEquals(pos.getIndex(), text.length()); + assertEquals(pos.getErrorIndex(), -1); + assertEquals(LocalTime.from(parsed), time); + } + +} diff --git a/jdk/test/java/time/tck/java/time/format/TCKOffsetPrinterParser.java b/jdk/test/java/time/tck/java/time/format/TCKOffsetPrinterParser.java new file mode 100644 index 00000000000..0ebc718c1e3 --- /dev/null +++ b/jdk/test/java/time/tck/java/time/format/TCKOffsetPrinterParser.java @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2012, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Copyright (c) 2010-2012, Stephen Colebourne & Michael Nascimento Santos + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of JSR-310 nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package tck.java.time.format; + +import static org.testng.Assert.assertEquals; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * Test DateTimeFormatterBuilder.appendOffset(). + */ +@Test +public class TCKOffsetPrinterParser { + + private static final ZoneOffset OFFSET_UTC = ZoneOffset.UTC; + private static final ZoneOffset OFFSET_P0100 = ZoneOffset.ofHours(1); + private static final ZoneOffset OFFSET_P0123 = ZoneOffset.ofHoursMinutes(1, 23); + private static final ZoneOffset OFFSET_P0023 = ZoneOffset.ofHoursMinutes(0, 23); + private static final ZoneOffset OFFSET_P012345 = ZoneOffset.ofHoursMinutesSeconds(1, 23, 45); + private static final ZoneOffset OFFSET_P000045 = ZoneOffset.ofHoursMinutesSeconds(0, 0, 45); + private static final ZoneOffset OFFSET_M0100 = ZoneOffset.ofHours(-1); + private static final ZoneOffset OFFSET_M0123 = ZoneOffset.ofHoursMinutes(-1, -23); + private static final ZoneOffset OFFSET_M0023 = ZoneOffset.ofHoursMinutes(0, -23); + private static final ZoneOffset OFFSET_M012345 = ZoneOffset.ofHoursMinutesSeconds(-1, -23, -45); + private static final ZoneOffset OFFSET_M000045 = ZoneOffset.ofHoursMinutesSeconds(0, 0, -45); + private static final LocalDateTime DT_2012_06_30_12_30_40 = LocalDateTime.of(2012, 6, 30, 12, 30, 40); + + private DateTimeFormatterBuilder builder; + + @BeforeMethod + public void setUp() { + builder = new DateTimeFormatterBuilder(); + } + + //----------------------------------------------------------------------- + @DataProvider(name="print") + Object[][] data_print() { + return new Object[][] { + {"+HH", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"}, + {"+HH", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+01"}, + {"+HH", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+01"}, + {"+HH", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "Z"}, + {"+HH", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+01"}, + {"+HH", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"}, + {"+HH", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-01"}, + {"+HH", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-01"}, + {"+HH", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "Z"}, + {"+HH", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-01"}, + {"+HH", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"}, + + {"+HHmm", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"}, + {"+HHmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+01"}, + {"+HHmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+0123"}, + {"+HHmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0023"}, + {"+HHmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+0123"}, + {"+HHmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"}, + {"+HHmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-01"}, + {"+HHmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-0123"}, + {"+HHmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0023"}, + {"+HHmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-0123"}, + {"+HHmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"}, + + {"+HHMM", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"}, + {"+HHMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+0100"}, + {"+HHMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+0123"}, + {"+HHMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0023"}, + {"+HHMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+0123"}, + {"+HHMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"}, + {"+HHMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-0100"}, + {"+HHMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-0123"}, + {"+HHMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0023"}, + {"+HHMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-0123"}, + {"+HHMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"}, + + {"+HH:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"}, + {"+HH:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+01:00"}, + {"+HH:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+01:23"}, + {"+HH:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+00:23"}, + {"+HH:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+01:23"}, + {"+HH:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"}, + {"+HH:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-01:00"}, + {"+HH:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-01:23"}, + {"+HH:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-00:23"}, + {"+HH:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-01:23"}, + {"+HH:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"}, + + {"+HHMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"}, + {"+HHMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+0100"}, + {"+HHMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+0123"}, + {"+HHMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0023"}, + {"+HHMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+012345"}, + {"+HHMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "+000045"}, + {"+HHMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-0100"}, + {"+HHMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-0123"}, + {"+HHMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0023"}, + {"+HHMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-012345"}, + {"+HHMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-000045"}, + + {"+HH:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"}, + {"+HH:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+01:00"}, + {"+HH:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+01:23"}, + {"+HH:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+00:23"}, + {"+HH:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+01:23:45"}, + {"+HH:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00:00:45"}, + {"+HH:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-01:00"}, + {"+HH:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-01:23"}, + {"+HH:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-00:23"}, + {"+HH:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-01:23:45"}, + {"+HH:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00:00:45"}, + + {"+HHMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"}, + {"+HHMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+010000"}, + {"+HHMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+012300"}, + {"+HHMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+002300"}, + {"+HHMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+012345"}, + {"+HHMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-000045"}, + {"+HHMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-010000"}, + {"+HHMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-012300"}, + {"+HHMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-002300"}, + {"+HHMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-012345"}, + {"+HHMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-000045"}, + + {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"}, + {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+01:00:00"}, + {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+01:23:00"}, + {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+00:23:00"}, + {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+01:23:45"}, + {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00:00:45"}, + {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-01:00:00"}, + {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-01:23:00"}, + {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-00:23:00"}, + {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-01:23:45"}, + {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00:00:45"}, + }; + } + + @Test(dataProvider="print") + public void test_print(String offsetPattern, String noOffset, LocalDateTime ldt, ZoneId zone, String expected) { + ZonedDateTime zdt = ldt.atZone(zone); + builder.appendOffset(offsetPattern, noOffset); + String output = builder.toFormatter().format(zdt); + assertEquals(output, expected); + } + + //----------------------------------------------------------------------- + @Test(dataProvider="print") + public void test_print_pattern_X(String offsetPattern, String noOffset, LocalDateTime ldt, ZoneId zone, String expected) { + String pattern = null; + if (offsetPattern.equals("+HHmm") && noOffset.equals("Z")) { + pattern = "X"; + } else if (offsetPattern.equals("+HHMM") && noOffset.equals("Z")) { + pattern = "XX"; + } else if (offsetPattern.equals("+HH:MM") && noOffset.equals("Z")) { + pattern = "XXX"; + } else if (offsetPattern.equals("+HHMMss") && noOffset.equals("Z")) { + pattern = "XXXX"; + } else if (offsetPattern.equals("+HH:MM:ss") && noOffset.equals("Z")) { + pattern = "XXXXX"; + } + if (pattern != null) { + ZonedDateTime zdt = ldt.atZone(zone); + builder.appendPattern(pattern); + String output = builder.toFormatter().format(zdt); + assertEquals(output, expected); + } + } + + @Test(dataProvider="print") + public void test_print_pattern_x(String offsetPattern, String noOffset, LocalDateTime ldt, ZoneId zone, String expected) { + String pattern = null; + String zero = null; + if (offsetPattern.equals("+HHmm") && noOffset.equals("Z")) { + pattern = "x"; + zero = "+00"; + } else if (offsetPattern.equals("+HHMM") && noOffset.equals("Z")) { + pattern = "xx"; + zero = "+0000"; + } else if (offsetPattern.equals("+HH:MM") && noOffset.equals("Z")) { + pattern = "xxx"; + zero = "+00:00"; + } else if (offsetPattern.equals("+HHMMss") && noOffset.equals("Z")) { + pattern = "xxxx"; + zero = "+0000"; + } else if (offsetPattern.equals("+HH:MM:ss") && noOffset.equals("Z")) { + pattern = "xxxxx"; + zero = "+00:00"; + } + if (pattern != null) { + ZonedDateTime zdt = ldt.atZone(zone); + builder.appendPattern(pattern); + String output = builder.toFormatter().format(zdt); + assertEquals(output, (expected.equals("Z") ? zero : expected)); + } + } + + @Test(dataProvider="print") + public void test_print_pattern_Z(String offsetPattern, String noOffset, LocalDateTime ldt, ZoneId zone, String expected) { + String pattern = null; + if (offsetPattern.equals("+HHMM") && noOffset.equals("Z")) { + ZonedDateTime zdt = ldt.atZone(zone); + DateTimeFormatter f1 = new DateTimeFormatterBuilder().appendPattern("Z").toFormatter(); + String output1 = f1.format(zdt); + assertEquals(output1, (expected.equals("Z") ? "+0000" : expected)); + + DateTimeFormatter f2 = new DateTimeFormatterBuilder().appendPattern("ZZ").toFormatter(); + String output2 = f2.format(zdt); + assertEquals(output2, (expected.equals("Z") ? "+0000" : expected)); + + DateTimeFormatter f3 = new DateTimeFormatterBuilder().appendPattern("ZZZ").toFormatter(); + String output3 = f3.format(zdt); + assertEquals(output3, (expected.equals("Z") ? "+0000" : expected)); + } + } + + //----------------------------------------------------------------------- + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_print_pattern_X6rejected() { + builder.appendPattern("XXXXXX"); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_print_pattern_x6rejected() { + builder.appendPattern("xxxxxx"); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_print_pattern_Z4rejected() { + builder.appendPattern("ZZZZ"); + } + +} diff --git a/jdk/test/java/time/tck/java/time/format/TCKPadPrinterParser.java b/jdk/test/java/time/tck/java/time/format/TCKPadPrinterParser.java new file mode 100644 index 00000000000..d6641f65e63 --- /dev/null +++ b/jdk/test/java/time/tck/java/time/format/TCKPadPrinterParser.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2012, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Copyright (c) 2010-2012, Stephen Colebourne & Michael Nascimento Santos + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of JSR-310 nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package tck.java.time.format; + +import static java.time.temporal.ChronoField.DAY_OF_MONTH; +import static java.time.temporal.ChronoField.MONTH_OF_YEAR; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +import java.text.ParsePosition; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.SignStyle; +import java.time.temporal.TemporalAccessor; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * Test padding behavior of formatter. + */ +@Test +public class TCKPadPrinterParser { + + private DateTimeFormatterBuilder builder; + private ParsePosition pos; + + @BeforeMethod + public void setUp() { + builder = new DateTimeFormatterBuilder(); + pos = new ParsePosition(0); + } + + //----------------------------------------------------------------------- + @Test(expectedExceptions=IndexOutOfBoundsException.class) + public void test_parse_negativePosition() { + builder.padNext(3, '-').appendLiteral('Z'); + builder.toFormatter().parseUnresolved("--Z", new ParsePosition(-1)); + } + + @Test(expectedExceptions=IndexOutOfBoundsException.class) + public void test_parse_offEndPosition() { + builder.padNext(3, '-').appendLiteral('Z'); + builder.toFormatter().parseUnresolved("--Z", new ParsePosition(4)); + } + + //----------------------------------------------------------------------- + @DataProvider(name="parseStrict") + Object[][] data_parseStrict() { + return new Object[][] { + {"222", 3, -1, 222}, + {"222X", 3, -1, 222}, + {"#22", 3, -1, 22}, + {"#22X", 3, -1, 22}, + {"##2", 3, -1, 2}, + {"##2X", 3, -1, 2}, + {"##22", 3, -1, 2}, + {"-22", 3, -1, -22}, + {"#-2", 3, -1, -2}, + {"3", 0, 0, null}, + {"3X", 0, 0, null}, + {"#3", 0, 0, null}, + {"#3X", 0, 1, null}, + {"##A", 0, 2, null}, + {" 3", 0, 0, null}, + {"##", 0, 0, null}, + {"#", 0, 0, null}, + {"", 0, 0, null}, + }; + } + + @Test(dataProvider="parseStrict") + public void test_parseStrict(String text, int expectedIndex, int expectedErrorIndex, Number expectedMonth) { + builder.padNext(3, '#').appendValue(MONTH_OF_YEAR, 1, 3, SignStyle.NORMAL); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved(text, pos); + assertEquals(pos.getIndex(), expectedIndex); + assertEquals(pos.getErrorIndex(), expectedErrorIndex); + if (expectedMonth != null) { + assertEquals(parsed.isSupported(MONTH_OF_YEAR), true); + assertEquals(parsed.getLong(MONTH_OF_YEAR), expectedMonth.longValue()); + } else { + assertEquals(parsed, null); + } + } + + //----------------------------------------------------------------------- + @DataProvider(name="parseLenient") + Object[][] data_parseLenient() { + return new Object[][] { + {"222", 3, -1, 222}, + {"222X", 3, -1, 222}, + {"#22", 3, -1, 22}, + {"#22X", 3, -1, 22}, + {"##2", 3, -1, 2}, + {"##2X", 3, -1, 2}, + {"##22", 3, -1, 2}, + {"-22", 3, -1, -22}, + {"#-2", 3, -1, -2}, + {"3", 1, -1, 3}, + {"3X", 1, -1, 3}, + {"33", 2, -1, 33}, + {"33X", 2, -1, 33}, + {"#3", 2, -1, 3}, + {"#3X", 2, -1, 3}, + {"##A", 0, 2, null}, + {" 1", 0, 0, null}, + {"##", 0, 2, null}, + {"#", 0, 1, null}, + {"", 0, 0, null}, + }; + } + + @Test(dataProvider="parseLenient") + public void test_parseLenient(String text, int expectedIndex, int expectedErrorIndex, Number expectedMonth) { + builder.parseLenient().padNext(3, '#').appendValue(MONTH_OF_YEAR, 1, 3, SignStyle.NORMAL); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved(text, pos); + assertEquals(pos.getIndex(), expectedIndex); + assertEquals(pos.getErrorIndex(), expectedErrorIndex); + if (expectedMonth != null) { + assertEquals(parsed.isSupported(MONTH_OF_YEAR), true); + assertEquals(parsed.getLong(MONTH_OF_YEAR), expectedMonth.longValue()); + } else { + assertEquals(parsed, null); + } + } + + //----------------------------------------------------------------------- + @Test + public void test_parse_decoratedStartsWithPad() { + builder.padNext(8, '-').appendLiteral("-HELLO-"); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved("--HELLO-", pos); + assertEquals(pos.getIndex(), 0); + assertEquals(pos.getErrorIndex(), 2); + assertEquals(parsed, null); + } + + @Test + public void test_parse_decoratedStartsWithPad_number() { + builder.padNext(3, '-').appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved("--2", pos); + assertEquals(pos.getIndex(), 3); + assertEquals(pos.getErrorIndex(), -1); + assertEquals(parsed.isSupported(MONTH_OF_YEAR), true); + assertEquals(parsed.getLong(MONTH_OF_YEAR), 2L); // +2, not -2 + } + + //----------------------------------------------------------------------- + @Test + public void test_parse_decoratedEmpty_strict() { + builder.padNext(4, '-').optionalStart().appendValue(DAY_OF_MONTH).optionalEnd(); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved("----", pos); + assertEquals(pos.getIndex(), 4); + assertEquals(pos.getErrorIndex(), -1); + assertNotNull(parsed); + } + + @Test + public void test_parse_decoratedEmpty_lenient() { + builder.parseLenient().padNext(4, '-').optionalStart().appendValue(DAY_OF_MONTH).optionalEnd(); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved("----", pos); + assertEquals(pos.getIndex(), 4); + assertEquals(pos.getErrorIndex(), -1); + assertNotNull(parsed); + } + +} diff --git a/jdk/test/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java b/jdk/test/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java new file mode 100644 index 00000000000..e346742dea3 --- /dev/null +++ b/jdk/test/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2012, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Copyright (c) 2010-2012, Stephen Colebourne & Michael Nascimento Santos + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of JSR-310 nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package tck.java.time.format; + +import static org.testng.Assert.assertEquals; + +import java.text.ParsePosition; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.Queries; +import java.time.temporal.TemporalAccessor; +import java.util.Locale; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * Test DateTimeFormatterBuilder.appendZoneId(). + */ +@Test +public class TCKZoneIdPrinterParser { + + private static final ZoneOffset OFFSET_UTC = ZoneOffset.UTC; + private static final ZoneOffset OFFSET_P0123 = ZoneOffset.ofHoursMinutes(1, 23); + private static final ZoneId EUROPE_PARIS = ZoneId.of("Europe/Paris"); + private static final ZoneId AMERICA_NEW_YORK = ZoneId.of("America/New_York"); + private static final LocalDateTime DT_2012_06_30_12_30_40 = LocalDateTime.of(2012, 6, 30, 12, 30, 40); + + private DateTimeFormatterBuilder builder; + private ParsePosition pos; + + @BeforeMethod + public void setUp() { + builder = new DateTimeFormatterBuilder(); + pos = new ParsePosition(0); + } + + //----------------------------------------------------------------------- + @DataProvider(name="print") + Object[][] data_print() { + return new Object[][] { + {DT_2012_06_30_12_30_40, EUROPE_PARIS, "Europe/Paris"}, + {DT_2012_06_30_12_30_40, AMERICA_NEW_YORK, "America/New_York"}, + {DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"}, + {DT_2012_06_30_12_30_40, OFFSET_P0123, "+01:23"}, + }; + } + + @Test(dataProvider="print") + public void test_print(LocalDateTime ldt, ZoneId zone, String expected) { + ZonedDateTime zdt = ldt.atZone(zone); + builder.appendZoneId(); + String output = builder.toFormatter().format(zdt); + assertEquals(output, expected); + } + + @Test(dataProvider="print") + public void test_print_pattern_VV(LocalDateTime ldt, ZoneId zone, String expected) { + ZonedDateTime zdt = ldt.atZone(zone); + builder.appendPattern("VV"); + String output = builder.toFormatter().format(zdt); + assertEquals(output, expected); + } + + //----------------------------------------------------------------------- + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_print_pattern_V1rejected() { + builder.appendPattern("V"); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_print_pattern_V3rejected() { + builder.appendPattern("VVV"); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_print_pattern_V4rejected() { + builder.appendPattern("VVVV"); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_print_pattern_V5rejected() { + builder.appendPattern("VVVVV"); + } + + //----------------------------------------------------------------------- + @DataProvider(name="parseSuccess") + Object[][] data_parseSuccess() { + return new Object[][] { + {"Z", 1, -1, ZoneOffset.UTC}, + {"UTC", 3, -1, ZoneOffset.UTC}, + {"UT", 2, -1, ZoneOffset.UTC}, + {"GMT", 3, -1, ZoneOffset.UTC}, + {"UTC0", 4, -1, ZoneOffset.UTC}, + {"UT0", 3, -1, ZoneOffset.UTC}, + {"GMT0", 4, -1, ZoneOffset.UTC}, + + {"+00:00", 6, -1, ZoneOffset.UTC}, + {"UTC+00:00", 9, -1, ZoneOffset.UTC}, + {"UT+00:00", 8, -1, ZoneOffset.UTC}, + {"GMT+00:00", 9, -1, ZoneOffset.UTC}, + {"-00:00", 6, -1, ZoneOffset.UTC}, + {"UTC-00:00", 9, -1, ZoneOffset.UTC}, + {"UT-00:00", 8, -1, ZoneOffset.UTC}, + {"GMT-00:00", 9, -1, ZoneOffset.UTC}, + + {"+01:30", 6, -1, ZoneOffset.ofHoursMinutes(1, 30)}, + {"UTC+01:30", 9, -1, ZoneOffset.ofHoursMinutes(1, 30)}, + {"UT+02:30", 8, -1, ZoneOffset.ofHoursMinutes(2, 30)}, + {"GMT+03:30", 9, -1, ZoneOffset.ofHoursMinutes(3, 30)}, + {"-01:30", 6, -1, ZoneOffset.ofHoursMinutes(-1, -30)}, + {"UTC-01:30", 9, -1, ZoneOffset.ofHoursMinutes(-1, -30)}, + {"UT-02:30", 8, -1, ZoneOffset.ofHoursMinutes(-2, -30)}, + {"GMT-03:30", 9, -1, ZoneOffset.ofHoursMinutes(-3, -30)}, + + // fallback to UTC + {"UTC-01:WW", 3, -1, ZoneOffset.UTC}, + {"UT-02:WW", 2, -1, ZoneOffset.UTC}, + {"GMT-03:WW", 3, -1, ZoneOffset.UTC}, + {"Z0", 1, -1, ZoneOffset.UTC}, + {"UTC1", 3, -1, ZoneOffset.UTC}, + + // Z not parsed as zero + {"UTCZ", 3, -1, ZoneOffset.UTC}, + {"UTZ", 2, -1, ZoneOffset.UTC}, + {"GMTZ", 3, -1, ZoneOffset.UTC}, + + // fail to parse + {"", 0, 0, null}, + {"A", 0, 0, null}, + {"UZ", 0, 0, null}, + {"GMA", 0, 0, null}, + {"0", 0, 0, null}, + {"+", 0, 0, null}, + {"-", 0, 0, null}, + + // zone IDs + {"Europe/London", 13, -1, ZoneId.of("Europe/London")}, + {"America/New_York", 16, -1, ZoneId.of("America/New_York")}, + {"America/Bogusville", 0, 0, null}, + }; + } + + @Test(dataProvider="parseSuccess") + public void test_parseSuccess_plain(String text, int expectedIndex, int expectedErrorIndex, ZoneId expected) { + builder.appendZoneId(); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved(text, pos); + assertEquals(pos.getErrorIndex(), expectedErrorIndex); + assertEquals(pos.getIndex(), expectedIndex); + if (expected != null) { + assertEquals(parsed.query(Queries.zoneId()), expected); + assertEquals(parsed.query(Queries.offset()), null); + assertEquals(parsed.query(Queries.zone()), expected); + } else { + assertEquals(parsed, null); + } + } + + @Test(dataProvider="parseSuccess") + public void test_parseSuccess_prefix(String text, int expectedIndex, int expectedErrorIndex, ZoneId expected) { + builder.appendZoneId(); + pos.setIndex(3); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved("XXX" + text, pos); + assertEquals(pos.getErrorIndex(), expectedErrorIndex >= 0 ? expectedErrorIndex + 3 : expectedErrorIndex); + assertEquals(pos.getIndex(), expectedIndex + 3); + if (expected != null) { + assertEquals(parsed.query(Queries.zoneId()), expected); + assertEquals(parsed.query(Queries.offset()), null); + assertEquals(parsed.query(Queries.zone()), expected); + } else { + assertEquals(parsed, null); + } + } + + @Test(dataProvider="parseSuccess") + public void test_parseSuccess_suffix(String text, int expectedIndex, int expectedErrorIndex, ZoneId expected) { + builder.appendZoneId(); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved(text + "XXX", pos); + assertEquals(pos.getErrorIndex(), expectedErrorIndex); + assertEquals(pos.getIndex(), expectedIndex); + if (expected != null) { + assertEquals(parsed.query(Queries.zoneId()), expected); + assertEquals(parsed.query(Queries.offset()), null); + assertEquals(parsed.query(Queries.zone()), expected); + } else { + assertEquals(parsed, null); + } + } + + @Test(dataProvider="parseSuccess") + public void test_parseSuccess_caseSensitive(String text, int expectedIndex, int expectedErrorIndex, ZoneId expected) { + builder.parseCaseSensitive().appendZoneId(); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved(text.toLowerCase(Locale.ENGLISH), pos); + if (text.matches("[^A-Z]*[A-Z].*")) { // if input has letters + assertEquals(pos.getErrorIndex() >= 0, true); + assertEquals(pos.getIndex(), 0); + assertEquals(parsed, null); + } else { + // case sensitive made no difference + assertEquals(pos.getIndex(), expectedIndex); + assertEquals(pos.getErrorIndex(), expectedErrorIndex); + if (expected != null) { + assertEquals(parsed.query(Queries.zoneId()), expected); + assertEquals(parsed.query(Queries.offset()), null); + assertEquals(parsed.query(Queries.zone()), expected); + } else { + assertEquals(parsed, null); + } + } + } + + @Test(dataProvider="parseSuccess") + public void test_parseSuccess_caseInsensitive(String text, int expectedIndex, int expectedErrorIndex, ZoneId expected) { + builder.parseCaseInsensitive().appendZoneId(); + TemporalAccessor parsed = builder.toFormatter().parseUnresolved(text.toLowerCase(Locale.ENGLISH), pos); + assertEquals(pos.getErrorIndex(), expectedErrorIndex); + assertEquals(pos.getIndex(), expectedIndex); + if (expected != null) { + assertEquals(parsed.query(Queries.zoneId()), expected); + assertEquals(parsed.query(Queries.offset()), null); + assertEquals(parsed.query(Queries.zone()), expected); + } else { + assertEquals(parsed, null); + } + } + +} diff --git a/jdk/test/java/time/tck/java/time/temporal/TCKISOFields.java b/jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java similarity index 64% rename from jdk/test/java/time/tck/java/time/temporal/TCKISOFields.java rename to jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java index c3acbdb6f82..359aac1b0e6 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TCKISOFields.java +++ b/jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java @@ -56,9 +56,6 @@ */ package tck.java.time.temporal; -import java.time.format.DateTimeBuilder; -import java.time.temporal.*; - import static java.time.DayOfWeek.FRIDAY; import static java.time.DayOfWeek.MONDAY; import static java.time.DayOfWeek.SATURDAY; @@ -69,10 +66,13 @@ import static java.time.DayOfWeek.WEDNESDAY; import static java.time.temporal.ChronoField.DAY_OF_WEEK; import static java.time.temporal.ChronoField.YEAR; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; import java.time.DayOfWeek; import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.IsoFields; +import java.time.temporal.ValueRange; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -81,7 +81,7 @@ import org.testng.annotations.Test; * Test. */ @Test(groups={"tck"}) -public class TCKISOFields { +public class TCKIsoFields { @DataProvider(name="quarter") Object[][] data_quarter() { @@ -117,8 +117,8 @@ public class TCKISOFields { //----------------------------------------------------------------------- @Test(dataProvider="quarter") public void test_DOQ(LocalDate date, int doq, int qoy) { - assertEquals(ISOFields.DAY_OF_QUARTER.doGet(date), doq); - assertEquals(date.get(ISOFields.DAY_OF_QUARTER), doq); + assertEquals(IsoFields.DAY_OF_QUARTER.getFrom(date), doq); + assertEquals(date.get(IsoFields.DAY_OF_QUARTER), doq); } //----------------------------------------------------------------------- @@ -126,21 +126,61 @@ public class TCKISOFields { //----------------------------------------------------------------------- @Test(dataProvider="quarter") public void test_QOY(LocalDate date, int doq, int qoy) { - assertEquals(ISOFields.QUARTER_OF_YEAR.doGet(date), qoy); - assertEquals(date.get(ISOFields.QUARTER_OF_YEAR), qoy); + assertEquals(IsoFields.QUARTER_OF_YEAR.getFrom(date), qoy); + assertEquals(date.get(IsoFields.QUARTER_OF_YEAR), qoy); } //----------------------------------------------------------------------- - // builder + // parse quarters //----------------------------------------------------------------------- @Test(dataProvider="quarter") - public void test_builder_quarters(LocalDate date, int doq, int qoy) { - DateTimeBuilder builder = new DateTimeBuilder(); - builder.addFieldValue(ISOFields.DAY_OF_QUARTER, doq); - builder.addFieldValue(ISOFields.QUARTER_OF_YEAR, qoy); - builder.addFieldValue(YEAR, date.getYear()); - builder.resolve(); - assertEquals(builder.query(LocalDate::from), date); + public void test_parse_quarters(LocalDate date, int doq, int qoy) { + DateTimeFormatter f = new DateTimeFormatterBuilder() + .appendValue(YEAR).appendLiteral('-') + .appendValue(IsoFields.QUARTER_OF_YEAR).appendLiteral('-') + .appendValue(IsoFields.DAY_OF_QUARTER).toFormatter(); + LocalDate parsed = LocalDate.parse(date.getYear() + "-" + qoy + "-" + doq, f); + assertEquals(parsed, date); + } + + //----------------------------------------------------------------------- + // quarters between + //----------------------------------------------------------------------- + @DataProvider(name="quartersBetween") + Object[][] data_quartersBetween() { + return new Object[][] { + {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 1), 0}, + {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 2), 0}, + {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 2, 1), 0}, + {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 3, 1), 0}, + {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 3, 31), 0}, + {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 4, 1), 1}, + {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 4, 2), 1}, + {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 6, 30), 1}, + {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 7, 1), 2}, + {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 10, 1), 3}, + {LocalDate.of(2000, 1, 1), LocalDate.of(2000, 12, 31), 3}, + {LocalDate.of(2000, 1, 1), LocalDate.of(2001, 1, 1), 4}, + {LocalDate.of(2000, 1, 1), LocalDate.of(2002, 1, 1), 8}, + + {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 12, 31), 0}, + {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 10, 2), 0}, + {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 10, 1), -1}, + {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 7, 2), -1}, + {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 7, 1), -2}, + {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 4, 2), -2}, + {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 4, 1), -3}, + {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 1, 2), -3}, + {LocalDate.of(2000, 1, 1), LocalDate.of(1999, 1, 1), -4}, + {LocalDate.of(2000, 1, 1), LocalDate.of(1998, 12, 31), -4}, + {LocalDate.of(2000, 1, 1), LocalDate.of(1998, 10, 2), -4}, + {LocalDate.of(2000, 1, 1), LocalDate.of(1998, 10, 1), -5}, + }; + } + + @Test(dataProvider="quartersBetween") + public void test_quarters_between(LocalDate start, LocalDate end, long expected) { + assertEquals(IsoFields.QUARTER_YEARS.between(start, end), expected); } //----------------------------------------------------------------------- @@ -170,8 +210,8 @@ public class TCKISOFields { @Test(dataProvider="week") public void test_WOWBY(LocalDate date, DayOfWeek dow, int week, int wby) { assertEquals(date.getDayOfWeek(), dow); - assertEquals(ISOFields.WEEK_OF_WEEK_BASED_YEAR.doGet(date), week); - assertEquals(date.get(ISOFields.WEEK_OF_WEEK_BASED_YEAR), week); + assertEquals(IsoFields.WEEK_OF_WEEK_BASED_YEAR.getFrom(date), week); + assertEquals(date.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR), week); } //----------------------------------------------------------------------- @@ -180,21 +220,21 @@ public class TCKISOFields { @Test(dataProvider="week") public void test_WBY(LocalDate date, DayOfWeek dow, int week, int wby) { assertEquals(date.getDayOfWeek(), dow); - assertEquals(ISOFields.WEEK_BASED_YEAR.doGet(date), wby); - assertEquals(date.get(ISOFields.WEEK_BASED_YEAR), wby); + assertEquals(IsoFields.WEEK_BASED_YEAR.getFrom(date), wby); + assertEquals(date.get(IsoFields.WEEK_BASED_YEAR), wby); } //----------------------------------------------------------------------- - // builder + // parse weeks //----------------------------------------------------------------------- @Test(dataProvider="week") - public void test_builder_weeks(LocalDate date, DayOfWeek dow, int week, int wby) { - DateTimeBuilder builder = new DateTimeBuilder(); - builder.addFieldValue(ISOFields.WEEK_BASED_YEAR, wby); - builder.addFieldValue(ISOFields.WEEK_OF_WEEK_BASED_YEAR, week); - builder.addFieldValue(DAY_OF_WEEK, dow.getValue()); - builder.resolve(); - assertEquals(builder.query(LocalDate::from), date); + public void test_parse_weeks(LocalDate date, DayOfWeek dow, int week, int wby) { + DateTimeFormatter f = new DateTimeFormatterBuilder() + .appendValue(IsoFields.WEEK_BASED_YEAR).appendLiteral('-') + .appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR).appendLiteral('-') + .appendValue(DAY_OF_WEEK).toFormatter(); + LocalDate parsed = LocalDate.parse(wby + "-" + week + "-" + dow.getValue(), f); + assertEquals(parsed, date); } //----------------------------------------------------------------------- @@ -220,11 +260,11 @@ public class TCKISOFields { wby++; } } - assertEquals(ISOFields.WEEK_OF_WEEK_BASED_YEAR.doRange(date), ValueRange.of(1, weekLen), "Failed on " + date + " " + date.getDayOfWeek()); - assertEquals(ISOFields.WEEK_OF_WEEK_BASED_YEAR.doGet(date), week, "Failed on " + date + " " + date.getDayOfWeek()); - assertEquals(date.get(ISOFields.WEEK_OF_WEEK_BASED_YEAR), week, "Failed on " + date + " " + date.getDayOfWeek()); - assertEquals(ISOFields.WEEK_BASED_YEAR.doGet(date), wby, "Failed on " + date + " " + date.getDayOfWeek()); - assertEquals(date.get(ISOFields.WEEK_BASED_YEAR), wby, "Failed on " + date + " " + date.getDayOfWeek()); + assertEquals(IsoFields.WEEK_OF_WEEK_BASED_YEAR.rangeRefinedBy(date), ValueRange.of(1, weekLen), "Failed on " + date + " " + date.getDayOfWeek()); + assertEquals(IsoFields.WEEK_OF_WEEK_BASED_YEAR.getFrom(date), week, "Failed on " + date + " " + date.getDayOfWeek()); + assertEquals(date.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR), week, "Failed on " + date + " " + date.getDayOfWeek()); + assertEquals(IsoFields.WEEK_BASED_YEAR.getFrom(date), wby, "Failed on " + date + " " + date.getDayOfWeek()); + assertEquals(date.get(IsoFields.WEEK_BASED_YEAR), wby, "Failed on " + date + " " + date.getDayOfWeek()); date = date.plusDays(1); } } diff --git a/jdk/test/java/time/tck/java/time/temporal/TCKJulianFields.java b/jdk/test/java/time/tck/java/time/temporal/TCKJulianFields.java index 81e8109c329..94399e0fdd8 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TCKJulianFields.java +++ b/jdk/test/java/time/tck/java/time/temporal/TCKJulianFields.java @@ -60,38 +60,30 @@ package tck.java.time.temporal; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertSame; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.ChronoField; +import java.time.temporal.JulianFields; +import java.time.temporal.TemporalField; -import java.time.temporal.*; - - -import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import tck.java.time.AbstractTCKTest; /** * Test. */ @Test -public class TCKJulianFields { +public class TCKJulianFields extends AbstractTCKTest { private static final LocalDate JAN01_1970 = LocalDate.of(1970, 1, 1); private static final LocalDate DEC31_1969 = LocalDate.of(1969, 12, 31); private static final LocalDate NOV12_1945 = LocalDate.of(1945, 11, 12); private static final LocalDate JAN01_0001 = LocalDate.of(1, 1, 1); - @BeforeMethod - public void setUp() { - } - //----------------------------------------------------------------------- @DataProvider(name="julian_fields") Object[][] julian_samples() { @@ -127,42 +119,33 @@ public class TCKJulianFields { }; } - @Test(dataProvider="samples", groups={"tck"}) + //----------------------------------------------------------------------- + @Test(dataProvider="julian_fields") + public void test_serializable(TemporalField field) throws IOException, ClassNotFoundException { + assertSerializable(field); + } + + //----------------------------------------------------------------------- + @Test(dataProvider="samples") public void test_samples_get(TemporalField field, LocalDate date, long expected) { assertEquals(date.getLong(field), expected); } - @Test(dataProvider="samples", groups={"tck"}) + @Test(dataProvider="samples") public void test_samples_set(TemporalField field, LocalDate date, long value) { - assertEquals(field.doWith(LocalDate.MAX, value), date); - assertEquals(field.doWith(LocalDate.MIN, value), date); - assertEquals(field.doWith(JAN01_1970, value), date); - assertEquals(field.doWith(DEC31_1969, value), date); - assertEquals(field.doWith(NOV12_1945, value), date); + assertEquals(field.adjustInto(LocalDate.MAX, value), date); + assertEquals(field.adjustInto(LocalDate.MIN, value), date); + assertEquals(field.adjustInto(JAN01_1970, value), date); + assertEquals(field.adjustInto(DEC31_1969, value), date); + assertEquals(field.adjustInto(NOV12_1945, value), date); } //----------------------------------------------------------------------- - // toString() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_toString() { - assertEquals(JulianFields.JULIAN_DAY.toString(), "JulianDay"); - assertEquals(JulianFields.MODIFIED_JULIAN_DAY.toString(), "ModifiedJulianDay"); - assertEquals(JulianFields.RATA_DIE.toString(), "RataDie"); - } - - @Test(groups = {"tck"},dataProvider="julian_fields") - public void test_JulianFieldsSingleton(TemporalField field) throws IOException, ClassNotFoundException { - try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos)) { - oos.writeObject(field); - - ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream( - baos.toByteArray())); - TemporalField result = (TemporalField)ois.readObject(); - assertSame(result, field, "Deserialized object same as serialized."); - } - // Exceptions will be handled as failures by TestNG + @Test(dataProvider="samples") + public void test_samples_parse(TemporalField field, LocalDate date, long value) { + DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(field).toFormatter(); + LocalDate parsed = LocalDate.parse(Long.toString(value), f); + assertEquals(parsed, date); } } diff --git a/jdk/test/java/time/tck/java/time/temporal/TCKOffsetDate.java b/jdk/test/java/time/tck/java/time/temporal/TCKOffsetDate.java deleted file mode 100644 index 77720220d69..00000000000 --- a/jdk/test/java/time/tck/java/time/temporal/TCKOffsetDate.java +++ /dev/null @@ -1,1949 +0,0 @@ -/* - * Copyright (c) 2012, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * -9 * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of JSR-310 nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package tck.java.time.temporal; - -import static java.time.Month.DECEMBER; -import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH; -import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR; -import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH; -import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR; -import static java.time.temporal.ChronoField.DAY_OF_MONTH; -import static java.time.temporal.ChronoField.DAY_OF_WEEK; -import static java.time.temporal.ChronoField.DAY_OF_YEAR; -import static java.time.temporal.ChronoField.EPOCH_DAY; -import static java.time.temporal.ChronoField.EPOCH_MONTH; -import static java.time.temporal.ChronoField.ERA; -import static java.time.temporal.ChronoField.MONTH_OF_YEAR; -import static java.time.temporal.ChronoField.OFFSET_SECONDS; -import static java.time.temporal.ChronoField.YEAR; -import static java.time.temporal.ChronoField.YEAR_OF_ERA; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import java.time.Clock; -import java.time.DateTimeException; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.Month; -import java.time.Period; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatters; -import java.time.format.DateTimeParseException; -import java.time.temporal.ChronoField; -import java.time.temporal.ChronoUnit; -import java.time.temporal.ISOChrono; -import java.time.temporal.JulianFields; -import java.time.temporal.OffsetDate; -import java.time.temporal.OffsetDateTime; -import java.time.temporal.Queries; -import java.time.temporal.Temporal; -import java.time.temporal.TemporalAccessor; -import java.time.temporal.TemporalAdder; -import java.time.temporal.TemporalAdjuster; -import java.time.temporal.TemporalField; -import java.time.temporal.TemporalSubtractor; -import java.time.temporal.Year; - -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import tck.java.time.AbstractDateTimeTest; -import test.java.time.MockSimplePeriod; - -/** - * Test OffsetDate. - */ -@Test -public class TCKOffsetDate extends AbstractDateTimeTest { - private static final ZoneOffset OFFSET_PONE = ZoneOffset.ofHours(1); - private static final ZoneOffset OFFSET_PTWO = ZoneOffset.ofHours(2); - - private OffsetDate TEST_2007_07_15_PONE; - - @BeforeMethod(groups={"tck","implementation"}) - public void setUp() { - TEST_2007_07_15_PONE = OffsetDate.of(LocalDate.of(2007, 7, 15), OFFSET_PONE); - } - - //----------------------------------------------------------------------- - @Override - protected List samples() { - TemporalAccessor[] array = {TEST_2007_07_15_PONE, OffsetDate.MIN, OffsetDate.MAX}; - return Arrays.asList(array); - } - - @Override - protected List validFields() { - TemporalField[] array = { - DAY_OF_WEEK, - ALIGNED_DAY_OF_WEEK_IN_MONTH, - ALIGNED_DAY_OF_WEEK_IN_YEAR, - DAY_OF_MONTH, - DAY_OF_YEAR, - EPOCH_DAY, - ALIGNED_WEEK_OF_MONTH, - ALIGNED_WEEK_OF_YEAR, - MONTH_OF_YEAR, - EPOCH_MONTH, - YEAR_OF_ERA, - YEAR, - ERA, - OFFSET_SECONDS, - JulianFields.JULIAN_DAY, - JulianFields.MODIFIED_JULIAN_DAY, - JulianFields.RATA_DIE, - }; - return Arrays.asList(array); - } - - @Override - protected List invalidFields() { - List list = new ArrayList<>(Arrays.asList(ChronoField.values())); - list.removeAll(validFields()); - return list; - } - - //----------------------------------------------------------------------- - @Test - public void test_serialization() throws ClassNotFoundException, IOException { - assertSerializable(TEST_2007_07_15_PONE); - assertSerializable(OffsetDate.MIN); - assertSerializable(OffsetDate.MAX); - } - - @Test - public void test_serialization_format() throws Exception { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (DataOutputStream dos = new DataOutputStream(baos) ) { - dos.writeByte(1); - } - byte[] bytes = baos.toByteArray(); - ByteArrayOutputStream baosDate = new ByteArrayOutputStream(); - try (DataOutputStream dos = new DataOutputStream(baosDate) ) { - dos.writeByte(3); - dos.writeInt(2012); - dos.writeByte(9); - dos.writeByte(16); - } - byte[] bytesDate = baosDate.toByteArray(); - ByteArrayOutputStream baosOffset = new ByteArrayOutputStream(); - try (DataOutputStream dos = new DataOutputStream(baosOffset) ) { - dos.writeByte(8); - dos.writeByte(4); // quarter hours stored: 3600 / 900 - } - byte[] bytesOffset = baosOffset.toByteArray(); - assertSerializedBySer(OffsetDate.of(LocalDate.of(2012, 9, 16), ZoneOffset.ofHours(1)), bytes, - bytesDate, bytesOffset); - } - - //----------------------------------------------------------------------- - // constants - //----------------------------------------------------------------------- - @Test - public void constant_MIN() { - check(OffsetDate.MIN, Year.MIN_VALUE, 1, 1, ZoneOffset.MAX); - } - - @Test - public void constant_MAX() { - check(OffsetDate.MAX, Year.MAX_VALUE, 12, 31, ZoneOffset.MIN); - } - - //----------------------------------------------------------------------- - // now() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void now() { - OffsetDate expected = OffsetDate.now(Clock.systemDefaultZone()); - OffsetDate test = OffsetDate.now(); - for (int i = 0; i < 100; i++) { - if (expected.equals(test)) { - return; - } - expected = OffsetDate.now(Clock.systemDefaultZone()); - test = OffsetDate.now(); - } - assertEquals(test, expected); - } - - @Test(groups={"tck"}) - public void now_Clock_allSecsInDay_utc() { - for (int i = 0; i < (2 * 24 * 60 * 60); i++) { - Instant instant = Instant.ofEpochSecond(i); - Clock clock = Clock.fixed(instant, ZoneOffset.UTC); - OffsetDate test = OffsetDate.now(clock); - check(test, 1970, 1, (i < 24 * 60 * 60 ? 1 : 2), ZoneOffset.UTC); - } - } - - @Test(groups={"tck"}) - public void now_Clock_allSecsInDay_beforeEpoch() { - for (int i =-1; i >= -(2 * 24 * 60 * 60); i--) { - Instant instant = Instant.ofEpochSecond(i); - Clock clock = Clock.fixed(instant, ZoneOffset.UTC); - OffsetDate test = OffsetDate.now(clock); - check(test, 1969, 12, (i >= -24 * 60 * 60 ? 31 : 30), ZoneOffset.UTC); - } - } - - @Test(groups={"tck"}) - public void now_Clock_offsets() { - Instant base = LocalDateTime.of(1970, 1, 1, 12, 0).toInstant(ZoneOffset.UTC); - for (int i = -9; i < 15; i++) { - ZoneOffset offset = ZoneOffset.ofHours(i); - Clock clock = Clock.fixed(base, offset); - OffsetDate test = OffsetDate.now(clock); - check(test, 1970, 1, (i >= 12 ? 2 : 1), offset); - } - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void now_Clock_nullZoneId() { - OffsetDate.now((ZoneId) null); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void now_Clock_nullClock() { - OffsetDate.now((Clock) null); - } - - //----------------------------------------------------------------------- - // factories - //----------------------------------------------------------------------- - private void check(OffsetDate test, int y, int mo, int d, ZoneOffset offset) { - assertEquals(test.getDate(), LocalDate.of(y, mo, d)); - assertEquals(test.getOffset(), offset); - - assertEquals(test.getYear(), y); - assertEquals(test.getMonth().getValue(), mo); - assertEquals(test.getDayOfMonth(), d); - - assertEquals(test, test); - assertEquals(test.hashCode(), test.hashCode()); - assertEquals(OffsetDate.of(LocalDate.of(y, mo, d), offset), test); - } - - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void factory_of_intMonthInt() { - OffsetDate test = OffsetDate.of(LocalDate.of(2007, Month.JULY, 15), OFFSET_PONE); - check(test, 2007, 7, 15, OFFSET_PONE); - } - - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void factory_of_ints() { - OffsetDate test = OffsetDate.of(LocalDate.of(2007, 7, 15), OFFSET_PONE); - check(test, 2007, 7, 15, OFFSET_PONE); - } - - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void factory_of_intsMonthOffset() { - assertEquals(TEST_2007_07_15_PONE, OffsetDate.of(LocalDate.of(2007, Month.JULY, 15), OFFSET_PONE)); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void factory_of_intsMonthOffset_dayTooLow() { - OffsetDate.of(LocalDate.of(2007, Month.JANUARY, 0), OFFSET_PONE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void factory_of_intsMonthOffset_dayTooHigh() { - OffsetDate.of(LocalDate.of(2007, Month.JANUARY, 32), OFFSET_PONE); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void factory_of_intsMonthOffset_nullMonth() { - OffsetDate.of(LocalDate.of(2007, null, 30), OFFSET_PONE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void factory_of_intsMonthOffset_yearTooLow() { - OffsetDate.of(LocalDate.of(Integer.MIN_VALUE, Month.JANUARY, 1), OFFSET_PONE); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void factory_of_intsMonthOffset_nullOffset() { - OffsetDate.of(LocalDate.of(2007, Month.JANUARY, 30), null); - } - - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void factory_of_intsOffset() { - OffsetDate test = OffsetDate.of(LocalDate.of(2007, 7, 15), OFFSET_PONE); - check(test, 2007, 7, 15, OFFSET_PONE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void factory_of_ints_dayTooLow() { - OffsetDate.of(LocalDate.of(2007, 1, 0), OFFSET_PONE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void factory_of_ints_dayTooHigh() { - OffsetDate.of(LocalDate.of(2007, 1, 32), OFFSET_PONE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void factory_of_ints_monthTooLow() { - OffsetDate.of(LocalDate.of(2007, 0, 1), OFFSET_PONE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void factory_of_ints_monthTooHigh() { - OffsetDate.of(LocalDate.of(2007, 13, 1), OFFSET_PONE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void factory_of_ints_yearTooLow() { - OffsetDate.of(LocalDate.of(Integer.MIN_VALUE, 1, 1), OFFSET_PONE); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void factory_of_ints_nullOffset() { - OffsetDate.of(LocalDate.of(2007, 1, 1), (ZoneOffset) null); - } - - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void factory_of_LocalDateZoneOffset() { - LocalDate localDate = LocalDate.of(2008, 6, 30); - OffsetDate test = OffsetDate.of(localDate, OFFSET_PONE); - check(test, 2008, 6, 30, OFFSET_PONE); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void factory_of_LocalDateZoneOffset_nullDate() { - OffsetDate.of((LocalDate) null, OFFSET_PONE); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void factory_of_LocalDateZoneOffset_nullOffset() { - LocalDate localDate = LocalDate.of(2008, 6, 30); - OffsetDate.of(localDate, (ZoneOffset) null); - } - - //----------------------------------------------------------------------- - // from(TemporalAccessor) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_from_TemporalAccessor_OD() { - assertEquals(OffsetDate.from(TEST_2007_07_15_PONE), TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_from_TemporalAccessor_ZDT() { - ZonedDateTime base = LocalDateTime.of(2007, 7, 15, 17, 30).atZone(OFFSET_PONE); - assertEquals(OffsetDate.from(base), TEST_2007_07_15_PONE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_from_TemporalAccessor_invalid_noDerive() { - OffsetDate.from(LocalTime.of(12, 30)); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_from_TemporalAccessor_null() { - OffsetDate.from((TemporalAccessor) null); - } - - //----------------------------------------------------------------------- - // parse() - //----------------------------------------------------------------------- - @Test(dataProvider="sampleToString", groups={"tck"}) - public void factory_parse_validText(int y, int m, int d, String offsetId, String parsable) { - OffsetDate t = OffsetDate.parse(parsable); - assertNotNull(t, parsable); - assertEquals(t.getYear(), y, parsable); - assertEquals(t.getMonth().getValue(), m, parsable); - assertEquals(t.getDayOfMonth(), d, parsable); - assertEquals(t.getOffset(), ZoneOffset.of(offsetId)); - } - - @DataProvider(name="sampleBadParse") - Object[][] provider_sampleBadParse() { - return new Object[][]{ - {"2008/07/05"}, - {"10000-01-01"}, - {"2008-1-1"}, - {"2008--01"}, - {"ABCD-02-01"}, - {"2008-AB-01"}, - {"2008-02-AB"}, - {"-0000-02-01"}, - {"2008-02-01Y"}, - {"2008-02-01+19:00"}, - {"2008-02-01+01/00"}, - {"2008-02-01+1900"}, - {"2008-02-01+01:60"}, - {"2008-02-01+01:30:123"}, - {"2008-02-01"}, - {"2008-02-01+01:00[Europe/Paris]"}, - }; - } - - @Test(dataProvider="sampleBadParse", expectedExceptions=DateTimeParseException.class, groups={"tck"}) - public void factory_parse_invalidText(String unparsable) { - OffsetDate.parse(unparsable); - } - - @Test(expectedExceptions=DateTimeParseException.class, groups={"tck"}) - public void factory_parse_illegalValue() { - OffsetDate.parse("2008-06-32+01:00"); - } - - @Test(expectedExceptions=DateTimeParseException.class, groups={"tck"}) - public void factory_parse_invalidValue() { - OffsetDate.parse("2008-06-31+01:00"); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void factory_parse_nullText() { - OffsetDate.parse((String) null); - } - - //----------------------------------------------------------------------- - // parse(DateTimeFormatter) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void factory_parse_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d XXX"); - OffsetDate test = OffsetDate.parse("2010 12 3 +01:00", f); - assertEquals(test, OffsetDate.of(LocalDate.of(2010, 12, 3), ZoneOffset.ofHours(1))); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void factory_parse_formatter_nullText() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d"); - OffsetDate.parse((String) null, f); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void factory_parse_formatter_nullFormatter() { - OffsetDate.parse("ANY", null); - } - - //----------------------------------------------------------------------- - // constructor - //----------------------------------------------------------------------- - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void constructor_nullDate() throws Throwable { - Constructor con = OffsetDate.class.getDeclaredConstructor(LocalDate.class, ZoneOffset.class); - con.setAccessible(true); - try { - con.newInstance(null, OFFSET_PONE); - } catch (InvocationTargetException ex) { - throw ex.getCause(); - } - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void constructor_nullOffset() throws Throwable { - Constructor con = OffsetDate.class.getDeclaredConstructor(LocalDate.class, ZoneOffset.class); - con.setAccessible(true); - try { - con.newInstance(LocalDate.of(2008, 6, 30), null); - } catch (InvocationTargetException ex) { - throw ex.getCause(); - } - } - - //----------------------------------------------------------------------- - // basics - //----------------------------------------------------------------------- - @DataProvider(name="sampleDates") - Object[][] provider_sampleDates() { - return new Object[][] { - {2008, 7, 5, OFFSET_PTWO}, - {2007, 7, 5, OFFSET_PONE}, - {2006, 7, 5, OFFSET_PTWO}, - {2005, 7, 5, OFFSET_PONE}, - {2004, 1, 1, OFFSET_PTWO}, - {-1, 1, 2, OFFSET_PONE}, - {999999, 11, 20, ZoneOffset.ofHoursMinutesSeconds(6, 9, 12)}, - }; - } - - @Test(dataProvider="sampleDates", groups={"tck"}) - public void test_get_OffsetDate(int y, int m, int d, ZoneOffset offset) { - LocalDate localDate = LocalDate.of(y, m, d); - OffsetDate a = OffsetDate.of(localDate, offset); - - assertEquals(a.getDate(), localDate); - assertEquals(a.getOffset(), offset); - assertEquals(a.toString(), localDate.toString() + offset.toString()); - assertEquals(a.getYear(), localDate.getYear()); - assertEquals(a.getMonth(), localDate.getMonth()); - assertEquals(a.getDayOfMonth(), localDate.getDayOfMonth()); - assertEquals(a.getDayOfYear(), localDate.getDayOfYear()); - assertEquals(a.getDayOfWeek(), localDate.getDayOfWeek()); - } - - //----------------------------------------------------------------------- - // get(TemporalField) - //----------------------------------------------------------------------- - @Test - public void test_get_TemporalField() { - OffsetDate test = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); - assertEquals(test.get(ChronoField.YEAR), 2008); - assertEquals(test.get(ChronoField.MONTH_OF_YEAR), 6); - assertEquals(test.get(ChronoField.DAY_OF_MONTH), 30); - assertEquals(test.get(ChronoField.DAY_OF_WEEK), 1); - assertEquals(test.get(ChronoField.DAY_OF_YEAR), 182); - - assertEquals(test.get(ChronoField.OFFSET_SECONDS), 3600); - } - - @Test - public void test_getLong_TemporalField() { - OffsetDate test = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); - assertEquals(test.getLong(ChronoField.YEAR), 2008); - assertEquals(test.getLong(ChronoField.MONTH_OF_YEAR), 6); - assertEquals(test.getLong(ChronoField.DAY_OF_MONTH), 30); - assertEquals(test.getLong(ChronoField.DAY_OF_WEEK), 1); - assertEquals(test.getLong(ChronoField.DAY_OF_YEAR), 182); - - assertEquals(test.getLong(ChronoField.OFFSET_SECONDS), 3600); - } - - //----------------------------------------------------------------------- - // query(TemporalQuery) - //----------------------------------------------------------------------- - @Test - public void test_query_chrono() { - assertEquals(TEST_2007_07_15_PONE.query(Queries.chrono()), ISOChrono.INSTANCE); - assertEquals(Queries.chrono().queryFrom(TEST_2007_07_15_PONE), ISOChrono.INSTANCE); - } - - @Test - public void test_query_zoneId() { - assertEquals(TEST_2007_07_15_PONE.query(Queries.zoneId()), null); - assertEquals(Queries.zoneId().queryFrom(TEST_2007_07_15_PONE), null); - } - - @Test - public void test_query_precision() { - assertEquals(TEST_2007_07_15_PONE.query(Queries.precision()), ChronoUnit.DAYS); - assertEquals(Queries.precision().queryFrom(TEST_2007_07_15_PONE), ChronoUnit.DAYS); - } - - @Test - public void test_query_offset() { - assertEquals(TEST_2007_07_15_PONE.query(Queries.offset()), OFFSET_PONE); - assertEquals(Queries.offset().queryFrom(TEST_2007_07_15_PONE), OFFSET_PONE); - } - - @Test - public void test_query_zone() { - assertEquals(TEST_2007_07_15_PONE.query(Queries.zone()), OFFSET_PONE); - assertEquals(Queries.zone().queryFrom(TEST_2007_07_15_PONE), OFFSET_PONE); - } - - @Test(expectedExceptions=NullPointerException.class) - public void test_query_null() { - TEST_2007_07_15_PONE.query(null); - } - - //----------------------------------------------------------------------- - // withOffset() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_withOffset() { - OffsetDate base = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); - OffsetDate test = base.withOffset(OFFSET_PTWO); - assertEquals(test.getDate(), base.getDate()); - assertEquals(test.getOffset(), OFFSET_PTWO); - } - - @Test(groups={"tck"}) - public void test_withOffset_noChange() { - OffsetDate base = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); - OffsetDate test = base.withOffset(OFFSET_PONE); - assertEquals(test, base); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_withOffset_null() { - TEST_2007_07_15_PONE.withOffset(null); - } - - //----------------------------------------------------------------------- - // with(WithAdjuster) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_with_adjustment() { - final OffsetDate sample = OffsetDate.of(LocalDate.of(2012, 3, 4), OFFSET_PONE); - TemporalAdjuster adjuster = new TemporalAdjuster() { - @Override - public Temporal adjustInto(Temporal dateTime) { - return sample; - } - }; - assertEquals(TEST_2007_07_15_PONE.with(adjuster), sample); - } - - @Test(groups={"tck"}) - public void test_with_adjustment_LocalDate() { - OffsetDate test = TEST_2007_07_15_PONE.with(LocalDate.of(2008, 6, 30)); - assertEquals(test, OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_with_adjustment_OffsetDate() { - OffsetDate test = TEST_2007_07_15_PONE.with(OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PTWO)); - assertEquals(test, OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PTWO)); - } - - @Test(groups={"tck"}) - public void test_with_adjustment_ZoneOffset() { - OffsetDate test = TEST_2007_07_15_PONE.with(OFFSET_PTWO); - assertEquals(test, OffsetDate.of(LocalDate.of(2007, 7, 15), OFFSET_PTWO)); - } - - @Test(groups={"tck"}) - public void test_with_adjustment_Month() { - OffsetDate test = TEST_2007_07_15_PONE.with(DECEMBER); - assertEquals(test, OffsetDate.of(LocalDate.of(2007, 12, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_with_adjustment_offsetUnchanged() { - OffsetDate base = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); - OffsetDate test = base.with(Year.of(2008)); - assertEquals(test, base); - } - - @Test(groups={"tck"}) - public void test_with_adjustment_noChange() { - LocalDate date = LocalDate.of(2008, 6, 30); - OffsetDate base = OffsetDate.of(date, OFFSET_PONE); - OffsetDate test = base.with(date); - assertEquals(test, base); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_with_adjustment_null() { - TEST_2007_07_15_PONE.with((TemporalAdjuster) null); - } - - //----------------------------------------------------------------------- - // with(TemporalField, long) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_with_TemporalField() { - OffsetDate test = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); - assertEquals(test.with(ChronoField.YEAR, 2009), OffsetDate.of(LocalDate.of(2009, 6, 30), OFFSET_PONE)); - assertEquals(test.with(ChronoField.MONTH_OF_YEAR, 7), OffsetDate.of(LocalDate.of(2008, 7, 30), OFFSET_PONE)); - assertEquals(test.with(ChronoField.DAY_OF_MONTH, 1), OffsetDate.of(LocalDate.of(2008, 6, 1), OFFSET_PONE)); - assertEquals(test.with(ChronoField.DAY_OF_WEEK, 2), OffsetDate.of(LocalDate.of(2008, 7, 1), OFFSET_PONE)); - assertEquals(test.with(ChronoField.DAY_OF_YEAR, 183), OffsetDate.of(LocalDate.of(2008, 7, 1), OFFSET_PONE)); - - assertEquals(test.with(ChronoField.OFFSET_SECONDS, 7205), OffsetDate.of(LocalDate.of(2008, 6, 30), ZoneOffset.ofHoursMinutesSeconds(2, 0, 5))); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"} ) - public void test_with_TemporalField_null() { - TEST_2007_07_15_PONE.with((TemporalField) null, 0); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"} ) - public void test_with_TemporalField_invalidField() { - TEST_2007_07_15_PONE.with(ChronoField.AMPM_OF_DAY, 0); - } - - //----------------------------------------------------------------------- - // withYear() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_withYear_int_normal() { - OffsetDate t = TEST_2007_07_15_PONE.withYear(2008); - assertEquals(t, OffsetDate.of(LocalDate.of(2008, 7, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_withYear_int_noChange() { - OffsetDate t = TEST_2007_07_15_PONE.withYear(2007); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_withYear_int_invalid() { - TEST_2007_07_15_PONE.withYear(Year.MIN_VALUE - 1); - } - - @Test(groups={"tck"}) - public void test_withYear_int_adjustDay() { - OffsetDate t = OffsetDate.of(LocalDate.of(2008, 2, 29), OFFSET_PONE).withYear(2007); - OffsetDate expected = OffsetDate.of(LocalDate.of(2007, 2, 28), OFFSET_PONE); - assertEquals(t, expected); - } - - //----------------------------------------------------------------------- - // withMonth() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_withMonth_int_normal() { - OffsetDate t = TEST_2007_07_15_PONE.withMonth(1); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 1, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_withMonth_int_noChange() { - OffsetDate t = TEST_2007_07_15_PONE.withMonth(7); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_withMonth_int_invalid() { - TEST_2007_07_15_PONE.withMonth(13); - } - - @Test(groups={"tck"}) - public void test_withMonth_int_adjustDay() { - OffsetDate t = OffsetDate.of(LocalDate.of(2007, 12, 31), OFFSET_PONE).withMonth(11); - OffsetDate expected = OffsetDate.of(LocalDate.of(2007, 11, 30), OFFSET_PONE); - assertEquals(t, expected); - } - - //----------------------------------------------------------------------- - // withDayOfMonth() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_withDayOfMonth_normal() { - OffsetDate t = TEST_2007_07_15_PONE.withDayOfMonth(1); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 7, 1), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_withDayOfMonth_noChange() { - OffsetDate t = TEST_2007_07_15_PONE.withDayOfMonth(15); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 7, 15), OFFSET_PONE)); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_withDayOfMonth_invalidForMonth() { - OffsetDate.of(LocalDate.of(2007, 11, 30), OFFSET_PONE).withDayOfMonth(31); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_withDayOfMonth_invalidAlways() { - OffsetDate.of(LocalDate.of(2007, 11, 30), OFFSET_PONE).withDayOfMonth(32); - } - - //----------------------------------------------------------------------- - // withDayOfYear(int) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_withDayOfYear_normal() { - OffsetDate t = TEST_2007_07_15_PONE.withDayOfYear(33); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 2, 2), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_withDayOfYear_noChange() { - OffsetDate t = TEST_2007_07_15_PONE.withDayOfYear(31 + 28 + 31 + 30 + 31 + 30 + 15); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_withDayOfYear_illegal() { - TEST_2007_07_15_PONE.withDayOfYear(367); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_withDayOfYear_invalid() { - TEST_2007_07_15_PONE.withDayOfYear(366); - } - - //----------------------------------------------------------------------- - // plus(PlusAdjuster) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_plus_PlusAdjuster() { - MockSimplePeriod period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); - OffsetDate t = TEST_2007_07_15_PONE.plus(period); - assertEquals(t, OffsetDate.of(LocalDate.of(2008, 2, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plus_PlusAdjuster_noChange() { - MockSimplePeriod period = MockSimplePeriod.of(0, ChronoUnit.MONTHS); - OffsetDate t = TEST_2007_07_15_PONE.plus(period); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_plus_PlusAdjuster_zero() { - OffsetDate t = TEST_2007_07_15_PONE.plus(Period.ZERO); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_plus_PlusAdjuster_null() { - TEST_2007_07_15_PONE.plus((TemporalAdder) null); - } - - //----------------------------------------------------------------------- - // plusYears() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_plusYears_long_normal() { - OffsetDate t = TEST_2007_07_15_PONE.plusYears(1); - assertEquals(t, OffsetDate.of(LocalDate.of(2008, 7, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusYears_long_negative() { - OffsetDate t = TEST_2007_07_15_PONE.plusYears(-1); - assertEquals(t, OffsetDate.of(LocalDate.of(2006, 7, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusYears_long_noChange() { - OffsetDate t = TEST_2007_07_15_PONE.plusYears(0); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_plusYears_long_adjustDay() { - OffsetDate t = OffsetDate.of(LocalDate.of(2008, 2, 29), OFFSET_PONE).plusYears(1); - OffsetDate expected = OffsetDate.of(LocalDate.of(2009, 2, 28), OFFSET_PONE); - assertEquals(t, expected); - } - - @Test(groups={"tck"}) - public void test_plusYears_long_big() { - long years = 20L + Year.MAX_VALUE; - OffsetDate test = OffsetDate.of(LocalDate.of(-40, 6, 1), OFFSET_PONE).plusYears(years); - assertEquals(test, OffsetDate.of(LocalDate.of((int) (-40L + years), 6, 1), OFFSET_PONE)); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_plusYears_long_invalidTooLarge() { - OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 1, 1), OFFSET_PONE).plusYears(1); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_plusYears_long_invalidTooLargeMaxAddMax() { - OffsetDate test = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 1), OFFSET_PONE); - test.plusYears(Long.MAX_VALUE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_plusYears_long_invalidTooLargeMaxAddMin() { - OffsetDate test = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 1), OFFSET_PONE); - test.plusYears(Long.MIN_VALUE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_plusYears_long_invalidTooSmall() { - OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 1), OFFSET_PONE).plusYears(-1); - } - - //----------------------------------------------------------------------- - // plusMonths() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_plusMonths_long_normal() { - OffsetDate t = TEST_2007_07_15_PONE.plusMonths(1); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 8, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusMonths_long_overYears() { - OffsetDate t = TEST_2007_07_15_PONE.plusMonths(25); - assertEquals(t, OffsetDate.of(LocalDate.of(2009, 8, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusMonths_long_negative() { - OffsetDate t = TEST_2007_07_15_PONE.plusMonths(-1); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 6, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusMonths_long_negativeAcrossYear() { - OffsetDate t = TEST_2007_07_15_PONE.plusMonths(-7); - assertEquals(t, OffsetDate.of(LocalDate.of(2006, 12, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusMonths_long_negativeOverYears() { - OffsetDate t = TEST_2007_07_15_PONE.plusMonths(-31); - assertEquals(t, OffsetDate.of(LocalDate.of(2004, 12, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusMonths_long_noChange() { - OffsetDate t = TEST_2007_07_15_PONE.plusMonths(0); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_plusMonths_long_adjustDayFromLeapYear() { - OffsetDate t = OffsetDate.of(LocalDate.of(2008, 2, 29), OFFSET_PONE).plusMonths(12); - OffsetDate expected = OffsetDate.of(LocalDate.of(2009, 2, 28), OFFSET_PONE); - assertEquals(t, expected); - } - - @Test(groups={"tck"}) - public void test_plusMonths_long_adjustDayFromMonthLength() { - OffsetDate t = OffsetDate.of(LocalDate.of(2007, 3, 31), OFFSET_PONE).plusMonths(1); - OffsetDate expected = OffsetDate.of(LocalDate.of(2007, 4, 30), OFFSET_PONE); - assertEquals(t, expected); - } - - @Test(groups={"tck"}) - public void test_plusMonths_long_big() { - long months = 20L + Integer.MAX_VALUE; - OffsetDate test = OffsetDate.of(LocalDate.of(-40, 6, 1), OFFSET_PONE).plusMonths(months); - assertEquals(test, OffsetDate.of(LocalDate.of((int) (-40L + months / 12), 6 + (int) (months % 12), 1), OFFSET_PONE)); - } - - @Test(expectedExceptions={DateTimeException.class}, groups={"tck"}) - public void test_plusMonths_long_invalidTooLarge() { - OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 1), OFFSET_PONE).plusMonths(1); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_plusMonths_long_invalidTooLargeMaxAddMax() { - OffsetDate test = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 1), OFFSET_PONE); - test.plusMonths(Long.MAX_VALUE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_plusMonths_long_invalidTooLargeMaxAddMin() { - OffsetDate test = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 1), OFFSET_PONE); - test.plusMonths(Long.MIN_VALUE); - } - - @Test(expectedExceptions={DateTimeException.class}, groups={"tck"}) - public void test_plusMonths_long_invalidTooSmall() { - OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 1), OFFSET_PONE).plusMonths(-1); - } - - //----------------------------------------------------------------------- - // plusWeeks() - //----------------------------------------------------------------------- - @DataProvider(name="samplePlusWeeksSymmetry") - Object[][] provider_samplePlusWeeksSymmetry() { - return new Object[][] { - {OffsetDate.of(LocalDate.of(-1, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(-1, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(-1, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(-1, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(0, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(0, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(0, 2, 29), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(0, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(0, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2007, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2007, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2007, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2007, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2008, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2008, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2008, 2, 29), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2008, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2008, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2099, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2099, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2099, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2099, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2100, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2100, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2100, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2100, 12, 31), OFFSET_PTWO)}, - }; - } - - @Test(dataProvider="samplePlusWeeksSymmetry", groups={"tck"}) - public void test_plusWeeks_symmetry(OffsetDate reference) { - for (int weeks = 0; weeks < 365 * 8; weeks++) { - OffsetDate t = reference.plusWeeks(weeks).plusWeeks(-weeks); - assertEquals(t, reference); - - t = reference.plusWeeks(-weeks).plusWeeks(weeks); - assertEquals(t, reference); - } - } - - @Test(groups={"tck"}) - public void test_plusWeeks_normal() { - OffsetDate t = TEST_2007_07_15_PONE.plusWeeks(1); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 7, 22), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusWeeks_overMonths() { - OffsetDate t = TEST_2007_07_15_PONE.plusWeeks(9); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 9, 16), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusWeeks_overYears() { - OffsetDate t = OffsetDate.of(LocalDate.of(2006, 7, 16), OFFSET_PONE).plusWeeks(52); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_plusWeeks_overLeapYears() { - OffsetDate t = TEST_2007_07_15_PONE.plusYears(-1).plusWeeks(104); - assertEquals(t, OffsetDate.of(LocalDate.of(2008, 7, 12), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusWeeks_negative() { - OffsetDate t = TEST_2007_07_15_PONE.plusWeeks(-1); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 7, 8), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusWeeks_negativeAcrossYear() { - OffsetDate t = TEST_2007_07_15_PONE.plusWeeks(-28); - assertEquals(t, OffsetDate.of(LocalDate.of(2006, 12, 31), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusWeeks_negativeOverYears() { - OffsetDate t = TEST_2007_07_15_PONE.plusWeeks(-104); - assertEquals(t, OffsetDate.of(LocalDate.of(2005, 7, 17), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusWeeks_noChange() { - OffsetDate t = TEST_2007_07_15_PONE.plusWeeks(0); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_plusWeeks_maximum() { - OffsetDate t = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 24), OFFSET_PONE).plusWeeks(1); - OffsetDate expected = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 31), OFFSET_PONE); - assertEquals(t, expected); - } - - @Test(groups={"tck"}) - public void test_plusWeeks_minimum() { - OffsetDate t = OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 8), OFFSET_PONE).plusWeeks(-1); - OffsetDate expected = OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 1), OFFSET_PONE); - assertEquals(t, expected); - } - - @Test(expectedExceptions={DateTimeException.class}, groups={"tck"}) - public void test_plusWeeks_invalidTooLarge() { - OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 25), OFFSET_PONE).plusWeeks(1); - } - - @Test(expectedExceptions={DateTimeException.class}, groups={"tck"}) - public void test_plusWeeks_invalidTooSmall() { - OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 7), OFFSET_PONE).plusWeeks(-1); - } - - @Test(expectedExceptions={ArithmeticException.class}, groups={"tck"}) - public void test_plusWeeks_invalidMaxMinusMax() { - OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 25), OFFSET_PONE).plusWeeks(Long.MAX_VALUE); - } - - @Test(expectedExceptions={ArithmeticException.class}, groups={"tck"}) - public void test_plusWeeks_invalidMaxMinusMin() { - OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 25), OFFSET_PONE).plusWeeks(Long.MIN_VALUE); - } - - //----------------------------------------------------------------------- - // plusDays() - //----------------------------------------------------------------------- - @DataProvider(name="samplePlusDaysSymmetry") - Object[][] provider_samplePlusDaysSymmetry() { - return new Object[][] { - {OffsetDate.of(LocalDate.of(-1, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(-1, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(-1, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(-1, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(0, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(0, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(0, 2, 29), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(0, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(0, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2007, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2007, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2007, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2007, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2008, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2008, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2008, 2, 29), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2008, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2008, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2099, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2099, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2099, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2099, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2100, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2100, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2100, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2100, 12, 31), OFFSET_PTWO)}, - }; - } - - @Test(dataProvider="samplePlusDaysSymmetry", groups={"tck"}) - public void test_plusDays_symmetry(OffsetDate reference) { - for (int days = 0; days < 365 * 8; days++) { - OffsetDate t = reference.plusDays(days).plusDays(-days); - assertEquals(t, reference); - - t = reference.plusDays(-days).plusDays(days); - assertEquals(t, reference); - } - } - - @Test(groups={"tck"}) - public void test_plusDays_normal() { - OffsetDate t = TEST_2007_07_15_PONE.plusDays(1); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 7, 16), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusDays_overMonths() { - OffsetDate t = TEST_2007_07_15_PONE.plusDays(62); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 9, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusDays_overYears() { - OffsetDate t = OffsetDate.of(LocalDate.of(2006, 7, 14), OFFSET_PONE).plusDays(366); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_plusDays_overLeapYears() { - OffsetDate t = TEST_2007_07_15_PONE.plusYears(-1).plusDays(365 + 366); - assertEquals(t, OffsetDate.of(LocalDate.of(2008, 7, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusDays_negative() { - OffsetDate t = TEST_2007_07_15_PONE.plusDays(-1); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 7, 14), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusDays_negativeAcrossYear() { - OffsetDate t = TEST_2007_07_15_PONE.plusDays(-196); - assertEquals(t, OffsetDate.of(LocalDate.of(2006, 12, 31), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusDays_negativeOverYears() { - OffsetDate t = TEST_2007_07_15_PONE.plusDays(-730); - assertEquals(t, OffsetDate.of(LocalDate.of(2005, 7, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_plusDays_noChange() { - OffsetDate t = TEST_2007_07_15_PONE.plusDays(0); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_plusDays_maximum() { - OffsetDate t = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 30), OFFSET_PONE).plusDays(1); - OffsetDate expected = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 31), OFFSET_PONE); - assertEquals(t, expected); - } - - @Test(groups={"tck"}) - public void test_plusDays_minimum() { - OffsetDate t = OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 2), OFFSET_PONE).plusDays(-1); - OffsetDate expected = OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 1), OFFSET_PONE); - assertEquals(t, expected); - } - - @Test(expectedExceptions={DateTimeException.class}, groups={"tck"}) - public void test_plusDays_invalidTooLarge() { - OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 31), OFFSET_PONE).plusDays(1); - } - - @Test(expectedExceptions={DateTimeException.class}, groups={"tck"}) - public void test_plusDays_invalidTooSmall() { - OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 1), OFFSET_PONE).plusDays(-1); - } - - @Test(expectedExceptions=ArithmeticException.class, groups={"tck"}) - public void test_plusDays_overflowTooLarge() { - OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 31), OFFSET_PONE).plusDays(Long.MAX_VALUE); - } - - @Test(expectedExceptions=ArithmeticException.class, groups={"tck"}) - public void test_plusDays_overflowTooSmall() { - OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 1), OFFSET_PONE).plusDays(Long.MIN_VALUE); - } - - //----------------------------------------------------------------------- - // minus(MinusAdjuster) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_minus_MinusAdjuster() { - MockSimplePeriod period = MockSimplePeriod.of(7, ChronoUnit.MONTHS); - OffsetDate t = TEST_2007_07_15_PONE.minus(period); - assertEquals(t, OffsetDate.of(LocalDate.of(2006, 12, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minus_MinusAdjuster_noChange() { - MockSimplePeriod period = MockSimplePeriod.of(0, ChronoUnit.MONTHS); - OffsetDate t = TEST_2007_07_15_PONE.minus(period); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_minus_MinusAdjuster_zero() { - OffsetDate t = TEST_2007_07_15_PONE.minus(Period.ZERO); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_plus_MinusAdjuster_null() { - TEST_2007_07_15_PONE.minus((TemporalSubtractor) null); - } - - //----------------------------------------------------------------------- - // minusYears() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_minusYears_long_normal() { - OffsetDate t = TEST_2007_07_15_PONE.minusYears(1); - assertEquals(t, OffsetDate.of(LocalDate.of(2006, 7, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusYears_long_negative() { - OffsetDate t = TEST_2007_07_15_PONE.minusYears(-1); - assertEquals(t, OffsetDate.of(LocalDate.of(2008, 7, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusYears_long_noChange() { - OffsetDate t = TEST_2007_07_15_PONE.minusYears(0); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_minusYears_long_adjustDay() { - OffsetDate t = OffsetDate.of(LocalDate.of(2008, 2, 29), OFFSET_PONE).minusYears(1); - OffsetDate expected = OffsetDate.of(LocalDate.of(2007, 2, 28), OFFSET_PONE); - assertEquals(t, expected); - } - - @Test(groups={"tck"}) - public void test_minusYears_long_big() { - long years = 20L + Year.MAX_VALUE; - OffsetDate test = OffsetDate.of(LocalDate.of(40, 6, 1), OFFSET_PONE).minusYears(years); - assertEquals(test, OffsetDate.of(LocalDate.of((int) (40L - years), 6, 1), OFFSET_PONE)); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_minusYears_long_invalidTooLarge() { - OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 1, 1), OFFSET_PONE).minusYears(-1); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_minusYears_long_invalidTooLargeMaxAddMax() { - OffsetDate test = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 1), OFFSET_PONE); - test.minusYears(Long.MAX_VALUE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_minusYears_long_invalidTooLargeMaxAddMin() { - OffsetDate test = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 1), OFFSET_PONE); - test.minusYears(Long.MIN_VALUE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_minusYears_long_invalidTooSmall() { - OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 1), OFFSET_PONE).minusYears(1); - } - - //----------------------------------------------------------------------- - // minusMonths() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_minusMonths_long_normal() { - OffsetDate t = TEST_2007_07_15_PONE.minusMonths(1); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 6, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusMonths_long_overYears() { - OffsetDate t = TEST_2007_07_15_PONE.minusMonths(25); - assertEquals(t, OffsetDate.of(LocalDate.of(2005, 6, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusMonths_long_negative() { - OffsetDate t = TEST_2007_07_15_PONE.minusMonths(-1); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 8, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusMonths_long_negativeAcrossYear() { - OffsetDate t = TEST_2007_07_15_PONE.minusMonths(-7); - assertEquals(t, OffsetDate.of(LocalDate.of(2008, 2, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusMonths_long_negativeOverYears() { - OffsetDate t = TEST_2007_07_15_PONE.minusMonths(-31); - assertEquals(t, OffsetDate.of(LocalDate.of(2010, 2, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusMonths_long_noChange() { - OffsetDate t = TEST_2007_07_15_PONE.minusMonths(0); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_minusMonths_long_adjustDayFromLeapYear() { - OffsetDate t = OffsetDate.of(LocalDate.of(2008, 2, 29), OFFSET_PONE).minusMonths(12); - OffsetDate expected = OffsetDate.of(LocalDate.of(2007, 2, 28), OFFSET_PONE); - assertEquals(t, expected); - } - - @Test(groups={"tck"}) - public void test_minusMonths_long_adjustDayFromMonthLength() { - OffsetDate t = OffsetDate.of(LocalDate.of(2007, 3, 31), OFFSET_PONE).minusMonths(1); - OffsetDate expected = OffsetDate.of(LocalDate.of(2007, 2, 28), OFFSET_PONE); - assertEquals(t, expected); - } - - @Test(groups={"tck"}) - public void test_minusMonths_long_big() { - long months = 20L + Integer.MAX_VALUE; - OffsetDate test = OffsetDate.of(LocalDate.of(40, 6, 1), OFFSET_PONE).minusMonths(months); - assertEquals(test, OffsetDate.of(LocalDate.of((int) (40L - months / 12), 6 - (int) (months % 12), 1), OFFSET_PONE)); - } - - @Test(expectedExceptions={DateTimeException.class}, groups={"tck"}) - public void test_minusMonths_long_invalidTooLarge() { - OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 1), OFFSET_PONE).minusMonths(-1); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_minusMonths_long_invalidTooLargeMaxAddMax() { - OffsetDate test = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 1), OFFSET_PONE); - test.minusMonths(Long.MAX_VALUE); - } - - @Test(expectedExceptions=DateTimeException.class, groups={"tck"}) - public void test_minusMonths_long_invalidTooLargeMaxAddMin() { - OffsetDate test = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 1), OFFSET_PONE); - test.minusMonths(Long.MIN_VALUE); - } - - @Test(expectedExceptions={DateTimeException.class}, groups={"tck"}) - public void test_minusMonths_long_invalidTooSmall() { - OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 1), OFFSET_PONE).minusMonths(1); - } - - //----------------------------------------------------------------------- - // minusWeeks() - //----------------------------------------------------------------------- - @DataProvider(name="sampleMinusWeeksSymmetry") - Object[][] provider_sampleMinusWeeksSymmetry() { - return new Object[][] { - {OffsetDate.of(LocalDate.of(-1, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(-1, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(-1, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(-1, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(0, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(0, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(0, 2, 29), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(0, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(0, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2007, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2007, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2007, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2007, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2008, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2008, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2008, 2, 29), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2008, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2008, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2099, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2099, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2099, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2099, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2100, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2100, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2100, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2100, 12, 31), OFFSET_PTWO)}, - }; - } - - @Test(dataProvider="sampleMinusWeeksSymmetry", groups={"tck"}) - public void test_minusWeeks_symmetry(OffsetDate reference) { - for (int weeks = 0; weeks < 365 * 8; weeks++) { - OffsetDate t = reference.minusWeeks(weeks).minusWeeks(-weeks); - assertEquals(t, reference); - - t = reference.minusWeeks(-weeks).minusWeeks(weeks); - assertEquals(t, reference); - } - } - - @Test(groups={"tck"}) - public void test_minusWeeks_normal() { - OffsetDate t = TEST_2007_07_15_PONE.minusWeeks(1); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 7, 8), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusWeeks_overMonths() { - OffsetDate t = TEST_2007_07_15_PONE.minusWeeks(9); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 5, 13), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusWeeks_overYears() { - OffsetDate t = OffsetDate.of(LocalDate.of(2008, 7, 13), OFFSET_PONE).minusWeeks(52); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_minusWeeks_overLeapYears() { - OffsetDate t = TEST_2007_07_15_PONE.minusYears(-1).minusWeeks(104); - assertEquals(t, OffsetDate.of(LocalDate.of(2006, 7, 18), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusWeeks_negative() { - OffsetDate t = TEST_2007_07_15_PONE.minusWeeks(-1); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 7, 22), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusWeeks_negativeAcrossYear() { - OffsetDate t = TEST_2007_07_15_PONE.minusWeeks(-28); - assertEquals(t, OffsetDate.of(LocalDate.of(2008, 1, 27), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusWeeks_negativeOverYears() { - OffsetDate t = TEST_2007_07_15_PONE.minusWeeks(-104); - assertEquals(t, OffsetDate.of(LocalDate.of(2009, 7, 12), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusWeeks_noChange() { - OffsetDate t = TEST_2007_07_15_PONE.minusWeeks(0); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_minusWeeks_maximum() { - OffsetDate t = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 24), OFFSET_PONE).minusWeeks(-1); - OffsetDate expected = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 31), OFFSET_PONE); - assertEquals(t, expected); - } - - @Test(groups={"tck"}) - public void test_minusWeeks_minimum() { - OffsetDate t = OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 8), OFFSET_PONE).minusWeeks(1); - OffsetDate expected = OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 1), OFFSET_PONE); - assertEquals(t, expected); - } - - @Test(expectedExceptions={DateTimeException.class}, groups={"tck"}) - public void test_minusWeeks_invalidTooLarge() { - OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 25), OFFSET_PONE).minusWeeks(-1); - } - - @Test(expectedExceptions={DateTimeException.class}, groups={"tck"}) - public void test_minusWeeks_invalidTooSmall() { - OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 7), OFFSET_PONE).minusWeeks(1); - } - - @Test(expectedExceptions={ArithmeticException.class}, groups={"tck"}) - public void test_minusWeeks_invalidMaxMinusMax() { - OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 25), OFFSET_PONE).minusWeeks(Long.MAX_VALUE); - } - - @Test(expectedExceptions={ArithmeticException.class}, groups={"tck"}) - public void test_minusWeeks_invalidMaxMinusMin() { - OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 25), OFFSET_PONE).minusWeeks(Long.MIN_VALUE); - } - - //----------------------------------------------------------------------- - // minusDays() - //----------------------------------------------------------------------- - @DataProvider(name="sampleMinusDaysSymmetry") - Object[][] provider_sampleMinusDaysSymmetry() { - return new Object[][] { - {OffsetDate.of(LocalDate.of(-1, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(-1, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(-1, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(-1, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(0, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(0, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(0, 2, 29), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(0, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(0, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2007, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2007, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2007, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2007, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2008, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2008, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2008, 2, 29), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2008, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2008, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2099, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2099, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2099, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2099, 12, 31), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2100, 1, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2100, 2, 28), OFFSET_PTWO)}, - {OffsetDate.of(LocalDate.of(2100, 3, 1), OFFSET_PONE)}, - {OffsetDate.of(LocalDate.of(2100, 12, 31), OFFSET_PTWO)}, - }; - } - - @Test(dataProvider="sampleMinusDaysSymmetry", groups={"tck"}) - public void test_minusDays_symmetry(OffsetDate reference) { - for (int days = 0; days < 365 * 8; days++) { - OffsetDate t = reference.minusDays(days).minusDays(-days); - assertEquals(t, reference); - - t = reference.minusDays(-days).minusDays(days); - assertEquals(t, reference); - } - } - - @Test(groups={"tck"}) - public void test_minusDays_normal() { - OffsetDate t = TEST_2007_07_15_PONE.minusDays(1); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 7, 14), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusDays_overMonths() { - OffsetDate t = TEST_2007_07_15_PONE.minusDays(62); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 5, 14), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusDays_overYears() { - OffsetDate t = OffsetDate.of(LocalDate.of(2008, 7, 16), OFFSET_PONE).minusDays(367); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_minusDays_overLeapYears() { - OffsetDate t = TEST_2007_07_15_PONE.plusYears(2).minusDays(365 + 366); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_minusDays_negative() { - OffsetDate t = TEST_2007_07_15_PONE.minusDays(-1); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 7, 16), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusDays_negativeAcrossYear() { - OffsetDate t = TEST_2007_07_15_PONE.minusDays(-169); - assertEquals(t, OffsetDate.of(LocalDate.of(2007, 12, 31), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusDays_negativeOverYears() { - OffsetDate t = TEST_2007_07_15_PONE.minusDays(-731); - assertEquals(t, OffsetDate.of(LocalDate.of(2009, 7, 15), OFFSET_PONE)); - } - - @Test(groups={"tck"}) - public void test_minusDays_noChange() { - OffsetDate t = TEST_2007_07_15_PONE.minusDays(0); - assertEquals(t, TEST_2007_07_15_PONE); - } - - @Test(groups={"tck"}) - public void test_minusDays_maximum() { - OffsetDate t = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 30), OFFSET_PONE).minusDays(-1); - OffsetDate expected = OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 31), OFFSET_PONE); - assertEquals(t, expected); - } - - @Test(groups={"tck"}) - public void test_minusDays_minimum() { - OffsetDate t = OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 2), OFFSET_PONE).minusDays(1); - OffsetDate expected = OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 1), OFFSET_PONE); - assertEquals(t, expected); - } - - @Test(expectedExceptions={DateTimeException.class}, groups={"tck"}) - public void test_minusDays_invalidTooLarge() { - OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 31), OFFSET_PONE).minusDays(-1); - } - - @Test(expectedExceptions={DateTimeException.class}, groups={"tck"}) - public void test_minusDays_invalidTooSmall() { - OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 1), OFFSET_PONE).minusDays(1); - } - - @Test(expectedExceptions=ArithmeticException.class, groups={"tck"}) - public void test_minusDays_overflowTooLarge() { - OffsetDate.of(LocalDate.of(Year.MAX_VALUE, 12, 31), OFFSET_PONE).minusDays(Long.MIN_VALUE); - } - - @Test(expectedExceptions=ArithmeticException.class, groups={"tck"}) - public void test_minusDays_overflowTooSmall() { - OffsetDate.of(LocalDate.of(Year.MIN_VALUE, 1, 1), OFFSET_PONE).minusDays(Long.MAX_VALUE); - } - - //----------------------------------------------------------------------- - // atTime() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_atTime_Local() { - OffsetDate t = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PTWO); - assertEquals(t.atTime(LocalTime.of(11, 30)), - OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30), OFFSET_PTWO)); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_atTime_Local_nullLocalTime() { - OffsetDate t = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PTWO); - t.atTime((LocalTime) null); - } - - //----------------------------------------------------------------------- - // getDate() - //----------------------------------------------------------------------- - @Test(dataProvider="sampleDates", groups={"tck"}) - public void test_getDate(int year, int month, int day, ZoneOffset offset) { - LocalDate t = LocalDate.of(year, month, day); - assertEquals(OffsetDate.of(LocalDate.of(year, month, day), offset).getDate(), t); - } - - //----------------------------------------------------------------------- - // compareTo() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_compareTo_date() { - OffsetDate a = OffsetDate.of(LocalDate.of(2008, 6, 29), OFFSET_PONE); - OffsetDate b = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); // a is before b due to date - assertEquals(a.compareTo(b) < 0, true); - assertEquals(b.compareTo(a) > 0, true); - assertEquals(a.compareTo(a) == 0, true); - assertEquals(b.compareTo(b) == 0, true); - assertEquals(a.atTime(LocalTime.MIDNIGHT).toInstant().compareTo(b.atTime(LocalTime.MIDNIGHT).toInstant()) < 0, true); - } - - @Test(groups={"tck"}) - public void test_compareTo_offset() { - OffsetDate a = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PTWO); - OffsetDate b = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); // a is before b due to offset - assertEquals(a.compareTo(b) < 0, true); - assertEquals(b.compareTo(a) > 0, true); - assertEquals(a.compareTo(a) == 0, true); - assertEquals(b.compareTo(b) == 0, true); - assertEquals(a.atTime(LocalTime.MIDNIGHT).toInstant().compareTo(b.atTime(LocalTime.MIDNIGHT).toInstant()) < 0, true); - } - - @Test(groups={"tck"}) - public void test_compareTo_both() { - OffsetDate a = OffsetDate.of(LocalDate.of(2008, 6, 29), OFFSET_PTWO); - OffsetDate b = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); // a is before b on instant scale - assertEquals(a.compareTo(b) < 0, true); - assertEquals(b.compareTo(a) > 0, true); - assertEquals(a.compareTo(a) == 0, true); - assertEquals(b.compareTo(b) == 0, true); - assertEquals(a.atTime(LocalTime.MIDNIGHT).toInstant().compareTo(b.atTime(LocalTime.MIDNIGHT).toInstant()) < 0, true); - } - - @Test(groups={"tck"}) - public void test_compareTo_24hourDifference() { - OffsetDate a = OffsetDate.of(LocalDate.of(2008, 6, 29), ZoneOffset.ofHours(-12)); - OffsetDate b = OffsetDate.of(LocalDate.of(2008, 6, 30), ZoneOffset.ofHours(12)); // a is before b despite being same time-line time - assertEquals(a.compareTo(b) < 0, true); - assertEquals(b.compareTo(a) > 0, true); - assertEquals(a.compareTo(a) == 0, true); - assertEquals(b.compareTo(b) == 0, true); - assertEquals(a.atTime(LocalTime.MIDNIGHT).toInstant().compareTo(b.atTime(LocalTime.MIDNIGHT).toInstant()) == 0, true); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_compareTo_null() { - OffsetDate a = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); - a.compareTo(null); - } - - @Test(expectedExceptions=ClassCastException.class, groups={"tck"}) - @SuppressWarnings({"unchecked", "rawtypes"}) - public void compareToNonOffsetDate() { - Comparable c = TEST_2007_07_15_PONE; - c.compareTo(new Object()); - } - - //----------------------------------------------------------------------- - // isAfter() / isBefore() / isEqual() - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_isBeforeIsAfterIsEqual1() { - OffsetDate a = OffsetDate.of(LocalDate.of(2008, 6, 29), OFFSET_PONE); - OffsetDate b = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); // a is before b due to time - assertEquals(a.isBefore(b), true); - assertEquals(a.isEqual(b), false); - assertEquals(a.isAfter(b), false); - - assertEquals(b.isBefore(a), false); - assertEquals(b.isEqual(a), false); - assertEquals(b.isAfter(a), true); - - assertEquals(a.isBefore(a), false); - assertEquals(b.isBefore(b), false); - - assertEquals(a.isEqual(a), true); - assertEquals(b.isEqual(b), true); - - assertEquals(a.isAfter(a), false); - assertEquals(b.isAfter(b), false); - } - - @Test(groups={"tck"}) - public void test_isBeforeIsAfterIsEqual2() { - OffsetDate a = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PTWO); - OffsetDate b = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); // a is before b due to offset - assertEquals(a.isBefore(b), true); - assertEquals(a.isEqual(b), false); - assertEquals(a.isAfter(b), false); - - assertEquals(b.isBefore(a), false); - assertEquals(b.isEqual(a), false); - assertEquals(b.isAfter(a), true); - - assertEquals(a.isBefore(a), false); - assertEquals(b.isBefore(b), false); - - assertEquals(a.isEqual(a), true); - assertEquals(b.isEqual(b), true); - - assertEquals(a.isAfter(a), false); - assertEquals(b.isAfter(b), false); - } - - @Test(groups={"tck"}) - public void test_isBeforeIsAfterIsEqual_instantComparison() { - OffsetDate a = OffsetDate.of(LocalDate.of(2008, 6, 30), ZoneOffset.ofHours(12)); - OffsetDate b = OffsetDate.of(LocalDate.of(2008, 6, 29), ZoneOffset.ofHours(-12)); // a is same instant as b - assertEquals(a.isBefore(b), false); - assertEquals(a.isEqual(b), true); - assertEquals(a.isAfter(b), false); - - assertEquals(b.isBefore(a), false); - assertEquals(b.isEqual(a), true); - assertEquals(b.isAfter(a), false); - - assertEquals(a.isBefore(a), false); - assertEquals(b.isBefore(b), false); - - assertEquals(a.isEqual(a), true); - assertEquals(b.isEqual(b), true); - - assertEquals(a.isAfter(a), false); - assertEquals(b.isAfter(b), false); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_isBefore_null() { - OffsetDate a = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); - a.isBefore(null); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_isAfter_null() { - OffsetDate a = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); - a.isAfter(null); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_isEqual_null() { - OffsetDate a = OffsetDate.of(LocalDate.of(2008, 6, 30), OFFSET_PONE); - a.isEqual(null); - } - - //----------------------------------------------------------------------- - // equals() / hashCode() - //----------------------------------------------------------------------- - @Test(dataProvider="sampleDates", groups={"tck"}) - public void test_equals_true(int y, int m, int d, ZoneOffset offset) { - OffsetDate a = OffsetDate.of(LocalDate.of(y, m, d), offset); - OffsetDate b = OffsetDate.of(LocalDate.of(y, m, d), offset); - assertEquals(a.equals(b), true); - assertEquals(a.hashCode() == b.hashCode(), true); - } - @Test(dataProvider="sampleDates", groups={"tck"}) - public void test_equals_false_year_differs(int y, int m, int d, ZoneOffset offset) { - OffsetDate a = OffsetDate.of(LocalDate.of(y, m, d), offset); - OffsetDate b = OffsetDate.of(LocalDate.of(y + 1, m, d), offset); - assertEquals(a.equals(b), false); - } - - @Test(dataProvider="sampleDates", groups={"tck"}) - public void test_equals_false_month_differs(int y, int m, int d, ZoneOffset offset) { - OffsetDate a = OffsetDate.of(LocalDate.of(y, m, d), offset); - OffsetDate b = OffsetDate.of(LocalDate.of(y, m + 1, d), offset); - assertEquals(a.equals(b), false); - } - - @Test(dataProvider="sampleDates", groups={"tck"}) - public void test_equals_false_day_differs(int y, int m, int d, ZoneOffset offset) { - OffsetDate a = OffsetDate.of(LocalDate.of(y, m, d), offset); - OffsetDate b = OffsetDate.of(LocalDate.of(y, m, d + 1), offset); - assertEquals(a.equals(b), false); - } - - @Test(dataProvider="sampleDates", groups={"tck"}) - public void test_equals_false_offset_differs(int y, int m, int d, ZoneOffset ignored) { - OffsetDate a = OffsetDate.of(LocalDate.of(y, m, d), OFFSET_PONE); - OffsetDate b = OffsetDate.of(LocalDate.of(y, m, d), OFFSET_PTWO); - assertEquals(a.equals(b), false); - } - - @Test(groups={"tck"}) - public void test_equals_itself_true() { - assertEquals(TEST_2007_07_15_PONE.equals(TEST_2007_07_15_PONE), true); - } - - @Test(groups={"tck"}) - public void test_equals_string_false() { - assertEquals(TEST_2007_07_15_PONE.equals("2007-07-15"), false); - } - - //----------------------------------------------------------------------- - // toString() - //----------------------------------------------------------------------- - @DataProvider(name="sampleToString") - Object[][] provider_sampleToString() { - return new Object[][] { - {2008, 7, 5, "Z", "2008-07-05Z"}, - {2008, 7, 5, "+00", "2008-07-05Z"}, - {2008, 7, 5, "+0000", "2008-07-05Z"}, - {2008, 7, 5, "+00:00", "2008-07-05Z"}, - {2008, 7, 5, "+000000", "2008-07-05Z"}, - {2008, 7, 5, "+00:00:00", "2008-07-05Z"}, - {2008, 7, 5, "-00", "2008-07-05Z"}, - {2008, 7, 5, "-0000", "2008-07-05Z"}, - {2008, 7, 5, "-00:00", "2008-07-05Z"}, - {2008, 7, 5, "-000000", "2008-07-05Z"}, - {2008, 7, 5, "-00:00:00", "2008-07-05Z"}, - {2008, 7, 5, "+01", "2008-07-05+01:00"}, - {2008, 7, 5, "+0100", "2008-07-05+01:00"}, - {2008, 7, 5, "+01:00", "2008-07-05+01:00"}, - {2008, 7, 5, "+010000", "2008-07-05+01:00"}, - {2008, 7, 5, "+01:00:00", "2008-07-05+01:00"}, - {2008, 7, 5, "+0130", "2008-07-05+01:30"}, - {2008, 7, 5, "+01:30", "2008-07-05+01:30"}, - {2008, 7, 5, "+013000", "2008-07-05+01:30"}, - {2008, 7, 5, "+01:30:00", "2008-07-05+01:30"}, - {2008, 7, 5, "+013040", "2008-07-05+01:30:40"}, - {2008, 7, 5, "+01:30:40", "2008-07-05+01:30:40"}, - }; - } - - @Test(dataProvider="sampleToString", groups={"tck"}) - public void test_toString(int y, int m, int d, String offsetId, String expected) { - OffsetDate t = OffsetDate.of(LocalDate.of(y, m, d), ZoneOffset.of(offsetId)); - String str = t.toString(); - assertEquals(str, expected); - } - - //----------------------------------------------------------------------- - // toString(DateTimeFormatter) - //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_toString_formatter() { - DateTimeFormatter f = DateTimeFormatters.pattern("y M d"); - String t = OffsetDate.of(LocalDate.of(2010, 12, 3), OFFSET_PONE).toString(f); - assertEquals(t, "2010 12 3"); - } - - @Test(expectedExceptions=NullPointerException.class, groups={"tck"}) - public void test_toString_formatter_null() { - OffsetDate.of(LocalDate.of(2010, 12, 3), OFFSET_PONE).toString(null); - } - -} diff --git a/jdk/test/java/time/tck/java/time/temporal/TCKSimplePeriod.java b/jdk/test/java/time/tck/java/time/temporal/TCKSimplePeriod.java deleted file mode 100644 index d67e6aae297..00000000000 --- a/jdk/test/java/time/tck/java/time/temporal/TCKSimplePeriod.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2012, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * - * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of JSR-310 nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package tck.java.time.temporal; - -import static java.time.temporal.ChronoUnit.DAYS; -import static java.time.temporal.ChronoUnit.MONTHS; -import static java.time.temporal.ChronoUnit.NANOS; -import static java.time.temporal.ChronoUnit.SECONDS; -import static java.time.temporal.ChronoUnit.YEARS; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertSame; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -import java.time.LocalDate; -import java.time.Period; -import java.time.temporal.ISOFields; -import java.time.temporal.SimplePeriod; -import java.time.temporal.TemporalUnit; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import tck.java.time.AbstractTCKTest; - -/** - * Test. - */ -@Test -public class TCKSimplePeriod extends AbstractTCKTest { - - private static final SimplePeriod TEST_12_MONTHS = SimplePeriod.of(12, MONTHS); - - //----------------------------------------------------------------------- - @Test(dataProvider="samples") - public void test_serialization(long amount, TemporalUnit unit) throws ClassNotFoundException, IOException { - SimplePeriod test = SimplePeriod.of(amount, unit); - assertSerializable(test); - } - - @Test - public void test_serialization_format_zoneOffset() throws Exception { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (DataOutputStream dos = new DataOutputStream(baos) ) { - dos.writeByte(10); - dos.writeLong(12); - } - byte[] bytes = baos.toByteArray(); - assertSerializedBySer(TEST_12_MONTHS, bytes, new byte[0]); - } - - //----------------------------------------------------------------------- - // of(long, TenmporalUnit) - //----------------------------------------------------------------------- - @DataProvider(name="samples") - Object[][] data_samples() { - return new Object[][] { - {0, YEARS}, - {1, YEARS}, - {-1, YEARS}, - {2, MONTHS}, - {-2, MONTHS}, - {43, ISOFields.WEEK_BASED_YEARS}, - {Long.MAX_VALUE, NANOS}, - {Long.MIN_VALUE, NANOS}, - }; - } - - @Test(dataProvider="samples") - public void factory_of(long amount, TemporalUnit unit) { - SimplePeriod test = SimplePeriod.of(amount, unit); - assertEquals(test.getAmount(), amount); - assertEquals(test.getUnit(), unit); - } - - //----------------------------------------------------------------------- - // addTo() - //----------------------------------------------------------------------- - @DataProvider(name="addTo") - Object[][] data_addTo() { - return new Object[][] { - {SimplePeriod.of(0, DAYS), date(2012, 6, 30), date(2012, 6, 30)}, - - {SimplePeriod.of(1, DAYS), date(2012, 6, 30), date(2012, 7, 1)}, - {SimplePeriod.of(-1, DAYS), date(2012, 6, 30), date(2012, 6, 29)}, - - {SimplePeriod.of(2, DAYS), date(2012, 6, 30), date(2012, 7, 2)}, - {SimplePeriod.of(-2, DAYS), date(2012, 6, 30), date(2012, 6, 28)}, - - {SimplePeriod.of(3, MONTHS), date(2012, 5, 31), date(2012, 8, 31)}, - {SimplePeriod.of(4, MONTHS), date(2012, 5, 31), date(2012, 9, 30)}, - {SimplePeriod.of(-3, MONTHS), date(2012, 5, 31), date(2012, 2, 29)}, - {SimplePeriod.of(-4, MONTHS), date(2012, 5, 31), date(2012, 1, 31)}, - }; - } - - @Test(dataProvider="addTo") - public void test_addTo(SimplePeriod period, LocalDate baseDate, LocalDate expected) { - assertEquals(period.addTo(baseDate), expected); - } - - @Test(dataProvider="addTo") - public void test_addTo_usingLocalDatePlus(SimplePeriod period, LocalDate baseDate, LocalDate expected) { - assertEquals(baseDate.plus(period), expected); - } - - @Test(expectedExceptions=NullPointerException.class) - public void test_addTo_nullZero() { - SimplePeriod.of(0, DAYS).addTo(null); - } - - @Test(expectedExceptions=NullPointerException.class) - public void test_addTo_nullNonZero() { - SimplePeriod.of(2, DAYS).addTo(null); - } - - //----------------------------------------------------------------------- - // subtractFrom() - //----------------------------------------------------------------------- - @DataProvider(name="subtractFrom") - Object[][] data_subtractFrom() { - return new Object[][] { - {SimplePeriod.of(0, DAYS), date(2012, 6, 30), date(2012, 6, 30)}, - - {SimplePeriod.of(1, DAYS), date(2012, 6, 30), date(2012, 6, 29)}, - {SimplePeriod.of(-1, DAYS), date(2012, 6, 30), date(2012, 7, 1)}, - - {SimplePeriod.of(2, DAYS), date(2012, 6, 30), date(2012, 6, 28)}, - {SimplePeriod.of(-2, DAYS), date(2012, 6, 30), date(2012, 7, 2)}, - - {SimplePeriod.of(3, MONTHS), date(2012, 5, 31), date(2012, 2, 29)}, - {SimplePeriod.of(4, MONTHS), date(2012, 5, 31), date(2012, 1, 31)}, - {SimplePeriod.of(-3, MONTHS), date(2012, 5, 31), date(2012, 8, 31)}, - {SimplePeriod.of(-4, MONTHS), date(2012, 5, 31), date(2012, 9, 30)}, - }; - } - - @Test(dataProvider="subtractFrom") - public void test_subtractFrom(SimplePeriod period, LocalDate baseDate, LocalDate expected) { - assertEquals(period.subtractFrom(baseDate), expected); - } - - @Test(dataProvider="subtractFrom") - public void test_subtractFrom_usingLocalDateMinus(SimplePeriod period, LocalDate baseDate, LocalDate expected) { - assertEquals(baseDate.minus(period), expected); - } - - @Test(expectedExceptions=NullPointerException.class) - public void test_subtractFrom_nullZero() { - SimplePeriod.of(0, DAYS).subtractFrom(null); - } - - @Test(expectedExceptions=NullPointerException.class) - public void test_subtractFrom_nullNonZero() { - SimplePeriod.of(2, DAYS).subtractFrom(null); - } - - //----------------------------------------------------------------------- - // abs() - //----------------------------------------------------------------------- - @Test(dataProvider="samples") - public void test_abs(long amount, TemporalUnit unit) { - SimplePeriod test = SimplePeriod.of(amount, unit); - if (amount >= 0) { - assertSame(test.abs(), test); // spec requires assertSame - } else if (amount == Long.MIN_VALUE) { - // ignore, separately tested - } else { - assertEquals(test.abs(), SimplePeriod.of(-amount, unit)); - } - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_abs_minValue() { - SimplePeriod.of(Long.MIN_VALUE, SECONDS).abs(); - } - - //----------------------------------------------------------------------- - // equals() / hashCode() - //----------------------------------------------------------------------- - @Test(dataProvider="samples") - public void test_equals(long amount, TemporalUnit unit) { - SimplePeriod test1 = SimplePeriod.of(amount, unit); - SimplePeriod test2 = SimplePeriod.of(amount, unit); - assertEquals(test1, test2); - } - - @Test(dataProvider="samples") - public void test_equals_self(long amount, TemporalUnit unit) { - SimplePeriod test = SimplePeriod.of(amount, unit); - assertEquals(test.equals(test), true); - } - - public void test_equals_null() { - assertEquals(TEST_12_MONTHS.equals(null), false); - } - - public void test_equals_otherClass() { - Period test = Period.of(1, 2, 3, 4, 5, 6); - assertEquals(test.equals(""), false); - } - - //----------------------------------------------------------------------- - public void test_hashCode() { - SimplePeriod test5 = SimplePeriod.of(5, DAYS); - SimplePeriod test6 = SimplePeriod.of(6, DAYS); - SimplePeriod test5M = SimplePeriod.of(5, MONTHS); - SimplePeriod test5Y = SimplePeriod.of(5, YEARS); - assertEquals(test5.hashCode() == test5.hashCode(), true); - assertEquals(test5.hashCode() == test6.hashCode(), false); - assertEquals(test5.hashCode() == test5M.hashCode(), false); - assertEquals(test5.hashCode() == test5Y.hashCode(), false); - } - - //----------------------------------------------------------------------- - // toString() - //----------------------------------------------------------------------- - @Test(dataProvider="samples") - public void test_toString(long amount, TemporalUnit unit) { - SimplePeriod test = SimplePeriod.of(amount, unit); - assertEquals(test.toString(), amount + " " + unit.getName()); - } - - private static LocalDate date(int y, int m, int d) { - return LocalDate.of(y, m, d); - } - -} diff --git a/jdk/test/java/time/tck/java/time/temporal/TCKWeekFields.java b/jdk/test/java/time/tck/java/time/temporal/TCKWeekFields.java index 9119a70fa65..76789cd00a2 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TCKWeekFields.java +++ b/jdk/test/java/time/tck/java/time/temporal/TCKWeekFields.java @@ -56,310 +56,349 @@ */ package tck.java.time.temporal; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertSame; -import static org.testng.Assert.fail; - -import static java.time.temporal.ChronoField.DAY_OF_WEEK; import static java.time.temporal.ChronoField.DAY_OF_MONTH; +import static java.time.temporal.ChronoField.DAY_OF_WEEK; import static java.time.temporal.ChronoField.DAY_OF_YEAR; import static java.time.temporal.ChronoField.MONTH_OF_YEAR; import static java.time.temporal.ChronoField.YEAR; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertSame; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - import java.time.DayOfWeek; import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.TemporalField; -import java.time.format.DateTimeBuilder; import java.time.temporal.ValueRange; import java.time.temporal.WeekFields; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import tck.java.time.AbstractTCKTest; /** * Test WeekFields. */ @Test -public class TCKWeekFields { +public class TCKWeekFields extends AbstractTCKTest { - @Test(groups={"tck"}) - public void test_WeekFieldsOf() { - for (DayOfWeek dow : DayOfWeek.values()) { - for (int minDays = 1; minDays <= 7; minDays++) { - WeekFields week = WeekFields.of(dow, minDays); - assertEquals(week.getFirstDayOfWeek(), dow, "Incorrect firstDayOfWeek"); - assertEquals(week.getMinimalDaysInFirstWeek(), minDays, "Incorrect MinimalDaysInFirstWeek"); - } - } + @Test(dataProvider="weekFields") + public void test_of_DayOfWeek_int_singleton(DayOfWeek firstDayOfWeek, int minDays) { + WeekFields week = WeekFields.of(firstDayOfWeek, minDays); + assertEquals(week.getFirstDayOfWeek(), firstDayOfWeek, "Incorrect firstDayOfWeek"); + assertEquals(week.getMinimalDaysInFirstWeek(), minDays, "Incorrect MinimalDaysInFirstWeek"); + assertSame(WeekFields.of(firstDayOfWeek, minDays), week); } - @Test(groups={"tck"}) - public void test_DayOfWeek() { + //----------------------------------------------------------------------- + @Test + public void test_dayOfWeekField_simpleGet() { + LocalDate date = LocalDate.of(2000, 1, 10); // Known to be ISO Monday + assertEquals(date.get(WeekFields.ISO.dayOfWeek()), 1); + assertEquals(date.get(WeekFields.of(DayOfWeek.MONDAY, 1).dayOfWeek()), 1); + assertEquals(date.get(WeekFields.of(DayOfWeek.MONDAY, 7).dayOfWeek()), 1); + assertEquals(date.get(WeekFields.SUNDAY_START.dayOfWeek()), 2); + assertEquals(date.get(WeekFields.of(DayOfWeek.SUNDAY, 1).dayOfWeek()), 2); + assertEquals(date.get(WeekFields.of(DayOfWeek.SUNDAY, 7).dayOfWeek()), 2); + assertEquals(date.get(WeekFields.of(DayOfWeek.SATURDAY, 1).dayOfWeek()), 3); + assertEquals(date.get(WeekFields.of(DayOfWeek.FRIDAY, 1).dayOfWeek()), 4); + assertEquals(date.get(WeekFields.of(DayOfWeek.TUESDAY, 1).dayOfWeek()), 7); + } + + @Test + public void test_dayOfWeekField_simpleSet() { + LocalDate date = LocalDate.of(2000, 1, 10); // Known to be ISO Monday + assertEquals(date.with(WeekFields.ISO.dayOfWeek(), 2), LocalDate.of(2000, 1, 11)); + assertEquals(date.with(WeekFields.ISO.dayOfWeek(), 7), LocalDate.of(2000, 1, 16)); + + assertEquals(date.with(WeekFields.SUNDAY_START.dayOfWeek(), 3), LocalDate.of(2000, 1, 11)); + assertEquals(date.with(WeekFields.SUNDAY_START.dayOfWeek(), 7), LocalDate.of(2000, 1, 15)); + + assertEquals(date.with(WeekFields.of(DayOfWeek.SATURDAY, 1).dayOfWeek(), 4), LocalDate.of(2000, 1, 11)); + assertEquals(date.with(WeekFields.of(DayOfWeek.TUESDAY, 1).dayOfWeek(), 1), LocalDate.of(2000, 1, 4)); + } + + @Test(dataProvider="weekFields") + public void test_dayOfWeekField(DayOfWeek firstDayOfWeek, int minDays) { LocalDate day = LocalDate.of(2000, 1, 10); // Known to be ISO Monday - for (DayOfWeek firstDayOfWeek : DayOfWeek.values()) { - for (int minDays = 1; minDays <= 7; minDays++) { - WeekFields week = WeekFields.of(firstDayOfWeek, minDays); - TemporalField f = week.dayOfWeek(); - //System.out.printf(" Week: %s; field: %s%n", week, f); + WeekFields week = WeekFields.of(firstDayOfWeek, minDays); + TemporalField f = week.dayOfWeek(); + //System.out.printf(" Week: %s; field: %s%n", week, f); - for (int i = 1; i <= 7; i++) { - //System.out.printf(" ISO Dow: %s, WeekDOW ordinal: %s%n", day.getDayOfWeek(), day.get(f)); - assertEquals(day.get(f), (7 + day.getDayOfWeek().getValue() - firstDayOfWeek.getValue()) % 7 + 1); - day = day.plusDays(1); - } - } + for (int i = 1; i <= 7; i++) { + //System.out.printf(" ISO Dow: %s, WeekDOW ordinal: %s%n", day.getDayOfWeek(), day.get(f)); + assertEquals(day.get(f), (7 + day.getDayOfWeek().getValue() - firstDayOfWeek.getValue()) % 7 + 1); + day = day.plusDays(1); } } - @Test(groups={"tck"}) - public void test_WeekOfMonth() { - for (DayOfWeek firstDayOfWeek : DayOfWeek.values()) { - for (int minDays = 1; minDays <= 7; minDays++) { - LocalDate day = LocalDate.of(2012, 12, 31); // Known to be ISO Monday - WeekFields week = WeekFields.of(firstDayOfWeek, minDays); - TemporalField dowField = week.dayOfWeek(); - TemporalField womField = week.weekOfMonth(); - //System.err.printf("%n Week: %s; dowField: %s, domField: %s%n", week, dowField, womField); + @Test(dataProvider="weekFields") + public void test_weekOfMonthField(DayOfWeek firstDayOfWeek, int minDays) { + LocalDate day = LocalDate.of(2012, 12, 31); // Known to be ISO Monday + WeekFields week = WeekFields.of(firstDayOfWeek, minDays); + TemporalField dowField = week.dayOfWeek(); + TemporalField womField = week.weekOfMonth(); + //System.err.printf("%n Week: %s; dowField: %s, domField: %s%n", week, dowField, womField); - DayOfWeek isoDOW = day.getDayOfWeek(); - int dow = (7 + isoDOW.getValue() - firstDayOfWeek.getValue()) % 7 + 1; + DayOfWeek isoDOW = day.getDayOfWeek(); + int dow = (7 + isoDOW.getValue() - firstDayOfWeek.getValue()) % 7 + 1; - for (int i = 1; i <= 15; i++) { - int actualDOW = day.get(dowField); - int actualWOM = day.get(womField); + for (int i = 1; i <= 15; i++) { + int actualDOW = day.get(dowField); + int actualWOM = day.get(womField); - // Verify that the combination of day of week and week of month can be used - // to reconstruct the same date. - LocalDate day1 = day.withDayOfMonth(1); - int offset = - (day1.get(dowField) - 1); - //System.err.printf(" refDay: %s%n", day1.plusDays(offset)); - int week1 = day1.get(womField); - if (week1 == 0) { - // week of the 1st is partial; start with first full week - offset += 7; - } - //System.err.printf(" refDay2: %s, offset: %d, week1: %d%n", day1.plusDays(offset), offset, week1); - offset += actualDOW - 1; - //System.err.printf(" refDay3: %s%n", day1.plusDays(offset)); - offset += (actualWOM - 1) * 7; - //System.err.printf(" refDay4: %s%n", day1.plusDays(offset)); - LocalDate result = day1.plusDays(offset); - - if (!day.equals(result)) { - System.err.printf("FAIL ISO Dow: %s, offset: %s, actualDOW: %s, actualWOM: %s, expected: %s, result: %s%n", - day.getDayOfWeek(), offset, actualDOW, actualWOM, day, result); - } - assertEquals(result, day, "Incorrect dayOfWeek or weekOfMonth: " - + String.format("%s, ISO Dow: %s, offset: %s, actualDOW: %s, actualWOM: %s, expected: %s, result: %s%n", - week, day.getDayOfWeek(), offset, actualDOW, actualWOM, day, result)); - day = day.plusDays(1); - } + // Verify that the combination of day of week and week of month can be used + // to reconstruct the same date. + LocalDate day1 = day.withDayOfMonth(1); + int offset = - (day1.get(dowField) - 1); + //System.err.printf(" refDay: %s%n", day1.plusDays(offset)); + int week1 = day1.get(womField); + if (week1 == 0) { + // week of the 1st is partial; start with first full week + offset += 7; } + //System.err.printf(" refDay2: %s, offset: %d, week1: %d%n", day1.plusDays(offset), offset, week1); + offset += actualDOW - 1; + //System.err.printf(" refDay3: %s%n", day1.plusDays(offset)); + offset += (actualWOM - 1) * 7; + //System.err.printf(" refDay4: %s%n", day1.plusDays(offset)); + LocalDate result = day1.plusDays(offset); + + if (!day.equals(result)) { + System.err.printf("FAIL ISO Dow: %s, offset: %s, actualDOW: %s, actualWOM: %s, expected: %s, result: %s%n", + day.getDayOfWeek(), offset, actualDOW, actualWOM, day, result); + } + assertEquals(result, day, "Incorrect dayOfWeek or weekOfMonth: " + + String.format("%s, ISO Dow: %s, offset: %s, actualDOW: %s, actualWOM: %s, expected: %s, result: %s%n", + week, day.getDayOfWeek(), offset, actualDOW, actualWOM, day, result)); + day = day.plusDays(1); } } - @Test(groups={"tck"}) - public void test_WeekOfYear() { - for (DayOfWeek firstDayOfWeek : DayOfWeek.values()) { - for (int minDays = 1; minDays <= 7; minDays++) { - LocalDate day = LocalDate.of(2012, 12, 31); // Known to be ISO Monday - WeekFields week = WeekFields.of(firstDayOfWeek, minDays); - TemporalField dowField = week.dayOfWeek(); - TemporalField woyField = week.weekOfYear(); - //System.err.printf("%n Year: %s; dowField: %s, woyField: %s%n", week, dowField, woyField); + @Test(dataProvider="weekFields") + public void test_weekOfYearField(DayOfWeek firstDayOfWeek, int minDays) { + LocalDate day = LocalDate.of(2012, 12, 31); // Known to be ISO Monday + WeekFields week = WeekFields.of(firstDayOfWeek, minDays); + TemporalField dowField = week.dayOfWeek(); + TemporalField woyField = week.weekOfYear(); + //System.err.printf("%n Year: %s; dowField: %s, woyField: %s%n", week, dowField, woyField); - DayOfWeek isoDOW = day.getDayOfWeek(); - int dow = (7 + isoDOW.getValue() - firstDayOfWeek.getValue()) % 7 + 1; + DayOfWeek isoDOW = day.getDayOfWeek(); + int dow = (7 + isoDOW.getValue() - firstDayOfWeek.getValue()) % 7 + 1; - for (int i = 1; i <= 15; i++) { - int actualDOW = day.get(dowField); - int actualWOY = day.get(woyField); + for (int i = 1; i <= 15; i++) { + int actualDOW = day.get(dowField); + int actualWOY = day.get(woyField); - // Verify that the combination of day of week and week of month can be used - // to reconstruct the same date. - LocalDate day1 = day.withDayOfYear(1); - int offset = - (day1.get(dowField) - 1); - //System.err.printf(" refDay: %s%n", day1.plusDays(offset)); - int week1 = day1.get(woyField); - if (week1 == 0) { - // week of the 1st is partial; start with first full week - offset += 7; - } - //System.err.printf(" refDay2: %s, offset: %d, week1: %d%n", day1.plusDays(offset), offset, week1); - offset += actualDOW - 1; - //System.err.printf(" refDay3: %s%n", day1.plusDays(offset)); - offset += (actualWOY - 1) * 7; - //System.err.printf(" refDay4: %s%n", day1.plusDays(offset)); - LocalDate result = day1.plusDays(offset); - - - if (!day.equals(result)) { - System.err.printf("FAIL ISO Dow: %s, offset: %s, actualDOW: %s, actualWOY: %s, expected: %s, result: %s%n", - day.getDayOfWeek(), offset, actualDOW, actualWOY, day, result); - } - assertEquals(result, day, "Incorrect dayOfWeek or weekOfYear " - + String.format("%s, ISO Dow: %s, offset: %s, actualDOW: %s, actualWOM: %s, expected: %s, result: %s%n", - week, day.getDayOfWeek(), offset, actualDOW, actualWOY, day, result)); - day = day.plusDays(1); - } + // Verify that the combination of day of week and week of month can be used + // to reconstruct the same date. + LocalDate day1 = day.withDayOfYear(1); + int offset = - (day1.get(dowField) - 1); + //System.err.printf(" refDay: %s%n", day1.plusDays(offset)); + int week1 = day1.get(woyField); + if (week1 == 0) { + // week of the 1st is partial; start with first full week + offset += 7; } + //System.err.printf(" refDay2: %s, offset: %d, week1: %d%n", day1.plusDays(offset), offset, week1); + offset += actualDOW - 1; + //System.err.printf(" refDay3: %s%n", day1.plusDays(offset)); + offset += (actualWOY - 1) * 7; + //System.err.printf(" refDay4: %s%n", day1.plusDays(offset)); + LocalDate result = day1.plusDays(offset); + + + if (!day.equals(result)) { + System.err.printf("FAIL ISO Dow: %s, offset: %s, actualDOW: %s, actualWOY: %s, expected: %s, result: %s%n", + day.getDayOfWeek(), offset, actualDOW, actualWOY, day, result); + } + assertEquals(result, day, "Incorrect dayOfWeek or weekOfYear " + + String.format("%s, ISO Dow: %s, offset: %s, actualDOW: %s, actualWOM: %s, expected: %s, result: %s%n", + week, day.getDayOfWeek(), offset, actualDOW, actualWOY, day, result)); + day = day.plusDays(1); } } - @Test(groups={"tck"}) - public void test_fieldRanges() { - for (DayOfWeek firstDayOfWeek : DayOfWeek.values()) { - for (int minDays = 1; minDays <= 7; minDays++) { - WeekFields weekDef = WeekFields.of(firstDayOfWeek, minDays); - TemporalField dowField = weekDef.dayOfWeek(); - TemporalField womField = weekDef.weekOfMonth(); - TemporalField woyField = weekDef.weekOfYear(); + @Test(dataProvider="weekFields") + public void test_fieldRanges(DayOfWeek firstDayOfWeek, int minDays) { + WeekFields weekDef = WeekFields.of(firstDayOfWeek, minDays); + TemporalField womField = weekDef.weekOfMonth(); + TemporalField woyField = weekDef.weekOfYear(); - LocalDate day = LocalDate.of(2012, 11, 30); - LocalDate endDay = LocalDate.of(2013, 1, 2); - while (day.isBefore(endDay)) { - LocalDate last = day.with(DAY_OF_MONTH, day.lengthOfMonth()); - int lastWOM = last.get(womField); - LocalDate first = day.with(DAY_OF_MONTH, 1); - int firstWOM = first.get(womField); - ValueRange rangeWOM = day.range(womField); - assertEquals(rangeWOM.getMinimum(), firstWOM, - "Range min should be same as WeekOfMonth for first day of month: " - + first + ", " + weekDef); - assertEquals(rangeWOM.getMaximum(), lastWOM, - "Range max should be same as WeekOfMonth for last day of month: " - + last + ", " + weekDef); + LocalDate day = LocalDate.of(2012, 11, 30); + LocalDate endDay = LocalDate.of(2013, 1, 2); + while (day.isBefore(endDay)) { + LocalDate last = day.with(DAY_OF_MONTH, day.lengthOfMonth()); + int lastWOM = last.get(womField); + LocalDate first = day.with(DAY_OF_MONTH, 1); + int firstWOM = first.get(womField); + ValueRange rangeWOM = day.range(womField); + assertEquals(rangeWOM.getMinimum(), firstWOM, + "Range min should be same as WeekOfMonth for first day of month: " + + first + ", " + weekDef); + assertEquals(rangeWOM.getMaximum(), lastWOM, + "Range max should be same as WeekOfMonth for last day of month: " + + last + ", " + weekDef); - last = day.with(DAY_OF_YEAR, day.lengthOfYear()); - int lastWOY = last.get(woyField); - first = day.with(DAY_OF_YEAR, 1); - int firstWOY = first.get(woyField); - ValueRange rangeWOY = day.range(woyField); - assertEquals(rangeWOY.getMinimum(), firstWOY, - "Range min should be same as WeekOfYear for first day of Year: " - + day + ", " + weekDef); - assertEquals(rangeWOY.getMaximum(), lastWOY, - "Range max should be same as WeekOfYear for last day of Year: " - + day + ", " + weekDef); + last = day.with(DAY_OF_YEAR, day.lengthOfYear()); + int lastWOY = last.get(woyField); + first = day.with(DAY_OF_YEAR, 1); + int firstWOY = first.get(woyField); + ValueRange rangeWOY = day.range(woyField); + assertEquals(rangeWOY.getMinimum(), firstWOY, + "Range min should be same as WeekOfYear for first day of Year: " + + day + ", " + weekDef); + assertEquals(rangeWOY.getMaximum(), lastWOY, + "Range max should be same as WeekOfYear for last day of Year: " + + day + ", " + weekDef); - day = day.plusDays(1); - } - } + day = day.plusDays(1); } } //----------------------------------------------------------------------- // withDayOfWeek() //----------------------------------------------------------------------- - @Test(groups = {"tck"}) - public void test_withDayOfWeek() { - for (DayOfWeek firstDayOfWeek : DayOfWeek.values()) { - for (int minDays = 1; minDays <= 7; minDays++) { - LocalDate day = LocalDate.of(2012, 12, 15); // Safely in the middle of a month - WeekFields week = WeekFields.of(firstDayOfWeek, minDays); + @Test(dataProvider="weekFields") + public void test_withDayOfWeek(DayOfWeek firstDayOfWeek, int minDays) { + LocalDate day = LocalDate.of(2012, 12, 15); // Safely in the middle of a month + WeekFields week = WeekFields.of(firstDayOfWeek, minDays); + TemporalField dowField = week.dayOfWeek(); + TemporalField womField = week.weekOfMonth(); + TemporalField woyField = week.weekOfYear(); - TemporalField dowField = week.dayOfWeek(); - TemporalField womField = week.weekOfMonth(); - TemporalField woyField = week.weekOfYear(); - int wom = day.get(womField); - int woy = day.get(woyField); - for (int dow = 1; dow <= 7; dow++) { - LocalDate result = day.with(dowField, dow); - if (result.get(dowField) != dow) { - System.err.printf(" DOW actual: %d, expected: %d, week:%s%n", - result.get(dowField), dow, week); - } - if (result.get(womField) != wom) { - System.err.printf(" WOM actual: %d, expected: %d, week:%s%n", - result.get(womField), wom, week); - } - if (result.get(woyField) != woy) { - System.err.printf(" WOY actual: %d, expected: %d, week:%s%n", - result.get(woyField), woy, week); - } - assertEquals(result.get(dowField), dow, String.format("Incorrect new Day of week: %s", result)); - assertEquals(result.get(womField), wom, "Week of Month should not change"); - assertEquals(result.get(woyField), woy, "Week of Year should not change"); - } + int wom = day.get(womField); + int woy = day.get(woyField); + for (int dow = 1; dow <= 7; dow++) { + LocalDate result = day.with(dowField, dow); + if (result.get(dowField) != dow) { + System.err.printf(" DOW actual: %d, expected: %d, week:%s%n", + result.get(dowField), dow, week); } + if (result.get(womField) != wom) { + System.err.printf(" WOM actual: %d, expected: %d, week:%s%n", + result.get(womField), wom, week); + } + if (result.get(woyField) != woy) { + System.err.printf(" WOY actual: %d, expected: %d, week:%s%n", + result.get(woyField), woy, week); + } + assertEquals(result.get(dowField), dow, String.format("Incorrect new Day of week: %s", result)); + assertEquals(result.get(womField), wom, "Week of Month should not change"); + assertEquals(result.get(woyField), woy, "Week of Year should not change"); } } - @Test() - public void test_computedFieldResolver() { - // For all starting days of week, for all minDays, for two weeks in Dec 2012 - // Test that when supplied with partial values, that the resolver - // fills in the month - for (DayOfWeek firstDayOfWeek : DayOfWeek.values()) { - for (int minDays = 1; minDays <= 7; minDays++) { - LocalDate day = LocalDate.of(2012, 12, 15); // Safely in the middle of a month - WeekFields week = WeekFields.of(firstDayOfWeek, minDays); + //----------------------------------------------------------------------- + @Test(dataProvider="weekFields") + public void test_parse_resolve_localizedWom(DayOfWeek firstDayOfWeek, int minDays) { + LocalDate date = LocalDate.of(2012, 12, 15); + WeekFields week = WeekFields.of(firstDayOfWeek, minDays); + TemporalField womField = week.weekOfMonth(); - TemporalField dowField = week.dayOfWeek(); - TemporalField womField = week.weekOfMonth(); - TemporalField woyField = week.weekOfYear(); - int wom = day.get(womField); - int woy = day.get(woyField); - for (int dow = 1; dow <= 15; dow++) { - // Test that with dayOfWeek and Week of month it computes the day of month - DateTimeBuilder builder = new DateTimeBuilder(); - builder.addFieldValue(YEAR, day.get(YEAR)); - builder.addFieldValue(MONTH_OF_YEAR, day.get(MONTH_OF_YEAR)); - builder.addFieldValue(DAY_OF_WEEK, day.get(DAY_OF_WEEK)); - builder.addFieldValue(dowField, day.get(dowField)); - builder.addFieldValue(womField, day.get(womField)); + for (int i = 1; i <= 60; i++) { + // Test that with dayOfWeek and Week of month it computes the date + DateTimeFormatter f = new DateTimeFormatterBuilder() + .appendValue(YEAR).appendLiteral('-') + .appendValue(MONTH_OF_YEAR).appendLiteral('-') + .appendValue(womField).appendLiteral('-') + .appendValue(DAY_OF_WEEK).toFormatter(); + String str = date.getYear() + "-" + date.getMonthValue() + "-" + + date.get(womField) + "-" + date.get(DAY_OF_WEEK); + LocalDate parsed = LocalDate.parse(str, f); + assertEquals(parsed, date, " ::" + str + "::" + i); - boolean res1 = dowField.resolve(builder, day.get(dowField)); - boolean res2 = womField.resolve(builder, day.get(womField)); - assertEquals(day.get(DAY_OF_MONTH), day.get(DAY_OF_MONTH)); - assertEquals(day.get(DAY_OF_YEAR), day.get(DAY_OF_YEAR)); - - day = day.plusDays(1); - } - day = LocalDate.of(2012, 12, 15); // Safely in the middle of a month - for (int dow = 1; dow <= 15; dow++) { - // Test that with dayOfWeek and Week of year it computes the day of year - DateTimeBuilder builder = new DateTimeBuilder(); - builder.addFieldValue(YEAR, day.get(YEAR)); - builder.addFieldValue(DAY_OF_WEEK, day.get(DAY_OF_WEEK)); - builder.addFieldValue(dowField, day.get(dowField)); - builder.addFieldValue(woyField, day.get(woyField)); - - boolean res1 = dowField.resolve(builder, day.get(dowField)); - boolean res2 = woyField.resolve(builder, day.get(woyField)); - - assertEquals(day.get(DAY_OF_MONTH), day.get(DAY_OF_MONTH)); - assertEquals(day.get(DAY_OF_YEAR), day.get(DAY_OF_YEAR)); - - day = day.plusDays(1); - } - } + date = date.plusDays(1); } } - @Test(groups = {"tck"}) - public void test_WeekFieldsSingleton() throws IOException, ClassNotFoundException { - for (DayOfWeek firstDayOfWeek : DayOfWeek.values()) { - for (int minDays = 1; minDays <= 7; minDays++) { - WeekFields weekDef = WeekFields.of(firstDayOfWeek, minDays); - WeekFields weekDef2 = WeekFields.of(firstDayOfWeek, minDays); - assertSame(weekDef2, weekDef, "WeekFields same parameters should be same instance"); - try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos)) { - oos.writeObject(weekDef); + @Test(dataProvider="weekFields") + public void test_parse_resolve_localizedWomDow(DayOfWeek firstDayOfWeek, int minDays) { + LocalDate date = LocalDate.of(2012, 12, 15); + WeekFields week = WeekFields.of(firstDayOfWeek, minDays); + TemporalField dowField = week.dayOfWeek(); + TemporalField womField = week.weekOfMonth(); - ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream( - baos.toByteArray())); - WeekFields result = (WeekFields)ois.readObject(); - assertSame(result, weekDef, "Deserialized object same as serialized."); - } - // Exceptions will be handled as failures by TestNG - } + for (int i = 1; i <= 15; i++) { + // Test that with dayOfWeek and Week of month it computes the date + DateTimeFormatter f = new DateTimeFormatterBuilder() + .appendValue(YEAR).appendLiteral('-') + .appendValue(MONTH_OF_YEAR).appendLiteral('-') + .appendValue(womField).appendLiteral('-') + .appendValue(dowField).toFormatter(); + String str = date.getYear() + "-" + date.getMonthValue() + "-" + + date.get(womField) + "-" + date.get(dowField); + LocalDate parsed = LocalDate.parse(str, f); + assertEquals(parsed, date, " :: " + str + " " + i); + + date = date.plusDays(1); } } + + @Test(dataProvider="weekFields") + public void test_parse_resolve_localizedWoy(DayOfWeek firstDayOfWeek, int minDays) { + LocalDate date = LocalDate.of(2012, 12, 15); + WeekFields week = WeekFields.of(firstDayOfWeek, minDays); + TemporalField woyField = week.weekOfYear(); + + for (int i = 1; i <= 60; i++) { + // Test that with dayOfWeek and Week of month it computes the date + DateTimeFormatter f = new DateTimeFormatterBuilder() + .appendValue(YEAR).appendLiteral('-') + .appendValue(MONTH_OF_YEAR).appendLiteral('-') + .appendValue(woyField).appendLiteral('-') + .appendValue(DAY_OF_WEEK).toFormatter(); + String str = date.getYear() + "-" + date.getMonthValue() + "-" + + date.get(woyField) + "-" + date.get(DAY_OF_WEEK); + LocalDate parsed = LocalDate.parse(str, f); + assertEquals(parsed, date, " :: " + str + " " + i); + + date = date.plusDays(1); + } + } + + @Test(dataProvider="weekFields") + public void test_parse_resolve_localizedWoyDow(DayOfWeek firstDayOfWeek, int minDays) { + LocalDate date = LocalDate.of(2012, 12, 15); + WeekFields week = WeekFields.of(firstDayOfWeek, minDays); + TemporalField dowField = week.dayOfWeek(); + TemporalField woyField = week.weekOfYear(); + + for (int i = 1; i <= 60; i++) { + // Test that with dayOfWeek and Week of month it computes the date + DateTimeFormatter f = new DateTimeFormatterBuilder() + .appendValue(YEAR).appendLiteral('-') + .appendValue(MONTH_OF_YEAR).appendLiteral('-') + .appendValue(woyField).appendLiteral('-') + .appendValue(dowField).toFormatter(); + String str = date.getYear() + "-" + date.getMonthValue() + "-" + + date.get(woyField) + "-" + date.get(dowField); + LocalDate parsed = LocalDate.parse(str, f); + assertEquals(parsed, date, " :: " + str + " " + i); + + date = date.plusDays(1); + } + } + + //----------------------------------------------------------------------- + @Test(dataProvider="weekFields") + public void test_serializable_singleton(DayOfWeek firstDayOfWeek, int minDays) throws IOException, ClassNotFoundException { + WeekFields weekDef = WeekFields.of(firstDayOfWeek, minDays); + assertSerializableSame(weekDef); // spec state singleton + } + + //----------------------------------------------------------------------- + @DataProvider(name="weekFields") + Object[][] data_weekFields() { + Object[][] objects = new Object[49][]; + int i = 0; + for (DayOfWeek firstDayOfWeek : DayOfWeek.values()) { + for (int minDays = 1; minDays <= 7; minDays++) { + objects[i++] = new Object[] {firstDayOfWeek, minDays}; + } + } + return objects; + } + } diff --git a/jdk/test/java/time/tck/java/time/temporal/TestChronoLocalDate.java b/jdk/test/java/time/tck/java/time/temporal/TestChronoLocalDate.java index 95caf573a68..6d156839dc8 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TestChronoLocalDate.java +++ b/jdk/test/java/time/tck/java/time/temporal/TestChronoLocalDate.java @@ -63,27 +63,23 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.time.Duration; +import java.time.LocalDate; +import java.time.chrono.Chronology; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.IsoChronology; +import java.time.temporal.ChronoUnit; +import java.time.temporal.Temporal; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalAdjuster; +import java.time.temporal.TemporalAmount; +import java.time.temporal.TemporalField; +import java.time.temporal.TemporalUnit; +import java.time.temporal.ValueRange; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.time.Duration; -import java.time.LocalDate; -import java.time.temporal.Chrono; -import java.time.temporal.ChronoLocalDate; -import java.time.temporal.ChronoUnit; -import java.time.temporal.SimplePeriod; -import java.time.temporal.Temporal; -import java.time.temporal.TemporalAccessor; -import java.time.format.DateTimeBuilder; -import java.time.temporal.TemporalAdder; -import java.time.temporal.TemporalAdjuster; -import java.time.temporal.TemporalField; -import java.time.temporal.TemporalSubtractor; -import java.time.temporal.ValueRange; -import java.time.temporal.TemporalUnit; -import java.time.temporal.ISOChrono; - import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -98,19 +94,19 @@ public class TestChronoLocalDate { // regular data factory for names and descriptions of ISO calendar //----------------------------------------------------------------------- @DataProvider(name = "calendars") - Chrono[][] data_of_calendars() { - return new Chrono[][]{ - {ISOChrono.INSTANCE}, + Chronology[][] data_of_calendars() { + return new Chronology[][]{ + {IsoChronology.INSTANCE}, }; } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badWithAdjusterChrono(Chrono chrono) { + public void test_badWithAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); - ChronoLocalDate date = chrono.date(refDate); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; - ChronoLocalDate date2 = chrono2.date(refDate); + ChronoLocalDate date = chrono.date(refDate); + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; + ChronoLocalDate date2 = chrono2.date(refDate); TemporalAdjuster adjuster = new FixedAdjuster(date2); if (chrono != chrono2) { try { @@ -121,20 +117,20 @@ public class TestChronoLocalDate { } } else { // Same chronology, - ChronoLocalDate result = date.with(adjuster); + ChronoLocalDate result = date.with(adjuster); assertEquals(result, date2, "WithAdjuster failed to replace date"); } } } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badPlusAdjusterChrono(Chrono chrono) { + public void test_badPlusAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); - ChronoLocalDate date = chrono.date(refDate); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; - ChronoLocalDate date2 = chrono2.date(refDate); - TemporalAdder adjuster = new FixedAdjuster(date2); + ChronoLocalDate date = chrono.date(refDate); + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; + ChronoLocalDate date2 = chrono2.date(refDate); + TemporalAmount adjuster = new FixedAdjuster(date2); if (chrono != chrono2) { try { date.plus(adjuster); @@ -144,20 +140,20 @@ public class TestChronoLocalDate { } } else { // Same chronology, - ChronoLocalDate result = date.plus(adjuster); + ChronoLocalDate result = date.plus(adjuster); assertEquals(result, date2, "WithAdjuster failed to replace date"); } } } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badMinusAdjusterChrono(Chrono chrono) { + public void test_badMinusAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); - ChronoLocalDate date = chrono.date(refDate); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; - ChronoLocalDate date2 = chrono2.date(refDate); - TemporalSubtractor adjuster = new FixedAdjuster(date2); + ChronoLocalDate date = chrono.date(refDate); + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; + ChronoLocalDate date2 = chrono2.date(refDate); + TemporalAmount adjuster = new FixedAdjuster(date2); if (chrono != chrono2) { try { date.minus(adjuster); @@ -167,19 +163,19 @@ public class TestChronoLocalDate { } } else { // Same chronology, - ChronoLocalDate result = date.minus(adjuster); + ChronoLocalDate result = date.minus(adjuster); assertEquals(result, date2, "WithAdjuster failed to replace date"); } } } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badPlusTemporalUnitChrono(Chrono chrono) { + public void test_badPlusTemporalUnitChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); - ChronoLocalDate date = chrono.date(refDate); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; - ChronoLocalDate date2 = chrono2.date(refDate); + ChronoLocalDate date = chrono.date(refDate); + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; + ChronoLocalDate date2 = chrono2.date(refDate); TemporalUnit adjuster = new FixedTemporalUnit(date2); if (chrono != chrono2) { try { @@ -191,19 +187,19 @@ public class TestChronoLocalDate { } } else { // Same chronology, - ChronoLocalDate result = date.plus(1, adjuster); + ChronoLocalDate result = date.plus(1, adjuster); assertEquals(result, date2, "WithAdjuster failed to replace date"); } } } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badMinusTemporalUnitChrono(Chrono chrono) { + public void test_badMinusTemporalUnitChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); - ChronoLocalDate date = chrono.date(refDate); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; - ChronoLocalDate date2 = chrono2.date(refDate); + ChronoLocalDate date = chrono.date(refDate); + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; + ChronoLocalDate date2 = chrono2.date(refDate); TemporalUnit adjuster = new FixedTemporalUnit(date2); if (chrono != chrono2) { try { @@ -215,19 +211,19 @@ public class TestChronoLocalDate { } } else { // Same chronology, - ChronoLocalDate result = date.minus(1, adjuster); + ChronoLocalDate result = date.minus(1, adjuster); assertEquals(result, date2, "WithAdjuster failed to replace date"); } } } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badTemporalFieldChrono(Chrono chrono) { + public void test_badTemporalFieldChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); - ChronoLocalDate date = chrono.date(refDate); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; - ChronoLocalDate date2 = chrono2.date(refDate); + ChronoLocalDate date = chrono.date(refDate); + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; + ChronoLocalDate date2 = chrono2.date(refDate); TemporalField adjuster = new FixedTemporalField(date2); if (chrono != chrono2) { try { @@ -239,7 +235,7 @@ public class TestChronoLocalDate { } } else { // Same chronology, - ChronoLocalDate result = date.with(adjuster, 1); + ChronoLocalDate result = date.with(adjuster, 1); assertEquals(result, date2, "TemporalField doWith() failed to replace date"); } } @@ -249,10 +245,10 @@ public class TestChronoLocalDate { // isBefore, isAfter, isEqual, DATE_COMPARATOR //----------------------------------------------------------------------- @Test(groups={"tck"}, dataProvider="calendars") - public void test_date_comparisons(Chrono chrono) { - List> dates = new ArrayList<>(); + public void test_date_comparisons(Chronology chrono) { + List dates = new ArrayList<>(); - ChronoLocalDate date = chrono.date(LocalDate.of(1900, 1, 1)); + ChronoLocalDate date = chrono.date(LocalDate.of(1900, 1, 1)); // Insert dates in order, no duplicates dates.add(date.minus(1000, ChronoUnit.YEARS)); @@ -272,18 +268,18 @@ public class TestChronoLocalDate { dates.add(date.plus(1000, ChronoUnit.YEARS)); // Check these dates against the corresponding dates for every calendar - for (Chrono[] clist : data_of_calendars()) { - List> otherDates = new ArrayList<>(); - Chrono chrono2 = clist[0]; - for (ChronoLocalDate d : dates) { + for (Chronology[] clist : data_of_calendars()) { + List otherDates = new ArrayList<>(); + Chronology chrono2 = clist[0]; + for (ChronoLocalDate d : dates) { otherDates.add(chrono2.date(d)); } // Now compare the sequence of original dates with the sequence of converted dates for (int i = 0; i < dates.size(); i++) { - ChronoLocalDate a = dates.get(i); + ChronoLocalDate a = dates.get(i); for (int j = 0; j < otherDates.size(); j++) { - ChronoLocalDate b = otherDates.get(j); + ChronoLocalDate b = otherDates.get(j); int cmp = ChronoLocalDate.DATE_COMPARATOR.compare(a, b); if (i < j) { assertTrue(cmp < 0, a + " compare " + b); @@ -307,8 +303,8 @@ public class TestChronoLocalDate { } public void test_date_comparator_checkGenerics_ISO() { - List> dates = new ArrayList<>(); - ChronoLocalDate date = LocalDate.of(1900, 1, 1); + List dates = new ArrayList<>(); + LocalDate date = LocalDate.of(1900, 1, 1); // Insert dates in order, no duplicates dates.add(date.minus(10, ChronoUnit.YEARS)); @@ -323,7 +319,7 @@ public class TestChronoLocalDate { dates.add(date.plus(1, ChronoUnit.YEARS)); dates.add(date.plus(10, ChronoUnit.YEARS)); - List> copy = new ArrayList<>(dates); + List copy = new ArrayList<>(dates); Collections.shuffle(copy); Collections.sort(copy, ChronoLocalDate.DATE_COMPARATOR); assertEquals(copy, dates); @@ -358,9 +354,9 @@ public class TestChronoLocalDate { // Test Serialization of ISO via chrono API //----------------------------------------------------------------------- @Test( groups={"tck"}, dataProvider="calendars") - public > void test_ChronoSerialization(C chrono) throws Exception { + public void test_ChronoSerialization(Chronology chrono) throws Exception { LocalDate ref = LocalDate.of(2000, 1, 5); - ChronoLocalDate orginal = chrono.date(ref); + ChronoLocalDate orginal = chrono.date(ref); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject(orginal); @@ -368,7 +364,7 @@ public class TestChronoLocalDate { ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream in = new ObjectInputStream(bais); @SuppressWarnings("unchecked") - ChronoLocalDate ser = (ChronoLocalDate) in.readObject(); + ChronoLocalDate ser = (ChronoLocalDate) in.readObject(); assertEquals(ser, orginal, "deserialized date is wrong"); } @@ -376,7 +372,7 @@ public class TestChronoLocalDate { * FixedAdjusted returns a fixed Temporal in all adjustments. * Construct an adjuster with the Temporal that should be returned from adjust. */ - static class FixedAdjuster implements TemporalAdjuster, TemporalAdder, TemporalSubtractor { + static class FixedAdjuster implements TemporalAdjuster, TemporalAmount { private Temporal datetime; FixedAdjuster(Temporal datetime) { @@ -398,11 +394,21 @@ public class TestChronoLocalDate { return datetime; } + @Override + public long get(TemporalUnit unit) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List getUnits() { + throw new UnsupportedOperationException("Not supported yet."); + } + } /** * FixedTemporalUnit returns a fixed Temporal in all adjustments. - * Construct an FixedTemporalUnit with the Temporal that should be returned from doPlus. + * Construct an FixedTemporalUnit with the Temporal that should be returned from addTo. */ static class FixedTemporalUnit implements TemporalUnit { private Temporal temporal; @@ -427,25 +433,25 @@ public class TestChronoLocalDate { } @Override - public boolean isSupported(Temporal temporal) { + public boolean isSupportedBy(Temporal temporal) { throw new UnsupportedOperationException("Not supported yet."); } @SuppressWarnings("unchecked") @Override - public R doPlus(R dateTime, long periodToAdd) { + public R addTo(R temporal, long amount) { return (R) this.temporal; } @Override - public SimplePeriod between(R dateTime1, R dateTime2) { + public long between(Temporal temporal1, Temporal temporal2) { throw new UnsupportedOperationException("Not supported yet."); } } /** * FixedTemporalField returns a fixed Temporal in all adjustments. - * Construct an FixedTemporalField with the Temporal that should be returned from doWith. + * Construct an FixedTemporalField with the Temporal that should be returned from adjustInto. */ static class FixedTemporalField implements TemporalField { private Temporal temporal; @@ -474,30 +480,24 @@ public class TestChronoLocalDate { } @Override - public boolean doIsSupported(TemporalAccessor temporal) { + public boolean isSupportedBy(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public ValueRange doRange(TemporalAccessor temporal) { + public ValueRange rangeRefinedBy(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public long doGet(TemporalAccessor temporal) { + public long getFrom(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @SuppressWarnings("unchecked") @Override - public R doWith(R temporal, long newValue) { + public R adjustInto(R temporal, long newValue) { return (R) this.temporal; } - - @Override - public boolean resolve(DateTimeBuilder builder, long value) { - throw new UnsupportedOperationException("Not supported yet."); - } - } } diff --git a/jdk/test/java/time/tck/java/time/temporal/TestChronoLocalDateTime.java b/jdk/test/java/time/tck/java/time/temporal/TestChronoLocalDateTime.java index c51be6c69b8..46335cedb4f 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TestChronoLocalDateTime.java +++ b/jdk/test/java/time/tck/java/time/temporal/TestChronoLocalDateTime.java @@ -63,31 +63,28 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.util.ArrayList; -import java.util.List; - import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.temporal.Chrono; -import java.time.temporal.ChronoLocalDateTime; +import java.time.chrono.HijrahChronology; +import java.time.chrono.JapaneseChronology; +import java.time.chrono.MinguoChronology; +import java.time.chrono.ThaiBuddhistChronology; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.ChronoLocalDateTime; +import java.time.chrono.Chronology; +import java.time.chrono.IsoChronology; import java.time.temporal.ChronoUnit; -import java.time.temporal.SimplePeriod; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; -import java.time.format.DateTimeBuilder; -import java.time.temporal.TemporalAdder; import java.time.temporal.TemporalAdjuster; +import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalField; -import java.time.temporal.TemporalSubtractor; -import java.time.temporal.ValueRange; import java.time.temporal.TemporalUnit; -import java.time.temporal.ISOChrono; -import java.time.calendar.HijrahChrono; -import java.time.calendar.JapaneseChrono; -import java.time.calendar.MinguoChrono; -import java.time.calendar.ThaiBuddhistChrono; +import java.time.temporal.ValueRange; +import java.util.ArrayList; +import java.util.List; import org.testng.Assert; import org.testng.annotations.DataProvider; @@ -103,21 +100,21 @@ public class TestChronoLocalDateTime { // regular data factory for names and descriptions of available calendars //----------------------------------------------------------------------- @DataProvider(name = "calendars") - Chrono[][] data_of_calendars() { - return new Chrono[][]{ - {HijrahChrono.INSTANCE}, - {ISOChrono.INSTANCE}, - {JapaneseChrono.INSTANCE}, - {MinguoChrono.INSTANCE}, - {ThaiBuddhistChrono.INSTANCE}}; + Chronology[][] data_of_calendars() { + return new Chronology[][]{ + {HijrahChronology.INSTANCE}, + {IsoChronology.INSTANCE}, + {JapaneseChronology.INSTANCE}, + {MinguoChronology.INSTANCE}, + {ThaiBuddhistChronology.INSTANCE}}; } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badWithAdjusterChrono(Chrono chrono) { + public void test_badWithAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDateTime cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON); TemporalAdjuster adjuster = new FixedAdjuster(cdt2); if (chrono != chrono2) { @@ -137,13 +134,13 @@ public class TestChronoLocalDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badPlusAdjusterChrono(Chrono chrono) { + public void test_badPlusAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDateTime cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON); - TemporalAdder adjuster = new FixedAdjuster(cdt2); + TemporalAmount adjuster = new FixedAdjuster(cdt2); if (chrono != chrono2) { try { cdt.plus(adjuster); @@ -161,13 +158,13 @@ public class TestChronoLocalDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badMinusAdjusterChrono(Chrono chrono) { + public void test_badMinusAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDateTime cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON); - TemporalSubtractor adjuster = new FixedAdjuster(cdt2); + TemporalAmount adjuster = new FixedAdjuster(cdt2); if (chrono != chrono2) { try { cdt.minus(adjuster); @@ -185,11 +182,11 @@ public class TestChronoLocalDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badPlusTemporalUnitChrono(Chrono chrono) { + public void test_badPlusTemporalUnitChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDateTime cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON); TemporalUnit adjuster = new FixedTemporalUnit(cdt2); if (chrono != chrono2) { @@ -209,11 +206,11 @@ public class TestChronoLocalDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badMinusTemporalUnitChrono(Chrono chrono) { + public void test_badMinusTemporalUnitChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDateTime cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON); TemporalUnit adjuster = new FixedTemporalUnit(cdt2); if (chrono != chrono2) { @@ -233,11 +230,11 @@ public class TestChronoLocalDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badTemporalFieldChrono(Chrono chrono) { + public void test_badTemporalFieldChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoLocalDateTime cdt = chrono.date(refDate).atTime(LocalTime.NOON); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoLocalDateTime cdt2 = chrono2.date(refDate).atTime(LocalTime.NOON); TemporalField adjuster = new FixedTemporalField(cdt2); if (chrono != chrono2) { @@ -260,7 +257,7 @@ public class TestChronoLocalDateTime { // isBefore, isAfter, isEqual //----------------------------------------------------------------------- @Test(groups={"tck"}, dataProvider="calendars") - public void test_datetime_comparisons(Chrono chrono) { + public void test_datetime_comparisons(Chronology chrono) { List> dates = new ArrayList<>(); ChronoLocalDateTime date = chrono.date(LocalDate.of(1900, 1, 1)).atTime(LocalTime.MIN); @@ -287,11 +284,11 @@ public class TestChronoLocalDateTime { dates.add(date.plus(100, ChronoUnit.YEARS)); // Check these dates against the corresponding dates for every calendar - for (Chrono[] clist : data_of_calendars()) { + for (Chronology[] clist : data_of_calendars()) { List> otherDates = new ArrayList<>(); - Chrono chrono2 = clist[0]; + Chronology chrono2 = clist[0]; for (ChronoLocalDateTime d : dates) { - otherDates.add(chrono2.date(d).atTime(d.getTime())); + otherDates.add(chrono2.date(d).atTime(d.toLocalTime())); } // Now compare the sequence of original dates with the sequence of converted dates @@ -325,9 +322,9 @@ public class TestChronoLocalDateTime { // Test Serialization of ISO via chrono API //----------------------------------------------------------------------- @Test( groups={"tck"}, dataProvider="calendars") - public > void test_ChronoLocalDateTimeSerialization(C chrono) throws Exception { + public void test_ChronoLocalDateTimeSerialization(Chronology chrono) throws Exception { LocalDateTime ref = LocalDate.of(2000, 1, 5).atTime(12, 1, 2, 3); - ChronoLocalDateTime orginal = chrono.date(ref).atTime(ref.getTime()); + ChronoLocalDateTime orginal = chrono.date(ref).atTime(ref.toLocalTime()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject(orginal); @@ -335,7 +332,7 @@ public class TestChronoLocalDateTime { ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream in = new ObjectInputStream(bais); @SuppressWarnings("unchecked") - ChronoLocalDateTime ser = (ChronoLocalDateTime) in.readObject(); + ChronoLocalDateTime ser = (ChronoLocalDateTime) in.readObject(); assertEquals(ser, orginal, "deserialized date is wrong"); } @@ -343,7 +340,7 @@ public class TestChronoLocalDateTime { * FixedAdjusted returns a fixed Temporal in all adjustments. * Construct an adjuster with the Temporal that should be returned from adjust. */ - static class FixedAdjuster implements TemporalAdjuster, TemporalAdder, TemporalSubtractor { + static class FixedAdjuster implements TemporalAdjuster, TemporalAmount { private Temporal datetime; FixedAdjuster(Temporal datetime) { @@ -365,11 +362,21 @@ public class TestChronoLocalDateTime { return datetime; } + @Override + public long get(TemporalUnit unit) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List getUnits() { + throw new UnsupportedOperationException("Not supported yet."); + } + } /** * FixedTemporalUnit returns a fixed Temporal in all adjustments. - * Construct an FixedTemporalUnit with the Temporal that should be returned from doPlus. + * Construct an FixedTemporalUnit with the Temporal that should be returned from addTo. */ static class FixedTemporalUnit implements TemporalUnit { private Temporal temporal; @@ -394,25 +401,25 @@ public class TestChronoLocalDateTime { } @Override - public boolean isSupported(Temporal temporal) { + public boolean isSupportedBy(Temporal temporal) { throw new UnsupportedOperationException("Not supported yet."); } @SuppressWarnings("unchecked") @Override - public R doPlus(R dateTime, long periodToAdd) { + public R addTo(R temporal, long amount) { return (R) this.temporal; } @Override - public SimplePeriod between(R dateTime1, R dateTime2) { + public long between(Temporal temporal1, Temporal temporal2) { throw new UnsupportedOperationException("Not supported yet."); } } /** * FixedTemporalField returns a fixed Temporal in all adjustments. - * Construct an FixedTemporalField with the Temporal that should be returned from doWith. + * Construct an FixedTemporalField with the Temporal that should be returned from adjustInto. */ static class FixedTemporalField implements TemporalField { private Temporal temporal; @@ -441,30 +448,24 @@ public class TestChronoLocalDateTime { } @Override - public boolean doIsSupported(TemporalAccessor temporal) { + public boolean isSupportedBy(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public ValueRange doRange(TemporalAccessor temporal) { + public ValueRange rangeRefinedBy(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public long doGet(TemporalAccessor temporal) { + public long getFrom(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @SuppressWarnings("unchecked") @Override - public R doWith(R temporal, long newValue) { + public R adjustInto(R temporal, long newValue) { return (R) this.temporal; } - - @Override - public boolean resolve(DateTimeBuilder builder, long value) { - throw new UnsupportedOperationException("Not supported yet."); - } - } } diff --git a/jdk/test/java/time/tck/java/time/temporal/TestChronoZonedDateTime.java b/jdk/test/java/time/tck/java/time/temporal/TestChronoZonedDateTime.java index e89725bb3d3..c97a0181003 100644 --- a/jdk/test/java/time/tck/java/time/temporal/TestChronoZonedDateTime.java +++ b/jdk/test/java/time/tck/java/time/temporal/TestChronoZonedDateTime.java @@ -63,33 +63,30 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.util.ArrayList; -import java.util.List; - import java.time.Duration; import java.time.LocalDate; import java.time.LocalTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; -import java.time.temporal.Chrono; +import java.time.chrono.HijrahChronology; +import java.time.chrono.JapaneseChronology; +import java.time.chrono.MinguoChronology; +import java.time.chrono.ThaiBuddhistChronology; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.ChronoZonedDateTime; +import java.time.chrono.Chronology; +import java.time.chrono.IsoChronology; import java.time.temporal.ChronoUnit; -import java.time.temporal.ChronoZonedDateTime; -import java.time.temporal.SimplePeriod; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; -import java.time.format.DateTimeBuilder; -import java.time.temporal.TemporalAdder; import java.time.temporal.TemporalAdjuster; +import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalField; -import java.time.temporal.TemporalSubtractor; -import java.time.temporal.ValueRange; -import java.time.temporal.ISOChrono; import java.time.temporal.TemporalUnit; -import java.time.calendar.HijrahChrono; -import java.time.calendar.JapaneseChrono; -import java.time.calendar.MinguoChrono; -import java.time.calendar.ThaiBuddhistChrono; +import java.time.temporal.ValueRange; +import java.util.ArrayList; +import java.util.List; import org.testng.Assert; import org.testng.annotations.DataProvider; @@ -105,22 +102,22 @@ public class TestChronoZonedDateTime { // regular data factory for names and descriptions of available calendars //----------------------------------------------------------------------- @DataProvider(name = "calendars") - Chrono[][] data_of_calendars() { - return new Chrono[][]{ - {HijrahChrono.INSTANCE}, - {ISOChrono.INSTANCE}, - {JapaneseChrono.INSTANCE}, - {MinguoChrono.INSTANCE}, - {ThaiBuddhistChrono.INSTANCE}, + Chronology[][] data_of_calendars() { + return new Chronology[][]{ + {HijrahChronology.INSTANCE}, + {IsoChronology.INSTANCE}, + {JapaneseChronology.INSTANCE}, + {MinguoChronology.INSTANCE}, + {ThaiBuddhistChronology.INSTANCE}, }; } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badWithAdjusterChrono(Chrono chrono) { + public void test_badWithAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoZonedDateTime czdt = chrono.date(refDate).atTime(LocalTime.NOON).atZone(ZoneOffset.UTC); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoZonedDateTime czdt2 = chrono2.date(refDate).atTime(LocalTime.NOON).atZone(ZoneOffset.UTC); TemporalAdjuster adjuster = new FixedAdjuster(czdt2); if (chrono != chrono2) { @@ -139,13 +136,13 @@ public class TestChronoZonedDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badPlusAdjusterChrono(Chrono chrono) { + public void test_badPlusAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoZonedDateTime czdt = chrono.date(refDate).atTime(LocalTime.NOON).atZone(ZoneOffset.UTC); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoZonedDateTime czdt2 = chrono2.date(refDate).atTime(LocalTime.NOON).atZone(ZoneOffset.UTC); - TemporalAdder adjuster = new FixedAdjuster(czdt2); + TemporalAmount adjuster = new FixedAdjuster(czdt2); if (chrono != chrono2) { try { czdt.plus(adjuster); @@ -163,13 +160,13 @@ public class TestChronoZonedDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badMinusAdjusterChrono(Chrono chrono) { + public void test_badMinusAdjusterChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoZonedDateTime czdt = chrono.date(refDate).atTime(LocalTime.NOON).atZone(ZoneOffset.UTC); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoZonedDateTime czdt2 = chrono2.date(refDate).atTime(LocalTime.NOON).atZone(ZoneOffset.UTC); - TemporalSubtractor adjuster = new FixedAdjuster(czdt2); + TemporalAmount adjuster = new FixedAdjuster(czdt2); if (chrono != chrono2) { try { czdt.minus(adjuster); @@ -187,11 +184,11 @@ public class TestChronoZonedDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badPlusTemporalUnitChrono(Chrono chrono) { + public void test_badPlusTemporalUnitChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoZonedDateTime czdt = chrono.date(refDate).atTime(LocalTime.NOON).atZone(ZoneOffset.UTC); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoZonedDateTime czdt2 = chrono2.date(refDate).atTime(LocalTime.NOON).atZone(ZoneOffset.UTC); TemporalUnit adjuster = new FixedTemporalUnit(czdt2); if (chrono != chrono2) { @@ -211,11 +208,11 @@ public class TestChronoZonedDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badMinusTemporalUnitChrono(Chrono chrono) { + public void test_badMinusTemporalUnitChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoZonedDateTime czdt = chrono.date(refDate).atTime(LocalTime.NOON).atZone(ZoneOffset.UTC); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoZonedDateTime czdt2 = chrono2.date(refDate).atTime(LocalTime.NOON).atZone(ZoneOffset.UTC); TemporalUnit adjuster = new FixedTemporalUnit(czdt2); if (chrono != chrono2) { @@ -235,11 +232,11 @@ public class TestChronoZonedDateTime { } @Test(groups={"tck"}, dataProvider="calendars") - public void test_badTemporalFieldChrono(Chrono chrono) { + public void test_badTemporalFieldChrono(Chronology chrono) { LocalDate refDate = LocalDate.of(1900, 1, 1); ChronoZonedDateTime czdt = chrono.date(refDate).atTime(LocalTime.NOON).atZone(ZoneOffset.UTC); - for (Chrono[] clist : data_of_calendars()) { - Chrono chrono2 = clist[0]; + for (Chronology[] clist : data_of_calendars()) { + Chronology chrono2 = clist[0]; ChronoZonedDateTime czdt2 = chrono2.date(refDate).atTime(LocalTime.NOON).atZone(ZoneOffset.UTC); TemporalField adjuster = new FixedTemporalField(czdt2); if (chrono != chrono2) { @@ -259,10 +256,10 @@ public class TestChronoZonedDateTime { } //----------------------------------------------------------------------- - // isBefore, isAfter, isEqual, INSTANT_COMPARATOR test a Chrono against the other Chronos + // isBefore, isAfter, isEqual, INSTANT_COMPARATOR test a Chronology against the other Chronos //----------------------------------------------------------------------- @Test(groups={"tck"}, dataProvider="calendars") - public void test_zonedDateTime_comparisons(Chrono chrono) { + public void test_zonedDateTime_comparisons(Chronology chrono) { List> dates = new ArrayList<>(); ChronoZonedDateTime date = chrono.date(LocalDate.of(1900, 1, 1)) @@ -291,11 +288,11 @@ public class TestChronoZonedDateTime { dates.add(date.plus(100, ChronoUnit.YEARS)); // Check these dates against the corresponding dates for every calendar - for (Chrono[] clist : data_of_calendars()) { + for (Chronology[] clist : data_of_calendars()) { List> otherDates = new ArrayList<>(); - Chrono chrono2 = ISOChrono.INSTANCE; //clist[0]; + Chronology chrono2 = IsoChronology.INSTANCE; //clist[0]; for (ChronoZonedDateTime d : dates) { - otherDates.add(chrono2.date(d).atTime(d.getTime()).atZone(d.getZone())); + otherDates.add(chrono2.date(d).atTime(d.toLocalTime()).atZone(d.getZone())); } // Now compare the sequence of original dates with the sequence of converted dates @@ -329,9 +326,9 @@ public class TestChronoZonedDateTime { // Test Serialization of ISO via chrono API //----------------------------------------------------------------------- @Test( groups={"tck"}, dataProvider="calendars") - public > void test_ChronoZonedDateTimeSerialization(C chrono) throws Exception { + public void test_ChronoZonedDateTimeSerialization(Chronology chrono) throws Exception { ZonedDateTime ref = LocalDate.of(2000, 1, 5).atTime(12, 1, 2, 3).atZone(ZoneId.of("GMT+01:23")); - ChronoZonedDateTime orginal = chrono.date(ref).atTime(ref.getTime()).atZone(ref.getZone()); + ChronoZonedDateTime orginal = chrono.date(ref).atTime(ref.toLocalTime()).atZone(ref.getZone()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject(orginal); @@ -339,7 +336,7 @@ public class TestChronoZonedDateTime { ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream in = new ObjectInputStream(bais); @SuppressWarnings("unchecked") - ChronoZonedDateTime ser = (ChronoZonedDateTime) in.readObject(); + ChronoZonedDateTime ser = (ChronoZonedDateTime) in.readObject(); assertEquals(ser, orginal, "deserialized date is wrong"); } @@ -348,7 +345,7 @@ public class TestChronoZonedDateTime { * FixedAdjusted returns a fixed Temporal in all adjustments. * Construct an adjuster with the Temporal that should be returned from adjust. */ - static class FixedAdjuster implements TemporalAdjuster, TemporalAdder, TemporalSubtractor { + static class FixedAdjuster implements TemporalAdjuster, TemporalAmount { private Temporal datetime; FixedAdjuster(Temporal datetime) { @@ -370,11 +367,21 @@ public class TestChronoZonedDateTime { return datetime; } + @Override + public long get(TemporalUnit unit) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List getUnits() { + throw new UnsupportedOperationException("Not supported yet."); + } + } /** * FixedTemporalUnit returns a fixed Temporal in all adjustments. - * Construct an FixedTemporalUnit with the Temporal that should be returned from doPlus. + * Construct an FixedTemporalUnit with the Temporal that should be returned from addTo. */ static class FixedTemporalUnit implements TemporalUnit { private Temporal temporal; @@ -399,25 +406,25 @@ public class TestChronoZonedDateTime { } @Override - public boolean isSupported(Temporal temporal) { + public boolean isSupportedBy(Temporal temporal) { throw new UnsupportedOperationException("Not supported yet."); } @SuppressWarnings("unchecked") @Override - public R doPlus(R dateTime, long periodToAdd) { + public R addTo(R temporal, long amount) { return (R) this.temporal; } @Override - public SimplePeriod between(R dateTime1, R dateTime2) { + public long between(Temporal temporal1, Temporal temporal2) { throw new UnsupportedOperationException("Not supported yet."); } } /** * FixedTemporalField returns a fixed Temporal in all adjustments. - * Construct an FixedTemporalField with the Temporal that should be returned from doWith. + * Construct an FixedTemporalField with the Temporal that should be returned from adjustInto. */ static class FixedTemporalField implements TemporalField { private Temporal temporal; @@ -446,30 +453,24 @@ public class TestChronoZonedDateTime { } @Override - public boolean doIsSupported(TemporalAccessor temporal) { + public boolean isSupportedBy(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public ValueRange doRange(TemporalAccessor temporal) { + public ValueRange rangeRefinedBy(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @Override - public long doGet(TemporalAccessor temporal) { + public long getFrom(TemporalAccessor temporal) { throw new UnsupportedOperationException("Not supported yet."); } @SuppressWarnings("unchecked") @Override - public R doWith(R temporal, long newValue) { + public R adjustInto(R temporal, long newValue) { return (R) this.temporal; } - - @Override - public boolean resolve(DateTimeBuilder builder, long value) { - throw new UnsupportedOperationException("Not supported yet."); - } - } } diff --git a/jdk/test/java/time/tck/java/time/zone/TCKFixedZoneRules.java b/jdk/test/java/time/tck/java/time/zone/TCKFixedZoneRules.java index 08617bae23b..3cf6053a2da 100644 --- a/jdk/test/java/time/tck/java/time/zone/TCKFixedZoneRules.java +++ b/jdk/test/java/time/tck/java/time/zone/TCKFixedZoneRules.java @@ -59,9 +59,6 @@ */ package tck.java.time.zone; -import java.time.zone.*; -import test.java.time.zone.*; - import static org.testng.Assert.assertEquals; import java.io.ByteArrayInputStream; @@ -75,7 +72,10 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; import java.time.ZoneOffset; +import java.time.zone.ZoneOffsetTransition; +import java.time.zone.ZoneOffsetTransitionRule; import java.time.zone.ZoneOffsetTransitionRule.TimeDefinition; +import java.time.zone.ZoneRules; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; diff --git a/jdk/test/java/time/tck/java/time/zone/TCKZoneOffsetTransition.java b/jdk/test/java/time/tck/java/time/zone/TCKZoneOffsetTransition.java index 36dc4ba0800..f98b82f1f18 100644 --- a/jdk/test/java/time/tck/java/time/zone/TCKZoneOffsetTransition.java +++ b/jdk/test/java/time/tck/java/time/zone/TCKZoneOffsetTransition.java @@ -59,19 +59,15 @@ */ package tck.java.time.zone; -import java.time.temporal.Year; -import java.time.zone.*; - import static java.time.temporal.ChronoUnit.HOURS; import static org.testng.Assert.assertEquals; -import java.io.IOException; - import tck.java.time.AbstractTCKTest; import java.time.Duration; import java.time.LocalDateTime; import java.time.ZoneOffset; - +import java.time.Year; +import java.time.zone.ZoneOffsetTransition; import org.testng.annotations.Test; /** diff --git a/jdk/test/java/time/tck/java/time/zone/TCKZoneOffsetTransitionRule.java b/jdk/test/java/time/tck/java/time/zone/TCKZoneOffsetTransitionRule.java index f98d7141b16..c98ddf02102 100644 --- a/jdk/test/java/time/tck/java/time/zone/TCKZoneOffsetTransitionRule.java +++ b/jdk/test/java/time/tck/java/time/zone/TCKZoneOffsetTransitionRule.java @@ -59,22 +59,16 @@ */ package tck.java.time.zone; -import java.time.ZoneId; -import java.time.zone.*; -import test.java.time.zone.*; - import static org.testng.Assert.assertEquals; -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; - import tck.java.time.AbstractTCKTest; import java.time.DayOfWeek; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; import java.time.ZoneOffset; +import java.time.zone.ZoneOffsetTransition; +import java.time.zone.ZoneOffsetTransitionRule; import java.time.zone.ZoneOffsetTransitionRule.TimeDefinition; import org.testng.annotations.Test; diff --git a/jdk/test/java/time/tck/java/time/zone/TCKZoneRules.java b/jdk/test/java/time/tck/java/time/zone/TCKZoneRules.java index 294e2e07cb2..5feac51ecac 100644 --- a/jdk/test/java/time/tck/java/time/zone/TCKZoneRules.java +++ b/jdk/test/java/time/tck/java/time/zone/TCKZoneRules.java @@ -59,9 +59,6 @@ */ package tck.java.time.zone; -import java.time.temporal.Year; -import java.time.zone.*; - import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; @@ -81,10 +78,14 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; +import java.time.Year; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; +import java.time.zone.ZoneOffsetTransition; +import java.time.zone.ZoneOffsetTransitionRule; import java.time.zone.ZoneOffsetTransitionRule.TimeDefinition; +import java.time.zone.ZoneRules; import org.testng.annotations.Test; @@ -142,7 +143,7 @@ public class TCKZoneRules { Instant instant = old.toInstant(); ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(0, -1, -15); assertEquals(test.getOffset(instant), offset); - checkOffset(test, old.getDateTime(), offset, 1); + checkOffset(test, old.toLocalDateTime(), offset, 1); assertEquals(test.getStandardOffset(instant), offset); assertEquals(test.getDaylightSavings(instant), Duration.ZERO); assertEquals(test.isDaylightSavings(instant), false); @@ -522,7 +523,7 @@ public class TCKZoneRules { Instant instant = old.toInstant(); ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(0, 9, 21); assertEquals(test.getOffset(instant), offset); - checkOffset(test, old.getDateTime(), offset, 1); + checkOffset(test, old.toLocalDateTime(), offset, 1); assertEquals(test.getStandardOffset(instant), offset); assertEquals(test.getDaylightSavings(instant), Duration.ZERO); assertEquals(test.isDaylightSavings(instant), false); @@ -672,13 +673,13 @@ public class TCKZoneRules { ZonedDateTime zdt = createZDT(1840, 1, 1, ZoneOffset.UTC); while (zdt.getYear() < 2010) { Instant instant = zdt.toInstant(); - if (zdt.getDate().isBefore(LocalDate.of(1911, 3, 11))) { + if (zdt.toLocalDate().isBefore(LocalDate.of(1911, 3, 11))) { assertEquals(test.getStandardOffset(instant), ZoneOffset.ofHoursMinutesSeconds(0, 9, 21)); - } else if (zdt.getDate().isBefore(LocalDate.of(1940, 6, 14))) { + } else if (zdt.toLocalDate().isBefore(LocalDate.of(1940, 6, 14))) { assertEquals(test.getStandardOffset(instant), OFFSET_ZERO); - } else if (zdt.getDate().isBefore(LocalDate.of(1944, 8, 25))) { + } else if (zdt.toLocalDate().isBefore(LocalDate.of(1944, 8, 25))) { assertEquals(test.getStandardOffset(instant), OFFSET_PONE); - } else if (zdt.getDate().isBefore(LocalDate.of(1945, 9, 16))) { + } else if (zdt.toLocalDate().isBefore(LocalDate.of(1945, 9, 16))) { assertEquals(test.getStandardOffset(instant), OFFSET_ZERO); } else { assertEquals(test.getStandardOffset(instant), OFFSET_PONE); @@ -705,7 +706,7 @@ public class TCKZoneRules { Instant instant = old.toInstant(); ZoneOffset offset = ZoneOffset.of("-04:56:02"); assertEquals(test.getOffset(instant), offset); - checkOffset(test, old.getDateTime(), offset, 1); + checkOffset(test, old.toLocalDateTime(), offset, 1); assertEquals(test.getStandardOffset(instant), offset); assertEquals(test.getDaylightSavings(instant), Duration.ZERO); assertEquals(test.isDaylightSavings(instant), false); @@ -878,7 +879,7 @@ public class TCKZoneRules { ZonedDateTime dateTime = createZDT(1860, 1, 1, ZoneOffset.UTC); while (dateTime.getYear() < 2010) { Instant instant = dateTime.toInstant(); - if (dateTime.getDate().isBefore(LocalDate.of(1883, 11, 18))) { + if (dateTime.toLocalDate().isBefore(LocalDate.of(1883, 11, 18))) { assertEquals(test.getStandardOffset(instant), ZoneOffset.of("-04:56:02")); } else { assertEquals(test.getStandardOffset(instant), ZoneOffset.ofHours(-5)); diff --git a/jdk/test/java/time/tck/java/time/zone/TCKZoneRulesProvider.java b/jdk/test/java/time/tck/java/time/zone/TCKZoneRulesProvider.java index 2d245f66115..a8081268ee4 100644 --- a/jdk/test/java/time/tck/java/time/zone/TCKZoneRulesProvider.java +++ b/jdk/test/java/time/tck/java/time/zone/TCKZoneRulesProvider.java @@ -59,8 +59,7 @@ */ package tck.java.time.zone; -import java.time.zone.*; -import test.java.time.zone.*; +import java.time.ZoneId; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; @@ -73,6 +72,9 @@ import java.util.Set; import java.util.TreeMap; import java.time.ZoneOffset; +import java.time.zone.ZoneRules; +import java.time.zone.ZoneRulesException; +import java.time.zone.ZoneRulesProvider; import org.testng.annotations.Test; @@ -87,7 +89,7 @@ public class TCKZoneRulesProvider { //----------------------------------------------------------------------- // getAvailableZoneIds() //----------------------------------------------------------------------- - @Test(groups={"tck"}) + @Test public void test_getAvailableGroupIds() { Set zoneIds = ZoneRulesProvider.getAvailableZoneIds(); assertEquals(zoneIds.contains("Europe/London"), true); @@ -98,34 +100,48 @@ public class TCKZoneRulesProvider { } //----------------------------------------------------------------------- - // getRules(String) + // getRules(String, boolean) //----------------------------------------------------------------------- - @Test(groups={"tck"}) - public void test_getRules_String() { - ZoneRules rules = ZoneRulesProvider.getRules("Europe/London"); + @Test + public void test_getRules_StringBoolean() { + ZoneRules rules = ZoneRulesProvider.getRules("Europe/London", false); assertNotNull(rules); - ZoneRules rules2 = ZoneRulesProvider.getRules("Europe/London"); + ZoneRules rules2 = ZoneRulesProvider.getRules("Europe/London", false); assertEquals(rules2, rules); } - @Test(groups={"tck"}, expectedExceptions=ZoneRulesException.class) - public void test_getRules_String_unknownId() { - ZoneRulesProvider.getRules("Europe/Lon"); + @Test(expectedExceptions=ZoneRulesException.class) + public void test_getRules_StringBoolean_unknownId() { + ZoneRulesProvider.getRules("Europe/Lon", false); } - @Test(groups={"tck"}, expectedExceptions=NullPointerException.class) - public void test_getRules_String_null() { - ZoneRulesProvider.getRules(null); + @Test(expectedExceptions=NullPointerException.class) + public void test_getRules_StringBoolean_null() { + ZoneRulesProvider.getRules(null, false); + } + + @Test + public void test_getRules_StringBoolean_dynamic() { + MockDynamicProvider dynamicProvider = new MockDynamicProvider(); + ZoneRulesProvider.registerProvider(dynamicProvider); + + assertEquals(dynamicProvider.count, 0); + ZoneRules rules1 = ZoneId.of("DynamicLocation").getRules(); + assertEquals(dynamicProvider.count, 2); + assertEquals(rules1, dynamicProvider.BASE); + ZoneRules rules2 = ZoneId.of("DynamicLocation").getRules(); + assertEquals(dynamicProvider.count, 4); + assertEquals(rules2, dynamicProvider.ALTERNATE); } //----------------------------------------------------------------------- // getVersions(String) //----------------------------------------------------------------------- - @Test(groups={"tck"}) + @Test public void test_getVersions_String() { NavigableMap versions = ZoneRulesProvider.getVersions("Europe/London"); assertTrue(versions.size() >= 1); - ZoneRules rules = ZoneRulesProvider.getRules("Europe/London"); + ZoneRules rules = ZoneRulesProvider.getRules("Europe/London", false); assertEquals(versions.lastEntry().getValue(), rules); NavigableMap copy = new TreeMap<>(versions); @@ -135,12 +151,12 @@ public class TCKZoneRulesProvider { assertEquals(versions2, copy); } - @Test(groups={"tck"}, expectedExceptions=ZoneRulesException.class) + @Test(expectedExceptions=ZoneRulesException.class) public void test_getVersions_String_unknownId() { ZoneRulesProvider.getVersions("Europe/Lon"); } - @Test(groups={"tck"}, expectedExceptions=NullPointerException.class) + @Test(expectedExceptions=NullPointerException.class) public void test_getVersions_String_null() { ZoneRulesProvider.getVersions(null); } @@ -148,7 +164,7 @@ public class TCKZoneRulesProvider { //----------------------------------------------------------------------- // refresh() //----------------------------------------------------------------------- - @Test(groups={"tck"}) + @Test public void test_refresh() { assertEquals(ZoneRulesProvider.refresh(), false); } @@ -164,8 +180,7 @@ public class TCKZoneRulesProvider { assertEquals(pre.contains("FooLocation"), false); Set post = ZoneRulesProvider.getAvailableZoneIds(); assertEquals(post.contains("FooLocation"), true); - - assertEquals(ZoneRulesProvider.getRules("FooLocation"), ZoneOffset.of("+01:45").getRules()); + assertEquals(ZoneRulesProvider.getRules("FooLocation", false), ZoneOffset.of("+01:45").getRules()); } static class MockTempProvider extends ZoneRulesProvider { @@ -175,17 +190,13 @@ public class TCKZoneRulesProvider { return new HashSet(Collections.singleton("FooLocation")); } @Override - protected ZoneRulesProvider provideBind(String zoneId) { - return this; - } - @Override protected NavigableMap provideVersions(String zoneId) { NavigableMap result = new TreeMap<>(); result.put("BarVersion", rules); return result; } @Override - protected ZoneRules provideRules(String zoneId) { + protected ZoneRules provideRules(String zoneId, boolean forCaching) { if (zoneId.equals("FooLocation")) { return rules; } @@ -193,4 +204,31 @@ public class TCKZoneRulesProvider { } } + static class MockDynamicProvider extends ZoneRulesProvider { + final ZoneRules BASE = ZoneOffset.of("+01:15").getRules(); + final ZoneRules ALTERNATE = ZoneOffset.of("+01:30").getRules(); + int count = 0; + @Override + public Set provideZoneIds() { + return new HashSet<>(Collections.singleton("DynamicLocation")); + } + @Override + protected NavigableMap provideVersions(String zoneId) { + NavigableMap result = new TreeMap<>(); + result.put("DynamicVersion1", BASE); + if (count > 2) { + result.put("DynamicVersion2", ALTERNATE); + } + return result; + } + @Override + protected ZoneRules provideRules(String zoneId, boolean forCaching) { + count++; + if (zoneId.equals("DynamicLocation")) { + return (forCaching ? null : (count > 2 ? ALTERNATE : BASE)); + } + throw new ZoneRulesException("Invalid"); + } + } + } diff --git a/jdk/test/java/time/test/java/time/MockSimplePeriod.java b/jdk/test/java/time/test/java/time/MockSimplePeriod.java index 1c5d8726bed..662c8b12100 100644 --- a/jdk/test/java/time/test/java/time/MockSimplePeriod.java +++ b/jdk/test/java/time/test/java/time/MockSimplePeriod.java @@ -68,15 +68,16 @@ import static java.time.temporal.ChronoUnit.SECONDS; import java.util.Objects; import java.time.temporal.Temporal; -import java.time.temporal.TemporalSubtractor; -import java.time.temporal.TemporalAdder; +import java.time.temporal.TemporalAmount; +import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalUnit; +import java.util.List; /** * Mock period of time measured using a single unit, such as {@code 3 Days}. */ public final class MockSimplePeriod - implements TemporalAdder, TemporalSubtractor, Comparable { + implements TemporalAmount, Comparable { /** * A constant for a period of zero, measured in days. @@ -119,6 +120,16 @@ public final class MockSimplePeriod this.unit = unit; } + @Override + public long get(TemporalUnit unit) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List getUnits() { + throw new UnsupportedOperationException("Not supported yet."); + } + //----------------------------------------------------------------------- public long getAmount() { return amount; diff --git a/jdk/test/java/time/test/java/time/TestDuration.java b/jdk/test/java/time/test/java/time/TestDuration.java index 2b2d8105003..786bfc0f05f 100644 --- a/jdk/test/java/time/test/java/time/TestDuration.java +++ b/jdk/test/java/time/test/java/time/TestDuration.java @@ -218,18 +218,12 @@ public class TestDuration extends AbstractTest { Duration b = durations[j]; if (i < j) { assertEquals(a.compareTo(b)< 0, true, a + " <=> " + b); - assertEquals(a.isLessThan(b), true, a + " <=> " + b); - assertEquals(a.isGreaterThan(b), false, a + " <=> " + b); assertEquals(a.equals(b), false, a + " <=> " + b); } else if (i > j) { assertEquals(a.compareTo(b) > 0, true, a + " <=> " + b); - assertEquals(a.isLessThan(b), false, a + " <=> " + b); - assertEquals(a.isGreaterThan(b), true, a + " <=> " + b); assertEquals(a.equals(b), false, a + " <=> " + b); } else { assertEquals(a.compareTo(b), 0, a + " <=> " + b); - assertEquals(a.isLessThan(b), false, a + " <=> " + b); - assertEquals(a.isGreaterThan(b), false, a + " <=> " + b); assertEquals(a.equals(b), true, a + " <=> " + b); } } diff --git a/jdk/test/java/time/test/java/time/TestLocalDateTime.java b/jdk/test/java/time/test/java/time/TestLocalDateTime.java index d850be50715..90c3927406f 100644 --- a/jdk/test/java/time/test/java/time/TestLocalDateTime.java +++ b/jdk/test/java/time/test/java/time/TestLocalDateTime.java @@ -124,15 +124,15 @@ public class TestLocalDateTime extends AbstractTest { @Test(groups={"implementation"}) public void test_withYear_int_noChange() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.withYear(2007); - assertSame(t.getDate(), TEST_2007_07_15_12_30_40_987654321.getDate()); - assertSame(t.getTime(), TEST_2007_07_15_12_30_40_987654321.getTime()); + assertSame(t.toLocalDate(), TEST_2007_07_15_12_30_40_987654321.toLocalDate()); + assertSame(t.toLocalTime(), TEST_2007_07_15_12_30_40_987654321.toLocalTime()); } @Test(groups={"implementation"}) public void test_withMonth_int_noChange() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.withMonth(7); - assertSame(t.getDate(), TEST_2007_07_15_12_30_40_987654321.getDate()); - assertSame(t.getTime(), TEST_2007_07_15_12_30_40_987654321.getTime()); + assertSame(t.toLocalDate(), TEST_2007_07_15_12_30_40_987654321.toLocalDate()); + assertSame(t.toLocalTime(), TEST_2007_07_15_12_30_40_987654321.toLocalTime()); } @Test(groups={"implementation"}) @@ -156,13 +156,13 @@ public class TestLocalDateTime extends AbstractTest { @Test(groups={"implementation"}) public void test_withHour_toMidnight() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(1, 0)).withHour(0); - assertSame(t.getTime(), LocalTime.MIDNIGHT); + assertSame(t.toLocalTime(), LocalTime.MIDNIGHT); } @Test(groups={"implementation"}) public void test_withHour_toMidday() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(1, 0)).withHour(12); - assertSame(t.getTime(), LocalTime.NOON); + assertSame(t.toLocalTime(), LocalTime.NOON); } @Test(groups={"implementation"}) @@ -174,13 +174,13 @@ public class TestLocalDateTime extends AbstractTest { @Test(groups={"implementation"}) public void test_withMinute_toMidnight() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(0, 1)).withMinute(0); - assertSame(t.getTime(), LocalTime.MIDNIGHT); + assertSame(t.toLocalTime(), LocalTime.MIDNIGHT); } @Test(groups={"implementation"}) public void test_withMinute_toMidday() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(12, 1)).withMinute(0); - assertSame(t.getTime(), LocalTime.NOON); + assertSame(t.toLocalTime(), LocalTime.NOON); } @Test(groups={"implementation"}) @@ -192,13 +192,13 @@ public class TestLocalDateTime extends AbstractTest { @Test(groups={"implementation"}) public void test_withSecond_toMidnight() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(0, 0, 1)).withSecond(0); - assertSame(t.getTime(), LocalTime.MIDNIGHT); + assertSame(t.toLocalTime(), LocalTime.MIDNIGHT); } @Test(groups={"implementation"}) public void test_withSecond_toMidday() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(12, 0, 1)).withSecond(0); - assertSame(t.getTime(), LocalTime.NOON); + assertSame(t.toLocalTime(), LocalTime.NOON); } @Test(groups={"implementation"}) @@ -210,13 +210,13 @@ public class TestLocalDateTime extends AbstractTest { @Test(groups={"implementation"}) public void test_withNanoOfSecond_toMidnight() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(0, 0, 0, 1)).withNano(0); - assertSame(t.getTime(), LocalTime.MIDNIGHT); + assertSame(t.toLocalTime(), LocalTime.MIDNIGHT); } @Test(groups={"implementation"}) public void test_withNanoOfSecond_toMidday() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(12, 0, 0, 1)).withNano(0); - assertSame(t.getTime(), LocalTime.NOON); + assertSame(t.toLocalTime(), LocalTime.NOON); } @Test(groups={"implementation"}) @@ -270,13 +270,13 @@ public class TestLocalDateTime extends AbstractTest { @Test(groups={"implementation"}) public void test_plusHours_toMidnight() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(23, 0)).plusHours(1); - assertSame(t.getTime(), LocalTime.MIDNIGHT); + assertSame(t.toLocalTime(), LocalTime.MIDNIGHT); } @Test(groups={"implementation"}) public void test_plusHours_toMidday() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(11, 0)).plusHours(1); - assertSame(t.getTime(), LocalTime.NOON); + assertSame(t.toLocalTime(), LocalTime.NOON); } @Test(groups={"implementation"}) @@ -288,19 +288,19 @@ public class TestLocalDateTime extends AbstractTest { @Test(groups={"implementation"}) public void test_plusMinutes_noChange_oneDay_same() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.plusMinutes(24 * 60); - assertSame(t.getTime(), TEST_2007_07_15_12_30_40_987654321.getTime()); + assertSame(t.toLocalTime(), TEST_2007_07_15_12_30_40_987654321.toLocalTime()); } @Test(groups={"implementation"}) public void test_plusMinutes_toMidnight() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(23, 59)).plusMinutes(1); - assertSame(t.getTime(), LocalTime.MIDNIGHT); + assertSame(t.toLocalTime(), LocalTime.MIDNIGHT); } @Test(groups={"implementation"}) public void test_plusMinutes_toMidday() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(11, 59)).plusMinutes(1); - assertSame(t.getTime(), LocalTime.NOON); + assertSame(t.toLocalTime(), LocalTime.NOON); } @Test(groups={"implementation"}) @@ -312,19 +312,19 @@ public class TestLocalDateTime extends AbstractTest { @Test(groups={"implementation"}) public void test_plusSeconds_noChange_oneDay_same() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.plusSeconds(24 * 60 * 60); - assertSame(t.getTime(), TEST_2007_07_15_12_30_40_987654321.getTime()); + assertSame(t.toLocalTime(), TEST_2007_07_15_12_30_40_987654321.toLocalTime()); } @Test(groups={"implementation"}) public void test_plusSeconds_toMidnight() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(23, 59, 59)).plusSeconds(1); - assertSame(t.getTime(), LocalTime.MIDNIGHT); + assertSame(t.toLocalTime(), LocalTime.MIDNIGHT); } @Test(groups={"implementation"}) public void test_plusSeconds_toMidday() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(11, 59, 59)).plusSeconds(1); - assertSame(t.getTime(), LocalTime.NOON); + assertSame(t.toLocalTime(), LocalTime.NOON); } @Test(groups={"implementation"}) @@ -336,19 +336,19 @@ public class TestLocalDateTime extends AbstractTest { @Test(groups={"implementation"}) public void test_plusNanos_noChange_oneDay_same() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.plusNanos(24 * 60 * 60 * 1000000000L); - assertSame(t.getTime(), TEST_2007_07_15_12_30_40_987654321.getTime()); + assertSame(t.toLocalTime(), TEST_2007_07_15_12_30_40_987654321.toLocalTime()); } @Test(groups={"implementation"}) public void test_plusNanos_toMidnight() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(23, 59, 59, 999999999)).plusNanos(1); - assertSame(t.getTime(), LocalTime.MIDNIGHT); + assertSame(t.toLocalTime(), LocalTime.MIDNIGHT); } @Test(groups={"implementation"}) public void test_plusNanos_toMidday() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(11, 59, 59, 999999999)).plusNanos(1); - assertSame(t.getTime(), LocalTime.NOON); + assertSame(t.toLocalTime(), LocalTime.NOON); } @Test(groups={"implementation"}) @@ -402,13 +402,13 @@ public class TestLocalDateTime extends AbstractTest { @Test(groups={"implementation"}) public void test_minusHours_toMidnight() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(1, 0)).minusHours(1); - assertSame(t.getTime(), LocalTime.MIDNIGHT); + assertSame(t.toLocalTime(), LocalTime.MIDNIGHT); } @Test(groups={"implementation"}) public void test_minusHours_toMidday() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(13, 0)).minusHours(1); - assertSame(t.getTime(), LocalTime.NOON); + assertSame(t.toLocalTime(), LocalTime.NOON); } @Test(groups={"implementation"}) @@ -420,19 +420,19 @@ public class TestLocalDateTime extends AbstractTest { @Test(groups={"implementation"}) public void test_minusMinutes_noChange_oneDay_same() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.minusMinutes(24 * 60); - assertSame(t.getTime(), TEST_2007_07_15_12_30_40_987654321.getTime()); + assertSame(t.toLocalTime(), TEST_2007_07_15_12_30_40_987654321.toLocalTime()); } @Test(groups={"implementation"}) public void test_minusMinutes_toMidnight() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(0, 1)).minusMinutes(1); - assertSame(t.getTime(), LocalTime.MIDNIGHT); + assertSame(t.toLocalTime(), LocalTime.MIDNIGHT); } @Test(groups={"implementation"}) public void test_minusMinutes_toMidday() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(12, 1)).minusMinutes(1); - assertSame(t.getTime(), LocalTime.NOON); + assertSame(t.toLocalTime(), LocalTime.NOON); } @Test(groups={"implementation"}) @@ -444,20 +444,20 @@ public class TestLocalDateTime extends AbstractTest { @Test(groups={"implementation"}) public void test_minusSeconds_noChange_oneDay() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.minusSeconds(24 * 60 * 60); - assertEquals(t.getDate(), TEST_2007_07_15_12_30_40_987654321.getDate().minusDays(1)); - assertSame(t.getTime(), TEST_2007_07_15_12_30_40_987654321.getTime()); + assertEquals(t.toLocalDate(), TEST_2007_07_15_12_30_40_987654321.toLocalDate().minusDays(1)); + assertSame(t.toLocalTime(), TEST_2007_07_15_12_30_40_987654321.toLocalTime()); } @Test(groups={"implementation"}) public void test_minusSeconds_toMidnight() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(0, 0, 1)).minusSeconds(1); - assertSame(t.getTime(), LocalTime.MIDNIGHT); + assertSame(t.toLocalTime(), LocalTime.MIDNIGHT); } @Test(groups={"implementation"}) public void test_minusSeconds_toMidday() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(12, 0, 1)).minusSeconds(1); - assertSame(t.getTime(), LocalTime.NOON); + assertSame(t.toLocalTime(), LocalTime.NOON); } @Test(groups={"implementation"}) @@ -469,40 +469,40 @@ public class TestLocalDateTime extends AbstractTest { @Test(groups={"implementation"}) public void test_minusNanos_noChange_oneDay() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.minusNanos(24 * 60 * 60 * 1000000000L); - assertEquals(t.getDate(), TEST_2007_07_15_12_30_40_987654321.getDate().minusDays(1)); - assertSame(t.getTime(), TEST_2007_07_15_12_30_40_987654321.getTime()); + assertEquals(t.toLocalDate(), TEST_2007_07_15_12_30_40_987654321.toLocalDate().minusDays(1)); + assertSame(t.toLocalTime(), TEST_2007_07_15_12_30_40_987654321.toLocalTime()); } @Test(groups={"implementation"}) public void test_minusNanos_toMidnight() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(0, 0, 0, 1)).minusNanos(1); - assertSame(t.getTime(), LocalTime.MIDNIGHT); + assertSame(t.toLocalTime(), LocalTime.MIDNIGHT); } @Test(groups={"implementation"}) public void test_minusNanos_toMidday() { LocalDateTime t = TEST_2007_07_15_12_30_40_987654321.with(LocalTime.of(12, 0, 0, 1)).minusNanos(1); - assertSame(t.getTime(), LocalTime.NOON); + assertSame(t.toLocalTime(), LocalTime.NOON); } //----------------------------------------------------------------------- - // getDate() + // toLocalDate() //----------------------------------------------------------------------- @Test(dataProvider="sampleDates", groups={"implementation"}) public void test_getDate(int year, int month, int day) { LocalDate d = LocalDate.of(year, month, day); LocalDateTime dt = LocalDateTime.of(d, LocalTime.MIDNIGHT); - assertSame(dt.getDate(), d); + assertSame(dt.toLocalDate(), d); } //----------------------------------------------------------------------- - // getTime() + // toLocalTime() //----------------------------------------------------------------------- @Test(dataProvider="sampleTimes", groups={"implementation"}) public void test_getTime(int h, int m, int s, int ns) { LocalTime t = LocalTime.of(h, m, s, ns); LocalDateTime dt = LocalDateTime.of(LocalDate.of(2011, 7, 30), t); - assertSame(dt.getTime(), t); + assertSame(dt.toLocalTime(), t); } void test_comparisons_LocalDateTime(LocalDate... localDates) { diff --git a/jdk/test/java/time/test/java/time/TestLocalTime.java b/jdk/test/java/time/test/java/time/TestLocalTime.java index 0a0b27796b1..47aa94a7ecd 100644 --- a/jdk/test/java/time/test/java/time/TestLocalTime.java +++ b/jdk/test/java/time/test/java/time/TestLocalTime.java @@ -167,15 +167,6 @@ public class TestLocalTime extends AbstractTest { } } - @Test(groups={"implementation"}) - public void factory_ofSecondOfDay7_long_int_singletons() { - for (int i = 0; i < 24; i++) { - LocalTime test1 = LocalTime.ofSecondOfDay(i * 60L * 60L, 0); - LocalTime test2 = LocalTime.of(i, 0); - assertSame(test1, test2); - } - } - @Test(groups={"implementation"}) public void factory_ofNanoOfDay_singletons() { for (int i = 0; i < 24; i++) { diff --git a/jdk/test/java/time/test/java/time/temporal/TestMonthDay.java b/jdk/test/java/time/test/java/time/TestMonthDay.java similarity index 98% rename from jdk/test/java/time/test/java/time/temporal/TestMonthDay.java rename to jdk/test/java/time/test/java/time/TestMonthDay.java index 002d4f7e286..ebfdc6de6e5 100644 --- a/jdk/test/java/time/test/java/time/temporal/TestMonthDay.java +++ b/jdk/test/java/time/test/java/time/TestMonthDay.java @@ -57,7 +57,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package test.java.time.temporal; +package test.java.time; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertSame; @@ -65,11 +65,10 @@ import static org.testng.Assert.assertTrue; import java.time.LocalDate; import java.time.Month; -import java.time.temporal.MonthDay; +import java.time.MonthDay; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import test.java.time.AbstractTest; /** * Test MonthDay. diff --git a/jdk/test/java/time/test/java/time/temporal/TestOffsetDateTime.java b/jdk/test/java/time/test/java/time/TestOffsetDateTime.java similarity index 97% rename from jdk/test/java/time/test/java/time/temporal/TestOffsetDateTime.java rename to jdk/test/java/time/test/java/time/TestOffsetDateTime.java index 9ee46725c8a..7766b5ffb3b 100644 --- a/jdk/test/java/time/test/java/time/temporal/TestOffsetDateTime.java +++ b/jdk/test/java/time/test/java/time/TestOffsetDateTime.java @@ -57,7 +57,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package test.java.time.temporal; +package test.java.time; import static org.testng.Assert.assertSame; @@ -65,13 +65,11 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneOffset; -import java.time.temporal.OffsetDateTime; +import java.time.OffsetDateTime; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import test.java.time.AbstractTest; -import test.java.time.MockSimplePeriod; /** * Test OffsetDateTime. @@ -114,9 +112,9 @@ public class TestOffsetDateTime extends AbstractTest { OffsetDateTime a = OffsetDateTime.of(localDateTime, offset); assertSame(a.getOffset(), offset); - assertSame(a.getDate(), localDate); - assertSame(a.getTime(), localTime); - assertSame(a.getDateTime(), localDateTime); + assertSame(a.toLocalDate(), localDate); + assertSame(a.toLocalTime(), localTime); + assertSame(a.toLocalDateTime(), localDateTime); } //----------------------------------------------------------------------- @@ -126,7 +124,7 @@ public class TestOffsetDateTime extends AbstractTest { public void test_withOffsetSameLocal() { OffsetDateTime base = OffsetDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30, 59), OFFSET_PONE); OffsetDateTime test = base.withOffsetSameLocal(OFFSET_PTWO); - assertSame(test.getDateTime(), base.getDateTime()); + assertSame(test.toLocalDateTime(), base.toLocalDateTime()); assertSame(test.getOffset(), OFFSET_PTWO); } diff --git a/jdk/test/java/time/test/java/time/temporal/TestOffsetDateTime_instants.java b/jdk/test/java/time/test/java/time/TestOffsetDateTime_instants.java similarity index 98% rename from jdk/test/java/time/test/java/time/temporal/TestOffsetDateTime_instants.java rename to jdk/test/java/time/test/java/time/TestOffsetDateTime_instants.java index 7922c37589f..86c887ac829 100644 --- a/jdk/test/java/time/test/java/time/temporal/TestOffsetDateTime_instants.java +++ b/jdk/test/java/time/test/java/time/TestOffsetDateTime_instants.java @@ -57,7 +57,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package test.java.time.temporal; +package test.java.time; import java.time.DateTimeException; import java.time.Instant; @@ -66,15 +66,15 @@ import java.time.LocalTime; import java.time.Month; import java.time.ZoneOffset; -import java.time.temporal.OffsetDateTime; -import java.time.temporal.Year; +import java.time.OffsetDateTime; +import java.time.Year; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; /** - * Test OffsetDate creation. + * Test OffsetDateTime creation. */ @Test public class TestOffsetDateTime_instants { @@ -243,7 +243,7 @@ public class TestOffsetDateTime_instants { try { OffsetDateTime test = OffsetDateTime.ofInstant(instant, ZoneOffset.UTC); assertEquals(test, expected); - if (expected.getDate().equals(maxDate) == false) { + if (expected.toLocalDate().equals(maxDate) == false) { expected = expected.plusDays(1); } } catch (RuntimeException|Error ex) { diff --git a/jdk/test/java/time/test/java/time/temporal/TestOffsetTime.java b/jdk/test/java/time/test/java/time/TestOffsetTime.java similarity index 96% rename from jdk/test/java/time/test/java/time/temporal/TestOffsetTime.java rename to jdk/test/java/time/test/java/time/TestOffsetTime.java index d6e9eff0b3f..41116a7c964 100644 --- a/jdk/test/java/time/test/java/time/temporal/TestOffsetTime.java +++ b/jdk/test/java/time/test/java/time/TestOffsetTime.java @@ -57,12 +57,11 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package test.java.time.temporal; +package test.java.time; -import java.time.temporal.OffsetTime; +import java.time.OffsetTime; import org.testng.annotations.Test; -import test.java.time.AbstractTest; /** * Test OffsetTime. diff --git a/jdk/test/java/time/test/java/time/TestPeriod.java b/jdk/test/java/time/test/java/time/TestPeriod.java index f7caf9e334b..6559947b145 100644 --- a/jdk/test/java/time/test/java/time/TestPeriod.java +++ b/jdk/test/java/time/test/java/time/TestPeriod.java @@ -59,35 +59,11 @@ */ package test.java.time; -import static java.time.temporal.ChronoUnit.DAYS; -import static java.time.temporal.ChronoUnit.HALF_DAYS; -import static java.time.temporal.ChronoUnit.HOURS; -import static java.time.temporal.ChronoUnit.MICROS; -import static java.time.temporal.ChronoUnit.MILLIS; -import static java.time.temporal.ChronoUnit.MINUTES; -import static java.time.temporal.ChronoUnit.MONTHS; -import static java.time.temporal.ChronoUnit.NANOS; -import static java.time.temporal.ChronoUnit.SECONDS; -import static java.time.temporal.ChronoUnit.YEARS; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertSame; -import static org.testng.Assert.assertTrue; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; - -import java.time.DateTimeException; -import java.time.Duration; -import java.time.LocalDate; -import java.time.LocalTime; -import java.time.Month; import java.time.Period; -import java.time.temporal.YearMonth; -import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** @@ -96,39 +72,6 @@ import org.testng.annotations.Test; @Test public class TestPeriod extends AbstractTest { - //----------------------------------------------------------------------- - // basics - //----------------------------------------------------------------------- - public void test_interfaces() { - assertTrue(Serializable.class.isAssignableFrom(Period.class)); - } - - @DataProvider(name="serialization") - Object[][] data_serialization() { - return new Object[][] { - {Period.ZERO}, - {Period.of(0, DAYS)}, - {Period.of(1, DAYS)}, - {Period.of(1, 2, 3, 4, 5, 6)}, - }; - } - - @Test(dataProvider="serialization") - public void test_serialization(Period period) throws Exception { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(period); - oos.close(); - - ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream( - baos.toByteArray())); - if (period.isZero()) { - assertSame(ois.readObject(), period); - } else { - assertEquals(ois.readObject(), period); - } - } - @Test public void test_immutable() { assertImmutable(Period.class); @@ -139,1437 +82,24 @@ public class TestPeriod extends AbstractTest { //----------------------------------------------------------------------- public void factory_zeroSingleton() { assertSame(Period.ZERO, Period.ZERO); - assertSame(Period.of(0, 0, 0, 0, 0, 0), Period.ZERO); - assertSame(Period.of(0, 0, 0, 0, 0, 0, 0), Period.ZERO); - assertSame(Period.ofDate(0, 0, 0), Period.ZERO); - assertSame(Period.ofTime(0, 0, 0), Period.ZERO); - assertSame(Period.ofTime(0, 0, 0, 0), Period.ZERO); - assertSame(Period.of(0, YEARS), Period.ZERO); - assertSame(Period.of(0, MONTHS), Period.ZERO); - assertSame(Period.of(0, DAYS), Period.ZERO); - assertSame(Period.of(0, HOURS), Period.ZERO); - assertSame(Period.of(0, MINUTES), Period.ZERO); - assertSame(Period.of(0, SECONDS), Period.ZERO); - assertSame(Period.of(0, NANOS), Period.ZERO); + assertSame(Period.ofYears(0), Period.ZERO); + assertSame(Period.ofMonths(0), Period.ZERO); + assertSame(Period.ofDays(0), Period.ZERO); + assertSame(Period.of(0, 0, 0), Period.ZERO); } //----------------------------------------------------------------------- - // of(PeriodProvider) - //----------------------------------------------------------------------- - public void factory_of_ints() { - assertPeriod(Period.of(1, 2, 3, 4, 5, 6), 1, 2, 3, 4, 5, 6, 0); - assertPeriod(Period.of(0, 2, 3, 4, 5, 6), 0, 2, 3, 4, 5, 6, 0); - assertPeriod(Period.of(1, 0, 0, 0, 0, 0), 1, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.of(0, 0, 0, 0, 0, 0), 0, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.of(-1, -2, -3, -4, -5, -6), -1, -2, -3, -4, -5, -6, 0); - } - - //----------------------------------------------------------------------- - // ofDate - //----------------------------------------------------------------------- - public void factory_ofDate_ints() { - assertPeriod(Period.ofDate(1, 2, 3), 1, 2, 3, 0, 0, 0, 0); - assertPeriod(Period.ofDate(0, 2, 3), 0, 2, 3, 0, 0, 0, 0); - assertPeriod(Period.ofDate(1, 0, 0), 1, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.ofDate(0, 0, 0), 0, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.ofDate(-1, -2, -3), -1, -2, -3, 0, 0, 0, 0); - } - - //----------------------------------------------------------------------- - // ofTime - //----------------------------------------------------------------------- - public void factory_ofTime_3ints() { - assertPeriod(Period.ofTime(1, 2, 3), 0, 0, 0, 1, 2, 3, 0); - assertPeriod(Period.ofTime(0, 2, 3), 0, 0, 0, 0, 2, 3, 0); - assertPeriod(Period.ofTime(1, 0, 0), 0, 0, 0, 1, 0, 0, 0); - assertPeriod(Period.ofTime(0, 0, 0), 0, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.ofTime(-1, -2, -3), 0, 0, 0, -1, -2, -3, 0); - } - - public void factory_ofTime_4ints() { - assertPeriod(Period.ofTime(1, 2, 3, 4), 0, 0, 0, 1, 2, 3, 4); - assertPeriod(Period.ofTime(0, 2, 3, 4), 0, 0, 0, 0, 2, 3, 4); - assertPeriod(Period.ofTime(1, 0, 0, 0), 0, 0, 0, 1, 0, 0, 0); - assertPeriod(Period.ofTime(0, 0, 0, 0), 0, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.ofTime(-1, -2, -3, -4), 0, 0, 0, -1, -2, -3, -4); - } - - //----------------------------------------------------------------------- - // of one field - //----------------------------------------------------------------------- - public void test_factory_of_intPeriodUnit() { - assertEquals(Period.of(1, YEARS), Period.of(1, YEARS)); - assertEquals(Period.of(2, MONTHS), Period.of(2, MONTHS)); - assertEquals(Period.of(3, DAYS), Period.of(3, DAYS)); - - assertEquals(Period.of(1, HALF_DAYS), Period.of(12, HOURS)); - assertEquals(Period.of(Integer.MAX_VALUE / (3600 * 8), HOURS), Period.of(Integer.MAX_VALUE / (3600 * 8), HOURS)); - assertEquals(Period.of(-1, MINUTES), Period.of(-1, MINUTES)); - assertEquals(Period.of(-2, SECONDS), Period.of(-2, SECONDS)); - assertEquals(Period.of(Integer.MIN_VALUE, NANOS), Period.of(Integer.MIN_VALUE, NANOS)); - assertEquals(Period.of(2, MILLIS), Period.of(2000000, NANOS)); - assertEquals(Period.of(2, MICROS), Period.of(2000, NANOS)); - } - - @Test(expectedExceptions=NullPointerException.class) - public void test_factory_of_intPeriodUnit_null() { - Period.of(1, null); - } - - //----------------------------------------------------------------------- - public void factory_years() { - assertPeriod(Period.of(1, YEARS), 1, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.of(0, YEARS), 0, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.of(-1, YEARS), -1, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.of(Integer.MAX_VALUE, YEARS), Integer.MAX_VALUE, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.of(Integer.MIN_VALUE, YEARS), Integer.MIN_VALUE, 0, 0, 0, 0, 0, 0); - } - - public void factory_months() { - assertPeriod(Period.of(1, MONTHS), 0, 1, 0, 0, 0, 0, 0); - assertPeriod(Period.of(0, MONTHS), 0, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.of(-1, MONTHS), 0, -1, 0, 0, 0, 0, 0); - assertPeriod(Period.of(Integer.MAX_VALUE, MONTHS), 0, Integer.MAX_VALUE, 0, 0, 0, 0, 0); - assertPeriod(Period.of(Integer.MIN_VALUE, MONTHS), 0, Integer.MIN_VALUE, 0, 0, 0, 0, 0); - } - - public void factory_days() { - assertPeriod(Period.of(1, DAYS), 0, 0, 1, 0, 0, 0, 0); - assertPeriod(Period.of(0, DAYS), 0, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.of(-1, DAYS), 0, 0, -1, 0, 0, 0, 0); - assertPeriod(Period.of(Integer.MAX_VALUE, DAYS), 0, 0, Integer.MAX_VALUE, 0, 0, 0, 0); - assertPeriod(Period.of(Integer.MIN_VALUE, DAYS), 0, 0, Integer.MIN_VALUE, 0, 0, 0, 0); - } - - public void factory_hours() { - assertPeriod(Period.of(1, HOURS), 0, 0, 0, 1, 0, 0, 0); - assertPeriod(Period.of(0, HOURS), 0, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.of(-1, HOURS), 0, 0, 0, -1, 0, 0, 0); - assertPeriod(Period.of(Integer.MAX_VALUE / (3600 * 8), HOURS), 0, 0, 0, Integer.MAX_VALUE / (3600 * 8), 0, 0, 0); - assertPeriod(Period.of(Integer.MIN_VALUE / (3600 * 8), HOURS), 0, 0, 0, Integer.MIN_VALUE / (3600 * 8), 0, 0, 0); - } - - public void factory_minutes() { - assertPeriod(Period.of(1, MINUTES), 0, 0, 0, 0, 1, 0, 0); - assertPeriod(Period.of(0, MINUTES), 0, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.of(-1, MINUTES), 0, 0, 0, 0, -1, 0, 0); - int val = Integer.MAX_VALUE / (60 * 8); - assertPeriod(Period.of(val, MINUTES), 0, 0, 0, - (int) (val / 60L), - (int) (val % 60), - 0, 0); - val = Integer.MIN_VALUE / (60 * 8); - assertPeriod(Period.of(val, MINUTES), 0, 0, 0, - (int) (val / 60L), - (int) (val % 60), - 0, 0); - } - - public void factory_seconds() { - assertPeriod(Period.of(1, SECONDS), 0, 0, 0, 0, 0, 1, 0); - assertPeriod(Period.of(0, SECONDS), 0, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.of(-1, SECONDS), 0, 0, 0, 0, 0, -1, 0); - assertPeriod(Period.of(Integer.MAX_VALUE, SECONDS), 0, 0, 0, - (int) (Integer.MAX_VALUE / 3600L), - (int) ((Integer.MAX_VALUE / 60L) % 60), - (int) (Integer.MAX_VALUE % 60), - 0); - assertPeriod(Period.of(Integer.MIN_VALUE, SECONDS), 0, 0, 0, - (int) (Integer.MIN_VALUE / 3600L), - (int) ((Integer.MIN_VALUE / 60L) % 60), - (int) (Integer.MIN_VALUE % 60), - 0); - } - - public void factory_nanos() { - assertPeriod(Period.of(1, NANOS), 0, 0, 0, 0, 0, 0, 1); - assertPeriod(Period.of(0, NANOS), 0, 0, 0, 0, 0, 0, 0); - assertPeriod(Period.of(-1, NANOS), 0, 0, 0, 0, 0, 0, -1); - assertPeriod(Period.of(Long.MAX_VALUE, NANOS), 0, 0, 0, - (int) (Long.MAX_VALUE / 3600_000_000_000L), - (int) ((Long.MAX_VALUE / 60_000_000_000L) % 60), - (int) ((Long.MAX_VALUE / 1_000_000_000L) % 60), - Long.MAX_VALUE % 1_000_000_000L); - assertPeriod(Period.of(Long.MIN_VALUE, NANOS), 0, 0, 0, - (int) (Long.MIN_VALUE / 3600_000_000_000L), - (int) ((Long.MIN_VALUE / 60_000_000_000L) % 60), - (int) ((Long.MIN_VALUE / 1_000_000_000L) % 60), - Long.MIN_VALUE % 1_000_000_000L); - } - - //----------------------------------------------------------------------- - // of(Duration) - //----------------------------------------------------------------------- - public void factory_duration() { - assertPeriod(Period.of(Duration.ofSeconds(2, 3)), 0, 0, 0, 0, 0, 2, 3); - assertPeriod(Period.of(Duration.ofSeconds(59, 3)), 0, 0, 0, 0, 0, 59, 3); - assertPeriod(Period.of(Duration.ofSeconds(60, 3)), 0, 0, 0, 0, 1, 0, 3); - assertPeriod(Period.of(Duration.ofSeconds(61, 3)), 0, 0, 0, 0, 1, 1, 3); - assertPeriod(Period.of(Duration.ofSeconds(3599, 3)), 0, 0, 0, 0, 59, 59, 3); - assertPeriod(Period.of(Duration.ofSeconds(3600, 3)), 0, 0, 0, 1, 0, 0, 3); - } - - public void factory_duration_negative() { - assertPeriod(Period.of(Duration.ofSeconds(-2, 3)), 0, 0, 0, 0, 0, -1, -999999997); - assertPeriod(Period.of(Duration.ofSeconds(-59, 3)), 0, 0, 0, 0, 0, -58, -999999997); - assertPeriod(Period.of(Duration.ofSeconds(-60, 3)), 0, 0, 0, 0, 0, -59, -999999997); - assertPeriod(Period.of(Duration.ofSeconds(-60, -3)), 0, 0, 0, 0, -1, 0, -3); - - assertPeriod(Period.of(Duration.ofSeconds(2, -3)), 0, 0, 0, 0, 0, 1, 999999997); - } - - public void factory_duration_big() { - Duration dur = Duration.ofSeconds(Integer.MAX_VALUE, 3); - long secs = Integer.MAX_VALUE; - assertPeriod(Period.of(dur), 0, 0, 0, (int) (secs / 3600), (int) ((secs % 3600) / 60), (int) (secs % 60), 3); - } - - @Test(expectedExceptions=NullPointerException.class) - public void factory_duration_null() { - Period.of((Duration) null); - } - - //----------------------------------------------------------------------- - // between - //----------------------------------------------------------------------- - @DataProvider(name="betweenDates") - Object[][] data_betweenDates() { - return new Object[][] { - {2010, 1, 1, 2010, 1, 1, 0, 0, 0}, - {2010, 1, 1, 2010, 1, 2, 0, 0, 1}, - {2010, 1, 1, 2010, 2, 1, 0, 1, 0}, - {2010, 1, 1, 2010, 2, 2, 0, 1, 1}, - {2010, 1, 1, 2011, 1, 1, 1, 0, 0}, - - {2010, 6, 12, 2010, 1, 1, 0, -5, -11}, - {2010, 6, 12, 2010, 1, 2, 0, -5, -10}, - {2010, 6, 12, 2010, 2, 1, 0, -4, -11}, - {2010, 6, 12, 2010, 9, 24, 0, 3, 12}, - - {2010, 6, 12, 2009, 1, 1, -1, -5, -11}, - {2010, 6, 12, 2009, 1, 2, -1, -5, -10}, - {2010, 6, 12, 2009, 2, 1, -1, -4, -11}, - {2010, 6, 12, 2009, 9, 24, 0, -9, 12}, - - {2010, 6, 12, 2008, 1, 1, -2, -5, -11}, - {2010, 6, 12, 2008, 1, 2, -2, -5, -10}, - {2010, 6, 12, 2008, 2, 1, -2, -4, -11}, - {2010, 6, 12, 2008, 9, 24, -1, -9, 12}, - }; - } - - @Test(dataProvider="betweenDates") - public void factory_between_LocalDate(int y1, int m1, int d1, int y2, int m2, int d2, int ye, int me, int de) { - LocalDate start = LocalDate.of(y1, m1, d1); - LocalDate end = LocalDate.of(y2, m2, d2); - Period test = Period.between(start, end); - assertPeriod(test, ye, me, de, 0, 0, 0, 0); - //assertEquals(start.plus(test), end); - } - - @DataProvider(name="betweenTimes") - Object[][] data_betweenTimes() { - return new Object[][] { - {12, 30, 40, 12, 30, 45, 0, 0, 5}, - {12, 30, 40, 12, 35, 40, 0, 5, 0}, - {12, 30, 40, 13, 30, 40, 1, 0, 0}, - - {12, 30, 40, 12, 30, 35, 0, 0, -5}, - {12, 30, 40, 12, 25, 40, 0, -5, 0}, - {12, 30, 40, 11, 30, 40, -1, 0, 0}, - }; - } - - @Test(dataProvider="betweenTimes") - public void factory_between_LocalTime(int h1, int m1, int s1, int h2, int m2, int s2, int he, int me, int se) { - LocalTime start = LocalTime.of(h1, m1, s1); - LocalTime end = LocalTime.of(h2, m2, s2); - Period test = Period.between(start, end); - assertPeriod(test, 0, 0, 0, he, me, se, 0); - //assertEquals(start.plus(test), end); - } - - public void factory_between_YearMonth() { - assertPeriod(Period.between(YearMonth.of(2012, 6), YearMonth.of(2013, 7)), 1, 1, 0, 0, 0, 0, 0); - assertPeriod(Period.between(YearMonth.of(2012, 6), YearMonth.of(2013, 3)), 0, 9, 0, 0, 0, 0, 0); - assertPeriod(Period.between(YearMonth.of(2012, 6), YearMonth.of(2011, 7)), 0, -11, 0, 0, 0, 0, 0); - } - - public void factory_between_Month() { - assertPeriod(Period.between(Month.FEBRUARY, Month.MAY), 0, 3, 0, 0, 0, 0, 0); - assertPeriod(Period.between(Month.NOVEMBER, Month.MAY), 0, -6, 0, 0, 0, 0, 0); - } - - //----------------------------------------------------------------------- - // betweenISO - //----------------------------------------------------------------------- - @DataProvider(name="betweenISO") - Object[][] data_betweenISO() { - return new Object[][] { - {2010, 1, 1, 2010, 1, 1, 0, 0, 0}, - {2010, 1, 1, 2010, 1, 2, 0, 0, 1}, - {2010, 1, 1, 2010, 1, 31, 0, 0, 30}, - {2010, 1, 1, 2010, 2, 1, 0, 1, 0}, - {2010, 1, 1, 2010, 2, 28, 0, 1, 27}, - {2010, 1, 1, 2010, 3, 1, 0, 2, 0}, - {2010, 1, 1, 2010, 12, 31, 0, 11, 30}, - {2010, 1, 1, 2011, 1, 1, 1, 0, 0}, - {2010, 1, 1, 2011, 12, 31, 1, 11, 30}, - {2010, 1, 1, 2012, 1, 1, 2, 0, 0}, - - {2010, 1, 10, 2010, 1, 1, 0, 0, -9}, - {2010, 1, 10, 2010, 1, 2, 0, 0, -8}, - {2010, 1, 10, 2010, 1, 9, 0, 0, -1}, - {2010, 1, 10, 2010, 1, 10, 0, 0, 0}, - {2010, 1, 10, 2010, 1, 11, 0, 0, 1}, - {2010, 1, 10, 2010, 1, 31, 0, 0, 21}, - {2010, 1, 10, 2010, 2, 1, 0, 0, 22}, - {2010, 1, 10, 2010, 2, 9, 0, 0, 30}, - {2010, 1, 10, 2010, 2, 10, 0, 1, 0}, - {2010, 1, 10, 2010, 2, 28, 0, 1, 18}, - {2010, 1, 10, 2010, 3, 1, 0, 1, 19}, - {2010, 1, 10, 2010, 3, 9, 0, 1, 27}, - {2010, 1, 10, 2010, 3, 10, 0, 2, 0}, - {2010, 1, 10, 2010, 12, 31, 0, 11, 21}, - {2010, 1, 10, 2011, 1, 1, 0, 11, 22}, - {2010, 1, 10, 2011, 1, 9, 0, 11, 30}, - {2010, 1, 10, 2011, 1, 10, 1, 0, 0}, - - {2010, 3, 30, 2011, 5, 1, 1, 1, 1}, - {2010, 4, 30, 2011, 5, 1, 1, 0, 1}, - - {2010, 2, 28, 2012, 2, 27, 1, 11, 30}, - {2010, 2, 28, 2012, 2, 28, 2, 0, 0}, - {2010, 2, 28, 2012, 2, 29, 2, 0, 1}, - - {2012, 2, 28, 2014, 2, 27, 1, 11, 30}, - {2012, 2, 28, 2014, 2, 28, 2, 0, 0}, - {2012, 2, 28, 2014, 3, 1, 2, 0, 1}, - - {2012, 2, 29, 2014, 2, 28, 1, 11, 30}, - {2012, 2, 29, 2014, 3, 1, 2, 0, 1}, - {2012, 2, 29, 2014, 3, 2, 2, 0, 2}, - - {2012, 2, 29, 2016, 2, 28, 3, 11, 30}, - {2012, 2, 29, 2016, 2, 29, 4, 0, 0}, - {2012, 2, 29, 2016, 3, 1, 4, 0, 1}, - - {2010, 1, 1, 2009, 12, 31, 0, 0, -1}, - {2010, 1, 1, 2009, 12, 30, 0, 0, -2}, - {2010, 1, 1, 2009, 12, 2, 0, 0, -30}, - {2010, 1, 1, 2009, 12, 1, 0, -1, 0}, - {2010, 1, 1, 2009, 11, 30, 0, -1, -1}, - {2010, 1, 1, 2009, 11, 2, 0, -1, -29}, - {2010, 1, 1, 2009, 11, 1, 0, -2, 0}, - {2010, 1, 1, 2009, 1, 2, 0, -11, -30}, - {2010, 1, 1, 2009, 1, 1, -1, 0, 0}, - - {2010, 1, 15, 2010, 1, 15, 0, 0, 0}, - {2010, 1, 15, 2010, 1, 14, 0, 0, -1}, - {2010, 1, 15, 2010, 1, 1, 0, 0, -14}, - {2010, 1, 15, 2009, 12, 31, 0, 0, -15}, - {2010, 1, 15, 2009, 12, 16, 0, 0, -30}, - {2010, 1, 15, 2009, 12, 15, 0, -1, 0}, - {2010, 1, 15, 2009, 12, 14, 0, -1, -1}, - - {2010, 2, 28, 2009, 3, 1, 0, -11, -27}, - {2010, 2, 28, 2009, 2, 28, -1, 0, 0}, - {2010, 2, 28, 2009, 2, 27, -1, 0, -1}, - - {2010, 2, 28, 2008, 2, 29, -1, -11, -28}, - {2010, 2, 28, 2008, 2, 28, -2, 0, 0}, - {2010, 2, 28, 2008, 2, 27, -2, 0, -1}, - - {2012, 2, 29, 2009, 3, 1, -2, -11, -28}, - {2012, 2, 29, 2009, 2, 28, -3, 0, -1}, - {2012, 2, 29, 2009, 2, 27, -3, 0, -2}, - - {2012, 2, 29, 2008, 3, 1, -3, -11, -28}, - {2012, 2, 29, 2008, 2, 29, -4, 0, 0}, - {2012, 2, 29, 2008, 2, 28, -4, 0, -1}, - }; - } - - @Test(dataProvider="betweenISO") - public void factory_betweenISO_LocalDate(int y1, int m1, int d1, int y2, int m2, int d2, int ye, int me, int de) { - LocalDate start = LocalDate.of(y1, m1, d1); - LocalDate end = LocalDate.of(y2, m2, d2); - Period test = Period.betweenISO(start, end); - assertPeriod(test, ye, me, de, 0, 0, 0, 0); - //assertEquals(start.plus(test), end); - } - - @Test(expectedExceptions=NullPointerException.class) - public void factory_betweenISO_LocalDate_nullFirst() { - Period.betweenISO((LocalDate) null, LocalDate.of(2010, 1, 1)); - } - - @Test(expectedExceptions=NullPointerException.class) - public void factory_betweenISO_LocalDate_nullSecond() { - Period.betweenISO(LocalDate.of(2010, 1, 1), (LocalDate) null); - } - - //------------------------------------------------------------------------- - @Test(expectedExceptions=NullPointerException.class) - public void factory_betweenISO_LocalTime_nullFirst() { - Period.betweenISO((LocalTime) null, LocalTime.of(12, 30)); - } - - @Test(expectedExceptions=NullPointerException.class) - public void factory_betweenISO_LocalTime_nullSecond() { - Period.betweenISO(LocalTime.of(12, 30), (LocalTime) null); - } - - //----------------------------------------------------------------------- - // parse() - //----------------------------------------------------------------------- - @Test(dataProvider="toStringAndParse") - public void test_parse(Period test, String expected) { - assertEquals(test, Period.parse(expected)); - } - - @Test(expectedExceptions=NullPointerException.class) - public void test_parse_nullText() { - Period.parse((String) null); - } - - //----------------------------------------------------------------------- - // isZero() - //----------------------------------------------------------------------- - public void test_isZero() { - assertEquals(Period.of(1, 2, 3, 4, 5, 6, 7).isZero(), false); - assertEquals(Period.of(1, 2, 3, 0, 0, 0, 0).isZero(), false); - assertEquals(Period.of(0, 0, 0, 4, 5, 6, 7).isZero(), false); - assertEquals(Period.of(1, 0, 0, 0, 0, 0, 0).isZero(), false); - assertEquals(Period.of(0, 2, 0, 0, 0, 0, 0).isZero(), false); - assertEquals(Period.of(0, 0, 3, 0, 0, 0, 0).isZero(), false); - assertEquals(Period.of(0, 0, 0, 4, 0, 0, 0).isZero(), false); - assertEquals(Period.of(0, 0, 0, 0, 5, 0, 0).isZero(), false); - assertEquals(Period.of(0, 0, 0, 0, 0, 6, 0).isZero(), false); - assertEquals(Period.of(0, 0, 0, 0, 0, 0, 7).isZero(), false); - assertEquals(Period.of(0, 0, 0, 0, 0, 0).isZero(), true); - } - - //----------------------------------------------------------------------- - // isPositive() - //----------------------------------------------------------------------- - public void test_isPositive() { - assertEquals(Period.of(1, 2, 3, 4, 5, 6, 7).isPositive(), true); - assertEquals(Period.of(1, 2, 3, 0, 0, 0, 0).isPositive(), true); - assertEquals(Period.of(0, 0, 0, 4, 5, 6, 7).isPositive(), true); - assertEquals(Period.of(1, 0, 0, 0, 0, 0, 0).isPositive(), true); - assertEquals(Period.of(0, 2, 0, 0, 0, 0, 0).isPositive(), true); - assertEquals(Period.of(0, 0, 3, 0, 0, 0, 0).isPositive(), true); - assertEquals(Period.of(0, 0, 0, 4, 0, 0, 0).isPositive(), true); - assertEquals(Period.of(0, 0, 0, 0, 5, 0, 0).isPositive(), true); - assertEquals(Period.of(0, 0, 0, 0, 0, 6, 0).isPositive(), true); - assertEquals(Period.of(0, 0, 0, 0, 0, 0, 7).isPositive(), true); - assertEquals(Period.of(-1, -2, -3, -4, -5, -6, -7).isPositive(), false); - assertEquals(Period.of(-1, -2, 3, 4, -5, -6, -7).isPositive(), false); - assertEquals(Period.of(-1, 0, 0, 0, 0, 0, 0).isPositive(), false); - assertEquals(Period.of(0, -2, 0, 0, 0, 0, 0).isPositive(), false); - assertEquals(Period.of(0, 0, -3, 0, 0, 0, 0).isPositive(), false); - assertEquals(Period.of(0, 0, 0, -4, 0, 0, 0).isPositive(), false); - assertEquals(Period.of(0, 0, 0, 0, -5, 0, 0).isPositive(), false); - assertEquals(Period.of(0, 0, 0, 0, 0, -6, 0).isPositive(), false); - assertEquals(Period.of(0, 0, 0, 0, 0, 0, -7).isPositive(), false); - assertEquals(Period.of(0, 0, 0, 0, 0, 0).isPositive(), false); - } - - //----------------------------------------------------------------------- - // withYears() - //----------------------------------------------------------------------- - public void test_withYears() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.withYears(10), 10, 2, 3, 4, 5, 6, 7); - } - - public void test_withYears_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.withYears(1), test); - } - - public void test_withYears_toZero() { - Period test = Period.of(1, YEARS); - assertSame(test.withYears(0), Period.ZERO); - } - - //----------------------------------------------------------------------- - // withMonths() - //----------------------------------------------------------------------- - public void test_withMonths() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.withMonths(10), 1, 10, 3, 4, 5, 6, 7); - } - - public void test_withMonths_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.withMonths(2), test); - } - - public void test_withMonths_toZero() { - Period test = Period.of(1, MONTHS); - assertSame(test.withMonths(0), Period.ZERO); - } - - //----------------------------------------------------------------------- - // withDays() - //----------------------------------------------------------------------- - public void test_withDays() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.withDays(10), 1, 2, 10, 4, 5, 6, 7); - } - - public void test_withDays_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.withDays(3), test); - } - - public void test_withDays_toZero() { - Period test = Period.of(1, DAYS); - assertSame(test.withDays(0), Period.ZERO); - } - - //----------------------------------------------------------------------- - // withTimeNanos() - //----------------------------------------------------------------------- - public void test_withNanos() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.withTimeNanos(10), 1, 2, 3, 0, 0, 0, 10); - } - - public void test_withNanos_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.withTimeNanos(((4 * 60 + 5) * 60 + 6) * 1_000_000_000L + 7), test); - } - - public void test_withNanos_toZero() { - Period test = Period.of(1, NANOS); - assertSame(test.withTimeNanos(0), Period.ZERO); - } - - - - //----------------------------------------------------------------------- - // plusYears() - //----------------------------------------------------------------------- - public void test_plusYears() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.plus(10, YEARS), 11, 2, 3, 4, 5, 6, 7); - assertPeriod(test.plus(Period.of(10, YEARS)), 11, 2, 3, 4, 5, 6, 7); - } - - public void test_plusYears_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.plus(0, YEARS), test); - assertPeriod(test.plus(Period.of(0, YEARS)), 1, 2, 3, 4, 5, 6, 7); - } - - public void test_plusYears_toZero() { - Period test = Period.of(-1, YEARS); - assertSame(test.plus(1, YEARS), Period.ZERO); - assertSame(test.plus(Period.of(1, YEARS)), Period.ZERO); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_plusYears_overflowTooBig() { - Period test = Period.of(Integer.MAX_VALUE, YEARS); - test.plus(1, YEARS); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_plusYears_overflowTooSmall() { - Period test = Period.of(Integer.MIN_VALUE, YEARS); - test.plus(-1, YEARS); - } - - //----------------------------------------------------------------------- - // plusMonths() - //----------------------------------------------------------------------- - public void test_plusMonths() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.plus(10, MONTHS), 1, 12, 3, 4, 5, 6, 7); - assertPeriod(test.plus(Period.of(10, MONTHS)), 1, 12, 3, 4, 5, 6, 7); - } - - public void test_plusMonths_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.plus(0, MONTHS), test); - assertEquals(test.plus(Period.of(0, MONTHS)), test); - } - - public void test_plusMonths_toZero() { - Period test = Period.of(-1, MONTHS); - assertSame(test.plus(1, MONTHS), Period.ZERO); - assertSame(test.plus(Period.of(1, MONTHS)), Period.ZERO); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_plusMonths_overflowTooBig() { - Period test = Period.of(Integer.MAX_VALUE, MONTHS); - test.plus(1, MONTHS); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_plusMonths_overflowTooSmall() { - Period test = Period.of(Integer.MIN_VALUE, MONTHS); - test.plus(-1, MONTHS); - } - - //----------------------------------------------------------------------- - // plusDays() - //----------------------------------------------------------------------- - public void test_plusDays() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.plus(10, DAYS), 1, 2, 13, 4, 5, 6, 7); - } - - public void test_plusDays_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.plus(0, DAYS), test); - } - - public void test_plusDays_toZero() { - Period test = Period.of(-1, DAYS); - assertSame(test.plus(1, DAYS), Period.ZERO); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_plusDays_overflowTooBig() { - Period test = Period.of(Integer.MAX_VALUE, DAYS); - test.plus(1, DAYS); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_plusDays_overflowTooSmall() { - Period test = Period.of(Integer.MIN_VALUE, DAYS); - test.plus(-1, DAYS); - } - - //----------------------------------------------------------------------- - // plusHours() - //----------------------------------------------------------------------- - public void test_plusHours() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.plus(10, HOURS), 1, 2, 3, 14, 5, 6, 7); - } - - public void test_plusHours_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.plus(0, HOURS), test); - } - - public void test_plusHours_toZero() { - Period test = Period.of(-1, HOURS); - assertSame(test.plus(1, HOURS), Period.ZERO); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_plusHours_overflowTooBig() { - Period test = Period.of(Integer.MAX_VALUE, HOURS); - test.plus(1, HOURS); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_plusHours_overflowTooSmall() { - Period test = Period.of(Integer.MIN_VALUE, HOURS); - test.plus(-1, HOURS); - } - - //----------------------------------------------------------------------- - // plusMinutes() - //----------------------------------------------------------------------- - public void test_plusMinutes() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.plus(10, MINUTES), 1, 2, 3, 4, 15, 6, 7); - } - - public void test_plusMinutes_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.plus(0, MINUTES), test); - } - - public void test_plusMinutes_toZero() { - Period test = Period.of(-1, MINUTES); - assertSame(test.plus(1, MINUTES), Period.ZERO); - } - - //----------------------------------------------------------------------- - // plusSeconds() - //----------------------------------------------------------------------- - public void test_plusSeconds() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.plus(10, SECONDS), 1, 2, 3, 4, 5, 16, 7); - } - - public void test_plusSeconds_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.plus(0, SECONDS), test); - } - - public void test_plusSeconds_toZero() { - Period test = Period.of(-1, SECONDS); - assertSame(test.plus(1, SECONDS), Period.ZERO); - } - - //----------------------------------------------------------------------- - // plusNanos() - //----------------------------------------------------------------------- - public void test_plusNanos() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.plus(10, NANOS), 1, 2, 3, 4, 5, 6, 17); - } - - public void test_plusNanos_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.plus(0, NANOS), test); - } - - public void test_plusNanos_toZero() { - Period test = Period.of(-1, NANOS); - assertSame(test.plus(1, NANOS), Period.ZERO); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_plusNanos_overflowTooBig() { - Period test = Period.of(Long.MAX_VALUE, NANOS); - test.plus(1, NANOS); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_plusNanos_overflowTooSmall() { - Period test = Period.of(Long.MIN_VALUE, NANOS); - test.plus(-1, NANOS); - } - - //----------------------------------------------------------------------- - // minusYears() - //----------------------------------------------------------------------- - public void test_minusYears() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.minus(10, YEARS), -9, 2, 3, 4, 5, 6, 7); - } - - public void test_minusYears_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.minus(0, YEARS), test); - } - - public void test_minusYears_toZero() { - Period test = Period.of(1, YEARS); - assertSame(test.minus(1, YEARS), Period.ZERO); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_minusYears_overflowTooBig() { - Period test = Period.of(Integer.MAX_VALUE, YEARS); - test.minus(-1, YEARS); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_minusYears_overflowTooSmall() { - Period test = Period.of(Integer.MIN_VALUE, YEARS); - test.minus(1, YEARS); - } - - //----------------------------------------------------------------------- - // minusMonths() - //----------------------------------------------------------------------- - public void test_minusMonths() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.minus(10, MONTHS), 1, -8, 3, 4, 5, 6, 7); - } - - public void test_minusMonths_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.minus(0, MONTHS), test); - } - - public void test_minusMonths_toZero() { - Period test = Period.of(1, MONTHS); - assertSame(test.minus(1, MONTHS), Period.ZERO); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_minusMonths_overflowTooBig() { - Period test = Period.of(Integer.MAX_VALUE, MONTHS); - test.minus(-1, MONTHS); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_minusMonths_overflowTooSmall() { - Period test = Period.of(Integer.MIN_VALUE, MONTHS); - test.minus(1, MONTHS); - } - - //----------------------------------------------------------------------- - // minusDays() - //----------------------------------------------------------------------- - public void test_minusDays() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.minus(10, DAYS), 1, 2, -7, 4, 5, 6, 7); - } - - public void test_minusDays_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.minus(0, DAYS), test); - } - - public void test_minusDays_toZero() { - Period test = Period.of(1, DAYS); - assertSame(test.minus(1, DAYS), Period.ZERO); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_minusDays_overflowTooBig() { - Period test = Period.of(Integer.MAX_VALUE, DAYS); - test.minus(-1, DAYS); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_minusDays_overflowTooSmall() { - Period test = Period.of(Integer.MIN_VALUE, DAYS); - test.minus(1, DAYS); - } - - //----------------------------------------------------------------------- - // minusHours() - //----------------------------------------------------------------------- - public void test_minusHours() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.minus(10, HOURS), 1, 2, 3, -5, -54, -53, -999999993); - assertEquals(test.minus(10, HOURS).plus(10, HOURS), test); - } - - public void test_minusHours_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.minus(0, HOURS), test); - } - - public void test_minusHours_toZero() { - Period test = Period.of(1, HOURS); - assertSame(test.minus(1, HOURS), Period.ZERO); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_minusHours_overflowTooBig() { - Period test = Period.of(Integer.MAX_VALUE, HOURS); - test.minus(-1, HOURS); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_minusHours_overflowTooSmall() { - Period test = Period.of(Integer.MIN_VALUE, HOURS); - test.minus(1, HOURS); - } - - //----------------------------------------------------------------------- - // minusMinutes() - //----------------------------------------------------------------------- - public void test_minusMinutes() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.minus(10, MINUTES), 1, 2, 3, 3, 55, 6, 7); - assertEquals(test.minus(10, MINUTES).plus(10, MINUTES), test); - } - - public void test_minusMinutes_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.minus(0, MINUTES), test); - } - - public void test_minusMinutes_toZero() { - Period test = Period.of(1, MINUTES); - assertSame(test.minus(1, MINUTES), Period.ZERO); - } - - //----------------------------------------------------------------------- - // minusSeconds() - //----------------------------------------------------------------------- - public void test_minusSeconds() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.minus(10, SECONDS), 1, 2, 3, 4, 4, 56, 7); - assertEquals(test.minus(10, SECONDS).plus(10, SECONDS), test); - } - - public void test_minusSeconds_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.minus(0, SECONDS), test); - } - - public void test_minusSeconds_toZero() { - Period test = Period.of(1, SECONDS); - assertSame(test.minus(1, SECONDS), Period.ZERO); - } - - //----------------------------------------------------------------------- - // minusNanos() - //----------------------------------------------------------------------- - public void test_minusNanos() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.minus(10, NANOS), 1, 2, 3, 4, 5, 5, 999999997); - } - - public void test_minusNanos_noChange() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.minus(0, NANOS), test); - } - - public void test_minusNanos_toZero() { - Period test = Period.of(1, NANOS); - assertSame(test.minus(1, NANOS), Period.ZERO); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_minusNanos_overflowTooBig() { - Period test = Period.of(Long.MAX_VALUE, NANOS); - test.minus(-1, NANOS); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_minusNanos_overflowTooSmall() { - Period test = Period.of(Long.MIN_VALUE, NANOS); - test.minus(1, NANOS); - } - - //----------------------------------------------------------------------- - // multipliedBy() - //----------------------------------------------------------------------- - public void test_multipliedBy() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.multipliedBy(2), 2, 4, 6, 8, 10, 12, 14); - assertPeriod(test.multipliedBy(-3), -3, -6, -9, -12, -15, -18, -21); - } - - public void test_multipliedBy_zeroBase() { - assertSame(Period.ZERO.multipliedBy(2), Period.ZERO); - } - - public void test_multipliedBy_zero() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.multipliedBy(0), Period.ZERO); - } - - public void test_multipliedBy_one() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertSame(test.multipliedBy(1), test); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_multipliedBy_overflowTooBig() { - Period test = Period.of(Integer.MAX_VALUE / 2 + 1, YEARS); - test.multipliedBy(2); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_multipliedBy_overflowTooSmall() { - Period test = Period.of(Integer.MIN_VALUE / 2 - 1, YEARS); - test.multipliedBy(2); - } - - //----------------------------------------------------------------------- - // negated() - //----------------------------------------------------------------------- - public void test_negated() { - Period test = Period.of(1, 2, 3, 4, 5, 6, 7); - assertPeriod(test.negated(), -1, -2, -3, -4, -5, -6, -7); - } - - public void test_negated_zero() { - assertSame(Period.ZERO.negated(), Period.ZERO); - } - - public void test_negated_max() { - assertPeriod(Period.of(Integer.MAX_VALUE, YEARS).negated(), -Integer.MAX_VALUE, 0, 0, 0, 0, 0, 0); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_negated_overflow() { - Period.of(Integer.MIN_VALUE, YEARS).negated(); - } - - //----------------------------------------------------------------------- - // normalizedHoursToDays() - //----------------------------------------------------------------------- - @DataProvider(name="normalizedHoursToDays") - Object[][] data_normalizedHoursToDays() { - return new Object[][] { - {0, 0, 0, 0}, - {1, 0, 1, 0}, - {-1, 0, -1, 0}, - - {1, 1, 1, 1}, - {1, 23, 1, 23}, - {1, 24, 2, 0}, - {1, 25, 2, 1}, - - {1, -1, 0, 23}, - {1, -23, 0, 1}, - {1, -24, 0, 0}, - {1, -25, 0, -1}, - {1, -47, 0, -23}, - {1, -48, -1, 0}, - {1, -49, -1, -1}, - - {-1, 1, 0, -23}, - {-1, 23, 0, -1}, - {-1, 24, 0, 0}, - {-1, 25, 0, 1}, - {-1, 47, 0, 23}, - {-1, 48, 1, 0}, - {-1, 49, 1, 1}, - - {-1, -1, -1, -1}, - {-1, -23, -1, -23}, - {-1, -24, -2, 0}, - {-1, -25, -2, -1}, - }; - } - - @Test(dataProvider="normalizedHoursToDays") - public void test_normalizedHoursToDays(int inputDays, int inputHours, int expectedDays, int expectedHours) { - assertPeriod(Period.of(0, 0, inputDays, inputHours, 0, 0, 0).normalizedHoursToDays(), 0, 0, expectedDays, expectedHours, 0, 0, 0); - } - - @Test(dataProvider="normalizedHoursToDays") - public void test_normalizedHoursToDays_yearsMonthsUnaffected(int inputDays, int inputHours, int expectedDays, int expectedHours) { - assertPeriod(Period.of(12, 6, inputDays, inputHours, 0, 0, 0).normalizedHoursToDays(), 12, 6, expectedDays, expectedHours, 0, 0, 0); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_normalizedHoursToDays_min() { - Period base = Period.of(0, 0, Integer.MIN_VALUE, -24, 0, 0, 0); - base.normalizedHoursToDays(); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_normalizedHoursToDays_max() { - Period base = Period.of(0, 0, Integer.MAX_VALUE, 24, 0, 0, 0); - base.normalizedHoursToDays(); - } - - //----------------------------------------------------------------------- - // normalizedDaysToHours() - //----------------------------------------------------------------------- - @DataProvider(name="normalizedDaysToHours") - Object[][] data_normalizedDaysToHours() { - return new Object[][] { - {0, 0, 0, 0, 0}, - - {1, 0, 0, 24, 0}, - {1, 1, 0, 25, 0}, - {1, 23, 0, 47, 0}, - {1, 24, 0, 48, 0}, - {1, 25, 0, 49, 0}, - {2, 23, 0, 71, 0}, - {2, 24, 0, 72, 0}, - {2, 25, 0, 73, 0}, - - {1, 0, 0, 24, 0}, - {1, -1, 0, 23, 0}, - {1, -23, 0, 1, 0}, - {1, -24, 0, 0, 0}, - {1, -25, 0, -1, 0}, - {2, -23, 0, 25, 0}, - {2, -24, 0, 24, 0}, - {2, -25, 0, 23, 0}, - - {-1, 0, 0, -24, 0}, - {-1, 1, 0, -23, 0}, - {-1, 23, 0, -1, 0}, - {-1, 24, 0, 0, 0}, - {-1, 25, 0, 1, 0}, - {-2, 23, 0, -25, 0}, - {-2, 24, 0, -24, 0}, - {-2, 25, 0, -23, 0}, - - {-1, 0, 0, -24, 0}, - {-1, -1, 0, -25, 0}, - {-1, -23, 0, -47, 0}, - {-1, -24, 0, -48, 0}, - {-1, -25, 0, -49, 0}, - - // minutes - {1, -1, -1, 22, 59}, - {1, -23, -1, 0, 59}, - {1, -24, -1, 0, -1}, - {1, -25, -1, -1, -1}, - {-1, 1, 1, -22, -59}, - {-1, 23, 1, 0, -59}, - {-1, 24, 1, 0, 1}, - {-1, 25, 1, 1, 1}, - }; - } - - @Test(dataProvider="normalizedDaysToHours") - public void test_normalizedDaysToHours(int inputDays, int inputHours, int inputMinutes, int expectedHours, int expectedMinutes) { - assertPeriod(Period.of(0, 0, inputDays, inputHours, inputMinutes, 0).normalizedDaysToHours(), 0, 0, 0, expectedHours, expectedMinutes, 0, 0); - } - - @Test(dataProvider="normalizedDaysToHours") - public void test_normalizedDaysToHours_yearsMonthsUnaffected(int inputDays, int inputHours, int inputMinutes, int expectedHours, int expectedMinutes) { - assertPeriod(Period.of(12, 6, inputDays, inputHours, inputMinutes, 0).normalizedDaysToHours(), 12, 6, 0, expectedHours, expectedMinutes, 0, 0); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_normalizedDaysToHours_min() { - Period base = Period.of(0, 0, -1_000, -10_000_000, 0, 0, 0); - base.normalizedDaysToHours(); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_normalizedDaysToHours_max() { - Period base = Period.of(0, 0, 1_000, 10_000_000, 0, 0, 0); - base.normalizedDaysToHours(); - } - - //----------------------------------------------------------------------- - // normalizedMonthsISO() - //----------------------------------------------------------------------- - @DataProvider(name="normalizedMonthsISO") - Object[][] data_normalizedMonthsISO() { - return new Object[][] { - {0, 0, 0, 0}, - {1, 0, 1, 0}, - {-1, 0, -1, 0}, - - {1, 1, 1, 1}, - {1, 2, 1, 2}, - {1, 11, 1, 11}, - {1, 12, 2, 0}, - {1, 13, 2, 1}, - {1, 23, 2, 11}, - {1, 24, 3, 0}, - {1, 25, 3, 1}, - - {1, -1, 0, 11}, - {1, -2, 0, 10}, - {1, -11, 0, 1}, - {1, -12, 0, 0}, - {1, -13, 0, -1}, - {1, -23, 0, -11}, - {1, -24, -1, 0}, - {1, -25, -1, -1}, - {1, -35, -1, -11}, - {1, -36, -2, 0}, - {1, -37, -2, -1}, - - {-1, 1, 0, -11}, - {-1, 11, 0, -1}, - {-1, 12, 0, 0}, - {-1, 13, 0, 1}, - {-1, 23, 0, 11}, - {-1, 24, 1, 0}, - {-1, 25, 1, 1}, - - {-1, -1, -1, -1}, - {-1, -11, -1, -11}, - {-1, -12, -2, 0}, - {-1, -13, -2, -1}, - }; - } - - @Test(dataProvider="normalizedMonthsISO") - public void test_normalizedMonthsISO(int inputYears, int inputMonths, int expectedYears, int expectedMonths) { - assertPeriod(Period.ofDate(inputYears, inputMonths, 0).normalizedMonthsISO(), expectedYears, expectedMonths, 0, 0, 0, 0, 0); - } - - @Test(dataProvider="normalizedMonthsISO") - public void test_normalizedMonthsISO_daysTimeUnaffected(int inputYears, int inputMonths, int expectedYears, int expectedMonths) { - assertPeriod(Period.of(inputYears, inputMonths, 5, 12, 30, 0, 0).normalizedMonthsISO(), expectedYears, expectedMonths, 5, 12, 30, 0, 0); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_normalizedMonthsISO_min() { - Period base = Period.ofDate(Integer.MIN_VALUE, -12, 0); - base.normalizedMonthsISO(); - } - - @Test(expectedExceptions=ArithmeticException.class) - public void test_normalizedMonthsISO_max() { - Period base = Period.ofDate(Integer.MAX_VALUE, 12, 0); - base.normalizedMonthsISO(); - } - - //----------------------------------------------------------------------- - // addTo() - //----------------------------------------------------------------------- - @DataProvider(name="addTo") - Object[][] data_addTo() { - return new Object[][] { - {pymd(0, 0, 0), date(2012, 6, 30), date(2012, 6, 30)}, - - {pymd(1, 0, 0), date(2012, 6, 10), date(2013, 6, 10)}, - {pymd(0, 1, 0), date(2012, 6, 10), date(2012, 7, 10)}, - {pymd(0, 0, 1), date(2012, 6, 10), date(2012, 6, 11)}, - - {pymd(-1, 0, 0), date(2012, 6, 10), date(2011, 6, 10)}, - {pymd(0, -1, 0), date(2012, 6, 10), date(2012, 5, 10)}, - {pymd(0, 0, -1), date(2012, 6, 10), date(2012, 6, 9)}, - - {pymd(1, 2, 3), date(2012, 6, 27), date(2013, 8, 30)}, - {pymd(1, 2, 3), date(2012, 6, 28), date(2013, 8, 31)}, - {pymd(1, 2, 3), date(2012, 6, 29), date(2013, 9, 1)}, - {pymd(1, 2, 3), date(2012, 6, 30), date(2013, 9, 2)}, - {pymd(1, 2, 3), date(2012, 7, 1), date(2013, 9, 4)}, - - {pymd(1, 0, 0), date(2011, 2, 28), date(2012, 2, 28)}, - {pymd(4, 0, 0), date(2011, 2, 28), date(2015, 2, 28)}, - {pymd(1, 0, 0), date(2012, 2, 29), date(2013, 2, 28)}, - {pymd(4, 0, 0), date(2012, 2, 29), date(2016, 2, 29)}, - - {pymd(1, 1, 0), date(2011, 1, 29), date(2012, 2, 29)}, - {pymd(1, 2, 0), date(2012, 2, 29), date(2013, 4, 29)}, - }; - } - - @Test(dataProvider="addTo") - public void test_addTo(Period period, LocalDate baseDate, LocalDate expected) { - assertEquals(period.addTo(baseDate), expected); - } - - @Test(dataProvider="addTo") - public void test_addTo_usingLocalDatePlus(Period period, LocalDate baseDate, LocalDate expected) { - assertEquals(baseDate.plus(period), expected); - } - - @Test(expectedExceptions=NullPointerException.class) - public void test_addTo_nullZero() { - Period.ZERO.addTo(null); - } - - @Test(expectedExceptions=NullPointerException.class) - public void test_addTo_nullNonZero() { - Period.of(2, DAYS).addTo(null); - } - - //----------------------------------------------------------------------- - // subtractFrom() - //----------------------------------------------------------------------- - @DataProvider(name="subtractFrom") - Object[][] data_subtractFrom() { - return new Object[][] { - {pymd(0, 0, 0), date(2012, 6, 30), date(2012, 6, 30)}, - - {pymd(1, 0, 0), date(2012, 6, 10), date(2011, 6, 10)}, - {pymd(0, 1, 0), date(2012, 6, 10), date(2012, 5, 10)}, - {pymd(0, 0, 1), date(2012, 6, 10), date(2012, 6, 9)}, - - {pymd(-1, 0, 0), date(2012, 6, 10), date(2013, 6, 10)}, - {pymd(0, -1, 0), date(2012, 6, 10), date(2012, 7, 10)}, - {pymd(0, 0, -1), date(2012, 6, 10), date(2012, 6, 11)}, - - {pymd(1, 2, 3), date(2012, 8, 30), date(2011, 6, 27)}, - {pymd(1, 2, 3), date(2012, 8, 31), date(2011, 6, 27)}, - {pymd(1, 2, 3), date(2012, 9, 1), date(2011, 6, 28)}, - {pymd(1, 2, 3), date(2012, 9, 2), date(2011, 6, 29)}, - {pymd(1, 2, 3), date(2012, 9, 3), date(2011, 6, 30)}, - {pymd(1, 2, 3), date(2012, 9, 4), date(2011, 7, 1)}, - - {pymd(1, 0, 0), date(2011, 2, 28), date(2010, 2, 28)}, - {pymd(4, 0, 0), date(2011, 2, 28), date(2007, 2, 28)}, - {pymd(1, 0, 0), date(2012, 2, 29), date(2011, 2, 28)}, - {pymd(4, 0, 0), date(2012, 2, 29), date(2008, 2, 29)}, - - {pymd(1, 1, 0), date(2013, 3, 29), date(2012, 2, 29)}, - {pymd(1, 2, 0), date(2012, 2, 29), date(2010, 12, 29)}, - }; - } - - @Test(dataProvider="subtractFrom") - public void test_subtractFrom(Period period, LocalDate baseDate, LocalDate expected) { - assertEquals(period.subtractFrom(baseDate), expected); - } - - @Test(dataProvider="subtractFrom") - public void test_subtractFrom_usingLocalDateMinus(Period period, LocalDate baseDate, LocalDate expected) { - assertEquals(baseDate.minus(period), expected); - } - - @Test(expectedExceptions=NullPointerException.class) - public void test_subtractFrom_nullZero() { - Period.ZERO.subtractFrom(null); - } - - @Test(expectedExceptions=NullPointerException.class) - public void test_subtractFrom_nullNonZero() { - Period.of(2, DAYS).subtractFrom(null); - } - - //----------------------------------------------------------------------- - // toDuration() - //----------------------------------------------------------------------- - public void test_toDuration() { - assertEquals(Period.ZERO.toDuration(), Duration.of(0, SECONDS)); - assertEquals(Period.of(0, 0, 0, 4, 5, 6, 7).toDuration(), Duration.ofSeconds((4 * 60 + 5) * 60L + 6, 7)); - } - - public void test_toDuration_calculation() { - assertEquals(Period.of(0, 0, 0, 2, 0, 0, 0).toDuration(), Duration.ofSeconds(2 * 3600)); - assertEquals(Period.of(0, 0, 0, 0, 2, 0, 0).toDuration(), Duration.of(120, SECONDS)); - assertEquals(Period.of(0, 0, 0, 0, 0, 2, 0).toDuration(), Duration.of(2, SECONDS)); - - assertEquals(Period.of(0, 0, 0, 0, 0, 3, 1000000000L - 1).toDuration(), Duration.ofSeconds(3, 999999999)); - assertEquals(Period.of(0, 0, 0, 0, 0, 3, 1000000000L).toDuration(), Duration.ofSeconds(4, 0)); - } - - public void test_toDuration_negatives() { - assertEquals(Period.of(0, 0, 0, 0, 0, 2, 1).toDuration(), Duration.ofSeconds(2, 1)); - assertEquals(Period.of(0, 0, 0, 0, 0, 2, -1).toDuration(), Duration.ofSeconds(1, 999999999)); - assertEquals(Period.of(0, 0, 0, 0, 0, -2, 1).toDuration(), Duration.ofSeconds(-2, 1)); - assertEquals(Period.of(0, 0, 0, 0, 0, -2, -1).toDuration(), Duration.ofSeconds(-3, 999999999)); - } - - @Test(expectedExceptions=DateTimeException.class) - public void test_toDuration_years() { - Period.of(1, 0, 0, 4, 5, 6, 7).toDuration(); - } - - @Test(expectedExceptions=DateTimeException.class) - public void test_toDuration_months() { - Period.of(0, 1, 0, 4, 5, 6, 7).toDuration(); - } - - @Test(expectedExceptions=DateTimeException.class) - public void test_toDuration_days() { - Duration test = Period.of(0, 0, 1, 4, 5, 6, 7).toDuration(); - assertEquals(test, Duration.ofSeconds(101106, 7L)); - } - - //----------------------------------------------------------------------- - // equals() / hashCode() - //----------------------------------------------------------------------- - public void test_equals() { - assertEquals(Period.of(1, 0, 0, 0, 0, 0).equals(Period.of(1, YEARS)), true); - assertEquals(Period.of(0, 1, 0, 0, 0, 0).equals(Period.of(1, MONTHS)), true); - assertEquals(Period.of(0, 0, 1, 0, 0, 0).equals(Period.of(1, DAYS)), true); - assertEquals(Period.of(0, 0, 0, 1, 0, 0).equals(Period.of(1, HOURS)), true); - assertEquals(Period.of(0, 0, 0, 0, 1, 0).equals(Period.of(1, MINUTES)), true); - assertEquals(Period.of(0, 0, 0, 0, 0, 1).equals(Period.of(1, SECONDS)), true); - assertEquals(Period.of(1, 2, 3, 0, 0, 0).equals(Period.ofDate(1, 2, 3)), true); - assertEquals(Period.of(0, 0, 0, 1, 2, 3).equals(Period.ofTime(1, 2, 3)), true); - assertEquals(Period.of(1, 2, 3, 4, 5, 6).equals(Period.of(1, 2, 3, 4, 5, 6)), true); - - assertEquals(Period.of(1, YEARS).equals(Period.of(1, YEARS)), true); - assertEquals(Period.of(1, YEARS).equals(Period.of(2, YEARS)), false); - - assertEquals(Period.of(1, MONTHS).equals(Period.of(1, MONTHS)), true); - assertEquals(Period.of(1, MONTHS).equals(Period.of(2, MONTHS)), false); - - assertEquals(Period.of(1, DAYS).equals(Period.of(1, DAYS)), true); - assertEquals(Period.of(1, DAYS).equals(Period.of(2, DAYS)), false); - - assertEquals(Period.of(1, HOURS).equals(Period.of(1, HOURS)), true); - assertEquals(Period.of(1, HOURS).equals(Period.of(2, HOURS)), false); - - assertEquals(Period.of(1, MINUTES).equals(Period.of(1, MINUTES)), true); - assertEquals(Period.of(1, MINUTES).equals(Period.of(2, MINUTES)), false); - - assertEquals(Period.of(1, SECONDS).equals(Period.of(1, SECONDS)), true); - assertEquals(Period.of(1, SECONDS).equals(Period.of(2, SECONDS)), false); - - assertEquals(Period.ofDate(1, 2, 3).equals(Period.ofDate(1, 2, 3)), true); - assertEquals(Period.ofDate(1, 2, 3).equals(Period.ofDate(0, 2, 3)), false); - assertEquals(Period.ofDate(1, 2, 3).equals(Period.ofDate(1, 0, 3)), false); - assertEquals(Period.ofDate(1, 2, 3).equals(Period.ofDate(1, 2, 0)), false); - - assertEquals(Period.ofTime(1, 2, 3).equals(Period.ofTime(1, 2, 3)), true); - assertEquals(Period.ofTime(1, 2, 3).equals(Period.ofTime(0, 2, 3)), false); - assertEquals(Period.ofTime(1, 2, 3).equals(Period.ofTime(1, 0, 3)), false); - assertEquals(Period.ofTime(1, 2, 3).equals(Period.ofTime(1, 2, 0)), false); - } - - public void test_equals_self() { - Period test = Period.of(1, 2, 3, 4, 5, 6); - assertEquals(test.equals(test), true); - } - - public void test_equals_null() { - Period test = Period.of(1, 2, 3, 4, 5, 6); - assertEquals(test.equals(null), false); - } - - public void test_equals_otherClass() { - Period test = Period.of(1, 2, 3, 4, 5, 6); - assertEquals(test.equals(""), false); - } - + // hashCode() //----------------------------------------------------------------------- public void test_hashCode() { - Period test5 = Period.of(5, DAYS); - Period test6 = Period.of(6, DAYS); - Period test5M = Period.of(5, MONTHS); - Period test5Y = Period.of(5, YEARS); + Period test5 = Period.ofDays(5); + Period test6 = Period.ofDays(6); + Period test5M = Period.ofMonths(5); + Period test5Y = Period.ofYears(5); assertEquals(test5.hashCode() == test5.hashCode(), true); assertEquals(test5.hashCode() == test6.hashCode(), false); assertEquals(test5.hashCode() == test5M.hashCode(), false); assertEquals(test5.hashCode() == test5Y.hashCode(), false); } - //----------------------------------------------------------------------- - // toString() - //----------------------------------------------------------------------- - @DataProvider(name="toStringAndParse") - Object[][] data_toString() { - return new Object[][] { - {Period.ZERO, "PT0S"}, - {Period.of(0, DAYS), "PT0S"}, - {Period.of(1, YEARS), "P1Y"}, - {Period.of(1, MONTHS), "P1M"}, - {Period.of(1, DAYS), "P1D"}, - {Period.of(1, HOURS), "PT1H"}, - {Period.of(1, MINUTES), "PT1M"}, - {Period.of(1, SECONDS), "PT1S"}, - {Period.of(12, SECONDS), "PT12S"}, - {Period.of(123, SECONDS), "PT2M3S"}, - {Period.of(1234, SECONDS), "PT20M34S"}, - {Period.of(-1, SECONDS), "PT-1S"}, - {Period.of(-12, SECONDS), "PT-12S"}, - {Period.of(-123, SECONDS), "PT-2M-3S"}, - {Period.of(-1234, SECONDS), "PT-20M-34S"}, - {Period.of(1, 2, 3, 4, 5, 6), "P1Y2M3DT4H5M6S"}, - {Period.of(1, 2, 3, 4, 5, 6, 700000000), "P1Y2M3DT4H5M6.7S"}, - {Period.of(0, 0, 0, 0, 0, 0, 100000000), "PT0.1S"}, - {Period.of(0, 0, 0, 0, 0, 0, -100000000), "PT-0.1S"}, - {Period.of(0, 0, 0, 0, 0, 1, -900000000), "PT0.1S"}, - {Period.of(0, 0, 0, 0, 0, -1, 900000000), "PT-0.1S"}, - {Period.of(0, 0, 0, 0, 0, 1, 100000000), "PT1.1S"}, - {Period.of(0, 0, 0, 0, 0, 1, -100000000), "PT0.9S"}, - {Period.of(0, 0, 0, 0, 0, -1, 100000000), "PT-0.9S"}, - {Period.of(0, 0, 0, 0, 0, -1, -100000000), "PT-1.1S"}, - {Period.of(0, 0, 0, 0, 0, 0, 10000000), "PT0.01S"}, - {Period.of(0, 0, 0, 0, 0, 0, -10000000), "PT-0.01S"}, - {Period.of(0, 0, 0, 0, 0, 0, 1000000), "PT0.001S"}, - {Period.of(0, 0, 0, 0, 0, 0, -1000000), "PT-0.001S"}, - {Period.of(0, 0, 0, 0, 0, 0, 1000), "PT0.000001S"}, - {Period.of(0, 0, 0, 0, 0, 0, -1000), "PT-0.000001S"}, - {Period.of(0, 0, 0, 0, 0, 0, 1), "PT0.000000001S"}, - {Period.of(0, 0, 0, 0, 0, 0, -1), "PT-0.000000001S"}, - }; - } - - @Test(groups="tck", dataProvider="toStringAndParse") - public void test_toString(Period input, String expected) { - assertEquals(input.toString(), expected); - } - - //----------------------------------------------------------------------- - private void assertPeriod(Period test, int y, int mo, int d, int h, int mn, int s, long n) { - assertEquals(test.getYears(), y, "years"); - assertEquals(test.getMonths(), mo, "months"); - assertEquals(test.getDays(), d, "days"); - assertEquals(test.getHours(), h, "hours"); - assertEquals(test.getMinutes(), mn, "mins"); - assertEquals(test.getSeconds(), s, "secs"); - assertEquals(test.getNanos(), n, "nanos"); - assertEquals(test.getTimeNanos(), (((h * 60L + mn) * 60 + s) * 1_000_000_000L + n), "total nanos"); - } - - private static Period pymd(int y, int m, int d) { - return Period.ofDate(y, m, d); - } - - private static LocalDate date(int y, int m, int d) { - return LocalDate.of(y, m, d); - } - } diff --git a/jdk/test/java/time/test/java/time/TestPeriodParser.java b/jdk/test/java/time/test/java/time/TestPeriodParser.java deleted file mode 100644 index 1d3a8abe373..00000000000 --- a/jdk/test/java/time/test/java/time/TestPeriodParser.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2012, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * - * Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of JSR-310 nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package test.java.time; - -import java.time.*; - -import static java.time.temporal.ChronoUnit.DAYS; -import static java.time.temporal.ChronoUnit.HOURS; -import static java.time.temporal.ChronoUnit.MINUTES; -import static java.time.temporal.ChronoUnit.MONTHS; -import static java.time.temporal.ChronoUnit.NANOS; -import static java.time.temporal.ChronoUnit.SECONDS; -import static java.time.temporal.ChronoUnit.YEARS; -import static org.testng.Assert.assertEquals; - -import java.time.format.DateTimeParseException; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -/** - * Test PeriodParser. - */ -@Test -public class TestPeriodParser { - - //----------------------------------------------------------------------- - // parse(String) - //----------------------------------------------------------------------- - @DataProvider(name="Parse") - Object[][] provider_factory_parse() { - return new Object[][] { - {"Pt0S", Period.ZERO}, - {"pT0S", Period.ZERO}, - {"PT0S", Period.ZERO}, - {"Pt0s", Period.ZERO}, - {"pt0s", Period.ZERO}, - {"P0Y0M0DT0H0M0.0S", Period.ZERO}, - - {"P1Y", Period.of(1, YEARS)}, - {"P100Y", Period.of(100, YEARS)}, - {"P-25Y", Period.of(-25, YEARS)}, - {"P" + Integer.MAX_VALUE + "Y", Period.of(Integer.MAX_VALUE, YEARS)}, - {"P" + Integer.MIN_VALUE + "Y", Period.of(Integer.MIN_VALUE, YEARS)}, - - {"P1M", Period.of(1, MONTHS)}, - {"P0M", Period.of(0, MONTHS)}, - {"P-1M", Period.of(-1, MONTHS)}, - {"P" + Integer.MAX_VALUE + "M", Period.of(Integer.MAX_VALUE, MONTHS)}, - {"P" + Integer.MIN_VALUE + "M", Period.of(Integer.MIN_VALUE, MONTHS)}, - - {"P1D", Period.of(1, DAYS)}, - {"P0D", Period.of(0, DAYS)}, - {"P-1D", Period.of(-1, DAYS)}, - {"P" + Integer.MAX_VALUE + "D", Period.of(Integer.MAX_VALUE, DAYS)}, - {"P" + Integer.MIN_VALUE + "D", Period.of(Integer.MIN_VALUE, DAYS)}, - - {"P2Y3M25D", Period.ofDate(2, 3, 25)}, - - {"PT1H", Period.of(1, HOURS)}, - {"PT-1H", Period.of(-1, HOURS)}, - {"PT24H", Period.of(24, HOURS)}, - {"PT-24H", Period.of(-24, HOURS)}, - {"PT" + Integer.MAX_VALUE / (3600 * 8) + "H", Period.of(Integer.MAX_VALUE / (3600 * 8), HOURS)}, - {"PT" + Integer.MIN_VALUE / (3600 * 8) + "H", Period.of(Integer.MIN_VALUE / (3600 * 8), HOURS)}, - - {"PT1M", Period.of(1, MINUTES)}, - {"PT-1M", Period.of(-1, MINUTES)}, - {"PT60M", Period.of(60, MINUTES)}, - {"PT-60M", Period.of(-60, MINUTES)}, - {"PT" + Integer.MAX_VALUE / (60 * 8) + "M", Period.of(Integer.MAX_VALUE / (60 * 8), MINUTES)}, - {"PT" + Integer.MIN_VALUE / (60 * 8) + "M", Period.of(Integer.MIN_VALUE / (60 * 8), MINUTES)}, - - {"PT1S", Period.of(1, SECONDS)}, - {"PT-1S", Period.of(-1, SECONDS)}, - {"PT60S", Period.of(60, SECONDS)}, - {"PT-60S", Period.of(-60, SECONDS)}, - {"PT" + Integer.MAX_VALUE + "S", Period.of(Integer.MAX_VALUE, SECONDS)}, - {"PT" + Integer.MIN_VALUE + "S", Period.of(Integer.MIN_VALUE, SECONDS)}, - - {"PT0.1S", Period.of( 0, 0, 0, 0, 0, 0, 100000000 ) }, - {"PT-0.1S", Period.of( 0, 0, 0, 0, 0, 0, -100000000 ) }, - {"PT1.1S", Period.of( 0, 0, 0, 0, 0, 1, 100000000 ) }, - {"PT-1.1S", Period.of( 0, 0, 0, 0, 0, -1, -100000000 ) }, - {"PT1.0001S", Period.of(1, SECONDS).plus( 100000, NANOS ) }, - {"PT1.0000001S", Period.of(1, SECONDS).plus( 100, NANOS ) }, - {"PT1.123456789S", Period.of( 0, 0, 0, 0, 0, 1, 123456789 ) }, - {"PT1.999999999S", Period.of( 0, 0, 0, 0, 0, 1, 999999999 ) }, - - }; - } - - @Test(dataProvider="Parse") - public void factory_parse(String text, Period expected) { - Period p = Period.parse(text); - assertEquals(p, expected); - } - - @Test(dataProvider="Parse") - public void factory_parse_comma(String text, Period expected) { - if (text.contains(".")) { - text = text.replace('.', ','); - Period p = Period.parse(text); - assertEquals(p, expected); - } - } - - @DataProvider(name="ParseFailures") - Object[][] provider_factory_parseFailures() { - return new Object[][] { - {"", 0}, - {"PTS", 2}, - {"AT0S", 0}, - {"PA0S", 1}, - {"PT0A", 3}, - - {"PT+S", 2}, - {"PT-S", 2}, - {"PT.S", 2}, - {"PTAS", 2}, - - {"PT+0S", 2}, - {"PT-0S", 2}, - {"PT+1S", 2}, - {"PT-.S", 2}, - - {"PT1ABC2S", 3}, - {"PT1.1ABC2S", 5}, - - {"PT123456789123456789123456789S", 2}, - {"PT0.1234567891S", 4}, - {"PT1.S", 2}, - {"PT.1S", 2}, - - {"PT2.-3S", 2}, - {"PT-2.-3S", 2}, - - {"P1Y1MT1DT1M1S", 7}, - {"P1Y1MT1HT1M1S", 8}, - {"P1YMD", 3}, - {"PT1ST1D", 4}, - {"P1Y2Y", 4}, - {"PT1M+3S", 4}, - - {"PT1S1", 4}, - {"PT1S.", 4}, - {"PT1SA", 4}, - {"PT1M1", 4}, - {"PT1M.", 4}, - {"PT1MA", 4}, - }; - } - - @Test(dataProvider="ParseFailures", expectedExceptions=DateTimeParseException.class) - public void factory_parseFailures(String text, int errPos) { - try { - Period.parse(text); - } catch (DateTimeParseException ex) { - assertEquals(ex.getParsedString(), text); - assertEquals(ex.getErrorIndex(), errPos); - throw ex; - } - } - - @Test(dataProvider="ParseFailures", expectedExceptions=DateTimeParseException.class) - public void factory_parseFailures_comma(String text, int errPos) { - text = text.replace('.', ','); - try { - Period.parse(text); - } catch (DateTimeParseException ex) { - assertEquals(ex.getParsedString(), text); - assertEquals(ex.getErrorIndex(), errPos); - throw ex; - } - } - - @Test(expectedExceptions=DateTimeParseException.class) - public void factory_parse_tooBig() { - String text = "PT" + Long.MAX_VALUE + "1S"; - Period.parse(text); - } - - @Test(expectedExceptions=DateTimeParseException.class) - public void factory_parse_tooBig_decimal() { - String text = "PT" + Long.MAX_VALUE + "1.1S"; - Period.parse(text); - } - - @Test(expectedExceptions=DateTimeParseException.class) - public void factory_parse_tooSmall() { - String text = "PT" + Long.MIN_VALUE + "1S"; - Period.parse(text); - } - - @Test(expectedExceptions=DateTimeParseException.class) - public void factory_parse_tooSmall_decimal() { - String text = "PT" + Long.MIN_VALUE + ".1S"; - Period.parse(text); - } - - @Test(expectedExceptions=NullPointerException.class) - public void factory_parse_null() { - Period.parse(null); - } - - @DataProvider(name="ParseSequenceFailures") - Object[][] provider_factory_parseSequenceFailures() { - return new Object[][] { - {"P0M0Y0DT0H0M0.0S"}, - {"P0M0D0YT0H0M0.0S"}, - {"P0S0D0YT0S0M0.0H"}, - {"PT0M0H0.0S"}, - {"PT0M0H"}, - {"PT0S0M"}, - {"PT0.0M2S"}, - }; - } - - @Test(dataProvider="ParseSequenceFailures", expectedExceptions=DateTimeParseException.class) - public void factory_parse_badSequence(String text) { - Period.parse(text); - } - -} diff --git a/jdk/test/java/time/test/java/time/temporal/TestYear.java b/jdk/test/java/time/test/java/time/TestYear.java similarity index 96% rename from jdk/test/java/time/test/java/time/temporal/TestYear.java rename to jdk/test/java/time/test/java/time/TestYear.java index 5880ac46820..71791ab5fa7 100644 --- a/jdk/test/java/time/test/java/time/temporal/TestYear.java +++ b/jdk/test/java/time/test/java/time/TestYear.java @@ -57,12 +57,11 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package test.java.time.temporal; +package test.java.time; -import java.time.temporal.Year; +import java.time.Year; import org.testng.annotations.Test; -import test.java.time.AbstractTest; /** * Test Year. diff --git a/jdk/test/java/time/test/java/time/temporal/TestYearMonth.java b/jdk/test/java/time/test/java/time/TestYearMonth.java similarity index 96% rename from jdk/test/java/time/test/java/time/temporal/TestYearMonth.java rename to jdk/test/java/time/test/java/time/TestYearMonth.java index ab0d7f4c8cb..f02ed96a5d7 100644 --- a/jdk/test/java/time/test/java/time/temporal/TestYearMonth.java +++ b/jdk/test/java/time/test/java/time/TestYearMonth.java @@ -57,12 +57,11 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package test.java.time.temporal; +package test.java.time; -import java.time.temporal.YearMonth; +import java.time.YearMonth; import org.testng.annotations.Test; -import test.java.time.AbstractTest; /** * Test YearMonth. diff --git a/jdk/test/java/time/test/java/time/TestZoneId.java b/jdk/test/java/time/test/java/time/TestZoneId.java index 5e9380391df..6aa373288a7 100644 --- a/jdk/test/java/time/test/java/time/TestZoneId.java +++ b/jdk/test/java/time/test/java/time/TestZoneId.java @@ -59,32 +59,28 @@ */ package test.java.time; -import java.time.*; - import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertSame; import static org.testng.Assert.assertTrue; -import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.SimpleTimeZone; -import java.util.TimeZone; - -import java.time.temporal.Queries; -import java.time.temporal.TemporalQuery; -import java.time.temporal.TemporalAccessor; -import java.time.temporal.TemporalField; +import java.time.DateTimeException; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; import java.time.format.TextStyle; import java.time.zone.ZoneOffsetTransition; import java.time.zone.ZoneRules; import java.time.zone.ZoneRulesException; +import java.util.List; +import java.util.Locale; +import java.util.SimpleTimeZone; +import java.util.TimeZone; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -95,8 +91,6 @@ import org.testng.annotations.Test; @Test public class TestZoneId extends AbstractTest { - private static final ZoneId ZONE_PARIS = ZoneId.of("Europe/Paris"); - public static final String LATEST_TZDB = "2010i"; private static final int OVERLAP = 2; private static final int GAP = 0; @@ -104,6 +98,7 @@ public class TestZoneId extends AbstractTest { // Basics //----------------------------------------------------------------------- public void test_immutable() { + // cannot use standard test as ZoneId is abstract Class cls = ZoneId.class; assertTrue(Modifier.isPublic(cls.getModifiers())); Field[] fields = cls.getDeclaredFields(); @@ -116,127 +111,27 @@ public class TestZoneId extends AbstractTest { } } - public void test_serialization_UTC() throws Exception { - ZoneId test = ZoneOffset.UTC; - assertSerializableAndSame(test); - } - - public void test_serialization_fixed() throws Exception { - ZoneId test = ZoneId.of("UTC+01:30"); - assertSerializable(test); - } - - public void test_serialization_Europe() throws Exception { - ZoneId test = ZoneId.of("Europe/London"); - assertSerializable(test); - } - - public void test_serialization_America() throws Exception { - ZoneId test = ZoneId.of("America/Chicago"); - assertSerializable(test); - } - //----------------------------------------------------------------------- // UTC //----------------------------------------------------------------------- public void test_constant_UTC() { ZoneId test = ZoneOffset.UTC; assertEquals(test.getId(), "Z"); - assertEquals(test.getText(TextStyle.FULL, Locale.UK), "Z"); + assertEquals(test.getDisplayName(TextStyle.FULL, Locale.UK), "Z"); assertEquals(test.getRules().isFixedOffset(), true); assertEquals(test.getRules().getOffset(Instant.ofEpochSecond(0L)), ZoneOffset.UTC); checkOffset(test.getRules(), createLDT(2008, 6, 30), ZoneOffset.UTC, 1); assertSame(test, ZoneId.of("UTC+00")); } - //----------------------------------------------------------------------- - // OLD_IDS_PRE_2005 - //----------------------------------------------------------------------- - public void test_constant_OLD_IDS_PRE_2005() { - Map ids = ZoneId.OLD_IDS_PRE_2005; - assertEquals(ids.get("EST"), "America/Indianapolis"); - assertEquals(ids.get("MST"), "America/Phoenix"); - assertEquals(ids.get("HST"), "Pacific/Honolulu"); - assertEquals(ids.get("ACT"), "Australia/Darwin"); - assertEquals(ids.get("AET"), "Australia/Sydney"); - assertEquals(ids.get("AGT"), "America/Argentina/Buenos_Aires"); - assertEquals(ids.get("ART"), "Africa/Cairo"); - assertEquals(ids.get("AST"), "America/Anchorage"); - assertEquals(ids.get("BET"), "America/Sao_Paulo"); - assertEquals(ids.get("BST"), "Asia/Dhaka"); - assertEquals(ids.get("CAT"), "Africa/Harare"); - assertEquals(ids.get("CNT"), "America/St_Johns"); - assertEquals(ids.get("CST"), "America/Chicago"); - assertEquals(ids.get("CTT"), "Asia/Shanghai"); - assertEquals(ids.get("EAT"), "Africa/Addis_Ababa"); - assertEquals(ids.get("ECT"), "Europe/Paris"); - assertEquals(ids.get("IET"), "America/Indiana/Indianapolis"); - assertEquals(ids.get("IST"), "Asia/Kolkata"); - assertEquals(ids.get("JST"), "Asia/Tokyo"); - assertEquals(ids.get("MIT"), "Pacific/Apia"); - assertEquals(ids.get("NET"), "Asia/Yerevan"); - assertEquals(ids.get("NST"), "Pacific/Auckland"); - assertEquals(ids.get("PLT"), "Asia/Karachi"); - assertEquals(ids.get("PNT"), "America/Phoenix"); - assertEquals(ids.get("PRT"), "America/Puerto_Rico"); - assertEquals(ids.get("PST"), "America/Los_Angeles"); - assertEquals(ids.get("SST"), "Pacific/Guadalcanal"); - assertEquals(ids.get("VST"), "Asia/Ho_Chi_Minh"); - } - - @Test(expectedExceptions=UnsupportedOperationException.class) - public void test_constant_OLD_IDS_PRE_2005_immutable() { - Map ids = ZoneId.OLD_IDS_PRE_2005; - ids.clear(); - } - - //----------------------------------------------------------------------- - // OLD_IDS_POST_2005 - //----------------------------------------------------------------------- - public void test_constant_OLD_IDS_POST_2005() { - Map ids = ZoneId.OLD_IDS_POST_2005; - assertEquals(ids.get("EST"), "-05:00"); - assertEquals(ids.get("MST"), "-07:00"); - assertEquals(ids.get("HST"), "-10:00"); - assertEquals(ids.get("ACT"), "Australia/Darwin"); - assertEquals(ids.get("AET"), "Australia/Sydney"); - assertEquals(ids.get("AGT"), "America/Argentina/Buenos_Aires"); - assertEquals(ids.get("ART"), "Africa/Cairo"); - assertEquals(ids.get("AST"), "America/Anchorage"); - assertEquals(ids.get("BET"), "America/Sao_Paulo"); - assertEquals(ids.get("BST"), "Asia/Dhaka"); - assertEquals(ids.get("CAT"), "Africa/Harare"); - assertEquals(ids.get("CNT"), "America/St_Johns"); - assertEquals(ids.get("CST"), "America/Chicago"); - assertEquals(ids.get("CTT"), "Asia/Shanghai"); - assertEquals(ids.get("EAT"), "Africa/Addis_Ababa"); - assertEquals(ids.get("ECT"), "Europe/Paris"); - assertEquals(ids.get("IET"), "America/Indiana/Indianapolis"); - assertEquals(ids.get("IST"), "Asia/Kolkata"); - assertEquals(ids.get("JST"), "Asia/Tokyo"); - assertEquals(ids.get("MIT"), "Pacific/Apia"); - assertEquals(ids.get("NET"), "Asia/Yerevan"); - assertEquals(ids.get("NST"), "Pacific/Auckland"); - assertEquals(ids.get("PLT"), "Asia/Karachi"); - assertEquals(ids.get("PNT"), "America/Phoenix"); - assertEquals(ids.get("PRT"), "America/Puerto_Rico"); - assertEquals(ids.get("PST"), "America/Los_Angeles"); - assertEquals(ids.get("SST"), "Pacific/Guadalcanal"); - assertEquals(ids.get("VST"), "Asia/Ho_Chi_Minh"); - } - - @Test(expectedExceptions=UnsupportedOperationException.class) - public void test_constant_OLD_IDS_POST_2005_immutable() { - Map ids = ZoneId.OLD_IDS_POST_2005; - ids.clear(); - } - //----------------------------------------------------------------------- // system default //----------------------------------------------------------------------- public void test_systemDefault() { ZoneId test = ZoneId.systemDefault(); - assertEquals(test.getId(), TimeZone.getDefault().getID()); + assertEquals(test.getId(), TimeZone.getDefault() + .getID() + .replaceAll("GMT|UTC|UT", "Z")); } @Test(expectedExceptions = DateTimeException.class) @@ -261,72 +156,10 @@ public class TestZoneId extends AbstractTest { } } - //----------------------------------------------------------------------- - // mapped factory - //----------------------------------------------------------------------- - public void test_of_string_Map() { - Map map = new HashMap(); - map.put("LONDON", "Europe/London"); - map.put("PARIS", "Europe/Paris"); - ZoneId test = ZoneId.of("LONDON", map); - assertEquals(test.getId(), "Europe/London"); - } - - public void test_of_string_Map_lookThrough() { - Map map = new HashMap(); - map.put("LONDON", "Europe/London"); - map.put("PARIS", "Europe/Paris"); - ZoneId test = ZoneId.of("Europe/Madrid", map); - assertEquals(test.getId(), "Europe/Madrid"); - } - - public void test_of_string_Map_emptyMap() { - Map map = new HashMap(); - ZoneId test = ZoneId.of("Europe/Madrid", map); - assertEquals(test.getId(), "Europe/Madrid"); - } - - @Test(expectedExceptions=DateTimeException.class) - public void test_of_string_Map_badFormat() { - Map map = new HashMap(); - ZoneId.of("Not kknown", map); - } - - @Test(expectedExceptions=ZoneRulesException.class) - public void test_of_string_Map_unknown() { - Map map = new HashMap(); - ZoneId.of("Unknown", map); - } - - //----------------------------------------------------------------------- - // regular factory - //----------------------------------------------------------------------- - @DataProvider(name="String_UTC") - Object[][] data_of_string_UTC() { - return new Object[][] { - {""}, {"Z"}, - {"+00"},{"+0000"},{"+00:00"},{"+000000"},{"+00:00:00"}, - {"-00"},{"-0000"},{"-00:00"},{"-000000"},{"-00:00:00"}, - }; - } - - @Test(dataProvider="String_UTC") - public void test_of_string_UTC(String id) { - ZoneId test = ZoneId.of("UTC" + id); - assertSame(test, ZoneOffset.UTC); - } - - @Test(dataProvider="String_UTC") - public void test_of_string_GMT(String id) { - ZoneId test = ZoneId.of("GMT" + id); - assertSame(test, ZoneOffset.UTC); - } - //----------------------------------------------------------------------- @DataProvider(name="String_Fixed") Object[][] data_of_string_Fixed() { return new Object[][] { - {"Z", "Z"}, {"+0", "Z"}, {"+5", "+05:00"}, {"+01", "+01:00"}, @@ -346,7 +179,7 @@ public class TestZoneId extends AbstractTest { public void test_of_string_offset(String input, String id) { ZoneId test = ZoneId.of(input); assertEquals(test.getId(), id); - assertEquals(test.getText(TextStyle.FULL, Locale.UK), id); + assertEquals(test.getDisplayName(TextStyle.FULL, Locale.UK), id); assertEquals(test.getRules().isFixedOffset(), true); ZoneOffset offset = ZoneOffset.of(id); assertEquals(test.getRules().getOffset(Instant.ofEpochSecond(0L)), offset); @@ -357,7 +190,7 @@ public class TestZoneId extends AbstractTest { public void test_of_string_FixedUTC(String input, String id) { ZoneId test = ZoneId.of("UTC" + input); assertEquals(test.getId(), id); - assertEquals(test.getText(TextStyle.FULL, Locale.UK), id); + assertEquals(test.getDisplayName(TextStyle.FULL, Locale.UK), id); assertEquals(test.getRules().isFixedOffset(), true); ZoneOffset offset = ZoneOffset.of(id); assertEquals(test.getRules().getOffset(Instant.ofEpochSecond(0L)), offset); @@ -368,143 +201,13 @@ public class TestZoneId extends AbstractTest { public void test_of_string_FixedGMT(String input, String id) { ZoneId test = ZoneId.of("GMT" + input); assertEquals(test.getId(), id); - assertEquals(test.getText(TextStyle.FULL, Locale.UK), id); + assertEquals(test.getDisplayName(TextStyle.FULL, Locale.UK), id); assertEquals(test.getRules().isFixedOffset(), true); ZoneOffset offset = ZoneOffset.of(id); assertEquals(test.getRules().getOffset(Instant.ofEpochSecond(0L)), offset); checkOffset(test.getRules(), createLDT(2008, 6, 30), offset, 1); } - //----------------------------------------------------------------------- - @DataProvider(name="String_UTC_Invalid") - Object[][] data_of_string_UTC_invalid() { - return new Object[][] { - {"A"}, {"B"}, {"C"}, {"D"}, {"E"}, {"F"}, {"G"}, {"H"}, {"I"}, {"J"}, {"K"}, {"L"}, {"M"}, - {"N"}, {"O"}, {"P"}, {"Q"}, {"R"}, {"S"}, {"T"}, {"U"}, {"V"}, {"W"}, {"X"}, {"Y"}, - {"+0:00"}, {"+00:0"}, {"+0:0"}, - {"+000"}, {"+00000"}, - {"+0:00:00"}, {"+00:0:00"}, {"+00:00:0"}, {"+0:0:0"}, {"+0:0:00"}, {"+00:0:0"}, {"+0:00:0"}, - {"+01_00"}, {"+01;00"}, {"+01@00"}, {"+01:AA"}, - {"+19"}, {"+19:00"}, {"+18:01"}, {"+18:00:01"}, {"+1801"}, {"+180001"}, - {"-0:00"}, {"-00:0"}, {"-0:0"}, - {"-000"}, {"-00000"}, - {"-0:00:00"}, {"-00:0:00"}, {"-00:00:0"}, {"-0:0:0"}, {"-0:0:00"}, {"-00:0:0"}, {"-0:00:0"}, - {"-19"}, {"-19:00"}, {"-18:01"}, {"-18:00:01"}, {"-1801"}, {"-180001"}, - {"-01_00"}, {"-01;00"}, {"-01@00"}, {"-01:AA"}, - {"@01:00"}, - }; - } - - @Test(dataProvider="String_UTC_Invalid", expectedExceptions=DateTimeException.class) - public void test_of_string_UTC_invalid(String id) { - ZoneId.of("UTC" + id); - } - - @Test(dataProvider="String_UTC_Invalid", expectedExceptions=DateTimeException.class) - public void test_of_string_GMT_invalid(String id) { - ZoneId.of("GMT" + id); - } - - //----------------------------------------------------------------------- - @DataProvider(name="String_Invalid") - Object[][] data_of_string_invalid() { - // \u00ef is a random unicode character - return new Object[][] { - {""}, {":"}, {"#"}, - {"\u00ef"}, {"`"}, {"!"}, {"\""}, {"\u00ef"}, {"$"}, {"^"}, {"&"}, {"*"}, {"("}, {")"}, {"="}, - {"\\"}, {"|"}, {","}, {"<"}, {">"}, {"?"}, {";"}, {"'"}, {"["}, {"]"}, {"{"}, {"}"}, - {"\u00ef:A"}, {"`:A"}, {"!:A"}, {"\":A"}, {"\u00ef:A"}, {"$:A"}, {"^:A"}, {"&:A"}, {"*:A"}, {"(:A"}, {"):A"}, {"=:A"}, {"+:A"}, - {"\\:A"}, {"|:A"}, {",:A"}, {"<:A"}, {">:A"}, {"?:A"}, {";:A"}, {"::A"}, {"':A"}, {"@:A"}, {"~:A"}, {"[:A"}, {"]:A"}, {"{:A"}, {"}:A"}, - {"A:B#\u00ef"}, {"A:B#`"}, {"A:B#!"}, {"A:B#\""}, {"A:B#\u00ef"}, {"A:B#$"}, {"A:B#^"}, {"A:B#&"}, {"A:B#*"}, - {"A:B#("}, {"A:B#)"}, {"A:B#="}, {"A:B#+"}, - {"A:B#\\"}, {"A:B#|"}, {"A:B#,"}, {"A:B#<"}, {"A:B#>"}, {"A:B#?"}, {"A:B#;"}, {"A:B#:"}, - {"A:B#'"}, {"A:B#@"}, {"A:B#~"}, {"A:B#["}, {"A:B#]"}, {"A:B#{"}, {"A:B#}"}, - }; - } - - @Test(dataProvider="String_Invalid", expectedExceptions=DateTimeException.class) - public void test_of_string_invalid(String id) { - ZoneId.of(id); - } - - //----------------------------------------------------------------------- - public void test_of_string_GMT0() { - ZoneId test = ZoneId.of("GMT0"); - assertEquals(test.getId(), "Z"); - assertEquals(test.getRules().isFixedOffset(), true); - } - - //----------------------------------------------------------------------- - public void test_of_string_London() { - ZoneId test = ZoneId.of("Europe/London"); - assertEquals(test.getId(), "Europe/London"); - assertEquals(test.getRules().isFixedOffset(), false); - } - - //----------------------------------------------------------------------- - @Test(expectedExceptions=NullPointerException.class) - public void test_of_string_null() { - ZoneId.of((String) null); - } - - @Test(expectedExceptions=ZoneRulesException.class) - public void test_of_string_unknown_simple() { - ZoneId.of("Unknown"); - } - - //------------------------------------------------------------------------- - // TODO: test by deserialization -// public void test_ofUnchecked_string_invalidNotChecked() { -// ZoneRegion test = ZoneRegion.ofLenient("Unknown"); -// assertEquals(test.getId(), "Unknown"); -// } -// -// public void test_ofUnchecked_string_invalidNotChecked_unusualCharacters() { -// ZoneRegion test = ZoneRegion.ofLenient("QWERTYUIOPASDFGHJKLZXCVBNM~/._+-"); -// assertEquals(test.getId(), "QWERTYUIOPASDFGHJKLZXCVBNM~/._+-"); -// } - - //----------------------------------------------------------------------- - // from(TemporalAccessor) - //----------------------------------------------------------------------- - public void test_factory_from_DateTimeAccessor_zoneId() { - TemporalAccessor mock = new TemporalAccessor() { - @Override - public boolean isSupported(TemporalField field) { - return false; - } - - @Override - public long getLong(TemporalField field) { - throw new DateTimeException("Mock"); - } - - @Override - public R query(TemporalQuery query) { - if (query == Queries.zoneId()) { - return (R) ZONE_PARIS; - } - return TemporalAccessor.super.query(query); - } - }; - assertEquals(ZoneId.from(mock), ZONE_PARIS); - } - - public void test_factory_from_DateTimeAccessor_offset() { - ZoneOffset offset = ZoneOffset.ofHours(1); - assertEquals(ZoneId.from(offset), offset); - } - - @Test(expectedExceptions=DateTimeException.class) - public void test_factory_from_DateTimeAccessor_invalid_noDerive() { - ZoneId.from(LocalTime.of(12, 30)); - } - - @Test(expectedExceptions=NullPointerException.class) - public void test_factory_from_DateTimeAccessor_null() { - ZoneId.from((TemporalAccessor) null); - } - //----------------------------------------------------------------------- // Europe/London //----------------------------------------------------------------------- @@ -998,53 +701,6 @@ public class TestZoneId extends AbstractTest { assertEquals(test.getRules().isFixedOffset(), true); } - //----------------------------------------------------------------------- - // equals() / hashCode() - //----------------------------------------------------------------------- - public void test_equals() { - ZoneId test1 = ZoneId.of("Europe/London"); - ZoneId test2 = ZoneId.of("Europe/Paris"); - ZoneId test2b = ZoneId.of("Europe/Paris"); - assertEquals(test1.equals(test2), false); - assertEquals(test2.equals(test1), false); - - assertEquals(test1.equals(test1), true); - assertEquals(test2.equals(test2), true); - assertEquals(test2.equals(test2b), true); - - assertEquals(test1.hashCode() == test1.hashCode(), true); - assertEquals(test2.hashCode() == test2.hashCode(), true); - assertEquals(test2.hashCode() == test2b.hashCode(), true); - } - - public void test_equals_null() { - assertEquals(ZoneId.of("Europe/London").equals(null), false); - } - - public void test_equals_notTimeZone() { - assertEquals(ZoneId.of("Europe/London").equals("Europe/London"), false); - } - - //----------------------------------------------------------------------- - // toString() - //----------------------------------------------------------------------- - @DataProvider(name="ToString") - Object[][] data_toString() { - return new Object[][] { - {"Europe/London", "Europe/London"}, - {"Europe/Paris", "Europe/Paris"}, - {"Europe/Berlin", "Europe/Berlin"}, - {"UTC", "Z"}, - {"UTC+01:00", "+01:00"}, - }; - } - - @Test(dataProvider="ToString") - public void test_toString(String id, String expected) { - ZoneId test = ZoneId.of(id); - assertEquals(test.toString(), expected); - } - //----------------------------------------------------------------------- //----------------------------------------------------------------------- //----------------------------------------------------------------------- diff --git a/jdk/test/java/time/test/java/time/chrono/TestExampleCode.java b/jdk/test/java/time/test/java/time/chrono/TestExampleCode.java new file mode 100644 index 00000000000..bfdec45c198 --- /dev/null +++ b/jdk/test/java/time/test/java/time/chrono/TestExampleCode.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2012, 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 + * 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. + */ + +/* + * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of JSR-310 nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package test.java.time.chrono; + +import java.time.LocalTime; +import java.time.chrono.HijrahDate; +import java.time.chrono.ThaiBuddhistDate; +import java.time.chrono.ChronoLocalDateTime; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.Chronology; +import java.time.temporal.ChronoField; +import java.time.temporal.ChronoUnit; +import java.util.Set; + +import org.testng.annotations.Test; + +/** + * Test case verify that the example code in the package-info.java compiles + * and runs. + */ +public class TestExampleCode { + + @Test + public void test_chronoPackageExample() { + // Print the Thai Buddhist date + ChronoLocalDate now1 = Chronology.of("ThaiBuddhist").dateNow(); + int day = now1.get(ChronoField.DAY_OF_MONTH); + int dow = now1.get(ChronoField.DAY_OF_WEEK); + int month = now1.get(ChronoField.MONTH_OF_YEAR); + int year = now1.get(ChronoField.YEAR); + System.out.printf(" Today is %s %s %d-%s-%d%n", now1.getChronology().getId(), + dow, day, month, year); + + // Enumerate the list of available calendars and print today for each + Set chronos = Chronology.getAvailableChronologies(); + for (Chronology chrono : chronos) { + ChronoLocalDate date = chrono.dateNow(); + System.out.printf(" %20s: %s%n", chrono.getId(), date.toString()); + } + + // Print today's date and the last day of the year for the Thai Buddhist Calendar. + ChronoLocalDate first = now1 + .with(ChronoField.DAY_OF_MONTH, 1) + .with(ChronoField.MONTH_OF_YEAR, 1); + ChronoLocalDate last = first + .plus(1, ChronoUnit.YEARS) + .minus(1, ChronoUnit.DAYS); + System.out.printf(" %s: 1st of year: %s; end of year: %s%n", last.getChronology().getId(), + first, last); + } + + @Test + public void test_calendarPackageExample() { + + // Enumerate the list of available calendars and print today for each + Set chronos = Chronology.getAvailableChronologies(); + for (Chronology chrono : chronos) { + ChronoLocalDate date = chrono.dateNow(); + System.out.printf(" %20s: %s%n", chrono.getId(), date.toString()); + } + + // Print the Thai Buddhist date + ThaiBuddhistDate now1 = ThaiBuddhistDate.now(); + int day = now1.get(ChronoField.DAY_OF_MONTH); + int dow = now1.get(ChronoField.DAY_OF_WEEK); + int month = now1.get(ChronoField.MONTH_OF_YEAR); + int year = now1.get(ChronoField.YEAR); + System.out.printf(" Today is %s %s %d-%s-%d%n", now1.getChronology().getId(), + dow, day, month, year); + + // Print today's date and the last day of the year for the Thai Buddhist Calendar. + ThaiBuddhistDate first = now1 + .with(ChronoField.DAY_OF_MONTH, 1) + .with(ChronoField.MONTH_OF_YEAR, 1); + ThaiBuddhistDate last = first + .plus(1, ChronoUnit.YEARS) + .minus(1, ChronoUnit.DAYS); + System.out.printf(" %s: 1st of year: %s; end of year: %s%n", last.getChronology().getId(), + first, last); + } + + @Test + public void test_library() { + HijrahDate date = HijrahDate.now(); + HijrahDate next = next(date); + ChronoLocalDateTime noonTomorrow = tomorrowNoon(date); + System.out.printf(" now: %s, noon tomorrow: %s%n", date, noonTomorrow); + } + + /** + * Simple function based on a date, returning a ChronoDate of the same type. + * @param a parameterized ChronoLocalDate + * @param date a specific date extending ChronoLocalDate + * @return a new date in the same chronology. + */ + private > D next(D date) { + return date.plus(1, ChronoUnit.DAYS); + } + + /** + * Simple function based on a date, returning a ChronoLocalDateTime of the + * same chronology. + * @param a parameterized ChronoLocalDate + * @param date a specific date extending ChronoLocalDate + * @return a [@code ChronoLocalDateTime} using the change chronology. + */ + private > ChronoLocalDateTime tomorrowNoon(D date) { + return date.plus(1, ChronoUnit.DAYS).atTime(LocalTime.of(12, 0)); + } +} diff --git a/jdk/test/java/time/test/java/time/temporal/TestISOChronoImpl.java b/jdk/test/java/time/test/java/time/chrono/TestIsoChronoImpl.java similarity index 94% rename from jdk/test/java/time/test/java/time/temporal/TestISOChronoImpl.java rename to jdk/test/java/time/test/java/time/chrono/TestIsoChronoImpl.java index 9fc01553202..1e66574a4a8 100644 --- a/jdk/test/java/time/test/java/time/temporal/TestISOChronoImpl.java +++ b/jdk/test/java/time/test/java/time/chrono/TestIsoChronoImpl.java @@ -54,7 +54,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package test.java.time.temporal; +package test.java.time.chrono; import static java.time.temporal.ChronoField.DAY_OF_MONTH; import static java.time.temporal.ChronoField.MONTH_OF_YEAR; @@ -69,10 +69,10 @@ import java.util.TimeZone; import java.time.DayOfWeek; import java.time.LocalDate; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.IsoChronology; import java.time.temporal.ChronoUnit; -import java.time.temporal.ISOChrono; import java.time.temporal.WeekFields; -import java.time.temporal.ChronoLocalDate; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -81,7 +81,7 @@ import org.testng.annotations.Test; * Test. */ @Test -public class TestISOChronoImpl { +public class TestIsoChronoImpl { @DataProvider(name = "RangeVersusCalendar") Object[][] provider_rangeVersusCalendar() { @@ -95,10 +95,10 @@ public class TestISOChronoImpl { // Verify ISO Calendar matches java.util.Calendar for range //----------------------------------------------------------------------- @Test(groups = {"implementation"}, dataProvider = "RangeVersusCalendar") - public void test_ISOChrono_vsCalendar(LocalDate isoStartDate, LocalDate isoEndDate) { + public void test_IsoChrono_vsCalendar(LocalDate isoStartDate, LocalDate isoEndDate) { GregorianCalendar cal = new GregorianCalendar(); assertEquals(cal.getCalendarType(), "gregory", "Unexpected calendar type"); - ChronoLocalDate isoDate = ISOChrono.INSTANCE.date(isoStartDate); + LocalDate isoDate = IsoChronology.INSTANCE.date(isoStartDate); cal.setTimeZone(TimeZone.getTimeZone("GMT+00")); cal.set(Calendar.YEAR, isoDate.get(YEAR)); @@ -120,10 +120,10 @@ public class TestISOChronoImpl { // DayOfWeek, WeekOfMonth, WeekOfYear for range //----------------------------------------------------------------------- @Test(groups = {"implementation"}, dataProvider = "RangeVersusCalendar") - public void test_DayOfWeek_ISOChrono_vsCalendar(LocalDate isoStartDate, LocalDate isoEndDate) { + public void test_DayOfWeek_IsoChronology_vsCalendar(LocalDate isoStartDate, LocalDate isoEndDate) { GregorianCalendar cal = new GregorianCalendar(); assertEquals(cal.getCalendarType(), "gregory", "Unexpected calendar type"); - ChronoLocalDate isoDate = ISOChrono.INSTANCE.date(isoStartDate); + LocalDate isoDate = IsoChronology.INSTANCE.date(isoStartDate); for (DayOfWeek firstDayOfWeek : DayOfWeek.values()) { for (int minDays = 1; minDays <= 7; minDays++) { diff --git a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatters.java b/jdk/test/java/time/test/java/time/chrono/TestServiceLoader.java similarity index 74% rename from jdk/test/java/time/test/java/time/format/TestDateTimeFormatters.java rename to jdk/test/java/time/test/java/time/chrono/TestServiceLoader.java index 5e7ab3ef7cb..99304a74cd5 100644 --- a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatters.java +++ b/jdk/test/java/time/test/java/time/chrono/TestServiceLoader.java @@ -1,5 +1,4 @@ /* - * Copyright (c) 2012, 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 @@ -27,7 +26,7 @@ * However, the following notice accompanied the original version of this * file: * - * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos + * Copyright (c) 2011-2012, Stephen Colebourne & Michael Nascimento Santos * * All rights reserved. * @@ -57,37 +56,31 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package test.java.time.format; +package test.java.time.chrono; -import java.time.format.*; +import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertTrue; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Modifier; -import java.util.Collections; - -import org.testng.annotations.BeforeMethod; +import java.util.HashMap; +import java.util.Map; +import java.util.ServiceLoader; +import java.time.chrono.Chronology; import org.testng.annotations.Test; /** - * Test DateTimeFormatters. + * Tests that a custom Chronology is available via the ServiceLoader. + * The CopticChronology is configured via META-INF/services/java.time.chrono.Chronology. */ @Test -public class TestDateTimeFormatters { +public class TestServiceLoader { - @BeforeMethod - public void setUp() { - } - - @Test(groups={"implementation"}) - @SuppressWarnings("rawtypes") - public void test_constructor() throws Exception { - for (Constructor constructor : DateTimeFormatters.class.getDeclaredConstructors()) { - assertTrue(Modifier.isPrivate(constructor.getModifiers())); - //constructor.setAccessible(true); - //constructor.newInstance(Collections.nCopies(constructor.getParameterTypes().length, null).toArray()); + @Test(groups="implementation") + public void test_copticServiceLoader() { + Map chronos = new HashMap<>(); + ServiceLoader loader = ServiceLoader.load(Chronology.class, null); + for (Chronology chrono : loader) { + chronos.put(chrono.getId(), chrono); } + assertNotNull(chronos.get("Coptic"), "CopticChronology not found"); } } diff --git a/jdk/test/java/time/test/java/time/format/TestCharLiteralParser.java b/jdk/test/java/time/test/java/time/format/TestCharLiteralParser.java index c2fe6290a5d..ff73696c3e5 100644 --- a/jdk/test/java/time/test/java/time/format/TestCharLiteralParser.java +++ b/jdk/test/java/time/test/java/time/format/TestCharLiteralParser.java @@ -59,11 +59,15 @@ */ package test.java.time.format; +import static java.time.temporal.ChronoField.YEAR; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; -import java.time.format.DateTimeBuilder; import java.text.ParsePosition; +import java.time.temporal.Queries; +import java.time.temporal.TemporalAccessor; + import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -101,13 +105,14 @@ public class TestCharLiteralParser extends AbstractTestPrinterParser { String text, int pos, int expectedPos) { setCaseSensitive(caseSensitive); ParsePosition ppos = new ParsePosition(pos); - DateTimeBuilder result = - getFormatter(c).parseToBuilder(text, ppos); + TemporalAccessor parsed = getFormatter(c).parseUnresolved(text, ppos); if (ppos.getErrorIndex() != -1) { assertEquals(ppos.getIndex(), expectedPos); } else { assertEquals(ppos.getIndex(), expectedPos); - assertEquals(result.getCalendricalList().size(), 0); + assertEquals(parsed.isSupported(YEAR), false); + assertEquals(parsed.query(Queries.chronology()), null); + assertEquals(parsed.query(Queries.zoneId()), null); } } @@ -123,9 +128,9 @@ public class TestCharLiteralParser extends AbstractTestPrinterParser { @Test(dataProvider="error") public void test_parse_error(char c, String text, int pos, Class expected) { try { - DateTimeBuilder result = - getFormatter(c).parseToBuilder(text, new ParsePosition(pos)); - assertTrue(false); + ParsePosition ppos = new ParsePosition(pos); + getFormatter(c).parseUnresolved(text, ppos); + fail(); } catch (RuntimeException ex) { assertTrue(expected.isInstance(ex)); } diff --git a/jdk/test/java/time/test/java/time/format/TestCharLiteralPrinter.java b/jdk/test/java/time/test/java/time/format/TestCharLiteralPrinter.java index f2c1f7d65b1..780c04db8cb 100644 --- a/jdk/test/java/time/test/java/time/format/TestCharLiteralPrinter.java +++ b/jdk/test/java/time/test/java/time/format/TestCharLiteralPrinter.java @@ -74,18 +74,18 @@ public class TestCharLiteralPrinter extends AbstractTestPrinterParser { //----------------------------------------------------------------------- public void test_print_emptyCalendrical() throws Exception { buf.append("EXISTING"); - getFormatter('a').printTo(EMPTY_DTA, buf); + getFormatter('a').formatTo(EMPTY_DTA, buf); assertEquals(buf.toString(), "EXISTINGa"); } public void test_print_dateTime() throws Exception { buf.append("EXISTING"); - getFormatter('a').printTo(dta, buf); + getFormatter('a').formatTo(dta, buf); assertEquals(buf.toString(), "EXISTINGa"); } public void test_print_emptyAppendable() throws Exception { - getFormatter('a').printTo(dta, buf); + getFormatter('a').formatTo(dta, buf); assertEquals(buf.toString(), "a"); } diff --git a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java new file mode 100644 index 00000000000..ec0d16e8fd4 --- /dev/null +++ b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java @@ -0,0 +1,864 @@ +/* + * Copyright (c) 2012, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of JSR-310 nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package test.java.time.format; + +import static java.time.temporal.ChronoField.DAY_OF_MONTH; +import static java.time.temporal.ChronoField.DAY_OF_WEEK; +import static java.time.temporal.ChronoField.MINUTE_OF_HOUR; +import static java.time.temporal.ChronoField.MONTH_OF_YEAR; +import static java.time.temporal.ChronoField.YEAR; +import static org.testng.Assert.assertEquals; + +import java.text.ParsePosition; +import java.time.LocalDate; +import java.time.YearMonth; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.SignStyle; +import java.time.format.TextStyle; +import java.time.temporal.Temporal; +import java.time.temporal.TemporalAccessor; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * Test DateTimeFormatterBuilder. + */ +@Test +public class TestDateTimeFormatterBuilder { + + private DateTimeFormatterBuilder builder; + + @BeforeMethod + public void setUp() { + builder = new DateTimeFormatterBuilder(); + } + + //----------------------------------------------------------------------- + @Test + public void test_toFormatter_empty() throws Exception { + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), ""); + } + + //----------------------------------------------------------------------- + @Test + public void test_parseCaseSensitive() throws Exception { + builder.parseCaseSensitive(); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "ParseCaseSensitive(true)"); + } + + @Test + public void test_parseCaseInsensitive() throws Exception { + builder.parseCaseInsensitive(); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "ParseCaseSensitive(false)"); + } + + //----------------------------------------------------------------------- + @Test + public void test_parseStrict() throws Exception { + builder.parseStrict(); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "ParseStrict(true)"); + } + + @Test + public void test_parseLenient() throws Exception { + builder.parseLenient(); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "ParseStrict(false)"); + } + + //----------------------------------------------------------------------- + @Test + public void test_appendValue_1arg() throws Exception { + builder.appendValue(DAY_OF_MONTH); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(DayOfMonth)"); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_appendValue_1arg_null() throws Exception { + builder.appendValue(null); + } + + //----------------------------------------------------------------------- + @Test + public void test_appendValue_2arg() throws Exception { + builder.appendValue(DAY_OF_MONTH, 3); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(DayOfMonth,3)"); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_appendValue_2arg_null() throws Exception { + builder.appendValue(null, 3); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_appendValue_2arg_widthTooSmall() throws Exception { + builder.appendValue(DAY_OF_MONTH, 0); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_appendValue_2arg_widthTooBig() throws Exception { + builder.appendValue(DAY_OF_MONTH, 20); + } + + //----------------------------------------------------------------------- + @Test + public void test_appendValue_3arg() throws Exception { + builder.appendValue(DAY_OF_MONTH, 2, 3, SignStyle.NORMAL); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(DayOfMonth,2,3,NORMAL)"); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_appendValue_3arg_nullField() throws Exception { + builder.appendValue(null, 2, 3, SignStyle.NORMAL); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_appendValue_3arg_minWidthTooSmall() throws Exception { + builder.appendValue(DAY_OF_MONTH, 0, 2, SignStyle.NORMAL); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_appendValue_3arg_minWidthTooBig() throws Exception { + builder.appendValue(DAY_OF_MONTH, 20, 2, SignStyle.NORMAL); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_appendValue_3arg_maxWidthTooSmall() throws Exception { + builder.appendValue(DAY_OF_MONTH, 2, 0, SignStyle.NORMAL); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_appendValue_3arg_maxWidthTooBig() throws Exception { + builder.appendValue(DAY_OF_MONTH, 2, 20, SignStyle.NORMAL); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_appendValue_3arg_maxWidthMinWidth() throws Exception { + builder.appendValue(DAY_OF_MONTH, 4, 2, SignStyle.NORMAL); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_appendValue_3arg_nullSignStyle() throws Exception { + builder.appendValue(DAY_OF_MONTH, 2, 3, null); + } + + //----------------------------------------------------------------------- + @Test + public void test_appendValue_subsequent2_parse3() throws Exception { + builder.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL).appendValue(DAY_OF_MONTH, 2); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(MonthOfYear,1,2,NORMAL)Value(DayOfMonth,2)"); + TemporalAccessor parsed = f.parseUnresolved("123", new ParsePosition(0)); + assertEquals(parsed.getLong(MONTH_OF_YEAR), 1L); + assertEquals(parsed.getLong(DAY_OF_MONTH), 23L); + } + + @Test + public void test_appendValue_subsequent2_parse4() throws Exception { + builder.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL).appendValue(DAY_OF_MONTH, 2); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(MonthOfYear,1,2,NORMAL)Value(DayOfMonth,2)"); + TemporalAccessor parsed = f.parseUnresolved("0123", new ParsePosition(0)); + assertEquals(parsed.getLong(MONTH_OF_YEAR), 1L); + assertEquals(parsed.getLong(DAY_OF_MONTH), 23L); + } + + @Test + public void test_appendValue_subsequent2_parse5() throws Exception { + builder.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL).appendValue(DAY_OF_MONTH, 2).appendLiteral('4'); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(MonthOfYear,1,2,NORMAL)Value(DayOfMonth,2)'4'"); + TemporalAccessor parsed = f.parseUnresolved("01234", new ParsePosition(0)); + assertEquals(parsed.getLong(MONTH_OF_YEAR), 1L); + assertEquals(parsed.getLong(DAY_OF_MONTH), 23L); + } + + @Test + public void test_appendValue_subsequent3_parse6() throws Exception { + builder + .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD) + .appendValue(MONTH_OF_YEAR, 2) + .appendValue(DAY_OF_MONTH, 2); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(Year,4,10,EXCEEDS_PAD)Value(MonthOfYear,2)Value(DayOfMonth,2)"); + TemporalAccessor parsed = f.parseUnresolved("20090630", new ParsePosition(0)); + assertEquals(parsed.getLong(YEAR), 2009L); + assertEquals(parsed.getLong(MONTH_OF_YEAR), 6L); + assertEquals(parsed.getLong(DAY_OF_MONTH), 30L); + } + + //----------------------------------------------------------------------- + @Test(expectedExceptions=NullPointerException.class) + public void test_appendValueReduced_null() throws Exception { + builder.appendValueReduced(null, 2, 2000); + } + + @Test + public void test_appendValueReduced() throws Exception { + builder.appendValueReduced(YEAR, 2, 2000); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "ReducedValue(Year,2,2000)"); + TemporalAccessor parsed = f.parseUnresolved("12", new ParsePosition(0)); + assertEquals(parsed.getLong(YEAR), 2012L); + } + + @Test + public void test_appendValueReduced_subsequent_parse() throws Exception { + builder.appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL).appendValueReduced(YEAR, 2, 2000); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(MonthOfYear,1,2,NORMAL)ReducedValue(Year,2,2000)"); + TemporalAccessor parsed = f.parseUnresolved("123", new ParsePosition(0)); + assertEquals(parsed.getLong(MONTH_OF_YEAR), 1L); + assertEquals(parsed.getLong(YEAR), 2023L); + } + + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + @Test + public void test_appendFraction_4arg() throws Exception { + builder.appendFraction(MINUTE_OF_HOUR, 1, 9, false); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Fraction(MinuteOfHour,1,9)"); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_appendFraction_4arg_nullRule() throws Exception { + builder.appendFraction(null, 1, 9, false); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_appendFraction_4arg_invalidRuleNotFixedSet() throws Exception { + builder.appendFraction(DAY_OF_MONTH, 1, 9, false); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_appendFraction_4arg_minTooSmall() throws Exception { + builder.appendFraction(MINUTE_OF_HOUR, -1, 9, false); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_appendFraction_4arg_minTooBig() throws Exception { + builder.appendFraction(MINUTE_OF_HOUR, 10, 9, false); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_appendFraction_4arg_maxTooSmall() throws Exception { + builder.appendFraction(MINUTE_OF_HOUR, 0, -1, false); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_appendFraction_4arg_maxTooBig() throws Exception { + builder.appendFraction(MINUTE_OF_HOUR, 1, 10, false); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_appendFraction_4arg_maxWidthMinWidth() throws Exception { + builder.appendFraction(MINUTE_OF_HOUR, 9, 3, false); + } + + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + @Test + public void test_appendText_1arg() throws Exception { + builder.appendText(MONTH_OF_YEAR); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Text(MonthOfYear)"); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_appendText_1arg_null() throws Exception { + builder.appendText(null); + } + + //----------------------------------------------------------------------- + @Test + public void test_appendText_2arg() throws Exception { + builder.appendText(MONTH_OF_YEAR, TextStyle.SHORT); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Text(MonthOfYear,SHORT)"); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_appendText_2arg_nullRule() throws Exception { + builder.appendText(null, TextStyle.SHORT); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_appendText_2arg_nullStyle() throws Exception { + builder.appendText(MONTH_OF_YEAR, (TextStyle) null); + } + + //----------------------------------------------------------------------- + @Test + public void test_appendTextMap() throws Exception { + Map map = new HashMap<>(); + map.put(1L, "JNY"); + map.put(2L, "FBY"); + map.put(3L, "MCH"); + map.put(4L, "APL"); + map.put(5L, "MAY"); + map.put(6L, "JUN"); + map.put(7L, "JLY"); + map.put(8L, "AGT"); + map.put(9L, "SPT"); + map.put(10L, "OBR"); + map.put(11L, "NVR"); + map.put(12L, "DBR"); + builder.appendText(MONTH_OF_YEAR, map); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Text(MonthOfYear)"); // TODO: toString should be different? + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_appendTextMap_nullRule() throws Exception { + builder.appendText(null, new HashMap()); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_appendTextMap_nullStyle() throws Exception { + builder.appendText(MONTH_OF_YEAR, (Map) null); + } + + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + @Test + public void test_appendOffsetId() throws Exception { + builder.appendOffsetId(); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Offset(+HH:MM:ss,'Z')"); + } + + @DataProvider(name="offsetPatterns") + Object[][] data_offsetPatterns() { + return new Object[][] { + {"+HH", 2, 0, 0, "+02"}, + {"+HH", -2, 0, 0, "-02"}, + {"+HH", 2, 30, 0, "+02"}, + {"+HH", 2, 0, 45, "+02"}, + {"+HH", 2, 30, 45, "+02"}, + + {"+HHMM", 2, 0, 0, "+0200"}, + {"+HHMM", -2, 0, 0, "-0200"}, + {"+HHMM", 2, 30, 0, "+0230"}, + {"+HHMM", 2, 0, 45, "+0200"}, + {"+HHMM", 2, 30, 45, "+0230"}, + + {"+HH:MM", 2, 0, 0, "+02:00"}, + {"+HH:MM", -2, 0, 0, "-02:00"}, + {"+HH:MM", 2, 30, 0, "+02:30"}, + {"+HH:MM", 2, 0, 45, "+02:00"}, + {"+HH:MM", 2, 30, 45, "+02:30"}, + + {"+HHMMss", 2, 0, 0, "+0200"}, + {"+HHMMss", -2, 0, 0, "-0200"}, + {"+HHMMss", 2, 30, 0, "+0230"}, + {"+HHMMss", 2, 0, 45, "+020045"}, + {"+HHMMss", 2, 30, 45, "+023045"}, + + {"+HH:MM:ss", 2, 0, 0, "+02:00"}, + {"+HH:MM:ss", -2, 0, 0, "-02:00"}, + {"+HH:MM:ss", 2, 30, 0, "+02:30"}, + {"+HH:MM:ss", 2, 0, 45, "+02:00:45"}, + {"+HH:MM:ss", 2, 30, 45, "+02:30:45"}, + + {"+HHMMSS", 2, 0, 0, "+020000"}, + {"+HHMMSS", -2, 0, 0, "-020000"}, + {"+HHMMSS", 2, 30, 0, "+023000"}, + {"+HHMMSS", 2, 0, 45, "+020045"}, + {"+HHMMSS", 2, 30, 45, "+023045"}, + + {"+HH:MM:SS", 2, 0, 0, "+02:00:00"}, + {"+HH:MM:SS", -2, 0, 0, "-02:00:00"}, + {"+HH:MM:SS", 2, 30, 0, "+02:30:00"}, + {"+HH:MM:SS", 2, 0, 45, "+02:00:45"}, + {"+HH:MM:SS", 2, 30, 45, "+02:30:45"}, + }; + } + + @Test(dataProvider="offsetPatterns") + public void test_appendOffset_format(String pattern, int h, int m, int s, String expected) throws Exception { + builder.appendOffset(pattern, "Z"); + DateTimeFormatter f = builder.toFormatter(); + ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(h, m, s); + assertEquals(f.format(offset), expected); + } + + @Test(dataProvider="offsetPatterns") + public void test_appendOffset_parse(String pattern, int h, int m, int s, String expected) throws Exception { + builder.appendOffset(pattern, "Z"); + DateTimeFormatter f = builder.toFormatter(); + ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(h, m, s); + ZoneOffset parsed = f.parse(expected, ZoneOffset::from); + assertEquals(f.format(parsed), expected); + } + + @DataProvider(name="badOffsetPatterns") + Object[][] data_badOffsetPatterns() { + return new Object[][] { + {"HH"}, + {"HHMM"}, + {"HH:MM"}, + {"HHMMss"}, + {"HH:MM:ss"}, + {"HHMMSS"}, + {"HH:MM:SS"}, + {"+H"}, + {"+HMM"}, + {"+HHM"}, + {"+A"}, + }; + } + + @Test(dataProvider="badOffsetPatterns", expectedExceptions=IllegalArgumentException.class) + public void test_appendOffset_badPattern(String pattern) throws Exception { + builder.appendOffset(pattern, "Z"); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_appendOffset_3arg_nullText() throws Exception { + builder.appendOffset("+HH:MM", null); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_appendOffset_3arg_nullPattern() throws Exception { + builder.appendOffset(null, "Z"); + } + + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + @Test + public void test_appendZoneId() throws Exception { + builder.appendZoneId(); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "ZoneId()"); + } + + @Test + public void test_appendZoneText_1arg() throws Exception { + builder.appendZoneText(TextStyle.FULL); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "ZoneText(FULL)"); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_appendZoneText_1arg_nullText() throws Exception { + builder.appendZoneText(null); + } + + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + @Test + public void test_padNext_1arg() { + builder.appendValue(MONTH_OF_YEAR).appendLiteral(':').padNext(2).appendValue(DAY_OF_MONTH); + assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2: 1"); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_padNext_1arg_invalidWidth() throws Exception { + builder.padNext(0); + } + + //----------------------------------------------------------------------- + @Test + public void test_padNext_2arg_dash() throws Exception { + builder.appendValue(MONTH_OF_YEAR).appendLiteral(':').padNext(2, '-').appendValue(DAY_OF_MONTH); + assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2:-1"); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_padNext_2arg_invalidWidth() throws Exception { + builder.padNext(0, '-'); + } + + //----------------------------------------------------------------------- + @Test + public void test_padOptional() throws Exception { + builder.appendValue(MONTH_OF_YEAR).appendLiteral(':') + .padNext(5).optionalStart().appendValue(DAY_OF_MONTH).optionalEnd() + .appendLiteral(':').appendValue(YEAR); + assertEquals(builder.toFormatter().format(LocalDate.of(2013, 2, 1)), "2: 1:2013"); + assertEquals(builder.toFormatter().format(YearMonth.of(2013, 2)), "2: :2013"); + } + + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + @Test + public void test_optionalStart_noEnd() throws Exception { + builder.appendValue(MONTH_OF_YEAR).optionalStart().appendValue(DAY_OF_MONTH).appendValue(DAY_OF_WEEK); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(MonthOfYear)[Value(DayOfMonth)Value(DayOfWeek)]"); + } + + @Test + public void test_optionalStart2_noEnd() throws Exception { + builder.appendValue(MONTH_OF_YEAR).optionalStart().appendValue(DAY_OF_MONTH).optionalStart().appendValue(DAY_OF_WEEK); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(MonthOfYear)[Value(DayOfMonth)[Value(DayOfWeek)]]"); + } + + @Test + public void test_optionalStart_doubleStart() throws Exception { + builder.appendValue(MONTH_OF_YEAR).optionalStart().optionalStart().appendValue(DAY_OF_MONTH); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(MonthOfYear)[[Value(DayOfMonth)]]"); + } + + //----------------------------------------------------------------------- + @Test + public void test_optionalEnd() throws Exception { + builder.appendValue(MONTH_OF_YEAR).optionalStart().appendValue(DAY_OF_MONTH).optionalEnd().appendValue(DAY_OF_WEEK); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(MonthOfYear)[Value(DayOfMonth)]Value(DayOfWeek)"); + } + + @Test + public void test_optionalEnd2() throws Exception { + builder.appendValue(MONTH_OF_YEAR).optionalStart().appendValue(DAY_OF_MONTH) + .optionalStart().appendValue(DAY_OF_WEEK).optionalEnd().appendValue(DAY_OF_MONTH).optionalEnd(); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(MonthOfYear)[Value(DayOfMonth)[Value(DayOfWeek)]Value(DayOfMonth)]"); + } + + @Test + public void test_optionalEnd_doubleStartSingleEnd() throws Exception { + builder.appendValue(MONTH_OF_YEAR).optionalStart().optionalStart().appendValue(DAY_OF_MONTH).optionalEnd(); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(MonthOfYear)[[Value(DayOfMonth)]]"); + } + + @Test + public void test_optionalEnd_doubleStartDoubleEnd() throws Exception { + builder.appendValue(MONTH_OF_YEAR).optionalStart().optionalStart().appendValue(DAY_OF_MONTH).optionalEnd().optionalEnd(); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(MonthOfYear)[[Value(DayOfMonth)]]"); + } + + @Test + public void test_optionalStartEnd_immediateStartEnd() throws Exception { + builder.appendValue(MONTH_OF_YEAR).optionalStart().optionalEnd().appendValue(DAY_OF_MONTH); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), "Value(MonthOfYear)Value(DayOfMonth)"); + } + + @Test(expectedExceptions=IllegalStateException.class) + public void test_optionalEnd_noStart() throws Exception { + builder.optionalEnd(); + } + + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + //----------------------------------------------------------------------- + @DataProvider(name="validPatterns") + Object[][] dataValid() { + return new Object[][] { + {"'a'", "'a'"}, + {"''", "''"}, + {"'!'", "'!'"}, + {"!", "'!'"}, + + {"'hello_people,][)('", "'hello_people,][)('"}, + {"'hi'", "'hi'"}, + {"'yyyy'", "'yyyy'"}, + {"''''", "''"}, + {"'o''clock'", "'o''clock'"}, + + {"G", "Text(Era,SHORT)"}, + {"GG", "Text(Era,SHORT)"}, + {"GGG", "Text(Era,SHORT)"}, + {"GGGG", "Text(Era)"}, + {"GGGGG", "Text(Era,NARROW)"}, + + {"y", "Value(Year)"}, + {"yy", "ReducedValue(Year,2,2000)"}, + {"yyy", "Value(Year,3,19,NORMAL)"}, + {"yyyy", "Value(Year,4,19,EXCEEDS_PAD)"}, + {"yyyyy", "Value(Year,5,19,EXCEEDS_PAD)"}, + +// {"Y", "Value(WeekBasedYear)"}, +// {"YY", "ReducedValue(WeekBasedYear,2,2000)"}, +// {"YYY", "Value(WeekBasedYear,3,19,NORMAL)"}, +// {"YYYY", "Value(WeekBasedYear,4,19,EXCEEDS_PAD)"}, +// {"YYYYY", "Value(WeekBasedYear,5,19,EXCEEDS_PAD)"}, + + {"M", "Value(MonthOfYear)"}, + {"MM", "Value(MonthOfYear,2)"}, + {"MMM", "Text(MonthOfYear,SHORT)"}, + {"MMMM", "Text(MonthOfYear)"}, + {"MMMMM", "Text(MonthOfYear,NARROW)"}, + + {"D", "Value(DayOfYear)"}, + {"DD", "Value(DayOfYear,2)"}, + {"DDD", "Value(DayOfYear,3)"}, + + {"d", "Value(DayOfMonth)"}, + {"dd", "Value(DayOfMonth,2)"}, + {"ddd", "Value(DayOfMonth,3)"}, + + {"F", "Value(AlignedWeekOfMonth)"}, + {"FF", "Value(AlignedWeekOfMonth,2)"}, + {"FFF", "Value(AlignedWeekOfMonth,3)"}, + + {"Q", "Value(QuarterOfYear)"}, + {"QQ", "Value(QuarterOfYear,2)"}, + {"QQQ", "Text(QuarterOfYear,SHORT)"}, + {"QQQQ", "Text(QuarterOfYear)"}, + {"QQQQQ", "Text(QuarterOfYear,NARROW)"}, + + {"E", "Value(DayOfWeek)"}, + {"EE", "Value(DayOfWeek,2)"}, + {"EEE", "Text(DayOfWeek,SHORT)"}, + {"EEEE", "Text(DayOfWeek)"}, + {"EEEEE", "Text(DayOfWeek,NARROW)"}, + + {"a", "Text(AmPmOfDay,SHORT)"}, + {"aa", "Text(AmPmOfDay,SHORT)"}, + {"aaa", "Text(AmPmOfDay,SHORT)"}, + {"aaaa", "Text(AmPmOfDay)"}, + {"aaaaa", "Text(AmPmOfDay,NARROW)"}, + + {"H", "Value(HourOfDay)"}, + {"HH", "Value(HourOfDay,2)"}, + {"HHH", "Value(HourOfDay,3)"}, + + {"K", "Value(HourOfAmPm)"}, + {"KK", "Value(HourOfAmPm,2)"}, + {"KKK", "Value(HourOfAmPm,3)"}, + + {"k", "Value(ClockHourOfDay)"}, + {"kk", "Value(ClockHourOfDay,2)"}, + {"kkk", "Value(ClockHourOfDay,3)"}, + + {"h", "Value(ClockHourOfAmPm)"}, + {"hh", "Value(ClockHourOfAmPm,2)"}, + {"hhh", "Value(ClockHourOfAmPm,3)"}, + + {"m", "Value(MinuteOfHour)"}, + {"mm", "Value(MinuteOfHour,2)"}, + {"mmm", "Value(MinuteOfHour,3)"}, + + {"s", "Value(SecondOfMinute)"}, + {"ss", "Value(SecondOfMinute,2)"}, + {"sss", "Value(SecondOfMinute,3)"}, + + {"S", "Fraction(NanoOfSecond,1,1)"}, + {"SS", "Fraction(NanoOfSecond,2,2)"}, + {"SSS", "Fraction(NanoOfSecond,3,3)"}, + {"SSSSSSSSS", "Fraction(NanoOfSecond,9,9)"}, + + {"A", "Value(MilliOfDay)"}, + {"AA", "Value(MilliOfDay,2)"}, + {"AAA", "Value(MilliOfDay,3)"}, + + {"n", "Value(NanoOfSecond)"}, + {"nn", "Value(NanoOfSecond,2)"}, + {"nnn", "Value(NanoOfSecond,3)"}, + + {"N", "Value(NanoOfDay)"}, + {"NN", "Value(NanoOfDay,2)"}, + {"NNN", "Value(NanoOfDay,3)"}, + + {"z", "ZoneText(SHORT)"}, + {"zz", "ZoneText(SHORT)"}, + {"zzz", "ZoneText(SHORT)"}, + {"zzzz", "ZoneText(FULL)"}, + + {"VV", "ZoneId()"}, + + {"Z", "Offset(+HHMM,'+0000')"}, // SimpleDateFormat + {"ZZ", "Offset(+HHMM,'+0000')"}, // SimpleDateFormat + {"ZZZ", "Offset(+HHMM,'+0000')"}, // SimpleDateFormat + + {"X", "Offset(+HHmm,'Z')"}, // LDML/almost SimpleDateFormat + {"XX", "Offset(+HHMM,'Z')"}, // LDML/SimpleDateFormat + {"XXX", "Offset(+HH:MM,'Z')"}, // LDML/SimpleDateFormat + {"XXXX", "Offset(+HHMMss,'Z')"}, // LDML + {"XXXXX", "Offset(+HH:MM:ss,'Z')"}, // LDML + + {"x", "Offset(+HHmm,'+00')"}, // LDML + {"xx", "Offset(+HHMM,'+0000')"}, // LDML + {"xxx", "Offset(+HH:MM,'+00:00')"}, // LDML + {"xxxx", "Offset(+HHMMss,'+0000')"}, // LDML + {"xxxxx", "Offset(+HH:MM:ss,'+00:00')"}, // LDML + + {"ppH", "Pad(Value(HourOfDay),2)"}, + {"pppDD", "Pad(Value(DayOfYear,2),3)"}, + + {"yyyy[-MM[-dd", "Value(Year,4,19,EXCEEDS_PAD)['-'Value(MonthOfYear,2)['-'Value(DayOfMonth,2)]]"}, + {"yyyy[-MM[-dd]]", "Value(Year,4,19,EXCEEDS_PAD)['-'Value(MonthOfYear,2)['-'Value(DayOfMonth,2)]]"}, + {"yyyy[-MM[]-dd]", "Value(Year,4,19,EXCEEDS_PAD)['-'Value(MonthOfYear,2)'-'Value(DayOfMonth,2)]"}, + + {"yyyy-MM-dd'T'HH:mm:ss.SSS", "Value(Year,4,19,EXCEEDS_PAD)'-'Value(MonthOfYear,2)'-'Value(DayOfMonth,2)" + + "'T'Value(HourOfDay,2)':'Value(MinuteOfHour,2)':'Value(SecondOfMinute,2)'.'Fraction(NanoOfSecond,3,3)"}, + + {"e", "WeekBased(e1)"}, + {"w", "WeekBased(w1)"}, + {"W", "WeekBased(W1)"}, + {"WW", "WeekBased(W2)"}, + + }; + } + + @Test(dataProvider="validPatterns", groups={"implementation"}) + public void test_appendPattern_valid(String input, String expected) throws Exception { + builder.appendPattern(input); + DateTimeFormatter f = builder.toFormatter(); + assertEquals(f.toString(), expected); + } + + //----------------------------------------------------------------------- + @DataProvider(name="invalidPatterns") + Object[][] dataInvalid() { + return new Object[][] { + {"'"}, + {"'hello"}, + {"'hel''lo"}, + {"'hello''"}, + {"{"}, + {"}"}, + {"{}"}, + {"]"}, + {"yyyy]"}, + {"yyyy]MM"}, + {"yyyy[MM]]"}, + + {"MMMMMM"}, + {"QQQQQQ"}, + {"EEEEEE"}, + {"aaaaaa"}, + {"ZZZZ"}, + {"XXXXXX"}, + {"zzzzz"}, + {"V"}, + {"VVV"}, + {"VVVV"}, + {"VVVVV"}, + + {"RO"}, + + {"p"}, + {"pp"}, + {"p:"}, + + {"f"}, + {"ff"}, + {"f:"}, + {"fy"}, + {"fa"}, + {"fM"}, + + {"ww"}, + {"ee"}, + {"WWW"}, + }; + } + + @Test(dataProvider="invalidPatterns", expectedExceptions=IllegalArgumentException.class) + public void test_appendPattern_invalid(String input) throws Exception { + try { + builder.appendPattern(input); + } catch (IllegalArgumentException ex) { + throw ex; + } + } + + //----------------------------------------------------------------------- + @DataProvider(name="patternPrint") + Object[][] data_patternPrint() { + return new Object[][] { + {"Q", date(2012, 2, 10), "1"}, + {"QQ", date(2012, 2, 10), "01"}, +// {"QQQ", date(2012, 2, 10), "Q1"}, // TODO: data for quarters? +// {"QQQQ", date(2012, 2, 10), "Q1"}, +// {"QQQQQ", date(2012, 2, 10), "Q1"}, + }; + } + + @Test(dataProvider="patternPrint") + public void test_appendPattern_patternPrint(String input, Temporal temporal, String expected) throws Exception { + DateTimeFormatter f = builder.appendPattern(input).toFormatter(Locale.UK); + String test = f.format(temporal); + assertEquals(test, expected); + } + + private static Temporal date(int y, int m, int d) { + return LocalDate.of(y, m, d); + } + +} diff --git a/jdk/test/java/time/test/java/time/format/TestDateTimePrintException.java b/jdk/test/java/time/test/java/time/format/TestDateTimePrintException.java deleted file mode 100644 index 3a737f33ed2..00000000000 --- a/jdk/test/java/time/test/java/time/format/TestDateTimePrintException.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2012, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * - * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of JSR-310 nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package test.java.time.format; - -import java.time.format.*; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertSame; - -import java.io.IOException; - -import org.testng.annotations.Test; - -/** - * Test DateTimePrintException. - */ -@Test -public class TestDateTimePrintException { - - @Test(groups={"implementation"}) - public void test_constructor_StringThrowable_notIOException_same() throws Exception { - IllegalArgumentException iaex = new IllegalArgumentException("INNER"); - DateTimePrintException ex = new DateTimePrintException("TEST", iaex); - assertEquals(ex.getMessage(), "TEST"); - assertSame(ex.getCause(), iaex); - ex.rethrowIOException(); // no effect - } - - @Test(expectedExceptions=IOException.class, groups={"implementation"}) - public void test_constructor_StringThrowable_IOException_same() throws Exception { - IOException ioex = new IOException("INNER"); - DateTimePrintException ex = new DateTimePrintException("TEST", ioex); - assertEquals(ex.getMessage(), "TEST"); - assertSame(ex.getCause(), ioex); - ex.rethrowIOException(); // rethrows - } - -} diff --git a/jdk/test/java/time/test/java/time/format/TestDateTimeTextProvider.java b/jdk/test/java/time/test/java/time/format/TestDateTimeTextProvider.java index ab8cec39822..1d34a2d05f1 100644 --- a/jdk/test/java/time/test/java/time/format/TestDateTimeTextProvider.java +++ b/jdk/test/java/time/test/java/time/format/TestDateTimeTextProvider.java @@ -180,7 +180,7 @@ public class TestDateTimeTextProvider extends AbstractTestPrinterParser { @Test(dataProvider = "Text") public void test_getText(TemporalField field, Number value, TextStyle style, Locale locale, String expected) { DateTimeFormatter fmt = getFormatter(field, style).withLocale(locale); - assertEquals(fmt.print(ZonedDateTime.now().with(field, value.longValue())), expected); + assertEquals(fmt.format(ZonedDateTime.now().with(field, value.longValue())), expected); } } diff --git a/jdk/test/java/time/test/java/time/format/TestFractionPrinterParser.java b/jdk/test/java/time/test/java/time/format/TestFractionPrinterParser.java index 4be3b6cce46..2925c9f7988 100644 --- a/jdk/test/java/time/test/java/time/format/TestFractionPrinterParser.java +++ b/jdk/test/java/time/test/java/time/format/TestFractionPrinterParser.java @@ -59,8 +59,6 @@ */ package test.java.time.format; -import java.time.format.*; - import static java.time.temporal.ChronoField.NANO_OF_SECOND; import static java.time.temporal.ChronoField.SECOND_OF_MINUTE; import static org.testng.Assert.assertEquals; @@ -69,13 +67,13 @@ import static org.testng.Assert.fail; import java.text.ParsePosition; import java.time.DateTimeException; import java.time.LocalTime; -import java.time.format.DateTimeBuilder; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; -import test.java.time.temporal.MockFieldValue; - import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import test.java.time.temporal.MockFieldValue; /** * Test FractionPrinterParser. @@ -92,12 +90,12 @@ public class TestFractionPrinterParser extends AbstractTestPrinterParser { //----------------------------------------------------------------------- @Test(expectedExceptions=DateTimeException.class) public void test_print_emptyCalendrical() throws Exception { - getFormatter(NANO_OF_SECOND, 0, 9, true).printTo(EMPTY_DTA, buf); + getFormatter(NANO_OF_SECOND, 0, 9, true).formatTo(EMPTY_DTA, buf); } public void test_print_append() throws Exception { buf.append("EXISTING"); - getFormatter(NANO_OF_SECOND, 0, 9, true).printTo(LocalTime.of(12, 30, 40, 3), buf); + getFormatter(NANO_OF_SECOND, 0, 9, true).formatTo(LocalTime.of(12, 30, 40, 3), buf); assertEquals(buf.toString(), "EXISTING.000000003"); } @@ -180,7 +178,7 @@ public class TestFractionPrinterParser extends AbstractTestPrinterParser { @Test(dataProvider="Nanos") public void test_print_nanos(int minWidth, int maxWidth, int value, String result) throws Exception { - getFormatter(NANO_OF_SECOND, minWidth, maxWidth, true).printTo(new MockFieldValue(NANO_OF_SECOND, value), buf); + getFormatter(NANO_OF_SECOND, minWidth, maxWidth, true).formatTo(new MockFieldValue(NANO_OF_SECOND, value), buf); if (result == null) { fail("Expected exception"); } @@ -189,7 +187,7 @@ public class TestFractionPrinterParser extends AbstractTestPrinterParser { @Test(dataProvider="Nanos") public void test_print_nanos_noDecimalPoint(int minWidth, int maxWidth, int value, String result) throws Exception { - getFormatter(NANO_OF_SECOND, minWidth, maxWidth, false).printTo(new MockFieldValue(NANO_OF_SECOND, value), buf); + getFormatter(NANO_OF_SECOND, minWidth, maxWidth, false).formatTo(new MockFieldValue(NANO_OF_SECOND, value), buf); if (result == null) { fail("Expected exception"); } @@ -222,7 +220,7 @@ public class TestFractionPrinterParser extends AbstractTestPrinterParser { @Test(dataProvider="Seconds") public void test_print_seconds(int minWidth, int maxWidth, int value, String result) throws Exception { - getFormatter(SECOND_OF_MINUTE, minWidth, maxWidth, true).printTo(new MockFieldValue(SECOND_OF_MINUTE, value), buf); + getFormatter(SECOND_OF_MINUTE, minWidth, maxWidth, true).formatTo(new MockFieldValue(SECOND_OF_MINUTE, value), buf); if (result == null) { fail("Expected exception"); } @@ -231,7 +229,7 @@ public class TestFractionPrinterParser extends AbstractTestPrinterParser { @Test(dataProvider="Seconds") public void test_print_seconds_noDecimalPoint(int minWidth, int maxWidth, int value, String result) throws Exception { - getFormatter(SECOND_OF_MINUTE, minWidth, maxWidth, false).printTo(new MockFieldValue(SECOND_OF_MINUTE, value), buf); + getFormatter(SECOND_OF_MINUTE, minWidth, maxWidth, false).formatTo(new MockFieldValue(SECOND_OF_MINUTE, value), buf); if (result == null) { fail("Expected exception"); } @@ -245,27 +243,27 @@ public class TestFractionPrinterParser extends AbstractTestPrinterParser { public void test_reverseParse(int minWidth, int maxWidth, int value, String result) throws Exception { ParsePosition pos = new ParsePosition(0); int expectedValue = fixParsedValue(maxWidth, value); - DateTimeBuilder dtb = getFormatter(NANO_OF_SECOND, minWidth, maxWidth, true).parseToBuilder(result, pos); + TemporalAccessor parsed = getFormatter(NANO_OF_SECOND, minWidth, maxWidth, true).parseUnresolved(result, pos); assertEquals(pos.getIndex(), result.length()); - assertParsed(dtb, NANO_OF_SECOND, value == 0 && minWidth == 0 ? null : (long) expectedValue); + assertParsed(parsed, NANO_OF_SECOND, value == 0 && minWidth == 0 ? null : (long) expectedValue); } @Test(dataProvider="Nanos") public void test_reverseParse_noDecimalPoint(int minWidth, int maxWidth, int value, String result) throws Exception { ParsePosition pos = new ParsePosition((result.startsWith(".") ? 1 : 0)); - DateTimeBuilder dtb = getFormatter(NANO_OF_SECOND, minWidth, maxWidth, false).parseToBuilder(result, pos); + TemporalAccessor parsed = getFormatter(NANO_OF_SECOND, minWidth, maxWidth, false).parseUnresolved(result, pos); assertEquals(pos.getIndex(), result.length()); int expectedValue = fixParsedValue(maxWidth, value); - assertParsed(dtb, NANO_OF_SECOND, value == 0 && minWidth == 0 ? null : (long) expectedValue); + assertParsed(parsed, NANO_OF_SECOND, value == 0 && minWidth == 0 ? null : (long) expectedValue); } @Test(dataProvider="Nanos") public void test_reverseParse_followedByNonDigit(int minWidth, int maxWidth, int value, String result) throws Exception { ParsePosition pos = new ParsePosition(0); int expectedValue = fixParsedValue(maxWidth, value); - DateTimeBuilder dtb = getFormatter(NANO_OF_SECOND, minWidth, maxWidth, true).parseToBuilder(result + " ", pos); + TemporalAccessor parsed = getFormatter(NANO_OF_SECOND, minWidth, maxWidth, true).parseUnresolved(result + " ", pos); assertEquals(pos.getIndex(), result.length()); - assertParsed(dtb, NANO_OF_SECOND, value == 0 && minWidth == 0 ? null : (long) expectedValue); + assertParsed(parsed, NANO_OF_SECOND, value == 0 && minWidth == 0 ? null : (long) expectedValue); } // @Test(dataProvider="Nanos") @@ -281,9 +279,9 @@ public class TestFractionPrinterParser extends AbstractTestPrinterParser { public void test_reverseParse_preceededByNonDigit(int minWidth, int maxWidth, int value, String result) throws Exception { ParsePosition pos = new ParsePosition(1); int expectedValue = fixParsedValue(maxWidth, value); - DateTimeBuilder dtb = getFormatter(NANO_OF_SECOND, minWidth, maxWidth, true).parseToBuilder(" " + result, pos); + TemporalAccessor parsed = getFormatter(NANO_OF_SECOND, minWidth, maxWidth, true).parseUnresolved(" " + result, pos); assertEquals(pos.getIndex(), result.length() + 1); - assertParsed(dtb, NANO_OF_SECOND, value == 0 && minWidth == 0 ? null : (long) expectedValue); + assertParsed(parsed, NANO_OF_SECOND, value == 0 && minWidth == 0 ? null : (long) expectedValue); } private int fixParsedValue(int maxWidth, int value) { @@ -297,16 +295,17 @@ public class TestFractionPrinterParser extends AbstractTestPrinterParser { @Test(dataProvider="Seconds") public void test_reverseParse_seconds(int minWidth, int maxWidth, int value, String result) throws Exception { ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter(SECOND_OF_MINUTE, minWidth, maxWidth, true).parseToBuilder(result, pos); + TemporalAccessor parsed = getFormatter(SECOND_OF_MINUTE, minWidth, maxWidth, true).parseUnresolved(result, pos); assertEquals(pos.getIndex(), result.length()); - assertParsed(dtb, SECOND_OF_MINUTE, value == 0 && minWidth == 0 ? null : (long) value); + assertParsed(parsed, SECOND_OF_MINUTE, value == 0 && minWidth == 0 ? null : (long) value); } - private void assertParsed(DateTimeBuilder dtb, TemporalField field, Long value) { + private void assertParsed(TemporalAccessor parsed, TemporalField field, Long value) { if (value == null) { - assertEquals(dtb.containsFieldValue(field), false); + assertEquals(parsed.isSupported(field), false); } else { - assertEquals(dtb.getLong(field), (long)value); + assertEquals(parsed.isSupported(field), true); + assertEquals(parsed.getLong(field), (long) value); } } @@ -327,8 +326,9 @@ public class TestFractionPrinterParser extends AbstractTestPrinterParser { @Test(dataProvider = "ParseNothing") public void test_parse_nothing(TemporalField field, int min, int max, boolean decimalPoint, String text, int pos, int expected) { ParsePosition ppos = new ParsePosition(pos); - DateTimeBuilder dtb = getFormatter(field, min, max, decimalPoint).parseToBuilder(text, ppos); + TemporalAccessor parsed = getFormatter(field, min, max, decimalPoint).parseUnresolved(text, ppos); assertEquals(ppos.getErrorIndex(), expected); + assertEquals(parsed, null); } //----------------------------------------------------------------------- diff --git a/jdk/test/java/time/test/java/time/format/TestNonIsoFormatter.java b/jdk/test/java/time/test/java/time/format/TestNonIsoFormatter.java new file mode 100644 index 00000000000..43a603cceae --- /dev/null +++ b/jdk/test/java/time/test/java/time/format/TestNonIsoFormatter.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 test.java.time.format; + +import java.time.*; +import java.time.chrono.*; +import java.time.format.*; +import java.time.temporal.*; +import java.util.Locale; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static org.testng.Assert.assertEquals; + +/** + * Test DateTimeFormatter with non-ISO chronology. + * + * Strings in test data are all dependent on CLDR data which may change + * in future CLDR releases. + */ +@Test(groups={"implementation"}) +public class TestNonIsoFormatter { + private static final Chronology JAPANESE = JapaneseChronology.INSTANCE; + private static final Chronology HIJRAH = HijrahChronology.INSTANCE; + private static final Chronology MINGUO = MinguoChronology.INSTANCE; + private static final Chronology BUDDHIST = ThaiBuddhistChronology.INSTANCE; + + private static final LocalDate IsoDate = LocalDate.of(2013, 2, 11); + + private static final Locale ARABIC = new Locale("ar"); + private static final Locale thTH = new Locale("th", "TH"); + private static final Locale thTHTH = new Locale("th", "TH", "TH"); + + @BeforeMethod + public void setUp() { + } + + @DataProvider(name="format_data") + Object[][] formatData() { + return new Object[][] { + // Chronology, Locale, ChronoLocalDate, expected string + { JAPANESE, Locale.JAPANESE, JAPANESE.date(IsoDate), + "\u5e73\u621025\u5e742\u670811\u65e5\u6708\u66dc\u65e5" }, // Japanese Heisei 25-02-11 (Mon) + { HIJRAH, ARABIC, HIJRAH.date(IsoDate), + "\u0627\u0644\u0627\u062b\u0646\u064a\u0646\u060c 30 \u0631\u0628\u064a\u0639 " + + "\u0627\u0644\u0623\u0648\u0644 1434" }, // Hijrah AH 1434-03-30 (Mon) + { MINGUO, Locale.TAIWAN, MINGUO.date(IsoDate), + "\u6c11\u570b102\u5e742\u670811\u65e5\u661f\u671f\u4e00" }, // Minguo ROC 102-02-11 (Mon) + { BUDDHIST, thTH, BUDDHIST.date(IsoDate), + "\u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c\u0e17\u0e35\u0e48" + + " 11 \u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c" + + " \u0e1e.\u0e28. 2556" }, // ThaiBuddhist BE 2556-02-11 + // { BUDDHIST, thTHTH, BUDDHIST.date(IsoDate), "" }, // doesn't work + }; + } + + @DataProvider(name="invalid_text") + Object[][] invalidText() { + return new Object[][] { + // TODO: currently fixed Chronology and Locale. + { "\u662d\u548c64\u5e741\u67089\u65e5\u6708\u66dc\u65e5" }, // S64.01.09 (Mon) + { "\u662d\u548c65\u5e741\u67081\u65e5\u6708\u66dc\u65e5" }, // S65.01.01 (Mon) + }; + } + + @Test(dataProvider="format_data") + public void test_formatLocalizedDate(Chronology chrono, Locale locale, ChronoLocalDate date, String expected) { + DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL) + .withChronology(chrono).withLocale(locale); + String text = dtf.format(date); + assertEquals(text, expected); + } + + @Test(dataProvider="format_data") + public void test_parseLocalizedText(Chronology chrono, Locale locale, ChronoLocalDate expected, String text) { + DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL) + .withChronology(chrono).withLocale(locale); + TemporalAccessor temporal = dtf.parse(text); + ChronoLocalDate date = chrono.date(temporal); + assertEquals(date, expected); + } + + @Test(dataProvider="invalid_text", expectedExceptions=DateTimeParseException.class) + public void test_parseInvalidText(String text) { + DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL) + .withChronology(JAPANESE).withLocale(Locale.JAPANESE); + TemporalAccessor temporal = dtf.parse(text); + } +} diff --git a/jdk/test/java/time/test/java/time/format/TestNumberParser.java b/jdk/test/java/time/test/java/time/format/TestNumberParser.java index af4b3b6e940..5dca693e80f 100644 --- a/jdk/test/java/time/test/java/time/format/TestNumberParser.java +++ b/jdk/test/java/time/test/java/time/format/TestNumberParser.java @@ -59,19 +59,20 @@ */ package test.java.time.format; -import java.time.format.*; - import static java.time.temporal.ChronoField.DAY_OF_MONTH; import static java.time.temporal.ChronoField.DAY_OF_WEEK; import static java.time.temporal.ChronoField.DAY_OF_YEAR; import static java.time.temporal.ChronoField.MONTH_OF_YEAR; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; import java.text.ParsePosition; -import java.time.format.DateTimeBuilder; -import java.time.temporal.TemporalField; import java.time.format.DateTimeFormatter; +import java.time.format.SignStyle; +import java.time.temporal.Queries; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalField; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -94,8 +95,8 @@ public class TestNumberParser extends AbstractTestPrinterParser { @Test(dataProvider="error") public void test_parse_error(TemporalField field, int min, int max, SignStyle style, String text, int pos, Class expected) { try { - getFormatter(field, min, max, style).parseToBuilder(text, new ParsePosition(pos)); - assertTrue(false); + getFormatter(field, min, max, style).parseUnresolved(text, new ParsePosition(pos)); + fail(); } catch (RuntimeException ex) { assertTrue(expected.isInstance(ex)); } @@ -170,13 +171,15 @@ public class TestNumberParser extends AbstractTestPrinterParser { // hacky, to reserve space dtf = builder.appendValue(DAY_OF_YEAR, subsequentWidth).toFormatter(locale).withSymbols(symbols); } - DateTimeBuilder dtb = dtf.parseToBuilder(text, ppos); + TemporalAccessor parsed = dtf.parseUnresolved(text, ppos); if (ppos.getErrorIndex() != -1) { assertEquals(ppos.getErrorIndex(), expectedPos); } else { assertTrue(subsequentWidth >= 0); assertEquals(ppos.getIndex(), expectedPos + subsequentWidth); - assertEquals(dtb.getLong(DAY_OF_MONTH), expectedValue); + assertEquals(parsed.getLong(DAY_OF_MONTH), expectedValue); + assertEquals(parsed.query(Queries.chronology()), null); + assertEquals(parsed.query(Queries.zoneId()), null); } } @@ -188,13 +191,15 @@ public class TestNumberParser extends AbstractTestPrinterParser { // hacky, to reserve space dtf = builder.appendValue(DAY_OF_YEAR, subsequentWidth).toFormatter(locale).withSymbols(symbols); } - DateTimeBuilder dtb = dtf.parseToBuilder(text, ppos); + TemporalAccessor parsed = dtf.parseUnresolved(text, ppos); if (ppos.getErrorIndex() != -1) { assertEquals(ppos.getErrorIndex(), expectedPos); } else { assertTrue(subsequentWidth >= 0); assertEquals(ppos.getIndex(), expectedPos + subsequentWidth); - assertEquals(dtb.getLong(DAY_OF_WEEK), expectedValue); + assertEquals(parsed.getLong(DAY_OF_WEEK), expectedValue); + assertEquals(parsed.query(Queries.chronology()), null); + assertEquals(parsed.query(Queries.zoneId()), null); } } @@ -302,12 +307,14 @@ public class TestNumberParser extends AbstractTestPrinterParser { @Test(dataProvider="parseSignsStrict") public void test_parseSignsStrict(String input, int min, int max, SignStyle style, int parseLen, Integer parseVal) throws Exception { ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter(DAY_OF_MONTH, min, max, style).parseToBuilder(input, pos); + TemporalAccessor parsed = getFormatter(DAY_OF_MONTH, min, max, style).parseUnresolved(input, pos); if (pos.getErrorIndex() != -1) { assertEquals(pos.getErrorIndex(), parseLen); } else { assertEquals(pos.getIndex(), parseLen); - assertEquals(dtb.getLong(DAY_OF_MONTH), (long)parseVal); + assertEquals(parsed.getLong(DAY_OF_MONTH), (long)parseVal); + assertEquals(parsed.query(Queries.chronology()), null); + assertEquals(parsed.query(Queries.zoneId()), null); } } @@ -410,12 +417,14 @@ public class TestNumberParser extends AbstractTestPrinterParser { public void test_parseSignsLenient(String input, int min, int max, SignStyle style, int parseLen, Integer parseVal) throws Exception { setStrict(false); ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter(DAY_OF_MONTH, min, max, style).parseToBuilder(input, pos); + TemporalAccessor parsed = getFormatter(DAY_OF_MONTH, min, max, style).parseUnresolved(input, pos); if (pos.getErrorIndex() != -1) { assertEquals(pos.getErrorIndex(), parseLen); } else { assertEquals(pos.getIndex(), parseLen); - assertEquals(dtb.getLong(DAY_OF_MONTH), (long)parseVal); + assertEquals(parsed.getLong(DAY_OF_MONTH), (long)parseVal); + assertEquals(parsed.query(Queries.chronology()), null); + assertEquals(parsed.query(Queries.zoneId()), null); } } @@ -499,12 +508,14 @@ public class TestNumberParser extends AbstractTestPrinterParser { public void test_parseDigitsLenient(String input, int min, int max, SignStyle style, int parseLen, Integer parseVal) throws Exception { setStrict(false); ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter(DAY_OF_MONTH, min, max, style).parseToBuilder(input, pos); + TemporalAccessor parsed = getFormatter(DAY_OF_MONTH, min, max, style).parseUnresolved(input, pos); if (pos.getErrorIndex() != -1) { assertEquals(pos.getErrorIndex(), parseLen); } else { assertEquals(pos.getIndex(), parseLen); - assertEquals(dtb.getLong(DAY_OF_MONTH), (long)parseVal); + assertEquals(parsed.getLong(DAY_OF_MONTH), (long)parseVal); + assertEquals(parsed.query(Queries.chronology()), null); + assertEquals(parsed.query(Queries.zoneId()), null); } } @@ -534,13 +545,15 @@ public class TestNumberParser extends AbstractTestPrinterParser { DateTimeFormatter f = builder .appendValue(MONTH_OF_YEAR, 1, 2, SignStyle.NORMAL) .appendValue(DAY_OF_MONTH, 2).toFormatter(locale).withSymbols(symbols); - DateTimeBuilder dtb = f.parseToBuilder(input, pos); + TemporalAccessor parsed = f.parseUnresolved(input, pos); if (pos.getErrorIndex() != -1) { assertEquals(pos.getErrorIndex(), parseLen); } else { assertEquals(pos.getIndex(), parseLen); - assertEquals(dtb.getLong(MONTH_OF_YEAR), (long) parseMonth); - assertEquals(dtb.getLong(DAY_OF_MONTH), (long) parsedDay); + assertEquals(parsed.getLong(MONTH_OF_YEAR), (long) parseMonth); + assertEquals(parsed.getLong(DAY_OF_MONTH), (long) parsedDay); + assertEquals(parsed.query(Queries.chronology()), null); + assertEquals(parsed.query(Queries.zoneId()), null); } } diff --git a/jdk/test/java/time/test/java/time/format/TestNumberPrinter.java b/jdk/test/java/time/test/java/time/format/TestNumberPrinter.java index 80c05b8eb9f..9d686472ab6 100644 --- a/jdk/test/java/time/test/java/time/format/TestNumberPrinter.java +++ b/jdk/test/java/time/test/java/time/format/TestNumberPrinter.java @@ -59,8 +59,6 @@ */ package test.java.time.format; -import java.time.format.*; - import static java.time.temporal.ChronoField.DAY_OF_MONTH; import static java.time.temporal.ChronoField.HOUR_OF_DAY; import static org.testng.Assert.assertEquals; @@ -68,10 +66,11 @@ import static org.testng.Assert.fail; import java.time.DateTimeException; import java.time.LocalDate; -import test.java.time.temporal.MockFieldValue; +import java.time.format.SignStyle; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import test.java.time.temporal.MockFieldValue; /** * Test SimpleNumberPrinterParser. @@ -82,12 +81,12 @@ public class TestNumberPrinter extends AbstractTestPrinterParser { //----------------------------------------------------------------------- @Test(expectedExceptions=DateTimeException.class) public void test_print_emptyCalendrical() throws Exception { - getFormatter(DAY_OF_MONTH, 1, 2, SignStyle.NEVER).printTo(EMPTY_DTA, buf); + getFormatter(DAY_OF_MONTH, 1, 2, SignStyle.NEVER).formatTo(EMPTY_DTA, buf); } public void test_print_append() throws Exception { buf.append("EXISTING"); - getFormatter(DAY_OF_MONTH, 1, 2, SignStyle.NEVER).printTo(LocalDate.of(2012, 1, 3), buf); + getFormatter(DAY_OF_MONTH, 1, 2, SignStyle.NEVER).formatTo(LocalDate.of(2012, 1, 3), buf); assertEquals(buf.toString(), "EXISTING3"); } @@ -185,12 +184,12 @@ public class TestNumberPrinter extends AbstractTestPrinterParser { @Test(dataProvider="Pad") public void test_pad_NOT_NEGATIVE(int minPad, int maxPad, long value, String result) throws Exception { try { - getFormatter(DAY_OF_MONTH, minPad, maxPad, SignStyle.NOT_NEGATIVE).printTo(new MockFieldValue(DAY_OF_MONTH, value), buf); + getFormatter(DAY_OF_MONTH, minPad, maxPad, SignStyle.NOT_NEGATIVE).formatTo(new MockFieldValue(DAY_OF_MONTH, value), buf); if (result == null || value < 0) { fail("Expected exception"); } assertEquals(buf.toString(), result); - } catch (DateTimePrintException ex) { + } catch (DateTimeException ex) { if (result == null || value < 0) { assertEquals(ex.getMessage().contains(DAY_OF_MONTH.getName()), true); } else { @@ -202,12 +201,12 @@ public class TestNumberPrinter extends AbstractTestPrinterParser { @Test(dataProvider="Pad") public void test_pad_NEVER(int minPad, int maxPad, long value, String result) throws Exception { try { - getFormatter(DAY_OF_MONTH, minPad, maxPad, SignStyle.NEVER).printTo(new MockFieldValue(DAY_OF_MONTH, value), buf); + getFormatter(DAY_OF_MONTH, minPad, maxPad, SignStyle.NEVER).formatTo(new MockFieldValue(DAY_OF_MONTH, value), buf); if (result == null) { fail("Expected exception"); } assertEquals(buf.toString(), result); - } catch (DateTimePrintException ex) { + } catch (DateTimeException ex) { if (result != null) { throw ex; } @@ -218,12 +217,12 @@ public class TestNumberPrinter extends AbstractTestPrinterParser { @Test(dataProvider="Pad") public void test_pad_NORMAL(int minPad, int maxPad, long value, String result) throws Exception { try { - getFormatter(DAY_OF_MONTH, minPad, maxPad, SignStyle.NORMAL).printTo(new MockFieldValue(DAY_OF_MONTH, value), buf); + getFormatter(DAY_OF_MONTH, minPad, maxPad, SignStyle.NORMAL).formatTo(new MockFieldValue(DAY_OF_MONTH, value), buf); if (result == null) { fail("Expected exception"); } assertEquals(buf.toString(), (value < 0 ? "-" + result : result)); - } catch (DateTimePrintException ex) { + } catch (DateTimeException ex) { if (result != null) { throw ex; } @@ -234,12 +233,12 @@ public class TestNumberPrinter extends AbstractTestPrinterParser { @Test(dataProvider="Pad") public void test_pad_ALWAYS(int minPad, int maxPad, long value, String result) throws Exception { try { - getFormatter(DAY_OF_MONTH, minPad, maxPad, SignStyle.ALWAYS).printTo(new MockFieldValue(DAY_OF_MONTH, value), buf); + getFormatter(DAY_OF_MONTH, minPad, maxPad, SignStyle.ALWAYS).formatTo(new MockFieldValue(DAY_OF_MONTH, value), buf); if (result == null) { fail("Expected exception"); } assertEquals(buf.toString(), (value < 0 ? "-" + result : "+" + result)); - } catch (DateTimePrintException ex) { + } catch (DateTimeException ex) { if (result != null) { throw ex; } @@ -250,7 +249,7 @@ public class TestNumberPrinter extends AbstractTestPrinterParser { @Test(dataProvider="Pad") public void test_pad_EXCEEDS_PAD(int minPad, int maxPad, long value, String result) throws Exception { try { - getFormatter(DAY_OF_MONTH, minPad, maxPad, SignStyle.EXCEEDS_PAD).printTo(new MockFieldValue(DAY_OF_MONTH, value), buf); + getFormatter(DAY_OF_MONTH, minPad, maxPad, SignStyle.EXCEEDS_PAD).formatTo(new MockFieldValue(DAY_OF_MONTH, value), buf); if (result == null) { fail("Expected exception"); return; // unreachable @@ -259,7 +258,7 @@ public class TestNumberPrinter extends AbstractTestPrinterParser { result = (value < 0 ? "-" + result : "+" + result); } assertEquals(buf.toString(), result); - } catch (DateTimePrintException ex) { + } catch (DateTimeException ex) { if (result != null) { throw ex; } diff --git a/jdk/test/java/time/test/java/time/format/TestPadPrinterDecorator.java b/jdk/test/java/time/test/java/time/format/TestPadPrinterDecorator.java index d6302aee4d7..c8dcbf39c53 100644 --- a/jdk/test/java/time/test/java/time/format/TestPadPrinterDecorator.java +++ b/jdk/test/java/time/test/java/time/format/TestPadPrinterDecorator.java @@ -59,10 +59,9 @@ */ package test.java.time.format; -import java.time.format.*; - import static org.testng.Assert.assertEquals; +import java.time.DateTimeException; import java.time.LocalDate; import org.testng.annotations.Test; @@ -76,52 +75,52 @@ public class TestPadPrinterDecorator extends AbstractTestPrinterParser { //----------------------------------------------------------------------- public void test_print_emptyCalendrical() throws Exception { builder.padNext(3, '-').appendLiteral('Z'); - getFormatter().printTo(EMPTY_DTA, buf); + getFormatter().formatTo(EMPTY_DTA, buf); assertEquals(buf.toString(), "--Z"); } public void test_print_fullDateTime() throws Exception { builder.padNext(3, '-').appendLiteral('Z'); - getFormatter().printTo(LocalDate.of(2008, 12, 3), buf); + getFormatter().formatTo(LocalDate.of(2008, 12, 3), buf); assertEquals(buf.toString(), "--Z"); } public void test_print_append() throws Exception { buf.append("EXISTING"); builder.padNext(3, '-').appendLiteral('Z'); - getFormatter().printTo(EMPTY_DTA, buf); + getFormatter().formatTo(EMPTY_DTA, buf); assertEquals(buf.toString(), "EXISTING--Z"); } //----------------------------------------------------------------------- public void test_print_noPadRequiredSingle() throws Exception { builder.padNext(1, '-').appendLiteral('Z'); - getFormatter().printTo(EMPTY_DTA, buf); + getFormatter().formatTo(EMPTY_DTA, buf); assertEquals(buf.toString(), "Z"); } public void test_print_padRequiredSingle() throws Exception { builder.padNext(5, '-').appendLiteral('Z'); - getFormatter().printTo(EMPTY_DTA, buf); + getFormatter().formatTo(EMPTY_DTA, buf); assertEquals(buf.toString(), "----Z"); } public void test_print_noPadRequiredMultiple() throws Exception { builder.padNext(4, '-').appendLiteral("WXYZ"); - getFormatter().printTo(EMPTY_DTA, buf); + getFormatter().formatTo(EMPTY_DTA, buf); assertEquals(buf.toString(), "WXYZ"); } public void test_print_padRequiredMultiple() throws Exception { builder.padNext(5, '-').appendLiteral("WXYZ"); - getFormatter().printTo(EMPTY_DTA, buf); + getFormatter().formatTo(EMPTY_DTA, buf); assertEquals(buf.toString(), "-WXYZ"); } - @Test(expectedExceptions=DateTimePrintException.class) + @Test(expectedExceptions=DateTimeException.class) public void test_print_overPad() throws Exception { builder.padNext(3, '-').appendLiteral("WXYZ"); - getFormatter().printTo(EMPTY_DTA, buf); + getFormatter().formatTo(EMPTY_DTA, buf); } //----------------------------------------------------------------------- diff --git a/jdk/test/java/time/test/java/time/format/TestReducedParser.java b/jdk/test/java/time/test/java/time/format/TestReducedParser.java index bcd383039ff..c1a41bbef95 100644 --- a/jdk/test/java/time/test/java/time/format/TestReducedParser.java +++ b/jdk/test/java/time/test/java/time/format/TestReducedParser.java @@ -59,15 +59,14 @@ */ package test.java.time.format; -import java.time.format.*; - import static java.time.temporal.ChronoField.DAY_OF_YEAR; import static java.time.temporal.ChronoField.YEAR; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import java.text.ParsePosition; -import java.time.format.DateTimeBuilder; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; import org.testng.annotations.DataProvider; @@ -95,7 +94,7 @@ public class TestReducedParser extends AbstractTestPrinterParser { @Test(dataProvider="error") public void test_parse_error(TemporalField field, int width, int baseValue, String text, int pos, Class expected) { try { - getFormatter0(field, width, baseValue).parseToBuilder(text, new ParsePosition(pos)); + getFormatter0(field, width, baseValue).parseUnresolved(text, new ParsePosition(pos)); } catch (RuntimeException ex) { assertTrue(expected.isInstance(ex)); } @@ -104,9 +103,9 @@ public class TestReducedParser extends AbstractTestPrinterParser { //----------------------------------------------------------------------- public void test_parse_fieldRangeIgnored() throws Exception { ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter0(DAY_OF_YEAR, 3, 10).parseToBuilder("456", pos); + TemporalAccessor parsed = getFormatter0(DAY_OF_YEAR, 3, 10).parseUnresolved("456", pos); assertEquals(pos.getIndex(), 3); - assertParsed(dtb, DAY_OF_YEAR, 456L); // parsed dayOfYear=456 + assertParsed(parsed, DAY_OF_YEAR, 456L); // parsed dayOfYear=456 } //----------------------------------------------------------------------- @@ -165,12 +164,12 @@ public class TestReducedParser extends AbstractTestPrinterParser { @Test(dataProvider="Parse") public void test_parse(TemporalField field, int width, int baseValue, String input, int pos, int parseLen, Integer parseVal) { ParsePosition ppos = new ParsePosition(pos); - DateTimeBuilder dtb = getFormatter0(field, width, baseValue).parseToBuilder(input, ppos); + TemporalAccessor parsed = getFormatter0(field, width, baseValue).parseUnresolved(input, ppos); if (ppos.getErrorIndex() != -1) { assertEquals(ppos.getErrorIndex(), parseLen); } else { assertEquals(ppos.getIndex(), parseLen); - assertParsed(dtb, YEAR, parseVal != null ? (long) parseVal : null); + assertParsed(parsed, YEAR, parseVal != null ? (long) parseVal : null); } } @@ -178,20 +177,21 @@ public class TestReducedParser extends AbstractTestPrinterParser { public void test_parseLenient(TemporalField field, int width, int baseValue, String input, int pos, int parseLen, Integer parseVal) { setStrict(false); ParsePosition ppos = new ParsePosition(pos); - DateTimeBuilder dtb = getFormatter0(field, width, baseValue).parseToBuilder(input, ppos); + TemporalAccessor parsed = getFormatter0(field, width, baseValue).parseUnresolved(input, ppos); if (ppos.getErrorIndex() != -1) { assertEquals(ppos.getErrorIndex(), parseLen); } else { assertEquals(ppos.getIndex(), parseLen); - assertParsed(dtb, YEAR, parseVal != null ? (long) parseVal : null); + assertParsed(parsed, YEAR, parseVal != null ? (long) parseVal : null); } } - private void assertParsed(DateTimeBuilder dtb, TemporalField field, Long value) { + private void assertParsed(TemporalAccessor parsed, TemporalField field, Long value) { if (value == null) { - assertEquals(dtb, null); + assertEquals(parsed, null); } else { - assertEquals(dtb.getLong(field), (long)value); + assertEquals(parsed.isSupported(field), true); + assertEquals(parsed.getLong(field), (long) value); } } diff --git a/jdk/test/java/time/test/java/time/format/TestReducedPrinter.java b/jdk/test/java/time/test/java/time/format/TestReducedPrinter.java index 698496dc57e..76060691910 100644 --- a/jdk/test/java/time/test/java/time/format/TestReducedPrinter.java +++ b/jdk/test/java/time/test/java/time/format/TestReducedPrinter.java @@ -86,13 +86,13 @@ public class TestReducedPrinter extends AbstractTestPrinterParser { //----------------------------------------------------------------------- @Test(expectedExceptions=DateTimeException.class) public void test_print_emptyCalendrical() throws Exception { - getFormatter0(YEAR, 2, 2010).printTo(EMPTY_DTA, buf); + getFormatter0(YEAR, 2, 2010).formatTo(EMPTY_DTA, buf); } //----------------------------------------------------------------------- public void test_print_append() throws Exception { buf.append("EXISTING"); - getFormatter0(YEAR, 2, 2010).printTo(LocalDate.of(2012, 1, 1), buf); + getFormatter0(YEAR, 2, 2010).formatTo(LocalDate.of(2012, 1, 1), buf); assertEquals(buf.toString(), "EXISTING12"); } @@ -159,12 +159,12 @@ public class TestReducedPrinter extends AbstractTestPrinterParser { @Test(dataProvider="Pivot") public void test_pivot(int width, int baseValue, int value, String result) throws Exception { try { - getFormatter0(YEAR, width, baseValue).printTo(new MockFieldValue(YEAR, value), buf); + getFormatter0(YEAR, width, baseValue).formatTo(new MockFieldValue(YEAR, value), buf); if (result == null) { fail("Expected exception"); } assertEquals(buf.toString(), result); - } catch (DateTimePrintException ex) { + } catch (DateTimeException ex) { if (result == null || value < 0) { assertEquals(ex.getMessage().contains(YEAR.getName()), true); } else { diff --git a/jdk/test/java/time/test/java/time/format/TestSettingsParser.java b/jdk/test/java/time/test/java/time/format/TestSettingsParser.java index 4b639aa56d4..ed3b0a58716 100644 --- a/jdk/test/java/time/test/java/time/format/TestSettingsParser.java +++ b/jdk/test/java/time/test/java/time/format/TestSettingsParser.java @@ -59,12 +59,9 @@ */ package test.java.time.format; -import java.time.format.*; - import static org.testng.Assert.assertEquals; import java.text.ParsePosition; -import java.time.ZoneOffset; import org.testng.annotations.Test; @@ -77,20 +74,20 @@ public class TestSettingsParser extends AbstractTestPrinterParser { //----------------------------------------------------------------------- public void test_print_sensitive() throws Exception { setCaseSensitive(true); - getFormatter().printTo(dta, buf); + getFormatter().formatTo(dta, buf); assertEquals(buf.toString(), ""); } public void test_print_strict() throws Exception { setStrict(true); - getFormatter().printTo(dta, buf); + getFormatter().formatTo(dta, buf); assertEquals(buf.toString(), ""); } /* public void test_print_nulls() throws Exception { setCaseSensitive(true); - getFormatter().printTo(null, null); + getFormatter().formatTo(null, null); } */ @@ -98,28 +95,28 @@ public class TestSettingsParser extends AbstractTestPrinterParser { public void test_parse_changeStyle_sensitive() throws Exception { setCaseSensitive(true); ParsePosition pos = new ParsePosition(0); - getFormatter().parseToBuilder("a", pos); + getFormatter().parseUnresolved("a", pos); assertEquals(pos.getIndex(), 0); } public void test_parse_changeStyle_insensitive() throws Exception { setCaseSensitive(false); ParsePosition pos = new ParsePosition(0); - getFormatter().parseToBuilder("a", pos); + getFormatter().parseUnresolved("a", pos); assertEquals(pos.getIndex(), 0); } public void test_parse_changeStyle_strict() throws Exception { setStrict(true); ParsePosition pos = new ParsePosition(0); - getFormatter().parseToBuilder("a", pos); + getFormatter().parseUnresolved("a", pos); assertEquals(pos.getIndex(), 0); } public void test_parse_changeStyle_lenient() throws Exception { setStrict(false); ParsePosition pos = new ParsePosition(0); - getFormatter().parseToBuilder("a", pos); + getFormatter().parseUnresolved("a", pos); assertEquals(pos.getIndex(), 0); } diff --git a/jdk/test/java/time/test/java/time/format/TestStringLiteralParser.java b/jdk/test/java/time/test/java/time/format/TestStringLiteralParser.java index bd67eab39f3..a2096521bff 100644 --- a/jdk/test/java/time/test/java/time/format/TestStringLiteralParser.java +++ b/jdk/test/java/time/test/java/time/format/TestStringLiteralParser.java @@ -59,11 +59,14 @@ */ package test.java.time.format; +import static java.time.temporal.ChronoField.YEAR; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; -import java.time.format.DateTimeBuilder; import java.text.ParsePosition; +import java.time.temporal.Queries; +import java.time.temporal.TemporalAccessor; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -105,13 +108,14 @@ public class TestStringLiteralParser extends AbstractTestPrinterParser { public void test_parse_success(String s, boolean caseSensitive, String text, int pos, int expectedPos) { setCaseSensitive(caseSensitive); ParsePosition ppos = new ParsePosition(pos); - DateTimeBuilder result = - getFormatter(s).parseToBuilder(text, ppos); + TemporalAccessor parsed = getFormatter(s).parseUnresolved(text, ppos); if (ppos.getErrorIndex() != -1) { assertEquals(ppos.getIndex(), expectedPos); } else { assertEquals(ppos.getIndex(), expectedPos); - assertEquals(result.getCalendricalList().size(), 0); + assertEquals(parsed.isSupported(YEAR), false); + assertEquals(parsed.query(Queries.chronology()), null); + assertEquals(parsed.query(Queries.zoneId()), null); } } @@ -127,9 +131,9 @@ public class TestStringLiteralParser extends AbstractTestPrinterParser { @Test(dataProvider="error") public void test_parse_error(String s, String text, int pos, Class expected) { try { - DateTimeBuilder result = - getFormatter(s).parseToBuilder(text, new ParsePosition(pos)); - assertTrue(false); + ParsePosition ppos = new ParsePosition(pos); + getFormatter(s).parseUnresolved(text, ppos); + fail(); } catch (RuntimeException ex) { assertTrue(expected.isInstance(ex)); } diff --git a/jdk/test/java/time/test/java/time/format/TestStringLiteralPrinter.java b/jdk/test/java/time/test/java/time/format/TestStringLiteralPrinter.java index df018701b3c..62d6a4efc0c 100644 --- a/jdk/test/java/time/test/java/time/format/TestStringLiteralPrinter.java +++ b/jdk/test/java/time/test/java/time/format/TestStringLiteralPrinter.java @@ -74,13 +74,13 @@ public class TestStringLiteralPrinter extends AbstractTestPrinterParser { //----------------------------------------------------------------------- public void test_print_emptyCalendrical() throws Exception { buf.append("EXISTING"); - getFormatter("hello").printTo(EMPTY_DTA, buf); + getFormatter("hello").formatTo(EMPTY_DTA, buf); assertEquals(buf.toString(), "EXISTINGhello"); } public void test_print_dateTime() throws Exception { buf.append("EXISTING"); - getFormatter("hello").printTo(dta, buf); + getFormatter("hello").formatTo(dta, buf); assertEquals(buf.toString(), "EXISTINGhello"); } @@ -88,7 +88,7 @@ public class TestStringLiteralPrinter extends AbstractTestPrinterParser { public void test_print_emptyAppendable() throws Exception { - getFormatter("hello").printTo(dta, buf); + getFormatter("hello").formatTo(dta, buf); assertEquals(buf.toString(), "hello"); } diff --git a/jdk/test/java/time/test/java/time/format/TestTextParser.java b/jdk/test/java/time/test/java/time/format/TestTextParser.java index 7961b27ac8b..9e9c3f73973 100644 --- a/jdk/test/java/time/test/java/time/format/TestTextParser.java +++ b/jdk/test/java/time/test/java/time/format/TestTextParser.java @@ -59,8 +59,6 @@ */ package test.java.time.format; -import java.time.format.*; - import static java.time.temporal.ChronoField.DAY_OF_MONTH; import static java.time.temporal.ChronoField.DAY_OF_WEEK; import static java.time.temporal.ChronoField.MONTH_OF_YEAR; @@ -68,9 +66,10 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import java.text.ParsePosition; -import java.util.Locale; -import java.time.format.DateTimeBuilder; +import java.time.format.TextStyle; +import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; +import java.util.Locale; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -93,7 +92,7 @@ public class TestTextParser extends AbstractTestPrinterParser { @Test(dataProvider="error") public void test_parse_error(TemporalField field, TextStyle style, String text, int pos, Class expected) { try { - getFormatter(field, style).parseToBuilder(text, new ParsePosition(pos)); + getFormatter(field, style).parseUnresolved(text, new ParsePosition(pos)); } catch (RuntimeException ex) { assertTrue(expected.isInstance(ex)); } @@ -103,7 +102,7 @@ public class TestTextParser extends AbstractTestPrinterParser { public void test_parse_midStr() throws Exception { ParsePosition pos = new ParsePosition(3); assertEquals(getFormatter(DAY_OF_WEEK, TextStyle.FULL) - .parseToBuilder("XxxMondayXxx", pos) + .parseUnresolved("XxxMondayXxx", pos) .getLong(DAY_OF_WEEK), 1L); assertEquals(pos.getIndex(), 9); } @@ -111,7 +110,7 @@ public class TestTextParser extends AbstractTestPrinterParser { public void test_parse_remainderIgnored() throws Exception { ParsePosition pos = new ParsePosition(0); assertEquals(getFormatter(DAY_OF_WEEK, TextStyle.SHORT) - .parseToBuilder("Wednesday", pos) + .parseUnresolved("Wednesday", pos) .getLong(DAY_OF_WEEK), 3L); assertEquals(pos.getIndex(), 3); } @@ -119,23 +118,26 @@ public class TestTextParser extends AbstractTestPrinterParser { //----------------------------------------------------------------------- public void test_parse_noMatch1() throws Exception { ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = - getFormatter(DAY_OF_WEEK, TextStyle.FULL).parseToBuilder("Munday", pos); + TemporalAccessor parsed = + getFormatter(DAY_OF_WEEK, TextStyle.FULL).parseUnresolved("Munday", pos); assertEquals(pos.getErrorIndex(), 0); + assertEquals(parsed, null); } public void test_parse_noMatch2() throws Exception { ParsePosition pos = new ParsePosition(3); - DateTimeBuilder dtb = - getFormatter(DAY_OF_WEEK, TextStyle.FULL).parseToBuilder("Monday", pos); + TemporalAccessor parsed = + getFormatter(DAY_OF_WEEK, TextStyle.FULL).parseUnresolved("Monday", pos); assertEquals(pos.getErrorIndex(), 3); + assertEquals(parsed, null); } public void test_parse_noMatch_atEnd() throws Exception { ParsePosition pos = new ParsePosition(6); - DateTimeBuilder dtb = - getFormatter(DAY_OF_WEEK, TextStyle.FULL).parseToBuilder("Monday", pos); + TemporalAccessor parsed = + getFormatter(DAY_OF_WEEK, TextStyle.FULL).parseUnresolved("Monday", pos); assertEquals(pos.getErrorIndex(), 6); + assertEquals(parsed, null); } //----------------------------------------------------------------------- @@ -184,14 +186,14 @@ public class TestTextParser extends AbstractTestPrinterParser { @Test(dataProvider="parseText") public void test_parseText(TemporalField field, TextStyle style, int value, String input) throws Exception { ParsePosition pos = new ParsePosition(0); - assertEquals(getFormatter(field, style).parseToBuilder(input, pos).getLong(field), (long) value); + assertEquals(getFormatter(field, style).parseUnresolved(input, pos).getLong(field), (long) value); assertEquals(pos.getIndex(), input.length()); } @Test(dataProvider="parseNumber") public void test_parseNumber(TemporalField field, TextStyle style, int value, String input) throws Exception { ParsePosition pos = new ParsePosition(0); - assertEquals(getFormatter(field, style).parseToBuilder(input, pos).getLong(field), (long) value); + assertEquals(getFormatter(field, style).parseUnresolved(input, pos).getLong(field), (long) value); assertEquals(pos.getIndex(), input.length()); } @@ -200,7 +202,7 @@ public class TestTextParser extends AbstractTestPrinterParser { public void test_parse_strict_caseSensitive_parseUpper(TemporalField field, TextStyle style, int value, String input) throws Exception { setCaseSensitive(true); ParsePosition pos = new ParsePosition(0); - getFormatter(field, style).parseToBuilder(input.toUpperCase(), pos); + getFormatter(field, style).parseUnresolved(input.toUpperCase(), pos); assertEquals(pos.getErrorIndex(), 0); } @@ -208,7 +210,7 @@ public class TestTextParser extends AbstractTestPrinterParser { public void test_parse_strict_caseInsensitive_parseUpper(TemporalField field, TextStyle style, int value, String input) throws Exception { setCaseSensitive(false); ParsePosition pos = new ParsePosition(0); - assertEquals(getFormatter(field, style).parseToBuilder(input.toUpperCase(), pos).getLong(field), (long) value); + assertEquals(getFormatter(field, style).parseUnresolved(input.toUpperCase(), pos).getLong(field), (long) value); assertEquals(pos.getIndex(), input.length()); } @@ -217,7 +219,7 @@ public class TestTextParser extends AbstractTestPrinterParser { public void test_parse_strict_caseSensitive_parseLower(TemporalField field, TextStyle style, int value, String input) throws Exception { setCaseSensitive(true); ParsePosition pos = new ParsePosition(0); - getFormatter(field, style).parseToBuilder(input.toLowerCase(), pos); + getFormatter(field, style).parseUnresolved(input.toLowerCase(), pos); assertEquals(pos.getErrorIndex(), 0); } @@ -225,7 +227,7 @@ public class TestTextParser extends AbstractTestPrinterParser { public void test_parse_strict_caseInsensitive_parseLower(TemporalField field, TextStyle style, int value, String input) throws Exception { setCaseSensitive(false); ParsePosition pos = new ParsePosition(0); - assertEquals(getFormatter(field, style).parseToBuilder(input.toLowerCase(), pos).getLong(field), (long) value); + assertEquals(getFormatter(field, style).parseUnresolved(input.toLowerCase(), pos).getLong(field), (long) value); assertEquals(pos.getIndex(), input.length()); } @@ -235,21 +237,21 @@ public class TestTextParser extends AbstractTestPrinterParser { public void test_parse_full_strict_full_match() throws Exception { setStrict(true); ParsePosition pos = new ParsePosition(0); - assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.FULL).parseToBuilder("January", pos).getLong(MONTH_OF_YEAR), 1L); + assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.FULL).parseUnresolved("January", pos).getLong(MONTH_OF_YEAR), 1L); assertEquals(pos.getIndex(), 7); } public void test_parse_full_strict_short_noMatch() throws Exception { setStrict(true); ParsePosition pos = new ParsePosition(0); - getFormatter(MONTH_OF_YEAR, TextStyle.FULL).parseToBuilder("Janua", pos); + getFormatter(MONTH_OF_YEAR, TextStyle.FULL).parseUnresolved("Janua", pos); assertEquals(pos.getErrorIndex(), 0); } public void test_parse_full_strict_number_noMatch() throws Exception { setStrict(true); ParsePosition pos = new ParsePosition(0); - getFormatter(MONTH_OF_YEAR, TextStyle.FULL).parseToBuilder("1", pos); + getFormatter(MONTH_OF_YEAR, TextStyle.FULL).parseUnresolved("1", pos); assertEquals(pos.getErrorIndex(), 0); } @@ -257,21 +259,21 @@ public class TestTextParser extends AbstractTestPrinterParser { public void test_parse_short_strict_full_match() throws Exception { setStrict(true); ParsePosition pos = new ParsePosition(0); - assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).parseToBuilder("January", pos).getLong(MONTH_OF_YEAR), 1L); + assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).parseUnresolved("January", pos).getLong(MONTH_OF_YEAR), 1L); assertEquals(pos.getIndex(), 3); } public void test_parse_short_strict_short_match() throws Exception { setStrict(true); ParsePosition pos = new ParsePosition(0); - assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).parseToBuilder("Janua", pos).getLong(MONTH_OF_YEAR), 1L); + assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).parseUnresolved("Janua", pos).getLong(MONTH_OF_YEAR), 1L); assertEquals(pos.getIndex(), 3); } public void test_parse_short_strict_number_noMatch() throws Exception { setStrict(true); ParsePosition pos = new ParsePosition(0); - getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).parseToBuilder("1", pos); + getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).parseUnresolved("1", pos); assertEquals(pos.getErrorIndex(), 0); } @@ -280,7 +282,7 @@ public class TestTextParser extends AbstractTestPrinterParser { setStrict(true); ParsePosition pos = new ParsePosition(0); getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH) - .parseToBuilder("janvier", pos); + .parseUnresolved("janvier", pos); assertEquals(pos.getErrorIndex(), 0); } @@ -288,7 +290,7 @@ public class TestTextParser extends AbstractTestPrinterParser { setStrict(true); ParsePosition pos = new ParsePosition(0); assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH) - .parseToBuilder("janv.", pos) + .parseUnresolved("janv.", pos) .getLong(MONTH_OF_YEAR), 1L); assertEquals(pos.getIndex(), 5); @@ -298,21 +300,21 @@ public class TestTextParser extends AbstractTestPrinterParser { public void test_parse_full_lenient_full_match() throws Exception { setStrict(false); ParsePosition pos = new ParsePosition(0); - assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.FULL).parseToBuilder("January.", pos).getLong(MONTH_OF_YEAR), 1L); + assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.FULL).parseUnresolved("January.", pos).getLong(MONTH_OF_YEAR), 1L); assertEquals(pos.getIndex(), 7); } public void test_parse_full_lenient_short_match() throws Exception { setStrict(false); ParsePosition pos = new ParsePosition(0); - assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.FULL).parseToBuilder("Janua", pos).getLong(MONTH_OF_YEAR), 1L); + assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.FULL).parseUnresolved("Janua", pos).getLong(MONTH_OF_YEAR), 1L); assertEquals(pos.getIndex(), 3); } public void test_parse_full_lenient_number_match() throws Exception { setStrict(false); ParsePosition pos = new ParsePosition(0); - assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.FULL).parseToBuilder("1", pos).getLong(MONTH_OF_YEAR), 1L); + assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.FULL).parseUnresolved("1", pos).getLong(MONTH_OF_YEAR), 1L); assertEquals(pos.getIndex(), 1); } @@ -320,21 +322,21 @@ public class TestTextParser extends AbstractTestPrinterParser { public void test_parse_short_lenient_full_match() throws Exception { setStrict(false); ParsePosition pos = new ParsePosition(0); - assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).parseToBuilder("January", pos).getLong(MONTH_OF_YEAR), 1L); + assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).parseUnresolved("January", pos).getLong(MONTH_OF_YEAR), 1L); assertEquals(pos.getIndex(), 7); } public void test_parse_short_lenient_short_match() throws Exception { setStrict(false); ParsePosition pos = new ParsePosition(0); - assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).parseToBuilder("Janua", pos).getLong(MONTH_OF_YEAR), 1L); + assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).parseUnresolved("Janua", pos).getLong(MONTH_OF_YEAR), 1L); assertEquals(pos.getIndex(), 3); } public void test_parse_short_lenient_number_match() throws Exception { setStrict(false); ParsePosition pos = new ParsePosition(0); - assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).parseToBuilder("1", pos).getLong(MONTH_OF_YEAR), 1L); + assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).parseUnresolved("1", pos).getLong(MONTH_OF_YEAR), 1L); assertEquals(pos.getIndex(), 1); } diff --git a/jdk/test/java/time/test/java/time/format/TestTextPrinter.java b/jdk/test/java/time/test/java/time/format/TestTextPrinter.java index cc93f461a78..43f2df31bef 100644 --- a/jdk/test/java/time/test/java/time/format/TestTextPrinter.java +++ b/jdk/test/java/time/test/java/time/format/TestTextPrinter.java @@ -64,6 +64,7 @@ import java.time.format.*; import static java.time.temporal.ChronoField.DAY_OF_MONTH; import static java.time.temporal.ChronoField.DAY_OF_WEEK; import static java.time.temporal.ChronoField.MONTH_OF_YEAR; +import static java.time.temporal.ChronoField.ERA; import static org.testng.Assert.assertEquals; import java.util.Locale; @@ -71,6 +72,7 @@ import java.util.Locale; import java.time.DateTimeException; import java.time.LocalDate; import java.time.temporal.TemporalField; +import java.time.chrono.JapaneseChronology; import test.java.time.temporal.MockFieldValue; import org.testng.annotations.DataProvider; @@ -85,12 +87,12 @@ public class TestTextPrinter extends AbstractTestPrinterParser { //----------------------------------------------------------------------- @Test(expectedExceptions=DateTimeException.class) public void test_print_emptyCalendrical() throws Exception { - getFormatter(DAY_OF_WEEK, TextStyle.FULL).printTo(EMPTY_DTA, buf); + getFormatter(DAY_OF_WEEK, TextStyle.FULL).formatTo(EMPTY_DTA, buf); } public void test_print_append() throws Exception { buf.append("EXISTING"); - getFormatter(DAY_OF_WEEK, TextStyle.FULL).printTo(LocalDate.of(2012, 4, 18), buf); + getFormatter(DAY_OF_WEEK, TextStyle.FULL).formatTo(LocalDate.of(2012, 4, 18), buf); assertEquals(buf.toString(), "EXISTINGWednesday"); } @@ -163,23 +165,46 @@ public class TestTextPrinter extends AbstractTestPrinterParser { {MONTH_OF_YEAR, TextStyle.SHORT, 10, "Oct"}, {MONTH_OF_YEAR, TextStyle.SHORT, 11, "Nov"}, {MONTH_OF_YEAR, TextStyle.SHORT, 12, "Dec"}, + + {ERA, TextStyle.FULL, 0, "Before Christ"}, + {ERA, TextStyle.FULL, 1, "Anno Domini"}, + {ERA, TextStyle.SHORT, 0, "BC"}, + {ERA, TextStyle.SHORT, 1, "AD"}, + {ERA, TextStyle.NARROW, 0, "B"}, + {ERA, TextStyle.NARROW, 1, "A"}, }; } + @DataProvider(name="print_JapaneseChronology") + Object[][] provider_japaneseEra() { + return new Object[][] { + {ERA, TextStyle.FULL, 2, "Heisei"}, // Note: CLDR doesn't define "wide" Japanese era names. + {ERA, TextStyle.SHORT, 2, "Heisei"}, + {ERA, TextStyle.NARROW, 2, "H"}, + }; + }; + @Test(dataProvider="print") - public void test_print(TemporalField field, TextStyle style, int value, String expected) throws Exception { - getFormatter(field, style).printTo(new MockFieldValue(field, value), buf); + public void test_format(TemporalField field, TextStyle style, int value, String expected) throws Exception { + getFormatter(field, style).formatTo(new MockFieldValue(field, value), buf); + assertEquals(buf.toString(), expected); + } + + @Test(dataProvider="print_JapaneseChronology") + public void test_formatJapaneseEra(TemporalField field, TextStyle style, int value, String expected) throws Exception { + LocalDate ld = LocalDate.of(2013, 1, 31); + getFormatter(field, style).withChronology(JapaneseChronology.INSTANCE).formatTo(ld, buf); assertEquals(buf.toString(), expected); } //----------------------------------------------------------------------- public void test_print_french_long() throws Exception { - getFormatter(MONTH_OF_YEAR, TextStyle.FULL).withLocale(Locale.FRENCH).printTo(LocalDate.of(2012, 1, 1), buf); + getFormatter(MONTH_OF_YEAR, TextStyle.FULL).withLocale(Locale.FRENCH).formatTo(LocalDate.of(2012, 1, 1), buf); assertEquals(buf.toString(), "janvier"); } public void test_print_french_short() throws Exception { - getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH).printTo(LocalDate.of(2012, 1, 1), buf); + getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH).formatTo(LocalDate.of(2012, 1, 1), buf); assertEquals(buf.toString(), "janv."); } diff --git a/jdk/test/java/time/test/java/time/format/TestZoneIdParser.java b/jdk/test/java/time/test/java/time/format/TestZoneIdParser.java deleted file mode 100644 index 99ee93bb52e..00000000000 --- a/jdk/test/java/time/test/java/time/format/TestZoneIdParser.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2012, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * - * Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of JSR-310 nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package test.java.time.format; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; - -import java.util.Set; - -import java.text.ParsePosition; -import java.time.ZoneId; -import java.time.format.DateTimeBuilder; -import java.time.format.DateTimeFormatter; -import java.time.format.TextStyle; -import java.time.format.DateTimeFormatterBuilder; -import java.time.temporal.Queries; -import java.time.zone.ZoneRulesProvider; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -/** - * Test ZonePrinterParser. - */ -@Test(groups={"implementation"}) -public class TestZoneIdParser extends AbstractTestPrinterParser { - - private static final String AMERICA_DENVER = "America/Denver"; - private static final ZoneId TIME_ZONE_DENVER = ZoneId.of(AMERICA_DENVER); - - private DateTimeFormatter getFormatter0(TextStyle style) { - if (style == null) - return builder.appendZoneId().toFormatter(locale).withSymbols(symbols); - return builder.appendZoneText(style).toFormatter(locale).withSymbols(symbols); - } - - //----------------------------------------------------------------------- - @DataProvider(name="error") - Object[][] data_error() { - return new Object[][] { - {null, "hello", -1, IndexOutOfBoundsException.class}, - {null, "hello", 6, IndexOutOfBoundsException.class}, - }; - } - - @Test(dataProvider="error") - public void test_parse_error(TextStyle style, String text, int pos, Class expected) { - try { - getFormatter0(style).parseToBuilder(text, new ParsePosition(pos)); - assertTrue(false); - } catch (RuntimeException ex) { - assertTrue(expected.isInstance(ex)); - } - } - - //----------------------------------------------------------------------- - public void test_parse_exactMatch_Denver() throws Exception { - ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter0(null).parseToBuilder(AMERICA_DENVER, pos); - assertEquals(pos.getIndex(), AMERICA_DENVER.length()); - assertParsed(dtb, TIME_ZONE_DENVER); - } - - public void test_parse_startStringMatch_Denver() throws Exception { - ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter0(null).parseToBuilder(AMERICA_DENVER + "OTHER", pos); - assertEquals(pos.getIndex(), AMERICA_DENVER.length()); - assertParsed(dtb, TIME_ZONE_DENVER); - } - - public void test_parse_midStringMatch_Denver() throws Exception { - ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter0(null).parseToBuilder("OTHER" + AMERICA_DENVER + "OTHER", pos); - assertEquals(pos.getIndex(), 5 + AMERICA_DENVER.length()); - assertParsed(dtb, TIME_ZONE_DENVER); - } - - public void test_parse_endStringMatch_Denver() throws Exception { - ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter0(null).parseToBuilder("OTHER" + AMERICA_DENVER, pos); - assertEquals(pos.getIndex(), 5 + AMERICA_DENVER.length()); - assertParsed(dtb, TIME_ZONE_DENVER); - } - - public void test_parse_partialMatch() throws Exception { - ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter0(null).parseToBuilder("OTHERAmerica/Bogusville", pos); - assertEquals(pos.getErrorIndex(), 5); // TBD: -6 ? - assertEquals(dtb, null); - } - - //----------------------------------------------------------------------- - @DataProvider(name="zones") - Object[][] populateTestData() { - Set ids = ZoneRulesProvider.getAvailableZoneIds(); - Object[][] rtnval = new Object[ids.size()][]; - int i = 0; - for (String id : ids) { - rtnval[i++] = new Object[] { id, ZoneId.of(id) }; - } - return rtnval; - } - - @Test(dataProvider="zones") - public void test_parse_exactMatch(String parse, ZoneId expected) throws Exception { - ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter0(null).parseToBuilder(parse, pos); - assertEquals(pos.getIndex(), parse.length()); - assertParsed(dtb, expected); - } - - @Test(dataProvider="zones") - public void test_parse_startMatch(String parse, ZoneId expected) throws Exception { - String append = " OTHER"; - parse += append; - ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter0(null).parseToBuilder(parse, pos); - assertEquals(pos.getIndex(), parse.length() - append.length()); - assertParsed(dtb, expected); - } - - //----------------------------------------------------------------------- - public void test_parse_caseInsensitive() throws Exception { - DateTimeFormatter fmt = new DateTimeFormatterBuilder().appendZoneId().toFormatter(); - DateTimeFormatter fmtCI = new DateTimeFormatterBuilder().parseCaseInsensitive() - .appendZoneId() - .toFormatter(); - for (String zidStr : ZoneRulesProvider.getAvailableZoneIds()) { - ZoneId zid = ZoneId.of(zidStr); - assertEquals(fmt.parse(zidStr, Queries.zoneId()), zid); - assertEquals(fmtCI.parse(zidStr.toLowerCase(), Queries.zoneId()), zid); - assertEquals(fmtCI.parse(zidStr.toUpperCase(), Queries.zoneId()), zid); - ParsePosition pos = new ParsePosition(5); - assertEquals(fmtCI.parseToBuilder("OTHER" + zidStr.toLowerCase() + "OTHER", pos) - .query(Queries.zoneId()), zid); - assertEquals(pos.getIndex(), zidStr.length() + 5); - pos = new ParsePosition(5); - assertEquals(fmtCI.parseToBuilder("OTHER" + zidStr.toUpperCase() + "OTHER", pos) - .query(Queries.zoneId()), zid); - assertEquals(pos.getIndex(), zidStr.length() + 5); - } - } - - //----------------------------------------------------------------------- - /* - public void test_parse_endStringMatch_utc() throws Exception { - ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter0(null).parseToBuilder("OTHERUTC", pos); - assertEquals(pos.getIndex(), 8); - assertParsed(dtb, ZoneOffset.UTC); - } - - public void test_parse_endStringMatch_utc_plus1() throws Exception { - ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter0(null).parseToBuilder("OTHERUTC+01:00", pos); - assertEquals(pos.getIndex(), 14); - assertParsed(dtb, ZoneId.of("UTC+01:00")); - } - - //----------------------------------------------------------------------- - public void test_parse_midStringMatch_utc() throws Exception { - ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter0(null).parseToBuilder("OTHERUTCOTHER", pos); - assertEquals(pos.getIndex(), 8); - assertParsed(dtb, ZoneOffset.UTC); - } - - public void test_parse_midStringMatch_utc_plus1() throws Exception { - ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter0(null).parseToBuilder("OTHERUTC+01:00OTHER", pos); - assertEquals(pos.getIndex(), 14); - assertParsed(dtb, ZoneId.of("UTC+01:00")); - } - */ - //----------------------------------------------------------------------- - public void test_toString_id() { - assertEquals(getFormatter0(null).toString(), "ZoneId()"); - } - - public void test_toString_text() { - assertEquals(getFormatter0(TextStyle.FULL).toString(), "ZoneText(FULL)"); - } - - private void assertParsed(DateTimeBuilder dtb, ZoneId expectedZone) { - assertEquals(dtb.query(ZoneId::from), expectedZone); - } - -} diff --git a/jdk/test/java/time/test/java/time/format/TestZoneOffsetParser.java b/jdk/test/java/time/test/java/time/format/TestZoneOffsetParser.java index 300411cb2eb..2c9065b93a4 100644 --- a/jdk/test/java/time/test/java/time/format/TestZoneOffsetParser.java +++ b/jdk/test/java/time/test/java/time/format/TestZoneOffsetParser.java @@ -65,7 +65,7 @@ import static org.testng.Assert.assertTrue; import java.text.ParsePosition; import java.time.ZoneOffset; -import java.time.format.DateTimeBuilder; +import java.time.temporal.TemporalAccessor; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -88,7 +88,7 @@ public class TestZoneOffsetParser extends AbstractTestPrinterParser { @Test(dataProvider="error") public void test_parse_error(String pattern, String noOffsetText, String text, int pos, Class expected) { try { - getFormatter(pattern, noOffsetText).parseToBuilder(text, new ParsePosition(pos)); + getFormatter(pattern, noOffsetText).parseUnresolved(text, new ParsePosition(pos)); } catch (RuntimeException ex) { assertTrue(expected.isInstance(ex)); } @@ -97,59 +97,59 @@ public class TestZoneOffsetParser extends AbstractTestPrinterParser { //----------------------------------------------------------------------- public void test_parse_exactMatch_UTC() throws Exception { ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter("+HH:MM:ss", "Z").parseToBuilder("Z", pos); + TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("Z", pos); assertEquals(pos.getIndex(), 1); - assertParsed(dtb, ZoneOffset.UTC); + assertParsed(parsed, ZoneOffset.UTC); } public void test_parse_startStringMatch_UTC() throws Exception { ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter("+HH:MM:ss", "Z").parseToBuilder("ZOTHER", pos); + TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("ZOTHER", pos); assertEquals(pos.getIndex(), 1); - assertParsed(dtb, ZoneOffset.UTC); + assertParsed(parsed, ZoneOffset.UTC); } public void test_parse_midStringMatch_UTC() throws Exception { ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter("+HH:MM:ss", "Z").parseToBuilder("OTHERZOTHER", pos); + TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("OTHERZOTHER", pos); assertEquals(pos.getIndex(), 6); - assertParsed(dtb, ZoneOffset.UTC); + assertParsed(parsed, ZoneOffset.UTC); } public void test_parse_endStringMatch_UTC() throws Exception { ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter("+HH:MM:ss", "Z").parseToBuilder("OTHERZ", pos); + TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("OTHERZ", pos); assertEquals(pos.getIndex(), 6); - assertParsed(dtb, ZoneOffset.UTC); + assertParsed(parsed, ZoneOffset.UTC); } //----------------------------------------------------------------------- public void test_parse_exactMatch_UTC_EmptyUTC() throws Exception { ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter("+HH:MM:ss", "").parseToBuilder("", pos); + TemporalAccessor parsed = getFormatter("+HH:MM:ss", "").parseUnresolved("", pos); assertEquals(pos.getIndex(), 0); - assertParsed(dtb, ZoneOffset.UTC); + assertParsed(parsed, ZoneOffset.UTC); } public void test_parse_startStringMatch_UTC_EmptyUTC() throws Exception { ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter("+HH:MM:ss", "").parseToBuilder("OTHER", pos); + TemporalAccessor parsed = getFormatter("+HH:MM:ss", "").parseUnresolved("OTHER", pos); assertEquals(pos.getIndex(), 0); - assertParsed(dtb, ZoneOffset.UTC); + assertParsed(parsed, ZoneOffset.UTC); } public void test_parse_midStringMatch_UTC_EmptyUTC() throws Exception { ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter("+HH:MM:ss", "").parseToBuilder("OTHEROTHER", pos); + TemporalAccessor parsed = getFormatter("+HH:MM:ss", "").parseUnresolved("OTHEROTHER", pos); assertEquals(pos.getIndex(), 5); - assertParsed(dtb, ZoneOffset.UTC); + assertParsed(parsed, ZoneOffset.UTC); } public void test_parse_endStringMatch_UTC_EmptyUTC() throws Exception { ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter("+HH:MM:ss", "").parseToBuilder("OTHER", pos); + TemporalAccessor parsed = getFormatter("+HH:MM:ss", "").parseUnresolved("OTHER", pos); assertEquals(pos.getIndex(), 5); - assertParsed(dtb, ZoneOffset.UTC); + assertParsed(parsed, ZoneOffset.UTC); } //----------------------------------------------------------------------- @@ -231,65 +231,65 @@ public class TestZoneOffsetParser extends AbstractTestPrinterParser { @Test(dataProvider="offsets") public void test_parse_exactMatch(String pattern, String parse, ZoneOffset expected) throws Exception { ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter(pattern, "Z").parseToBuilder(parse, pos); + TemporalAccessor parsed = getFormatter(pattern, "Z").parseUnresolved(parse, pos); assertEquals(pos.getIndex(), parse.length()); - assertParsed(dtb, expected); + assertParsed(parsed, expected); } @Test(dataProvider="offsets") public void test_parse_startStringMatch(String pattern, String parse, ZoneOffset expected) throws Exception { ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter(pattern, "Z").parseToBuilder(parse + ":OTHER", pos); + TemporalAccessor parsed = getFormatter(pattern, "Z").parseUnresolved(parse + ":OTHER", pos); assertEquals(pos.getIndex(), parse.length()); - assertParsed(dtb, expected); + assertParsed(parsed, expected); } @Test(dataProvider="offsets") public void test_parse_midStringMatch(String pattern, String parse, ZoneOffset expected) throws Exception { ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter(pattern, "Z").parseToBuilder("OTHER" + parse + ":OTHER", pos); + TemporalAccessor parsed = getFormatter(pattern, "Z").parseUnresolved("OTHER" + parse + ":OTHER", pos); assertEquals(pos.getIndex(), parse.length() + 5); - assertParsed(dtb, expected); + assertParsed(parsed, expected); } @Test(dataProvider="offsets") public void test_parse_endStringMatch(String pattern, String parse, ZoneOffset expected) throws Exception { ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter(pattern, "Z").parseToBuilder("OTHER" + parse, pos); + TemporalAccessor parsed = getFormatter(pattern, "Z").parseUnresolved("OTHER" + parse, pos); assertEquals(pos.getIndex(), parse.length() + 5); - assertParsed(dtb, expected); + assertParsed(parsed, expected); } @Test(dataProvider="offsets") public void test_parse_exactMatch_EmptyUTC(String pattern, String parse, ZoneOffset expected) throws Exception { ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter(pattern, "").parseToBuilder(parse, pos); + TemporalAccessor parsed = getFormatter(pattern, "").parseUnresolved(parse, pos); assertEquals(pos.getIndex(), parse.length()); - assertParsed(dtb, expected); + assertParsed(parsed, expected); } @Test(dataProvider="offsets") public void test_parse_startStringMatch_EmptyUTC(String pattern, String parse, ZoneOffset expected) throws Exception { ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter(pattern, "").parseToBuilder(parse + ":OTHER", pos); + TemporalAccessor parsed = getFormatter(pattern, "").parseUnresolved(parse + ":OTHER", pos); assertEquals(pos.getIndex(), parse.length()); - assertParsed(dtb, expected); + assertParsed(parsed, expected); } @Test(dataProvider="offsets") public void test_parse_midStringMatch_EmptyUTC(String pattern, String parse, ZoneOffset expected) throws Exception { ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter(pattern, "").parseToBuilder("OTHER" + parse + ":OTHER", pos); + TemporalAccessor parsed = getFormatter(pattern, "").parseUnresolved("OTHER" + parse + ":OTHER", pos); assertEquals(pos.getIndex(), parse.length() + 5); - assertParsed(dtb, expected); + assertParsed(parsed, expected); } @Test(dataProvider="offsets") public void test_parse_endStringMatch_EmptyUTC(String pattern, String parse, ZoneOffset expected) throws Exception { ParsePosition pos = new ParsePosition(5); - DateTimeBuilder dtb = getFormatter(pattern, "").parseToBuilder("OTHER" + parse, pos); + TemporalAccessor parsed = getFormatter(pattern, "").parseUnresolved("OTHER" + parse, pos); assertEquals(pos.getIndex(), parse.length() + 5); - assertParsed(dtb, expected); + assertParsed(parsed, expected); } //----------------------------------------------------------------------- @@ -322,9 +322,9 @@ public class TestZoneOffsetParser extends AbstractTestPrinterParser { @Test(dataProvider="bigOffsets") public void test_parse_bigOffsets(String pattern, String parse, long offsetSecs) throws Exception { ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter(pattern, "").parseToBuilder(parse, pos); + TemporalAccessor parsed = getFormatter(pattern, "").parseUnresolved(parse, pos); assertEquals(pos.getIndex(), parse.length()); - assertEquals(dtb.getLong(OFFSET_SECONDS), offsetSecs); + assertEquals(parsed.getLong(OFFSET_SECONDS), offsetSecs); } //----------------------------------------------------------------------- @@ -393,8 +393,9 @@ public class TestZoneOffsetParser extends AbstractTestPrinterParser { @Test(dataProvider="badOffsets") public void test_parse_invalid(String pattern, String parse, int expectedPosition) throws Exception { ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter(pattern, "Z").parseToBuilder(parse, pos); + TemporalAccessor parsed = getFormatter(pattern, "Z").parseUnresolved(parse, pos); assertEquals(pos.getErrorIndex(), expectedPosition); + assertEquals(parsed, null); } //----------------------------------------------------------------------- @@ -403,41 +404,41 @@ public class TestZoneOffsetParser extends AbstractTestPrinterParser { public void test_parse_caseSensitiveUTC_matchedCase() throws Exception { setCaseSensitive(true); ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter("+HH:MM:ss", "Z").parseToBuilder("Z", pos); + TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("Z", pos); assertEquals(pos.getIndex(), 1); - assertParsed(dtb, ZoneOffset.UTC); + assertParsed(parsed, ZoneOffset.UTC); } public void test_parse_caseSensitiveUTC_unmatchedCase() throws Exception { setCaseSensitive(true); ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter("+HH:MM:ss", "Z").parseToBuilder("z", pos); + TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("z", pos); assertEquals(pos.getErrorIndex(), 0); - assertEquals(dtb, null); + assertEquals(parsed, null); } public void test_parse_caseInsensitiveUTC_matchedCase() throws Exception { setCaseSensitive(false); ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter("+HH:MM:ss", "Z").parseToBuilder("Z", pos); + TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("Z", pos); assertEquals(pos.getIndex(), 1); - assertParsed(dtb, ZoneOffset.UTC); + assertParsed(parsed, ZoneOffset.UTC); } public void test_parse_caseInsensitiveUTC_unmatchedCase() throws Exception { setCaseSensitive(false); ParsePosition pos = new ParsePosition(0); - DateTimeBuilder dtb = getFormatter("+HH:MM:ss", "Z").parseToBuilder("z", pos); + TemporalAccessor parsed = getFormatter("+HH:MM:ss", "Z").parseUnresolved("z", pos); assertEquals(pos.getIndex(), 1); - assertParsed(dtb, ZoneOffset.UTC); + assertParsed(parsed, ZoneOffset.UTC); } - private void assertParsed(DateTimeBuilder dtb, ZoneOffset expectedOffset) { + private void assertParsed(TemporalAccessor parsed, ZoneOffset expectedOffset) { if (expectedOffset == null) { - assertEquals(dtb, null); + assertEquals(parsed, null); } else { - assertEquals(dtb.getFieldValueMap().size(), 1); - assertEquals(dtb.getLong(OFFSET_SECONDS), (long) expectedOffset.getTotalSeconds()); + assertEquals(parsed.isSupported(OFFSET_SECONDS), true); + assertEquals(parsed.getLong(OFFSET_SECONDS), (long) expectedOffset.getTotalSeconds()); } } diff --git a/jdk/test/java/time/test/java/time/format/TestZoneOffsetPrinter.java b/jdk/test/java/time/test/java/time/format/TestZoneOffsetPrinter.java index e4250900b05..c84ad05a479 100644 --- a/jdk/test/java/time/test/java/time/format/TestZoneOffsetPrinter.java +++ b/jdk/test/java/time/test/java/time/format/TestZoneOffsetPrinter.java @@ -59,12 +59,10 @@ */ package test.java.time.format; -import static java.time.temporal.ChronoField.OFFSET_SECONDS; import static org.testng.Assert.assertEquals; import java.time.DateTimeException; import java.time.ZoneOffset; -import java.time.format.DateTimeBuilder; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -150,25 +148,25 @@ public class TestZoneOffsetPrinter extends AbstractTestPrinterParser { } @Test(dataProvider="offsets") - public void test_print(String pattern, String expected, ZoneOffset offset) throws Exception { + public void test_format(String pattern, String expected, ZoneOffset offset) throws Exception { buf.append("EXISTING"); - getFormatter(pattern, "NO-OFFSET").printTo(new DateTimeBuilder(OFFSET_SECONDS, offset.getTotalSeconds()), buf); + getFormatter(pattern, "NO-OFFSET").formatTo(offset, buf); assertEquals(buf.toString(), "EXISTING" + expected); } @Test(dataProvider="offsets") public void test_toString(String pattern, String expected, ZoneOffset offset) throws Exception { - assertEquals(getFormatter(pattern, "NO-OFFSET").toString(), "Offset('NO-OFFSET'," + pattern + ")"); + assertEquals(getFormatter(pattern, "NO-OFFSET").toString(), "Offset(" + pattern + ",'NO-OFFSET')"); } //----------------------------------------------------------------------- @Test(expectedExceptions=DateTimeException.class) public void test_print_emptyCalendrical() throws Exception { - getFormatter("+HH:MM:ss", "Z").printTo(EMPTY_DTA, buf); + getFormatter("+HH:MM:ss", "Z").formatTo(EMPTY_DTA, buf); } public void test_print_emptyAppendable() throws Exception { - getFormatter("+HH:MM:ss", "Z").printTo(new DateTimeBuilder(OFFSET_SECONDS, OFFSET_0130.getTotalSeconds()), buf); + getFormatter("+HH:MM:ss", "Z").formatTo(OFFSET_0130, buf); assertEquals(buf.toString(), "+01:30"); } diff --git a/jdk/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java b/jdk/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java index 0f58634b655..a7d63e8c47b 100644 --- a/jdk/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java +++ b/jdk/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java @@ -23,7 +23,10 @@ package test.java.time.format; +import java.text.DateFormatSymbols; +import java.util.Arrays; import java.util.Date; +import java.util.HashSet; import java.util.Locale; import java.util.Random; import java.util.Set; @@ -32,12 +35,14 @@ import java.util.TimeZone; import java.time.ZonedDateTime; import java.time.ZoneId; import java.time.temporal.ChronoField; +import java.time.temporal.Queries; import java.time.format.DateTimeFormatSymbols; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.TextStyle; import java.time.zone.ZoneRulesProvider; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; @@ -65,6 +70,12 @@ public class TestZoneTextPrinterParser extends AbstractTestPrinterParser { zdt = zdt.withDayOfYear(r.nextInt(365) + 1) .with(ChronoField.SECOND_OF_DAY, r.nextInt(86400)); for (String zid : zids) { + if (zid.equals("ROC") || + zid.startsWith("UTC") || + zid.startsWith("GMT") || zid.startsWith("Etc/GMT")) { + // UTC, GMT are treated as zone offset + continue; // TBD: match jdk behavior? + } zdt = zdt.withZoneSameLocal(ZoneId.of(zid)); TimeZone tz = TimeZone.getTimeZone(zid); boolean isDST = tz.inDaylightTime(new Date(zdt.toInstant().toEpochMilli())); @@ -79,10 +90,9 @@ public class TestZoneTextPrinterParser extends AbstractTestPrinterParser { } private void printText(Locale locale, ZonedDateTime zdt, TextStyle style, String expected) { - String result = getFormatter(locale, style).print(zdt); + String result = getFormatter(locale, style).format(zdt); if (!result.equals(expected)) { - if (result.equals("FooLocation") || // from rules provider test if same vm - result.startsWith("Etc/GMT") || result.equals("ROC")) { // TBD: match jdk behavior? + if (result.equals("FooLocation")) { // from rules provider test if same vm return; } System.out.println("----------------"); @@ -92,4 +102,117 @@ public class TestZoneTextPrinterParser extends AbstractTestPrinterParser { } assertEquals(result, expected); } + + public void test_ParseText() { + Locale[] locales = new Locale[] { Locale.ENGLISH, Locale.JAPANESE, Locale.FRENCH }; + Set zids = ZoneRulesProvider.getAvailableZoneIds(); + for (Locale locale : locales) { + parseText(zids, locale, TextStyle.FULL, false); + parseText(zids, locale, TextStyle.FULL, true); + parseText(zids, locale, TextStyle.SHORT, false); + parseText(zids, locale, TextStyle.SHORT, true); + } + } + + private static Set preferred = new HashSet<>(Arrays.asList(new ZoneId[] { + ZoneId.of("EST"), + ZoneId.of("Asia/Taipei"), + ZoneId.of("CET"), + })); + + private static Set preferred_s = new HashSet<>(Arrays.asList(new ZoneId[] { + ZoneId.of("EST"), + ZoneId.of("CET"), + ZoneId.of("Australia/South"), + ZoneId.of("Australia/West"), + ZoneId.of("Asia/Shanghai"), + })); + + private static Set none = new HashSet<>(); + + @DataProvider(name="preferredZones") + Object[][] data_preferredZones() { + return new Object[][] { + {"America/New_York", "Eastern Standard Time", none, Locale.ENGLISH, TextStyle.FULL}, + {"EST", "Eastern Standard Time", preferred, Locale.ENGLISH, TextStyle.FULL}, + {"Europe/Paris", "Central European Time", none, Locale.ENGLISH, TextStyle.FULL}, + {"CET", "Central European Time", preferred, Locale.ENGLISH, TextStyle.FULL}, + {"Asia/Shanghai", "China Standard Time", none, Locale.ENGLISH, TextStyle.FULL}, + {"Asia/Taipei", "China Standard Time", preferred, Locale.ENGLISH, TextStyle.FULL}, + {"America/Chicago", "CST", none, Locale.ENGLISH, TextStyle.SHORT}, + {"Asia/Taipei", "CST", preferred, Locale.ENGLISH, TextStyle.SHORT}, + {"Australia/South", "CST", preferred_s, Locale.ENGLISH, TextStyle.SHORT}, + {"America/Chicago", "CDT", none, Locale.ENGLISH, TextStyle.SHORT}, + {"Asia/Shanghai", "CDT", preferred_s, Locale.ENGLISH, TextStyle.SHORT}, + }; + } + + @Test(dataProvider="preferredZones") + public void test_ParseText(String expected, String text, Set preferred, Locale locale, TextStyle style) { + DateTimeFormatter fmt = new DateTimeFormatterBuilder().appendZoneText(style, preferred) + .toFormatter(locale) + .withSymbols(DateTimeFormatSymbols.of(locale)); + + String ret = fmt.parse(text, Queries.zone()).getId(); + + System.out.printf("[%-5s %s] %24s -> %s(%s)%n", + locale.toString(), + style == TextStyle.FULL ? " full" :"short", + text, ret, expected); + + assertEquals(ret, expected); + + } + + + private void parseText(Set zids, Locale locale, TextStyle style, boolean ci) { + System.out.println("---------------------------------------"); + DateTimeFormatter fmt = getFormatter(locale, style, ci); + for (String[] names : new DateFormatSymbols(locale).getZoneStrings()) { + if (!zids.contains(names[0])) { + continue; + } + String zid = names[0]; + String expected = ZoneName.toZid(zid, locale); + + parse(fmt, zid, expected, zid, locale, style, ci); + int i = style == TextStyle.FULL ? 1 : 2; + for (; i < names.length; i += 2) { + parse(fmt, zid, expected, names[i], locale, style, ci); + } + } + } + + private void parse(DateTimeFormatter fmt, + String zid, String expected, String text, + Locale locale, TextStyle style, boolean ci) { + if (ci) { + text = text.toUpperCase(); + } + String ret = fmt.parse(text, Queries.zone()).getId(); + // TBD: need an excluding list + // assertEquals(...); + if (ret.equals(expected) || + ret.equals(zid) || + ret.equals(ZoneName.toZid(zid)) || + ret.equals(expected.replace("UTC", "UCT"))) { + return; + } + System.out.printf("[%-5s %s %s %16s] %24s -> %s(%s)%n", + locale.toString(), + ci ? "ci" : " ", + style == TextStyle.FULL ? " full" :"short", + zid, text, ret, expected); + } + + private DateTimeFormatter getFormatter(Locale locale, TextStyle style, boolean ci) { + DateTimeFormatterBuilder db = new DateTimeFormatterBuilder(); + if (ci) { + db = db.parseCaseInsensitive(); + } + return db.appendZoneText(style) + .toFormatter(locale) + .withSymbols(DateTimeFormatSymbols.of(locale)); + } + } diff --git a/jdk/test/java/time/test/java/time/format/ZoneName.java b/jdk/test/java/time/test/java/time/format/ZoneName.java new file mode 100644 index 00000000000..4ae5b43f30b --- /dev/null +++ b/jdk/test/java/time/test/java/time/format/ZoneName.java @@ -0,0 +1,780 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 test.java.time.format; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +class ZoneName { + + public static String toZid(String zid, Locale locale) { + String mzone = zidToMzone.get(zid); + if (mzone == null && aliases.containsKey(zid)) { + zid = aliases.get(zid); + mzone = zidToMzone.get(zid); + } + if (mzone != null) { + Map map = mzoneToZidL.get(mzone); + if (map != null && map.containsKey(locale.getCountry())) { + zid = map.get(locale.getCountry()); + } else { + zid = mzoneToZid.get(mzone); + } + } + return toZid(zid); + } + + public static String toZid(String zid) { + if (aliases.containsKey(zid)) { + return aliases.get(zid); + } + return zid; + } + + private static final String[] zidMap = new String[] { + "Asia/Bangkok", "Indochina", "Asia/Saigon", + "Pacific/Pago_Pago", "Samoa", "Pacific/Apia", + "Africa/Blantyre", "Africa_Central", "Africa/Maputo", + "America/Argentina/San_Juan", "Argentina", "America/Buenos_Aires", + "America/Cancun", "America_Central", "America/Chicago", + "Pacific/Nauru", "Nauru", "Pacific/Nauru", + "America/Atikokan", "America_Eastern", "America/New_York", + "Africa/Asmara", "Africa_Eastern", "Africa/Nairobi", + "Europe/Berlin", "Europe_Central", "Europe/Paris", + "Asia/Kolkata", "India", "Asia/Calcutta", + "Australia/Darwin", "Australia_Central", "Australia/Adelaide", + "America/Guayaquil", "Ecuador", "America/Guayaquil", + "Europe/Vienna", "Europe_Central", "Europe/Paris", + "Atlantic/St_Helena", "GMT", "Atlantic/Reykjavik", + "Europe/London", "GMT", "Atlantic/Reykjavik", + "Europe/Moscow", "Moscow", "Europe/Moscow", + "America/St_Vincent", "Atlantic", "America/Halifax", + "America/Bogota", "Colombia", "America/Bogota", + "America/Marigot", "Atlantic", "America/Halifax", + "Europe/Sarajevo", "Europe_Central", "Europe/Paris", + "America/Hermosillo", "America_Mountain", "America/Denver", + "America/Winnipeg", "America_Central", "America/Chicago", + "America/Rainy_River", "America_Central", "America/Chicago", + "Indian/Mahe", "Seychelles", "Indian/Mahe", + "Africa/Freetown", "GMT", "Atlantic/Reykjavik", + "America/Grand_Turk", "America_Eastern", "America/New_York", + "America/Argentina/Ushuaia", "Argentina", "America/Buenos_Aires", + "Atlantic/Azores", "Azores", "Atlantic/Azores", + "Asia/Harbin", "China", "Asia/Shanghai", + "America/Cuiaba", "Amazon", "America/Manaus", + "Asia/Bahrain", "Arabian", "Asia/Riyadh", + "Asia/Katmandu", "Nepal", "Asia/Katmandu", + "Pacific/Galapagos", "Galapagos", "Pacific/Galapagos", + "Asia/Brunei", "Brunei", "Asia/Brunei", + "Africa/Kigali", "Africa_Central", "Africa/Maputo", + "Asia/Makassar", "Indonesia_Central", "Asia/Makassar", + "Africa/Maputo", "Africa_Central", "Africa/Maputo", + "Asia/Kamchatka", "Magadan", "Asia/Magadan", + "Atlantic/Faroe", "Europe_Western", "Atlantic/Canary", + "America/El_Salvador", "America_Central", "America/Chicago", + "Asia/Saigon", "Indochina", "Asia/Saigon", + "Africa/Kinshasa", "Africa_Western", "Africa/Lagos", + "Europe/Oslo", "Europe_Central", "Europe/Paris", + "Asia/Hong_Kong", "Hong_Kong", "Asia/Hong_Kong", + "Pacific/Midway", "Samoa", "Pacific/Apia", + "Africa/Douala", "Africa_Western", "Africa/Lagos", + "Europe/San_Marino", "Europe_Central", "Europe/Paris", + "Pacific/Chuuk", "Truk", "Pacific/Truk", + "Africa/Gaborone", "Africa_Central", "Africa/Maputo", + "Africa/Tunis", "Europe_Central", "Europe/Paris", + "Africa/Khartoum", "Africa_Eastern", "Africa/Nairobi", + "Europe/Isle_of_Man", "GMT", "Atlantic/Reykjavik", + "Europe/Skopje", "Europe_Central", "Europe/Paris", + "America/Merida", "America_Central", "America/Chicago", + "Antarctica/DumontDUrville", "DumontDUrville", "Antarctica/DumontDUrville", + "Atlantic/Reykjavik", "GMT", "Atlantic/Reykjavik", + "Indian/Mauritius", "Mauritius", "Indian/Mauritius", + "Africa/Malabo", "Africa_Western", "Africa/Lagos", + "Africa/Juba", "Africa_Eastern", "Africa/Nairobi", + "America/Resolute", "America_Central", "America/Chicago", + "Africa/Abidjan", "GMT", "Atlantic/Reykjavik", + "Antarctica/McMurdo", "New_Zealand", "Pacific/Auckland", + "Asia/Thimphu", "Bhutan", "Asia/Thimphu", + "Europe/Zaporozhye", "Europe_Eastern", "Europe/Bucharest", + "Antarctica/Davis", "Davis", "Antarctica/Davis", + "Indian/Antananarivo", "Africa_Eastern", "Africa/Nairobi", + "Africa/Harare", "Africa_Central", "Africa/Maputo", + "Pacific/Marquesas", "Marquesas", "Pacific/Marquesas", + "Africa/Tripoli", "Europe_Eastern", "Europe/Bucharest", + "America/North_Dakota/Beulah", "America_Central", "America/Chicago", + "America/Buenos_Aires", "Argentina", "America/Buenos_Aires", + "America/Tortola", "Atlantic", "America/Halifax", + "Asia/Kuwait", "Arabian", "Asia/Riyadh", + "Europe/Rome", "Europe_Central", "Europe/Paris", + "America/Eirunepe", "Amazon", "America/Manaus", + "Australia/Hobart", "Australia_Eastern", "Australia/Sydney", + "America/Thule", "Atlantic", "America/Halifax", + "Asia/Beirut", "Europe_Eastern", "Europe/Bucharest", + "America/Bahia_Banderas", "America_Central", "America/Chicago", + "Africa/Dar_es_Salaam", "Africa_Eastern", "Africa/Nairobi", + "America/Argentina/Tucuman", "Argentina", "America/Buenos_Aires", + "America/Paramaribo", "Suriname", "America/Paramaribo", + "Africa/Kampala", "Africa_Eastern", "Africa/Nairobi", + "Pacific/Port_Moresby", "Papua_New_Guinea", "Pacific/Port_Moresby", + "America/Mendoza", "Argentina", "America/Buenos_Aires", + "Asia/Dushanbe", "Tajikistan", "Asia/Dushanbe", + "Asia/Qyzylorda", "Kazakhstan_Eastern", "Asia/Almaty", + "Antarctica/Vostok", "Vostok", "Antarctica/Vostok", + "Pacific/Majuro", "Marshall_Islands", "Pacific/Majuro", + "Asia/Tehran", "Iran", "Asia/Tehran", + "Asia/Hovd", "Hovd", "Asia/Hovd", + "Antarctica/Rothera", "Rothera", "Antarctica/Rothera", + "Africa/Brazzaville", "Africa_Western", "Africa/Lagos", + "Europe/Tirane", "Europe_Central", "Europe/Paris", + "Asia/Urumqi", "China", "Asia/Shanghai", + "Asia/Krasnoyarsk", "Krasnoyarsk", "Asia/Krasnoyarsk", + "America/Tegucigalpa", "America_Central", "America/Chicago", + "Asia/Vientiane", "Indochina", "Asia/Saigon", + "Asia/Pontianak", "Indonesia_Western", "Asia/Jakarta", + "America/Bahia", "Brasilia", "America/Sao_Paulo", + "Asia/Choibalsan", "Choibalsan", "Asia/Choibalsan", + "America/Regina", "America_Central", "America/Chicago", + "Africa/Cairo", "Europe_Eastern", "Europe/Bucharest", + "Asia/Irkutsk", "Irkutsk", "Asia/Irkutsk", + "Europe/Luxembourg", "Europe_Central", "Europe/Paris", + "America/St_Kitts", "Atlantic", "America/Halifax", + "America/Manaus", "Amazon", "America/Manaus", + "America/Noronha", "Noronha", "America/Noronha", + "Pacific/Gambier", "Gambier", "Pacific/Gambier", + "America/Edmonton", "America_Mountain", "America/Denver", + "Pacific/Palau", "Palau", "Pacific/Palau", + "America/Lower_Princes", "Atlantic", "America/Halifax", + "Africa/Ouagadougou", "GMT", "Atlantic/Reykjavik", + "Asia/Yerevan", "Armenia", "Asia/Yerevan", + "America/Montevideo", "Uruguay", "America/Montevideo", + "Europe/Minsk", "Europe_Eastern", "Europe/Bucharest", + "Europe/Amsterdam", "Europe_Central", "Europe/Paris", + "Pacific/Efate", "Vanuatu", "Pacific/Efate", + "Asia/Manila", "Philippines", "Asia/Manila", + "America/Dawson", "America_Pacific", "America/Los_Angeles", + "America/Argentina/Cordoba", "Argentina", "America/Buenos_Aires", + "Australia/Melbourne", "Australia_Eastern", "Australia/Sydney", + "Asia/Rangoon", "Myanmar", "Asia/Rangoon", + "America/Los_Angeles", "America_Pacific", "America/Los_Angeles", + "Africa/Casablanca", "Europe_Western", "Atlantic/Canary", + "Africa/Porto-Novo", "Africa_Western", "Africa/Lagos", + "Asia/Macau", "China", "Asia/Shanghai", + "America/Boa_Vista", "Amazon", "America/Manaus", + "Europe/Guernsey", "GMT", "Atlantic/Reykjavik", + "Africa/Monrovia", "GMT", "Atlantic/Reykjavik", + "America/Godthab", "Greenland_Western", "America/Godthab", + "Africa/Ceuta", "Europe_Central", "Europe/Paris", + "Asia/Oral", "Kazakhstan_Western", "Asia/Aqtobe", + "America/Yakutat", "Alaska", "America/Juneau", + "Indian/Mayotte", "Africa_Eastern", "Africa/Nairobi", + "America/Denver", "America_Mountain", "America/Denver", + "America/New_York", "America_Eastern", "America/New_York", + "Pacific/Rarotonga", "Cook", "Pacific/Rarotonga", + "America/Louisville", "America_Eastern", "America/New_York", + "Africa/El_Aaiun", "Europe_Western", "Atlantic/Canary", + "Africa/Sao_Tome", "GMT", "Atlantic/Reykjavik", + "Pacific/Fiji", "Fiji", "Pacific/Fiji", + "Asia/Damascus", "Europe_Eastern", "Europe/Bucharest", + "Asia/Ulaanbaatar", "Mongolia", "Asia/Ulaanbaatar", + "America/Cayman", "America_Eastern", "America/New_York", + "America/Tijuana", "America_Pacific", "America/Los_Angeles", + "Atlantic/Bermuda", "Atlantic", "America/Halifax", + "Australia/Sydney", "Australia_Eastern", "Australia/Sydney", + "Asia/Aden", "Arabian", "Asia/Riyadh", + "Australia/Eucla", "Australia_CentralWestern", "Australia/Eucla", + "America/Indiana/Petersburg", "America_Eastern", "America/New_York", + "America/Panama", "America_Eastern", "America/New_York", + "Europe/Istanbul", "Europe_Eastern", "Europe/Bucharest", + "America/Kralendijk", "Atlantic", "America/Halifax", + "America/Catamarca", "Argentina", "America/Buenos_Aires", + "America/Nassau", "America_Eastern", "America/New_York", + "Europe/Paris", "Europe_Central", "Europe/Paris", + "Asia/Jakarta", "Indonesia_Western", "Asia/Jakarta", + "Australia/Lindeman", "Australia_Eastern", "Australia/Sydney", + "America/Sao_Paulo", "Brasilia", "America/Sao_Paulo", + "America/Juneau", "Alaska", "America/Juneau", + "America/Grenada", "Atlantic", "America/Halifax", + "America/Cayenne", "French_Guiana", "America/Cayenne", + "Antarctica/Casey", "Australia_Western", "Australia/Perth", + "Africa/Algiers", "Europe_Central", "Europe/Paris", + "America/Miquelon", "Pierre_Miquelon", "America/Miquelon", + "Asia/Tokyo", "Japan", "Asia/Tokyo", + "Africa/Windhoek", "Africa_Western", "Africa/Lagos", + "Africa/Bujumbura", "Africa_Central", "Africa/Maputo", + "America/Guatemala", "America_Central", "America/Chicago", + "Africa/Dakar", "GMT", "Atlantic/Reykjavik", + "Asia/Bishkek", "Kyrgystan", "Asia/Bishkek", + "America/Guadeloupe", "Atlantic", "America/Halifax", + "Africa/Ndjamena", "Africa_Western", "Africa/Lagos", + "Europe/Simferopol", "Europe_Eastern", "Europe/Bucharest", + "America/Santa_Isabel", "America_Pacific", "America/Los_Angeles", + "Asia/Dubai", "Gulf", "Asia/Dubai", + "America/Maceio", "Brasilia", "America/Sao_Paulo", + "America/Anchorage", "Alaska", "America/Juneau", + "Australia/Currie", "Australia_Eastern", "Australia/Sydney", + "Africa/Djibouti", "Africa_Eastern", "Africa/Nairobi", + "Europe/Budapest", "Europe_Central", "Europe/Paris", + "America/Argentina/Salta", "Argentina", "America/Buenos_Aires", + "Asia/Calcutta", "India", "Asia/Calcutta", + "America/Indiana/Winamac", "America_Eastern", "America/New_York", + "Asia/Yekaterinburg", "Yekaterinburg", "Asia/Yekaterinburg", + "America/Santiago", "Chile", "America/Santiago", + "Asia/Aqtobe", "Kazakhstan_Western", "Asia/Aqtobe", + "Asia/Dili", "East_Timor", "Asia/Dili", + "America/Detroit", "America_Eastern", "America/New_York", + "Africa/Libreville", "Africa_Western", "Africa/Lagos", + "Pacific/Ponape", "Ponape", "Pacific/Ponape", + "Pacific/Wallis", "Wallis", "Pacific/Wallis", + "Asia/Vladivostok", "Vladivostok", "Asia/Vladivostok", + "Africa/Lubumbashi", "Africa_Central", "Africa/Maputo", + "Africa/Asmera", "Africa_Eastern", "Africa/Nairobi", + "Pacific/Guam", "Chamorro", "Pacific/Saipan", + "America/Chicago", "America_Central", "America/Chicago", + "America/Swift_Current", "America_Central", "America/Chicago", + "America/Coral_Harbour", "America_Eastern", "America/New_York", + "America/Cambridge_Bay", "America_Mountain", "America/Denver", + "America/Costa_Rica", "America_Central", "America/Chicago", + "America/Curacao", "Atlantic", "America/Halifax", + "America/Recife", "Brasilia", "America/Sao_Paulo", + "Africa/Bangui", "Africa_Western", "Africa/Lagos", + "America/Cordoba", "Argentina", "America/Buenos_Aires", + "Asia/Baghdad", "Arabian", "Asia/Riyadh", + "America/Shiprock", "America_Mountain", "America/Denver", + "America/Glace_Bay", "Atlantic", "America/Halifax", + "America/North_Dakota/Center", "America_Central", "America/Chicago", + "Europe/Stockholm", "Europe_Central", "Europe/Paris", + "America/Halifax", "Atlantic", "America/Halifax", + "Atlantic/Canary", "Europe_Western", "Atlantic/Canary", + "Europe/Volgograd", "Volgograd", "Europe/Volgograd", + "America/Moncton", "Atlantic", "America/Halifax", + "Pacific/Tongatapu", "Tonga", "Pacific/Tongatapu", + "America/Argentina/Buenos_Aires", "Argentina", "America/Buenos_Aires", + "Asia/Samarkand", "Uzbekistan", "Asia/Tashkent", + "Pacific/Apia", "Samoa", "Pacific/Apia", + "America/Sitka", "Alaska", "America/Juneau", + "Europe/Warsaw", "Europe_Central", "Europe/Paris", + "Africa/Accra", "GMT", "Atlantic/Reykjavik", + "Europe/Bratislava", "Europe_Central", "Europe/Paris", + "Europe/Zurich", "Europe_Central", "Europe/Paris", + "Indian/Reunion", "Reunion", "Indian/Reunion", + "America/Mazatlan", "America_Mountain", "America/Denver", + "Pacific/Tarawa", "Gilbert_Islands", "Pacific/Tarawa", + "America/Indiana/Knox", "America_Central", "America/Chicago", + "Asia/Tbilisi", "Georgia", "Asia/Tbilisi", + "Asia/Novosibirsk", "Novosibirsk", "Asia/Novosibirsk", + "Atlantic/Faeroe", "Europe_Western", "Atlantic/Canary", + "Africa/Bissau", "GMT", "Atlantic/Reykjavik", + "Asia/Amman", "Europe_Eastern", "Europe/Bucharest", + "Africa/Lagos", "Africa_Western", "Africa/Lagos", + "Africa/Banjul", "GMT", "Atlantic/Reykjavik", + "America/Araguaina", "Brasilia", "America/Sao_Paulo", + "America/Nipigon", "America_Eastern", "America/New_York", + "Europe/Vilnius", "Europe_Eastern", "Europe/Bucharest", + "America/Montserrat", "Atlantic", "America/Halifax", + "Asia/Baku", "Azerbaijan", "Asia/Baku", + "Africa/Lusaka", "Africa_Central", "Africa/Maputo", + "Europe/Uzhgorod", "Europe_Eastern", "Europe/Bucharest", + "America/Argentina/Rio_Gallegos", "Argentina", "America/Buenos_Aires", + "America/Blanc-Sablon", "Atlantic", "America/Halifax", + "Asia/Kabul", "Afghanistan", "Asia/Kabul", + "America/Jamaica", "America_Eastern", "America/New_York", + "Europe/Vatican", "Europe_Central", "Europe/Paris", + "Africa/Nouakchott", "GMT", "Atlantic/Reykjavik", + "Africa/Addis_Ababa", "Africa_Eastern", "Africa/Nairobi", + "Europe/Athens", "Europe_Eastern", "Europe/Bucharest", + "Atlantic/Madeira", "Europe_Western", "Atlantic/Canary", + "America/Thunder_Bay", "America_Eastern", "America/New_York", + "Europe/Brussels", "Europe_Central", "Europe/Paris", + "Africa/Luanda", "Africa_Western", "Africa/Lagos", + "Africa/Mogadishu", "Africa_Eastern", "Africa/Nairobi", + "America/Matamoros", "America_Central", "America/Chicago", + "Pacific/Norfolk", "Norfolk", "Pacific/Norfolk", + "America/Scoresbysund", "Greenland_Eastern", "America/Scoresbysund", + "America/Indianapolis", "America_Eastern", "America/New_York", + "Pacific/Pitcairn", "Pitcairn", "Pacific/Pitcairn", + "Asia/Singapore", "Singapore", "Asia/Singapore", + "America/Port-au-Prince", "America_Eastern", "America/New_York", + "Pacific/Honolulu", "Hawaii_Aleutian", "Pacific/Honolulu", + "Antarctica/Syowa", "Syowa", "Antarctica/Syowa", + "Atlantic/Cape_Verde", "Cape_Verde", "Atlantic/Cape_Verde", + "America/Asuncion", "Paraguay", "America/Asuncion", + "America/Martinique", "Atlantic", "America/Halifax", + "Europe/Gibraltar", "Europe_Central", "Europe/Paris", + "Africa/Lome", "GMT", "Atlantic/Reykjavik", + "Australia/Lord_Howe", "Lord_Howe", "Australia/Lord_Howe", + "America/Argentina/La_Rioja", "Argentina", "America/Buenos_Aires", + "Europe/Jersey", "GMT", "Atlantic/Reykjavik", + "America/Kentucky/Louisville", "America_Eastern", "America/New_York", + "America/Monterrey", "America_Central", "America/Chicago", + "Europe/Belgrade", "Europe_Central", "Europe/Paris", + "Asia/Gaza", "Europe_Eastern", "Europe/Bucharest", + "Asia/Ho_Chi_Minh", "Indochina", "Asia/Saigon", + "Europe/Prague", "Europe_Central", "Europe/Paris", + "Indian/Christmas", "Christmas", "Indian/Christmas", + "Pacific/Fakaofo", "Tokelau", "Pacific/Fakaofo", + "America/Dominica", "Atlantic", "America/Halifax", + "America/Ojinaga", "America_Mountain", "America/Denver", + "Asia/Colombo", "India", "Asia/Calcutta", + "Asia/Nicosia", "Europe_Eastern", "Europe/Bucharest", + "Europe/Copenhagen", "Europe_Central", "Europe/Paris", + "America/Creston", "America_Mountain", "America/Denver", + "Asia/Ashgabat", "Turkmenistan", "Asia/Ashgabat", + "Asia/Shanghai", "China", "Asia/Shanghai", + "Pacific/Easter", "Easter", "Pacific/Easter", + "Africa/Maseru", "Africa_Southern", "Africa/Johannesburg", + "America/La_Paz", "Bolivia", "America/La_Paz", + "Pacific/Truk", "Truk", "Pacific/Truk", + "America/Inuvik", "America_Mountain", "America/Denver", + "America/Belem", "Brasilia", "America/Sao_Paulo", + "Asia/Hebron", "Europe_Eastern", "Europe/Bucharest", + "Asia/Jerusalem", "Israel", "Asia/Jerusalem", + "America/Belize", "America_Central", "America/Chicago", + "America/Rio_Branco", "Amazon", "America/Manaus", + "America/Dawson_Creek", "America_Mountain", "America/Denver", + "America/Anguilla", "Atlantic", "America/Halifax", + "America/Port_of_Spain", "Atlantic", "America/Halifax", + "America/St_Barthelemy", "Atlantic", "America/Halifax", + "America/Indiana/Marengo", "America_Eastern", "America/New_York", + "America/St_Johns", "Newfoundland", "America/St_Johns", + "Asia/Jayapura", "Indonesia_Eastern", "Asia/Jayapura", + "Europe/Riga", "Europe_Eastern", "Europe/Bucharest", + "America/Phoenix", "America_Mountain", "America/Denver", + "America/Boise", "America_Mountain", "America/Denver", + "Pacific/Kiritimati", "Line_Islands", "Pacific/Kiritimati", + "Africa/Johannesburg", "Africa_Southern", "Africa/Johannesburg", + "America/Pangnirtung", "America_Eastern", "America/New_York", + "America/Toronto", "America_Eastern", "America/New_York", + "Australia/Brisbane", "Australia_Eastern", "Australia/Sydney", + "Asia/Aqtau", "Kazakhstan_Western", "Asia/Aqtobe", + "America/Vancouver", "America_Pacific", "America/Los_Angeles", + "Africa/Mbabane", "Africa_Southern", "Africa/Johannesburg", + "Europe/Vaduz", "Europe_Central", "Europe/Paris", + "Asia/Karachi", "Pakistan", "Asia/Karachi", + "Asia/Riyadh", "Arabian", "Asia/Riyadh", + "Indian/Maldives", "Maldives", "Indian/Maldives", + "Asia/Anadyr", "Magadan", "Asia/Magadan", + "Europe/Helsinki", "Europe_Eastern", "Europe/Bucharest", + "America/Nome", "Alaska", "America/Juneau", + "Asia/Yakutsk", "Yakutsk", "Asia/Yakutsk", + "Africa/Conakry", "GMT", "Atlantic/Reykjavik", + "Asia/Seoul", "Korea", "Asia/Seoul", + "America/Antigua", "Atlantic", "America/Halifax", + "Asia/Almaty", "Kazakhstan_Eastern", "Asia/Almaty", + "America/Fortaleza", "Brasilia", "America/Sao_Paulo", + "Pacific/Tahiti", "Tahiti", "Pacific/Tahiti", + "Asia/Kashgar", "China", "Asia/Shanghai", + "America/Whitehorse", "America_Pacific", "America/Los_Angeles", + "Europe/Kaliningrad", "Europe_Eastern", "Europe/Bucharest", + "Pacific/Enderbury", "Phoenix_Islands", "Pacific/Enderbury", + "America/St_Lucia", "Atlantic", "America/Halifax", + "Atlantic/Stanley", "Falkland", "Atlantic/Stanley", + "Asia/Omsk", "Omsk", "Asia/Omsk", + "America/Menominee", "America_Central", "America/Chicago", + "Asia/Novokuznetsk", "Novosibirsk", "Asia/Novosibirsk", + "Asia/Sakhalin", "Sakhalin", "Asia/Sakhalin", + "Asia/Muscat", "Gulf", "Asia/Dubai", + "Pacific/Noumea", "New_Caledonia", "Pacific/Noumea", + "Asia/Phnom_Penh", "Indochina", "Asia/Saigon", + "Antarctica/Mawson", "Mawson", "Antarctica/Mawson", + "Indian/Cocos", "Cocos", "Indian/Cocos", + "Europe/Tallinn", "Europe_Eastern", "Europe/Bucharest", + "Africa/Nairobi", "Africa_Eastern", "Africa/Nairobi", + "Europe/Ljubljana", "Europe_Central", "Europe/Paris", + "America/Montreal", "America_Eastern", "America/New_York", + "Asia/Kuala_Lumpur", "Malaysia", "Asia/Kuching", + "Asia/Magadan", "Magadan", "Asia/Magadan", + "Africa/Bamako", "GMT", "Atlantic/Reykjavik", + "Australia/Broken_Hill", "Australia_Central", "Australia/Adelaide", + "America/Indiana/Indianapolis", "America_Eastern", "America/New_York", + "Asia/Taipei", "Taipei", "Asia/Taipei", + "Europe/Samara", "Moscow", "Europe/Moscow", + "America/Indiana/Vevay", "America_Eastern", "America/New_York", + "Atlantic/South_Georgia", "South_Georgia", "Atlantic/South_Georgia", + "Pacific/Wake", "Wake", "Pacific/Wake", + "Asia/Tashkent", "Uzbekistan", "Asia/Tashkent", + "America/St_Thomas", "Atlantic", "America/Halifax", + "America/Argentina/San_Luis", "Argentina_Western", "America/Argentina/San_Luis", + "Arctic/Longyearbyen", "Europe_Central", "Europe/Paris", + "Asia/Chongqing", "China", "Asia/Shanghai", + "Europe/Monaco", "Europe_Central", "Europe/Paris", + "Asia/Qatar", "Arabian", "Asia/Riyadh", + "America/Chihuahua", "America_Mountain", "America/Denver", + "America/Havana", "Cuba", "America/Havana", + "Pacific/Auckland", "New_Zealand", "Pacific/Auckland", + "America/Jujuy", "Argentina", "America/Buenos_Aires", + "America/Goose_Bay", "Atlantic", "America/Halifax", + "Africa/Niamey", "Africa_Western", "Africa/Lagos", + "Asia/Kathmandu", "Nepal", "Asia/Katmandu", + "America/Caracas", "Venezuela", "America/Caracas", + "Indian/Comoro", "Africa_Eastern", "Africa/Nairobi", + "America/Argentina/Jujuy", "Argentina", "America/Buenos_Aires", + "America/Guyana", "Guyana", "America/Guyana", + "America/Indiana/Tell_City", "America_Central", "America/Chicago", + "America/Metlakatla", "America_Pacific", "America/Los_Angeles", + "Europe/Mariehamn", "Europe_Eastern", "Europe/Bucharest", + "Europe/Dublin", "GMT", "Atlantic/Reykjavik", + "Europe/Lisbon", "Europe_Western", "Atlantic/Canary", + "America/Puerto_Rico", "Atlantic", "America/Halifax", + "Asia/Pyongyang", "Korea", "Asia/Seoul", + "America/North_Dakota/New_Salem", "America_Central", "America/Chicago", + "Asia/Dhaka", "Bangladesh", "Asia/Dhaka", + "America/Rankin_Inlet", "America_Central", "America/Chicago", + "America/Adak", "Hawaii_Aleutian", "Pacific/Honolulu", + "America/Campo_Grande", "Amazon", "America/Manaus", + "Europe/Chisinau", "Europe_Eastern", "Europe/Bucharest", + "Pacific/Saipan", "Chamorro", "Pacific/Saipan", + "Pacific/Niue", "Niue", "Pacific/Niue", + "Europe/Madrid", "Europe_Central", "Europe/Paris", + "Pacific/Kwajalein", "Marshall_Islands", "Pacific/Majuro", + "America/Porto_Velho", "Amazon", "America/Manaus", + "Indian/Kerguelen", "French_Southern", "Indian/Kerguelen", + "America/Santarem", "Brasilia", "America/Sao_Paulo", + "Asia/Kuching", "Malaysia", "Asia/Kuching", + "Australia/Adelaide", "Australia_Central", "Australia/Adelaide", + "Europe/Bucharest", "Europe_Eastern", "Europe/Bucharest", + "Australia/Perth", "Australia_Western", "Australia/Perth", + "Europe/Sofia", "Europe_Eastern", "Europe/Bucharest", + "Indian/Chagos", "Indian_Ocean", "Indian/Chagos", + "America/Yellowknife", "America_Mountain", "America/Denver", + "America/Managua", "America_Central", "America/Chicago", + "America/Iqaluit", "America_Eastern", "America/New_York", + "Pacific/Kosrae", "Kosrae", "Pacific/Kosrae", + "Pacific/Guadalcanal", "Solomon", "Pacific/Guadalcanal", + "America/Barbados", "Atlantic", "America/Halifax", + "America/Aruba", "Atlantic", "America/Halifax", + "Europe/Andorra", "Europe_Central", "Europe/Paris", + "Pacific/Chatham", "Chatham", "Pacific/Chatham", + "America/Santo_Domingo", "Atlantic", "America/Halifax", + "America/Indiana/Vincennes", "America_Eastern", "America/New_York", + "Europe/Kiev", "Europe_Eastern", "Europe/Bucharest", + "Pacific/Funafuti", "Tuvalu", "Pacific/Funafuti", + "America/Mexico_City", "America_Central", "America/Chicago", + "America/Kentucky/Monticello", "America_Eastern", "America/New_York", + "America/Argentina/Catamarca", "Argentina", "America/Buenos_Aires", + "Pacific/Johnston", "Hawaii_Aleutian", "Pacific/Honolulu", + "Europe/Podgorica", "Europe_Central", "Europe/Paris", + "Europe/Zagreb", "Europe_Central", "Europe/Paris", + "Pacific/Pohnpei", "Ponape", "Pacific/Ponape", + "Antarctica/Palmer", "Chile", "America/Santiago", + "America/Argentina/Mendoza", "Argentina", "America/Buenos_Aires", + "America/Lima", "Peru", "America/Lima", + "Antarctica/Macquarie", "Macquarie", "Antarctica/Macquarie", + "Europe/Malta", "Europe_Central", "Europe/Paris", + "America/Danmarkshavn", "GMT", "Atlantic/Reykjavik", + }; + private static final String[] mzoneMap = new String[] { + "America_Eastern", "TC", "America/Grand_Turk", + "America_Eastern", "BS", "America/Nassau", + "America_Eastern", "CA", "America/Toronto", + "America_Eastern", "KY", "America/Cayman", + "America_Eastern", "PA", "America/Panama", + "America_Eastern", "JM", "America/Jamaica", + "America_Pacific", "CA", "America/Vancouver", + "America_Pacific", "MX", "America/Tijuana", + "Europe_Western", "FO", "Atlantic/Faeroe", + "Arabian", "YE", "Asia/Aden", + "Arabian", "BH", "Asia/Bahrain", + "Arabian", "KW", "Asia/Kuwait", + "Arabian", "QA", "Asia/Qatar", + "Arabian", "IQ", "Asia/Baghdad", + "Korea", "KP", "Asia/Pyongyang", + "Africa_Central", "ZW", "Africa/Harare", + "Africa_Central", "ZM", "Africa/Lusaka", + "Africa_Central", "MW", "Africa/Blantyre", + "Africa_Central", "BW", "Africa/Gaborone", + "Africa_Central", "CD", "Africa/Lubumbashi", + "Africa_Central", "BI", "Africa/Bujumbura", + "Africa_Central", "RW", "Africa/Kigali", + "Africa_Western", "CF", "Africa/Bangui", + "Africa_Western", "AO", "Africa/Luanda", + "Africa_Western", "NE", "Africa/Niamey", + "Africa_Western", "CD", "Africa/Kinshasa", + "Africa_Western", "CM", "Africa/Douala", + "Africa_Western", "CG", "Africa/Brazzaville", + "Africa_Western", "GQ", "Africa/Malabo", + "Africa_Western", "TD", "Africa/Ndjamena", + "Africa_Western", "GA", "Africa/Libreville", + "Atlantic", "PR", "America/Puerto_Rico", + "Atlantic", "AN", "America/Curacao", + "Atlantic", "VI", "America/St_Thomas", + "Atlantic", "GP", "America/Guadeloupe", + "Atlantic", "TT", "America/Port_of_Spain", + "Atlantic", "AG", "America/Antigua", + "Atlantic", "MF", "America/Marigot", + "Atlantic", "DM", "America/Dominica", + "Atlantic", "VG", "America/Tortola", + "Atlantic", "MQ", "America/Martinique", + "Atlantic", "GL", "America/Thule", + "Atlantic", "AI", "America/Anguilla", + "Atlantic", "BB", "America/Barbados", + "Atlantic", "BM", "Atlantic/Bermuda", + "Atlantic", "BQ", "America/Kralendijk", + "Atlantic", "LC", "America/St_Lucia", + "Atlantic", "MS", "America/Montserrat", + "Atlantic", "SX", "America/Lower_Princes", + "Atlantic", "GD", "America/Grenada", + "Atlantic", "VC", "America/St_Vincent", + "Atlantic", "KN", "America/St_Kitts", + "Atlantic", "AW", "America/Aruba", + "GMT", "GM", "Africa/Banjul", + "GMT", "LR", "Africa/Monrovia", + "GMT", "ML", "Africa/Bamako", + "GMT", "SH", "Atlantic/St_Helena", + "GMT", "TG", "Africa/Lome", + "GMT", "GB", "Europe/London", + "GMT", "MR", "Africa/Nouakchott", + "GMT", "GN", "Africa/Conakry", + "GMT", "SL", "Africa/Freetown", + "GMT", "BF", "Africa/Ouagadougou", + "GMT", "ST", "Africa/Sao_Tome", + "GMT", "SN", "Africa/Dakar", + "GMT", "CI", "Africa/Abidjan", + "GMT", "IE", "Europe/Dublin", + "GMT", "GH", "Africa/Accra", + "Chile", "AQ", "Antarctica/Palmer", + "America_Central", "CR", "America/Costa_Rica", + "America_Central", "HN", "America/Tegucigalpa", + "America_Central", "CA", "America/Winnipeg", + "America_Central", "SV", "America/El_Salvador", + "America_Central", "MX", "America/Mexico_City", + "America_Central", "BZ", "America/Belize", + "America_Central", "GT", "America/Guatemala", + "America_Mountain", "CA", "America/Edmonton", + "America_Mountain", "MX", "America/Hermosillo", + "New_Zealand", "AQ", "Antarctica/McMurdo", + "India", "LK", "Asia/Colombo", + "Gulf", "OM", "Asia/Muscat", + "China", "MO", "Asia/Macau", + "Africa_Eastern", "ER", "Africa/Asmera", + "Africa_Eastern", "TZ", "Africa/Dar_es_Salaam", + "Africa_Eastern", "SO", "Africa/Mogadishu", + "Africa_Eastern", "DJ", "Africa/Djibouti", + "Africa_Eastern", "MG", "Indian/Antananarivo", + "Africa_Eastern", "KM", "Indian/Comoro", + "Africa_Eastern", "UG", "Africa/Kampala", + "Africa_Eastern", "YT", "Indian/Mayotte", + "Africa_Eastern", "ET", "Africa/Addis_Ababa", + "Chamorro", "GU", "Pacific/Guam", + "Africa_Southern", "LS", "Africa/Maseru", + "Africa_Southern", "SZ", "Africa/Mbabane", + "Indochina", "KH", "Asia/Phnom_Penh", + "Indochina", "TH", "Asia/Bangkok", + "Indochina", "LA", "Asia/Vientiane", + "Europe_Central", "AT", "Europe/Vienna", + "Europe_Central", "SK", "Europe/Bratislava", + "Europe_Central", "BA", "Europe/Sarajevo", + "Europe_Central", "CZ", "Europe/Prague", + "Europe_Central", "BE", "Europe/Brussels", + "Europe_Central", "RS", "Europe/Belgrade", + "Europe_Central", "SE", "Europe/Stockholm", + "Europe_Central", "MT", "Europe/Malta", + "Europe_Central", "IT", "Europe/Rome", + "Europe_Central", "LU", "Europe/Luxembourg", + "Europe_Central", "HU", "Europe/Budapest", + "Europe_Central", "NO", "Europe/Oslo", + "Europe_Central", "ME", "Europe/Podgorica", + "Europe_Central", "MK", "Europe/Skopje", + "Europe_Central", "NL", "Europe/Amsterdam", + "Europe_Central", "LI", "Europe/Vaduz", + "Europe_Central", "PL", "Europe/Warsaw", + "Europe_Central", "ES", "Europe/Madrid", + "Europe_Central", "TN", "Africa/Tunis", + "Europe_Central", "SI", "Europe/Ljubljana", + "Europe_Central", "DE", "Europe/Berlin", + "Europe_Central", "GI", "Europe/Gibraltar", + "Europe_Central", "CH", "Europe/Zurich", + "Europe_Central", "MC", "Europe/Monaco", + "Europe_Central", "VA", "Europe/Vatican", + "Europe_Central", "HR", "Europe/Zagreb", + "Europe_Central", "AL", "Europe/Tirane", + "Europe_Central", "AD", "Europe/Andorra", + "Europe_Central", "DK", "Europe/Copenhagen", + "Europe_Central", "SM", "Europe/San_Marino", + "Europe_Eastern", "SY", "Asia/Damascus", + "Europe_Eastern", "FI", "Europe/Helsinki", + "Europe_Eastern", "AX", "Europe/Mariehamn", + "Europe_Eastern", "BG", "Europe/Sofia", + "Europe_Eastern", "EG", "Africa/Cairo", + "Europe_Eastern", "LB", "Asia/Beirut", + "Europe_Eastern", "GR", "Europe/Athens", + "Europe_Eastern", "JO", "Asia/Amman", + "Europe_Eastern", "CY", "Asia/Nicosia", + }; + private static final String[] aliasMap = new String[] { + "Mexico/BajaNorte", "America/Tijuana", + "Antarctica/South_Pole", "Antarctica/McMurdo", + "US/Michigan", "America/Detroit", + "America/Porto_Acre", "America/Rio_Branco", + "US/Alaska", "America/Anchorage", + "Asia/Ujung_Pandang", "Asia/Makassar", + "Canada/Atlantic", "America/Halifax", + "W-SU", "Europe/Moscow", + "Kwajalein", "Pacific/Kwajalein", + "Europe/Bratislava", "Europe/Prague", + "Canada/Central", "America/Winnipeg", + "Canada/Mountain", "America/Edmonton", + "Iceland", "Atlantic/Reykjavik", + "Asia/Ulan_Bator", "Asia/Ulaanbaatar", + "UTC", "Etc/UTC", + "Europe/Guernsey", "Europe/London", + "Singapore", "Asia/Singapore", + "Atlantic/Faeroe", "Atlantic/Faroe", + "Greenwich", "Etc/GMT", + "America/Fort_Wayne", "America/Indiana/Indianapolis", + "Etc/Universal", "Etc/UTC", + "Chile/EasterIsland", "Pacific/Easter", + "Pacific/Samoa", "Pacific/Pago_Pago", + "Europe/Nicosia", "Asia/Nicosia", + "Etc/Zulu", "Etc/UTC", + "Asia/Ashkhabad", "Asia/Ashgabat", + "America/Louisville", "America/Kentucky/Louisville", + "Australia/North", "Australia/Darwin", + "America/Atka", "America/Adak", + "America/Marigot", "America/Guadeloupe", + "Brazil/DeNoronha", "America/Noronha", + "Turkey", "Europe/Istanbul", + "Zulu", "Etc/UTC", + "Europe/Vatican", "Europe/Rome", + "Israel", "Asia/Jerusalem", + "America/Rosario", "America/Argentina/Cordoba", + "Jamaica", "America/Jamaica", + "Asia/Katmandu", "Asia/Kathmandu", + "Canada/East-Saskatchewan", "America/Regina", + "ROK", "Asia/Seoul", + "Asia/Macao", "Asia/Macau", + "Australia/South", "Australia/Adelaide", + "US/Arizona", "America/Phoenix", + "Australia/Yancowinna", "Australia/Broken_Hill", + "Canada/Pacific", "America/Vancouver", + "Libya", "Africa/Tripoli", + "Japan", "Asia/Tokyo", + "Arctic/Longyearbyen", "Europe/Oslo", + "Africa/Timbuktu", "Africa/Bamako", + "America/Indianapolis", "America/Indiana/Indianapolis", + "Etc/Greenwich", "Etc/GMT", + "Australia/ACT", "Australia/Sydney", + "GMT", "Etc/GMT", + "Mexico/BajaSur", "America/Mazatlan", + "Cuba", "America/Havana", + "Brazil/West", "America/Manaus", + "Asia/Saigon", "Asia/Ho_Chi_Minh", + "America/Jujuy", "America/Argentina/Jujuy", + "Australia/Victoria", "Australia/Melbourne", + "America/Catamarca", "America/Argentina/Catamarca", + "America/Ensenada", "America/Tijuana", + "Europe/San_Marino", "Europe/Rome", + "Europe/Isle_of_Man", "Europe/London", + "Mexico/General", "America/Mexico_City", + "US/Hawaii", "Pacific/Honolulu", + "Europe/Mariehamn", "Europe/Helsinki", + "US/Indiana-Starke", "America/Indiana/Knox", + "Australia/NSW", "Australia/Sydney", + "Australia/West", "Australia/Perth", + "Brazil/Acre", "America/Rio_Branco", + "Australia/Tasmania", "Australia/Hobart", + "Atlantic/Jan_Mayen", "Europe/Oslo", + "America/Buenos_Aires", "America/Argentina/Buenos_Aires", + "Europe/Jersey", "Europe/London", + "Brazil/East", "America/Sao_Paulo", + "America/Virgin", "America/St_Thomas", + "Navajo", "America/Denver", + "GB", "Europe/London", + "Poland", "Europe/Warsaw", + "Pacific/Yap", "Pacific/Chuuk", + "America/Argentina/ComodRivadavia", "America/Argentina/Catamarca", + "Asia/Calcutta", "Asia/Kolkata", + "America/Mendoza", "America/Argentina/Mendoza", + "Universal", "Etc/UTC", + "Australia/Queensland", "Australia/Brisbane", + "Asia/Dacca", "Asia/Dhaka", + "US/Pacific", "America/Los_Angeles", + "Asia/Chungking", "Asia/Chongqing", + "Pacific/Truk", "Pacific/Chuuk", + "ROC", "Asia/Taipei", + "US/Aleutian", "America/Adak", + "Pacific/Ponape", "Pacific/Pohnpei", + "Canada/Yukon", "America/Whitehorse", + "PRC", "Asia/Shanghai", + "Africa/Asmera", "Africa/Asmara", + "GB-Eire", "Europe/London", + "America/St_Barthelemy", "America/Guadeloupe", + "US/Central", "America/Chicago", + "Egypt", "Africa/Cairo", + "Chile/Continental", "America/Santiago", + "Portugal", "Europe/Lisbon", + "Europe/Tiraspol", "Europe/Chisinau", + "America/Coral_Harbour", "America/Atikokan", + "Europe/Belfast", "Europe/London", + "America/Cordoba", "America/Argentina/Cordoba", + "America/Shiprock", "America/Denver", + "NZ-CHAT", "Pacific/Chatham", + "Eire", "Europe/Dublin", + "US/East-Indiana", "America/Indiana/Indianapolis", + "Australia/Canberra", "Australia/Sydney", + "Canada/Newfoundland", "America/St_Johns", + "UCT", "Etc/UCT", + "Australia/LHI", "Australia/Lord_Howe", + "Iran", "Asia/Tehran", + "US/Eastern", "America/New_York", + "Canada/Eastern", "America/Toronto", + "US/Samoa", "Pacific/Pago_Pago", + "America/Knox_IN", "America/Indiana/Knox", + "Canada/Saskatchewan", "America/Regina", + "Asia/Thimbu", "Asia/Thimphu", + "US/Mountain", "America/Denver", + "NZ", "Pacific/Auckland", + "Asia/Tel_Aviv", "Asia/Jerusalem", + "Hongkong", "Asia/Hong_Kong", + }; + + private static final Map zidToMzone = new HashMap<>(); + private static final Map mzoneToZid = new HashMap<>(); + private static final Map> mzoneToZidL = new HashMap<>(); + private static final Map aliases = new HashMap<>(); + + static { + for (int i = 0; i < zidMap.length; i += 3) { + zidToMzone.put(zidMap[i], zidMap[i + 1]); + mzoneToZid.put(zidMap[i + 1], zidMap[i + 2]); + } + + for (int i = 0; i < mzoneMap.length; i += 3) { + String mzone = mzoneMap[i]; + Map map = mzoneToZidL.get(mzone); + if (map == null) { + map = new HashMap<>(); + mzoneToZidL.put(mzone, map); + } + map.put(mzoneMap[i + 1], mzoneMap[i + 2]); + } + + for (int i = 0; i < aliasMap.length; i += 2) { + aliases.put(aliasMap[i], aliasMap[i + 1]); + } + } +} diff --git a/jdk/test/java/time/test/java/time/temporal/MockFieldNoValue.java b/jdk/test/java/time/test/java/time/temporal/MockFieldNoValue.java index 255735db006..eb97313ae19 100644 --- a/jdk/test/java/time/test/java/time/temporal/MockFieldNoValue.java +++ b/jdk/test/java/time/test/java/time/temporal/MockFieldNoValue.java @@ -59,13 +59,15 @@ */ package test.java.time.temporal; -import java.time.format.DateTimeBuilder; -import java.time.temporal.*; - import static java.time.temporal.ChronoUnit.MONTHS; import static java.time.temporal.ChronoUnit.WEEKS; import java.time.DateTimeException; +import java.time.temporal.Temporal; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalField; +import java.time.temporal.TemporalUnit; +import java.time.temporal.ValueRange; /** * Mock TemporalField that returns null. @@ -96,29 +98,23 @@ public enum MockFieldNoValue implements TemporalField { //----------------------------------------------------------------------- @Override - public boolean doIsSupported(TemporalAccessor temporal) { + public boolean isSupportedBy(TemporalAccessor temporal) { return true; } @Override - public ValueRange doRange(TemporalAccessor temporal) { + public ValueRange rangeRefinedBy(TemporalAccessor temporal) { return ValueRange.of(1, 20); } @Override - public long doGet(TemporalAccessor temporal) { + public long getFrom(TemporalAccessor temporal) { throw new DateTimeException("Mock"); } @Override - public R doWith(R temporal, long newValue) { + public R adjustInto(R temporal, long newValue) { throw new DateTimeException("Mock"); } - //----------------------------------------------------------------------- - @Override - public boolean resolve(DateTimeBuilder dateTimeBuilder, long value) { - return false; - } - } diff --git a/jdk/test/java/time/test/java/time/temporal/MockFieldValue.java b/jdk/test/java/time/test/java/time/temporal/MockFieldValue.java index 7f478a9a539..cceb4c89958 100644 --- a/jdk/test/java/time/test/java/time/temporal/MockFieldValue.java +++ b/jdk/test/java/time/test/java/time/temporal/MockFieldValue.java @@ -90,7 +90,7 @@ public final class MockFieldValue implements TemporalAccessor { } throw new DateTimeException("Unsupported field: " + field.getName()); } - return field.doRange(this); + return field.rangeRefinedBy(this); } @Override diff --git a/jdk/test/java/time/test/java/time/temporal/TestChronoUnit.java b/jdk/test/java/time/test/java/time/temporal/TestChronoUnit.java index b282cda2f85..0f84d39591c 100644 --- a/jdk/test/java/time/test/java/time/temporal/TestChronoUnit.java +++ b/jdk/test/java/time/test/java/time/temporal/TestChronoUnit.java @@ -106,35 +106,33 @@ public class TestChronoUnit { @Test(dataProvider = "yearsBetween") public void test_yearsBetween(LocalDate start, LocalDate end, long expected) { - assertEquals(YEARS.between(start, end).getAmount(), expected); - assertEquals(YEARS.between(start, end).getUnit(), YEARS); + assertEquals(YEARS.between(start, end), expected); } @Test(dataProvider = "yearsBetween") public void test_yearsBetweenReversed(LocalDate start, LocalDate end, long expected) { - assertEquals(YEARS.between(end, start).getAmount(), -expected); - assertEquals(YEARS.between(end, start).getUnit(), YEARS); + assertEquals(YEARS.between(end, start), -expected); } @Test(dataProvider = "yearsBetween") public void test_yearsBetween_LocalDateTimeSameTime(LocalDate start, LocalDate end, long expected) { - assertEquals(YEARS.between(start.atTime(12, 30), end.atTime(12, 30)).getAmount(), expected); + assertEquals(YEARS.between(start.atTime(12, 30), end.atTime(12, 30)), expected); } @Test(dataProvider = "yearsBetween") public void test_yearsBetween_LocalDateTimeLaterTime(LocalDate start, LocalDate end, long expected) { - assertEquals(YEARS.between(start.atTime(12, 30), end.atTime(12, 31)).getAmount(), expected); + assertEquals(YEARS.between(start.atTime(12, 30), end.atTime(12, 31)), expected); } @Test(dataProvider = "yearsBetween") public void test_yearsBetween_ZonedDateSameOffset(LocalDate start, LocalDate end, long expected) { - assertEquals(YEARS.between(start.atStartOfDay(ZoneOffset.ofHours(2)), end.atStartOfDay(ZoneOffset.ofHours(2))).getAmount(), expected); + assertEquals(YEARS.between(start.atStartOfDay(ZoneOffset.ofHours(2)), end.atStartOfDay(ZoneOffset.ofHours(2))), expected); } @Test(dataProvider = "yearsBetween") public void test_yearsBetween_ZonedDateLaterOffset(LocalDate start, LocalDate end, long expected) { // +01:00 is later than +02:00 - assertEquals(YEARS.between(start.atStartOfDay(ZoneOffset.ofHours(2)), end.atStartOfDay(ZoneOffset.ofHours(1))).getAmount(), expected); + assertEquals(YEARS.between(start.atStartOfDay(ZoneOffset.ofHours(2)), end.atStartOfDay(ZoneOffset.ofHours(1))), expected); } //----------------------------------------------------------------------- @@ -173,35 +171,33 @@ public class TestChronoUnit { @Test(dataProvider = "monthsBetween") public void test_monthsBetween(LocalDate start, LocalDate end, long expected) { - assertEquals(MONTHS.between(start, end).getAmount(), expected); - assertEquals(MONTHS.between(start, end).getUnit(), MONTHS); + assertEquals(MONTHS.between(start, end), expected); } @Test(dataProvider = "monthsBetween") public void test_monthsBetweenReversed(LocalDate start, LocalDate end, long expected) { - assertEquals(MONTHS.between(end, start).getAmount(), -expected); - assertEquals(MONTHS.between(end, start).getUnit(), MONTHS); + assertEquals(MONTHS.between(end, start), -expected); } @Test(dataProvider = "monthsBetween") public void test_monthsBetween_LocalDateTimeSameTime(LocalDate start, LocalDate end, long expected) { - assertEquals(MONTHS.between(start.atTime(12, 30), end.atTime(12, 30)).getAmount(), expected); + assertEquals(MONTHS.between(start.atTime(12, 30), end.atTime(12, 30)), expected); } @Test(dataProvider = "monthsBetween") public void test_monthsBetween_LocalDateTimeLaterTime(LocalDate start, LocalDate end, long expected) { - assertEquals(MONTHS.between(start.atTime(12, 30), end.atTime(12, 31)).getAmount(), expected); + assertEquals(MONTHS.between(start.atTime(12, 30), end.atTime(12, 31)), expected); } @Test(dataProvider = "monthsBetween") public void test_monthsBetween_ZonedDateSameOffset(LocalDate start, LocalDate end, long expected) { - assertEquals(MONTHS.between(start.atStartOfDay(ZoneOffset.ofHours(2)), end.atStartOfDay(ZoneOffset.ofHours(2))).getAmount(), expected); + assertEquals(MONTHS.between(start.atStartOfDay(ZoneOffset.ofHours(2)), end.atStartOfDay(ZoneOffset.ofHours(2))), expected); } @Test(dataProvider = "monthsBetween") public void test_monthsBetween_ZonedDateLaterOffset(LocalDate start, LocalDate end, long expected) { // +01:00 is later than +02:00 - assertEquals(MONTHS.between(start.atStartOfDay(ZoneOffset.ofHours(2)), end.atStartOfDay(ZoneOffset.ofHours(1))).getAmount(), expected); + assertEquals(MONTHS.between(start.atStartOfDay(ZoneOffset.ofHours(2)), end.atStartOfDay(ZoneOffset.ofHours(1))), expected); } //----------------------------------------------------------------------- @@ -234,14 +230,12 @@ public class TestChronoUnit { @Test(dataProvider = "weeksBetween") public void test_weeksBetween(LocalDate start, LocalDate end, long expected) { - assertEquals(WEEKS.between(start, end).getAmount(), expected); - assertEquals(WEEKS.between(start, end).getUnit(), WEEKS); + assertEquals(WEEKS.between(start, end), expected); } @Test(dataProvider = "weeksBetween") public void test_weeksBetweenReversed(LocalDate start, LocalDate end, long expected) { - assertEquals(WEEKS.between(end, start).getAmount(), -expected); - assertEquals(WEEKS.between(end, start).getUnit(), WEEKS); + assertEquals(WEEKS.between(end, start), -expected); } //----------------------------------------------------------------------- @@ -279,35 +273,33 @@ public class TestChronoUnit { @Test(dataProvider = "daysBetween") public void test_daysBetween(LocalDate start, LocalDate end, long expected) { - assertEquals(DAYS.between(start, end).getAmount(), expected); - assertEquals(DAYS.between(start, end).getUnit(), DAYS); + assertEquals(DAYS.between(start, end), expected); } @Test(dataProvider = "daysBetween") public void test_daysBetweenReversed(LocalDate start, LocalDate end, long expected) { - assertEquals(DAYS.between(end, start).getAmount(), -expected); - assertEquals(DAYS.between(end, start).getUnit(), DAYS); + assertEquals(DAYS.between(end, start), -expected); } @Test(dataProvider = "daysBetween") public void test_daysBetween_LocalDateTimeSameTime(LocalDate start, LocalDate end, long expected) { - assertEquals(DAYS.between(start.atTime(12, 30), end.atTime(12, 30)).getAmount(), expected); + assertEquals(DAYS.between(start.atTime(12, 30), end.atTime(12, 30)), expected); } @Test(dataProvider = "daysBetween") public void test_daysBetween_LocalDateTimeLaterTime(LocalDate start, LocalDate end, long expected) { - assertEquals(DAYS.between(start.atTime(12, 30), end.atTime(12, 31)).getAmount(), expected); + assertEquals(DAYS.between(start.atTime(12, 30), end.atTime(12, 31)), expected); } @Test(dataProvider = "daysBetween") public void test_daysBetween_ZonedDateSameOffset(LocalDate start, LocalDate end, long expected) { - assertEquals(DAYS.between(start.atStartOfDay(ZoneOffset.ofHours(2)), end.atStartOfDay(ZoneOffset.ofHours(2))).getAmount(), expected); + assertEquals(DAYS.between(start.atStartOfDay(ZoneOffset.ofHours(2)), end.atStartOfDay(ZoneOffset.ofHours(2))), expected); } @Test(dataProvider = "daysBetween") public void test_daysBetween_ZonedDateLaterOffset(LocalDate start, LocalDate end, long expected) { // +01:00 is later than +02:00 - assertEquals(DAYS.between(start.atStartOfDay(ZoneOffset.ofHours(2)), end.atStartOfDay(ZoneOffset.ofHours(1))).getAmount(), expected); + assertEquals(DAYS.between(start.atStartOfDay(ZoneOffset.ofHours(2)), end.atStartOfDay(ZoneOffset.ofHours(1))), expected); } //----------------------------------------------------------------------- diff --git a/jdk/test/java/time/test/java/time/temporal/TestDateTimeBuilderCombinations.java b/jdk/test/java/time/test/java/time/temporal/TestDateTimeBuilderCombinations.java index 328ead5e4e2..941e08e3be7 100644 --- a/jdk/test/java/time/test/java/time/temporal/TestDateTimeBuilderCombinations.java +++ b/jdk/test/java/time/test/java/time/temporal/TestDateTimeBuilderCombinations.java @@ -71,9 +71,13 @@ import static java.time.temporal.ChronoField.EPOCH_MONTH; import static java.time.temporal.ChronoField.MONTH_OF_YEAR; import static java.time.temporal.ChronoField.YEAR; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; +import java.time.DateTimeException; import java.time.LocalDate; -import java.time.format.DateTimeBuilder; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; import org.testng.annotations.DataProvider; @@ -98,74 +102,110 @@ public class TestDateTimeBuilderCombinations { } @Test(dataProvider = "combine") - public void test_derive(TemporalField field1, Number value1, TemporalField field2, Number value2, - TemporalField field3, Number value3, TemporalField field4, Number value4, Class query, Object expectedVal) { - DateTimeBuilder builder = new DateTimeBuilder(field1, value1.longValue()); + public void test_derive(final TemporalField field1, final Number value1, + final TemporalField field2, final Number value2, + final TemporalField field3, final Number value3, + final TemporalField field4, final Number value4, + Class query, Object expectedVal) { + // mock for testing that does not fully comply with TemporalAccessor contract + TemporalAccessor test = new TemporalAccessor() { + @Override + public boolean isSupported(TemporalField field) { + return field == field1 || field == field2 || field == field3 || field == field4; + } + @Override + public long getLong(TemporalField field) { + if (field == field1) { + return value1.longValue(); + } + if (field == field2) { + return value2.longValue(); + } + if (field == field3) { + return value3.longValue(); + } + if (field == field4) { + return value4.longValue(); + } + throw new DateTimeException("Unsupported"); + } + }; + String str = ""; + DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder(); + dtfb.appendValue(field1).appendLiteral('-'); + str += value1 + "-"; if (field2 != null) { - builder.addFieldValue(field2, value2.longValue()); + dtfb.appendValue(field2).appendLiteral('-'); + str += value2 + "-"; } if (field3 != null) { - builder.addFieldValue(field3, value3.longValue()); + dtfb.appendValue(field3).appendLiteral('-'); + str += value3 + "-"; } if (field4 != null) { - builder.addFieldValue(field4, value4.longValue()); + dtfb.appendValue(field4).appendLiteral('-'); + str += value4 + "-"; + } + TemporalAccessor parsed = dtfb.toFormatter().parse(str); + if (query == LocalDate.class) { + if (expectedVal != null) { + assertEquals(parsed.query(LocalDate::from), expectedVal); + } else { + try { + parsed.query(LocalDate::from); + fail(); + } catch (DateTimeException ex) { + // expected + } + } + } else { + throw new IllegalArgumentException(); } - builder.resolve(); - assertEquals(builder.extract((Class) query), expectedVal); } //----------------------------------------------------------------------- @DataProvider(name = "normalized") Object[][] data_normalized() { return new Object[][] { - {YEAR, 2127, null, null, null, null, YEAR, 2127}, - {MONTH_OF_YEAR, 12, null, null, null, null, MONTH_OF_YEAR, 12}, - {DAY_OF_YEAR, 127, null, null, null, null, DAY_OF_YEAR, 127}, - {DAY_OF_MONTH, 23, null, null, null, null, DAY_OF_MONTH, 23}, - {DAY_OF_WEEK, 127, null, null, null, null, DAY_OF_WEEK, 127L}, - {ALIGNED_WEEK_OF_YEAR, 23, null, null, null, null, ALIGNED_WEEK_OF_YEAR, 23}, - {ALIGNED_DAY_OF_WEEK_IN_YEAR, 4, null, null, null, null, ALIGNED_DAY_OF_WEEK_IN_YEAR, 4L}, - {ALIGNED_WEEK_OF_MONTH, 4, null, null, null, null, ALIGNED_WEEK_OF_MONTH, 4}, - {ALIGNED_DAY_OF_WEEK_IN_MONTH, 3, null, null, null, null, ALIGNED_DAY_OF_WEEK_IN_MONTH, 3}, - {EPOCH_MONTH, 15, null, null, null, null, EPOCH_MONTH, null}, - {EPOCH_MONTH, 15, null, null, null, null, YEAR, 1971}, - {EPOCH_MONTH, 15, null, null, null, null, MONTH_OF_YEAR, 4}, + {YEAR, 2127, YEAR, 2127}, + {MONTH_OF_YEAR, 12, MONTH_OF_YEAR, 12}, + {DAY_OF_YEAR, 127, DAY_OF_YEAR, 127}, + {DAY_OF_MONTH, 23, DAY_OF_MONTH, 23}, + {DAY_OF_WEEK, 127, DAY_OF_WEEK, 127L}, + {ALIGNED_WEEK_OF_YEAR, 23, ALIGNED_WEEK_OF_YEAR, 23}, + {ALIGNED_DAY_OF_WEEK_IN_YEAR, 4, ALIGNED_DAY_OF_WEEK_IN_YEAR, 4L}, + {ALIGNED_WEEK_OF_MONTH, 4, ALIGNED_WEEK_OF_MONTH, 4}, + {ALIGNED_DAY_OF_WEEK_IN_MONTH, 3, ALIGNED_DAY_OF_WEEK_IN_MONTH, 3}, + {EPOCH_MONTH, 15, EPOCH_MONTH, null}, + {EPOCH_MONTH, 15, YEAR, 1971}, + {EPOCH_MONTH, 15, MONTH_OF_YEAR, 4}, }; } @Test(dataProvider = "normalized") - public void test_normalized(TemporalField field1, Number value1, TemporalField field2, Number value2, - TemporalField field3, Number value3, TemporalField query, Number expectedVal) { - DateTimeBuilder builder = new DateTimeBuilder(field1, value1.longValue()); - if (field2 != null) { - builder.addFieldValue(field2, value2.longValue()); - } - if (field3 != null) { - builder.addFieldValue(field3, value3.longValue()); - } - builder.resolve(); + public void test_normalized(final TemporalField field1, final Number value1, TemporalField expectedField, Number expectedVal) { + // mock for testing that does not fully comply with TemporalAccessor contract + TemporalAccessor test = new TemporalAccessor() { + @Override + public boolean isSupported(TemporalField field) { + return field == field1; + } + @Override + public long getLong(TemporalField field) { + if (field == field1) { + return value1.longValue(); + } + throw new DateTimeException("Unsupported"); + } + }; + DateTimeFormatter f = new DateTimeFormatterBuilder().appendValue(field1).toFormatter(); + String str = value1.toString(); + TemporalAccessor temporal = f.parse(str); if (expectedVal != null) { - assertEquals(builder.getLong(query), expectedVal.longValue()); + assertEquals(temporal.getLong(expectedField), expectedVal.longValue()); } else { - assertEquals(builder.containsFieldValue(query), false); + assertEquals(temporal.isSupported(expectedField), false); } } - //----------------------------------------------------------------------- - // TODO: maybe reinstate -// public void test_split() { -// DateTimeBuilder builder = new DateTimeBuilder(); -// builder.addCalendrical(LocalDateTime.of(2012, 6, 30, 12, 30)); -// builder.addCalendrical(ZoneOffset.ofHours(2)); -// builder.resolve(); -// assertEquals(builder.build(LocalDate.class), LocalDate.of(2012, 6, 30)); -// assertEquals(builder.build(LocalTime.class), LocalTime.of(12, 30)); -// assertEquals(builder.build(ZoneOffset.class), ZoneOffset.ofHours(2)); -// -// assertEquals(builder.build(LocalDateTime.class), LocalDateTime.of(2012, 6, 30, 12, 30)); -// assertEquals(builder.build(OffsetDate.class), OffsetDate.of(LocalDate.of(2012, 6, 30), ZoneOffset.ofHours(2))); -// assertEquals(builder.build(OffsetTime.class), OffsetTime.of(LocalTime.of(12, 30), ZoneOffset.ofHours(2))); -//// assertEquals(builder.build(OffsetDateTime.class), OffsetDateTime.of(2012, 6, 30, 12, 30, ZoneOffset.ofHours(2))); -// } - } diff --git a/jdk/test/java/time/test/java/time/temporal/TestJapaneseChronoImpl.java b/jdk/test/java/time/test/java/time/temporal/TestJapaneseChronoImpl.java index cadd1a378c6..ababf14cb4a 100644 --- a/jdk/test/java/time/test/java/time/temporal/TestJapaneseChronoImpl.java +++ b/jdk/test/java/time/test/java/time/temporal/TestJapaneseChronoImpl.java @@ -63,12 +63,13 @@ import java.util.Locale; import java.util.TimeZone; import java.time.LocalDate; import java.time.LocalTime; -import java.time.temporal.OffsetDateTime; +import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.time.temporal.ChronoField; -import java.time.temporal.ChronoLocalDate; +import java.time.chrono.ChronoLocalDate; import java.time.temporal.ChronoUnit; -import java.time.calendar.JapaneseChrono; +import java.time.chrono.JapaneseChronology; +import java.time.chrono.JapaneseDate; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -100,7 +101,7 @@ public class TestJapaneseChronoImpl { Calendar cal = java.util.Calendar.getInstance(locale); assertEquals(cal.getCalendarType(), "japanese", "Unexpected calendar type"); - ChronoLocalDate jDate = JapaneseChrono.INSTANCE.date(isoStartDate); + JapaneseDate jDate = JapaneseChronology.INSTANCE.date(isoStartDate); // Convert to millis and set Japanese Calendar to that start date (at GMT) OffsetDateTime jodt = OffsetDateTime.of(isoStartDate, LocalTime.MIN, ZoneOffset.UTC); diff --git a/jdk/test/java/time/test/java/time/temporal/TestOffsetDate.java b/jdk/test/java/time/test/java/time/temporal/TestJulianFields.java similarity index 84% rename from jdk/test/java/time/test/java/time/temporal/TestOffsetDate.java rename to jdk/test/java/time/test/java/time/temporal/TestJulianFields.java index 5ba00329b8f..0d9d79e3158 100644 --- a/jdk/test/java/time/test/java/time/temporal/TestOffsetDate.java +++ b/jdk/test/java/time/test/java/time/temporal/TestJulianFields.java @@ -59,20 +59,26 @@ */ package test.java.time.temporal; -import java.time.temporal.OffsetDate; +import static org.testng.Assert.assertEquals; + +import java.time.temporal.JulianFields; import org.testng.annotations.Test; -import test.java.time.AbstractTest; /** - * Test OffsetDate. + * Test. */ @Test -public class TestOffsetDate extends AbstractTest { +public class TestJulianFields { + //----------------------------------------------------------------------- + // toString() + //----------------------------------------------------------------------- @Test - public void test_immutable() { - assertImmutable(OffsetDate.class); + public void test_toString() { + assertEquals(JulianFields.JULIAN_DAY.toString(), "JulianDay"); + assertEquals(JulianFields.MODIFIED_JULIAN_DAY.toString(), "ModifiedJulianDay"); + assertEquals(JulianFields.RATA_DIE.toString(), "RataDie"); } } diff --git a/jdk/test/java/time/test/java/time/temporal/TestThaiBuddhistChronoImpl.java b/jdk/test/java/time/test/java/time/temporal/TestThaiBuddhistChronoImpl.java index 9fd69cfa76b..14b0a45fe0c 100644 --- a/jdk/test/java/time/test/java/time/temporal/TestThaiBuddhistChronoImpl.java +++ b/jdk/test/java/time/test/java/time/temporal/TestThaiBuddhistChronoImpl.java @@ -65,8 +65,9 @@ import java.util.TimeZone; import java.time.LocalDate; import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; -import java.time.temporal.ChronoLocalDate; -import java.time.calendar.ThaiBuddhistChrono; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.ThaiBuddhistChronology; +import java.time.chrono.ThaiBuddhistDate; import org.testng.annotations.Test; import org.testng.annotations.DataProvider; @@ -97,7 +98,7 @@ public class TestThaiBuddhistChronoImpl { Calendar cal = java.util.Calendar.getInstance(locale); assertEquals(cal.getCalendarType(), "buddhist", "Unexpected calendar type"); - ChronoLocalDate thaiDate = ThaiBuddhistChrono.INSTANCE.date(isoStartDate); + ThaiBuddhistDate thaiDate = ThaiBuddhistChronology.INSTANCE.date(isoStartDate); cal.setTimeZone(TimeZone.getTimeZone("GMT+00")); cal.set(Calendar.YEAR, thaiDate.get(ChronoField.YEAR)); diff --git a/jdk/test/java/time/test/java/time/zone/TestFixedZoneRules.java b/jdk/test/java/time/test/java/time/zone/TestFixedZoneRules.java index 80569674bb6..67b6e0a2c40 100644 --- a/jdk/test/java/time/test/java/time/zone/TestFixedZoneRules.java +++ b/jdk/test/java/time/test/java/time/zone/TestFixedZoneRules.java @@ -59,7 +59,7 @@ */ package test.java.time.zone; -import java.time.zone.*; +import java.time.zone.ZoneRules; import static org.testng.Assert.assertEquals; diff --git a/jdk/test/java/time/test/java/util/TestFormatter.java b/jdk/test/java/time/test/java/util/TestFormatter.java index 54331ed2c9b..69c55f22131 100644 --- a/jdk/test/java/time/test/java/util/TestFormatter.java +++ b/jdk/test/java/time/test/java/util/TestFormatter.java @@ -23,7 +23,7 @@ package test.java.util; import java.time.Instant; -import java.time.temporal.OffsetDateTime; +import java.time.OffsetDateTime; import java.time.ZonedDateTime; import java.time.temporal.ChronoField; @@ -129,10 +129,9 @@ public class TestFormatter { printFmtStr(locale, fmtStr); String expected = test(fmtStr, locale, null, cal); test(fmtStr, locale, expected, zdt); - test(fmtStr, locale, expected, OffsetDateTime.of(zdt)); - test(fmtStr, locale, expected, zdt.getDateTime()); - test(fmtStr, locale, expected, OffsetDateTime.of(zdt).toOffsetDate()); - test(fmtStr, locale, expected, zdt.getDate()); + test(fmtStr, locale, expected, zdt.toOffsetDateTime()); + test(fmtStr, locale, expected, zdt.toLocalDateTime()); + test(fmtStr, locale, expected, zdt.toLocalDate()); } private void testTime(String fmtStr, Locale locale, @@ -140,30 +139,34 @@ public class TestFormatter { printFmtStr(locale, fmtStr); String expected = test(fmtStr, locale, null, cal); test(fmtStr, locale, expected, zdt); - test(fmtStr, locale, expected, OffsetDateTime.of(zdt)); - test(fmtStr, locale, expected, zdt.getDateTime()); - test(fmtStr, locale, expected, OffsetDateTime.of(zdt).toOffsetTime()); - test(fmtStr, locale, expected, zdt.getTime()); + test(fmtStr, locale, expected, zdt.toOffsetDateTime()); + test(fmtStr, locale, expected, zdt.toLocalDateTime()); + test(fmtStr, locale, expected, zdt.toOffsetDateTime().toOffsetTime()); + test(fmtStr, locale, expected, zdt.toLocalTime()); + } + + private String toZoneIdStr(String expected) { + return expected.replaceAll("(?:GMT|UTC)(?[+\\-]?[0-9]{2}:[0-9]{2})", "${off}") + .replaceAll("GMT|UTC|UT", "Z"); } private void testZoneId(Locale locale, ZonedDateTime zdt, Calendar cal) { String fmtStr = "z:[%tz] z:[%1$Tz] Z:[%1$tZ] Z:[%1$TZ]"; printFmtStr(locale, fmtStr); - String expected = test(fmtStr, locale, null, cal); + String expected = toZoneIdStr(test(fmtStr, locale, null, cal)); test(fmtStr, locale, expected, zdt); // get a new cal with fixed tz Calendar cal0 = Calendar.getInstance(); cal0.setTimeInMillis(zdt.toInstant().toEpochMilli()); cal0.setTimeZone(TimeZone.getTimeZone("GMT" + zdt.getOffset().getId())); - expected = test(fmtStr, locale, null, cal0).replaceAll("GMT", ""); - test(fmtStr, locale, expected, OffsetDateTime.of(zdt)); - test(fmtStr, locale, expected, OffsetDateTime.of(zdt).toOffsetDate()); - test(fmtStr, locale, expected, OffsetDateTime.of(zdt).toOffsetTime()); + expected = toZoneIdStr(test(fmtStr, locale, null, cal0)); + test(fmtStr, locale, expected, zdt.toOffsetDateTime()); + test(fmtStr, locale, expected, zdt.toOffsetDateTime().toOffsetTime()); // datetime + zid fmtStr = "c:[%tc] c:[%1$Tc]"; printFmtStr(locale, fmtStr); - expected = test(fmtStr, locale, null, cal); + expected = toZoneIdStr(test(fmtStr, locale, null, cal)); test(fmtStr, locale, expected, zdt); } @@ -174,6 +177,6 @@ public class TestFormatter { String expected = test(fmtStr, locale, null, cal); test(fmtStr, locale, expected, instant); test(fmtStr, locale, expected, zdt); - test(fmtStr, locale, expected, OffsetDateTime.of(zdt)); + test(fmtStr, locale, expected, zdt.toOffsetDateTime()); } } diff --git a/jdk/test/java/util/Calendar/JavatimeTest.java b/jdk/test/java/util/Calendar/JavatimeTest.java new file mode 100644 index 00000000000..5b9a7101805 --- /dev/null +++ b/jdk/test/java/util/Calendar/JavatimeTest.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + *@test + *@bug 8007520 + *@summary Test those bridge methods to/from java.time date/time classes + */ + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Random; +import java.util.TimeZone; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZonedDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; + +public class JavatimeTest { + + static final int NANOS_PER_SECOND = 1000_000_000; + + public static void main(String[] args) throws Throwable { + + int N = 10000; + long t1970 = new java.util.Date(70, 0, 01).getTime(); + Random r = new Random(); + for (int i = 0; i < N; i++) { + int days = r.nextInt(50) * 365 + r.nextInt(365); + long secs = t1970 + days * 86400 + r.nextInt(86400); + int nanos = r.nextInt(NANOS_PER_SECOND); + int nanos_ms = nanos / 1000000 * 1000000; // millis precision + long millis = secs * 1000 + r.nextInt(1000); + + LocalDateTime ldt = LocalDateTime.ofEpochSecond(secs, nanos, ZoneOffset.UTC); + LocalDateTime ldt_ms = LocalDateTime.ofEpochSecond(secs, nanos_ms, ZoneOffset.UTC); + Instant inst = Instant.ofEpochSecond(secs, nanos); + Instant inst_ms = Instant.ofEpochSecond(secs, nanos_ms); + //System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + + ///////////// java.util.Date ///////////////////////// + Date jud = new java.util.Date(millis); + Instant inst0 = jud.toInstant(); + if (jud.getTime() != inst0.toEpochMilli() || + !jud.equals(Date.from(inst0))) { + System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + throw new RuntimeException("FAILED: j.u.d -> instant -> j.u.d"); + } + // roundtrip only with millis precision + Date jud0 = Date.from(inst_ms); + if (jud0.getTime() != inst_ms.toEpochMilli() || + !inst_ms.equals(jud0.toInstant())) { + System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + throw new RuntimeException("FAILED: instant -> j.u.d -> instant"); + } + //////////// java.util.GregorianCalendar ///////////// + GregorianCalendar cal = new GregorianCalendar(); + cal.setGregorianChange(new java.util.Date(Long.MIN_VALUE)); + cal.setFirstDayOfWeek(Calendar.MONDAY); + cal.setMinimalDaysInFirstWeek(4); + cal.setTimeInMillis(millis); + ZonedDateTime zdt0 = cal.toZonedDateTime(); + if (cal.getTimeInMillis() != zdt0.toInstant().toEpochMilli() || + !cal.equals(GregorianCalendar.from(zdt0))) { + System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + throw new RuntimeException("FAILED: gcal -> zdt -> gcal"); + } + inst0 = cal.toInstant(); + if (cal.getTimeInMillis() != inst0.toEpochMilli()) { + System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + throw new RuntimeException("FAILED: gcal -> zdt"); + } + ZonedDateTime zdt = ZonedDateTime.of(ldt_ms, ZoneId.systemDefault()); + GregorianCalendar cal0 = GregorianCalendar.from(zdt); + if (zdt.toInstant().toEpochMilli() != cal0.getTimeInMillis() || + !zdt.equals(GregorianCalendar.from(zdt).toZonedDateTime())) { + System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); + throw new RuntimeException("FAILED: zdt -> gcal -> zdt"); + } + } + + ///////////// java.util.TimeZone ///////////////////////// + for (String zidStr : TimeZone.getAvailableIDs()) { + // TBD: tzdt intergration + if (zidStr.startsWith("SystemV") || + zidStr.contains("Riyadh8") || + zidStr.equals("US/Pacific-New")) { + continue; + } + ZoneId zid = ZoneId.of(zidStr, ZoneId.OLD_IDS_POST_2005); + if (!zid.equals(TimeZone.getTimeZone(zid).toZoneId())) { + throw new RuntimeException("FAILED: zid -> tz -> zid :" + zidStr); + } + TimeZone tz = TimeZone.getTimeZone(zidStr); + // no round-trip for alias and "GMT" + if (!tz.equals(TimeZone.getTimeZone(tz.toZoneId())) && + !ZoneId.OLD_IDS_POST_2005.containsKey(zidStr) && + !zidStr.startsWith("GMT")) { + throw new RuntimeException("FAILED: tz -> zid -> tz :" + zidStr); + } + } + System.out.println("Passed!"); + } +} diff --git a/jdk/test/java/util/TimeZone/OldIDMappingTest.java b/jdk/test/java/util/TimeZone/OldIDMappingTest.java index e60ec53175a..35e19cbfc36 100644 --- a/jdk/test/java/util/TimeZone/OldIDMappingTest.java +++ b/jdk/test/java/util/TimeZone/OldIDMappingTest.java @@ -51,17 +51,7 @@ public class OldIDMappingTest { throw new RuntimeException("-old or -new must be specified; got " + arg); } - // Get a Field for TzIDOldMapping in sun.util.calendar. - Map oldmap = null; - try { - Class oldmapClass = Class.forName("sun.util.calendar.TzIDOldMapping"); - Field map = oldmapClass.getDeclaredField("MAP"); - map.setAccessible(true); - oldmap = (Map) map.get(null); - } catch (Exception e) { - throw new RuntimeException("can't get TzIDOldMapping.MAP", e); - } - + Map oldmap = TzIDOldMapping.MAP; String prop = System.getProperty(MAPPING_PROPERTY_NAME); System.out.println(MAPPING_PROPERTY_NAME + "=" + prop); diff --git a/jdk/src/share/classes/sun/util/calendar/TzIDOldMapping.java b/jdk/test/java/util/TimeZone/TzIDOldMapping.java similarity index 98% rename from jdk/src/share/classes/sun/util/calendar/TzIDOldMapping.java rename to jdk/test/java/util/TimeZone/TzIDOldMapping.java index 4f230074235..e9ea6b5dfe1 100644 --- a/jdk/src/share/classes/sun/util/calendar/TzIDOldMapping.java +++ b/jdk/test/java/util/TimeZone/TzIDOldMapping.java @@ -23,8 +23,6 @@ * questions. */ -package sun.util.calendar; - import java.util.Map; import java.util.HashMap; diff --git a/jdk/test/sun/util/calendar/zi/BackEnd.java b/jdk/test/sun/util/calendar/zi/BackEnd.java new file mode 100644 index 00000000000..29d0201b320 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/BackEnd.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2000, 2004, 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. + */ + +/** + * BackEnd is an abstract base class for a back-end of compiling + * Olson's zoneinfo database and generating Java zoneinfo database. + * + * @since 1.4 + */ +abstract class BackEnd { + + /** + * Receives each zone's TimeZone information which was created by + * {@link Zoneinfo#parse} in class Zoneinfo, + * and processes it. + * + * @param tz Timezone object for each zone + * @return 0 if no error occurred, otherwise 1. + */ + abstract int processZoneinfo(Timezone tz); + + /** + * Receives whole information which is generated by JavaZic's front-end + * in the form of Mapping object and generates all Java zone information + * files. + * + * @param m Mappings object which is generated by + * {@link Main#compile() Main.compile()}. + * @return 0 if no error occurred, otherwise 1. + */ + abstract int generateSrc(Mappings m); + + /** + * Decides which backend class should be used and returns its instance. + * @return an instance of backend class + */ + static BackEnd getBackEnd() { + if (Zoneinfo.isYearForTimeZoneDataSpecified) { + return new Simple(); + } else if (Main.outputDoc) { + return new GenDoc(); + } else { + return new Gen(); + } + } +} diff --git a/jdk/test/sun/util/calendar/zi/Checksum.java b/jdk/test/sun/util/calendar/zi/Checksum.java new file mode 100644 index 00000000000..01232503ac3 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/Checksum.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2000, 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. + */ + +import java.util.zip.CRC32; + +/** + * Checksum provides methods for calculating a CRC32 value for a + * transitions table. + * + * @since 1.4 + */ +public class Checksum extends CRC32 +{ + /** + * Updates the CRC32 value from each byte of the given int + * value. The bytes are used in the big endian order. + * @param val the int value + */ + public void update(int val) { + byte[] b = new byte[4]; + b[0] = (byte)((val >>> 24) & 0xff); + b[1] = (byte)((val >>> 16) & 0xff); + b[2] = (byte)((val >>> 8) & 0xff); + b[3] = (byte)(val & 0xff); + update(b); + } + + /** + * Updates the CRC32 value from each byte of the given long + * value. The bytes are used in the big endian order. + * @param val the long value + */ + void update(long val) { + byte[] b = new byte[8]; + b[0] = (byte)((val >>> 56) & 0xff); + b[1] = (byte)((val >>> 48) & 0xff); + b[2] = (byte)((val >>> 40) & 0xff); + b[3] = (byte)((val >>> 32) & 0xff); + b[4] = (byte)((val >>> 24) & 0xff); + b[5] = (byte)((val >>> 16) & 0xff); + b[6] = (byte)((val >>> 8) & 0xff); + b[7] = (byte)(val & 0xff); + update(b); + } +} diff --git a/jdk/test/sun/util/calendar/zi/DayOfWeek.java b/jdk/test/sun/util/calendar/zi/DayOfWeek.java new file mode 100644 index 00000000000..9470d961b82 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/DayOfWeek.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2004, 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. + */ + +/** + * Day of week enum. + * + * @since 1.6 + */ + +enum DayOfWeek { + SUNDAY("Sun"), + MONDAY("Mon"), + TUESDAY("Tue"), + WEDNESDAY("Wed"), + THURSDAY("Thu"), + FRIDAY("Fri"), + SATURDAY("Sat"); + + private final String abbr; + + private DayOfWeek(String abbr) { + this.abbr = abbr; + } + + String getAbbr() { + return abbr; + } + + int value() { + return ordinal() + 1; + } +} diff --git a/jdk/test/sun/util/calendar/zi/Gen.java b/jdk/test/sun/util/calendar/zi/Gen.java new file mode 100644 index 00000000000..70ad6b572c0 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/Gen.java @@ -0,0 +1,344 @@ +/* + * 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. + */ + +import java.io.IOException; +import java.io.File; +import java.io.FileOutputStream; +import java.io.DataOutputStream; +import java.io.RandomAccessFile; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Gen is one of back-end classes of javazic, and generates + * ZoneInfoMappings and zone-specific file for each zone. + */ +class Gen extends BackEnd { + + /** + * Generates datafile in binary TLV format for each time zone. + * Regarding contents of output files, see {@link ZoneInfoFile}. + * + * @param Timezone + * @return 0 if no errors, or 1 if error occurred. + */ + int processZoneinfo(Timezone tz) { + try { + int size; + String outputDir = Main.getOutputDir(); + String zonefile = ZoneInfoFile.getFileName(tz.getName()); + + /* If outputDir doesn't end with file-separator, adds it. */ + if (!outputDir.endsWith(File.separator)) { + outputDir += File.separatorChar; + } + + /* If zonefile includes file-separator, it's treated as part of + * pathname. And make directory if necessary. + */ + int index = zonefile.lastIndexOf(File.separatorChar); + if (index != -1) { + outputDir += zonefile.substring(0, index+1); + } + File outD = new File(outputDir); + outD.mkdirs(); + + FileOutputStream fos = + new FileOutputStream(outputDir + zonefile.substring(index+1)); + DataOutputStream dos = new DataOutputStream(fos); + + /* Output Label */ + dos.write(ZoneInfoFile.JAVAZI_LABEL, 0, + ZoneInfoFile.JAVAZI_LABEL.length); + + /* Output Version of ZoneInfoFile */ + dos.writeByte(ZoneInfoFile.JAVAZI_VERSION); + + List transitions = tz.getTransitions(); + if (transitions != null) { + List dstOffsets = tz.getDstOffsets(); + List offsets = tz.getOffsets(); + + if ((dstOffsets == null && offsets != null) || + (dstOffsets != null && offsets == null)) { + Main.panic("Data not exist. (dstOffsets or offsets)"); + return 1; + } + + /* Output Transition records */ + dos.writeByte(ZoneInfoFile.TAG_Transition); + size = transitions.size(); + dos.writeShort((size * 8) & 0xFFFF); + int dstoffset; + for (int i = 0; i < size; i++) { + /* if DST offset is 0, this means DST isn't used. + * (NOT: offset's index is 0.) + */ + if ((dstoffset = dstOffsets.get(i).intValue()) == -1) { + dstoffset = 0; + } + + dos.writeLong((transitions.get(i).longValue() << 12) + | (dstoffset << 4) + | offsets.get(i).intValue()); + + } + + /* Output data for GMTOffset */ + List gmtoffset = tz.getGmtOffsets(); + dos.writeByte(ZoneInfoFile.TAG_Offset); + size = gmtoffset.size(); + dos.writeShort((size * 4) & 0xFFFF); + for (int i = 0; i < size; i++) { + dos.writeInt(gmtoffset.get(i)); + } + } + + /* Output data for SimpleTimeZone */ + List stz = tz.getLastRules(); + if (stz != null) { + RuleRec[] rr = new RuleRec[2]; + boolean wall = true; + + rr[0] = stz.get(0); + rr[1] = stz.get(1); + + dos.writeByte(ZoneInfoFile.TAG_SimpleTimeZone); + wall = rr[0].getTime().isWall() && rr[1].getTime().isWall(); + if (wall) { + dos.writeShort(32); + } else { + dos.writeShort(40); + } + + for (int i = 0; i < 2; i++) { + dos.writeInt(rr[i].getMonthNum() - 1); // 0-based month number + dos.writeInt(rr[i].getDay().getDayForSimpleTimeZone()); + dos.writeInt(rr[i].getDay().getDayOfWeekForSimpleTimeZoneInt()); + dos.writeInt((int)rr[i].getTime().getTime()); + if (!wall) { + dos.writeInt((rr[i].getTime().getType() & 0xFF) - 1); + } + } + } + + /* Output RawOffset */ + dos.writeByte(ZoneInfoFile.TAG_RawOffset); + dos.writeShort(4); + dos.writeInt(tz.getRawOffset()); + + /* Output willGMTOffsetChange flag */ + if (tz.willGMTOffsetChange()) { + dos.writeByte(ZoneInfoFile.TAG_GMTOffsetWillChange); + dos.writeShort(1); + dos.writeByte(1); + } + + /* Output LastDSTSaving */ + dos.writeByte(ZoneInfoFile.TAG_LastDSTSaving); + dos.writeShort(2); + dos.writeShort(tz.getLastDSTSaving()/1000); + + /* Output checksum */ + dos.writeByte(ZoneInfoFile.TAG_CRC32); + dos.writeShort(4); + dos.writeInt(tz.getCRC32()); + + fos.close(); + dos.close(); + } catch(IOException e) { + Main.panic("IO error: "+e.getMessage()); + return 1; + } + + return 0; + } + + /** + * Generates ZoneInfoMappings in binary TLV format for each zone. + * Regarding contents of output files, see {@link ZoneInfoFile}. + * + * @param Mappings + * @return 0 if no errors, or 1 if error occurred. + */ + int generateSrc(Mappings map) { + try { + int index; + int block_size; + int roi_size; + long fp; + String outputDir = Main.getOutputDir(); + + /* If outputDir doesn't end with file-separator, adds it. */ + if (!outputDir.endsWith(File.separator)) { + outputDir += File.separatorChar; + } + + File outD = new File(outputDir); + outD.mkdirs(); + + /* Open ZoneInfoMapping file to write. */ + RandomAccessFile raf = + new RandomAccessFile(outputDir + ZoneInfoFile.JAVAZM_FILE_NAME, "rw"); + + /* Whether rawOffsetIndex list exists or not. */ + List roi = map.getRawOffsetsIndex(); + if (roi == null) { + Main.panic("Data not exist. (rawOffsetsIndex)"); + return 1; + } + roi_size = roi.size(); + + /* Whether rawOffsetIndexTable list exists or not. */ + List> roit = map.getRawOffsetsIndexTable(); + if (roit == null || roit.size() != roi_size) { + Main.panic("Data not exist. (rawOffsetsIndexTable) Otherwise, Invalid size"); + return 1; + } + + /* Output Label */ + raf.write(ZoneInfoFile.JAVAZM_LABEL, 0, + ZoneInfoFile.JAVAZM_LABEL.length); + + /* Output Version */ + raf.writeByte(ZoneInfoFile.JAVAZM_VERSION); + + index = ZoneInfoFile.JAVAZM_LABEL.length + 2; + + /* Output Version of Olson's tzdata */ + byte[] b = Main.getVersionName().getBytes("UTF-8"); + raf.writeByte(ZoneInfoFile.TAG_TZDataVersion); + raf.writeShort((b.length+1) & 0xFFFF); + raf.write(b); + raf.writeByte(0x00); + index += b.length + 4; + + /* Output ID list. */ + raf.writeByte(ZoneInfoFile.TAG_ZoneIDs); + block_size = 2; + raf.writeShort(block_size & 0xFFFF); + short nID = 0; + raf.writeShort(nID & 0xFFFF); + for (int i = 0; i < roi_size; i++) { + for (String key : roit.get(i)) { + byte size = (byte)key.getBytes("UTF-8").length; + raf.writeByte(size & 0xFF); + raf.write(key.getBytes("UTF-8"), 0, size); + block_size += 1 + size; + nID++; + } + } + fp = raf.getFilePointer(); + raf.seek(index); + raf.writeShort((block_size) & 0xFFFF); + raf.writeShort(nID & 0xFFFF); + raf.seek(fp); + + /* Output sorted rawOffset list. */ + raf.writeByte(ZoneInfoFile.TAG_RawOffsets); + index += 3 + block_size; + block_size = roi_size * 4; + raf.writeShort(block_size & 0xFFFF); + for (int i = 0; i < roi_size; i++) { + raf.writeInt(Integer.parseInt(roi.get(i).toString())); + } + + /* Output sorted rawOffsetIndex list. */ + raf.writeByte(ZoneInfoFile.TAG_RawOffsetIndices); + index += 3 + block_size; + block_size = 0; + raf.writeShort(block_size & 0xFFFF); + int num; + for (int i = 0; i < roi_size; i++) { + num = roit.get(i).size(); + block_size += num; + for (int j = 0; j < num; j++) { + raf.writeByte(i); + } + } + fp = raf.getFilePointer(); + raf.seek(index); + raf.writeShort((block_size) & 0xFFFF); + raf.seek(fp); + + /* Whether alias list exists or not. */ + Map a = map.getAliases(); + if (a == null) { + Main.panic("Data not exist. (aliases)"); + return 0; + } + + /* Output ID list. */ + raf.writeByte(ZoneInfoFile.TAG_ZoneAliases); + index += 3 + block_size; + block_size = 2; + raf.writeShort(block_size & 0xFFFF); + raf.writeShort(a.size() & 0xFFFF); + for (String key : a.keySet()) { + String alias = a.get(key); + byte key_size = (byte)key.length(); + byte alias_size = (byte)alias.length(); + raf.writeByte(key_size & 0xFF); + raf.write(key.getBytes("UTF-8"), 0, key_size); + raf.writeByte(alias_size & 0xFF); + raf.write(alias.getBytes("UTF-8"), 0, alias_size); + block_size += 2 + key_size + alias_size; + } + fp = raf.getFilePointer(); + raf.seek(index); + raf.writeShort((block_size) & 0xFFFF); + raf.seek(fp); + + /* Output the exclude list if it exists. */ + List excludedZones = map.getExcludeList(); + if (excludedZones != null) { + raf.writeByte(ZoneInfoFile.TAG_ExcludedZones); + index += 3 + block_size; + block_size = 2; + raf.writeShort(block_size & 0xFFFF); // place holder + raf.writeShort(excludedZones.size()); // the number of excluded zones + for (String name : excludedZones) { + byte size = (byte) name.length(); + raf.writeByte(size); // byte length + raf.write(name.getBytes("UTF-8"), 0, size); // zone name + block_size += 1 + size; + } + fp = raf.getFilePointer(); + raf.seek(index); + raf.writeShort(block_size & 0xFFFF); + raf.seek(fp); + } + + /* Close ZoneInfoMapping file. */ + raf.close(); + } catch(IOException e) { + Main.panic("IO error: "+e.getMessage()); + return 1; + } + + return 0; + } +} diff --git a/jdk/test/sun/util/calendar/zi/GenDoc.java b/jdk/test/sun/util/calendar/zi/GenDoc.java new file mode 100644 index 00000000000..c3b520ce292 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/GenDoc.java @@ -0,0 +1,778 @@ +/* + * Copyright (c) 2001, 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. + */ + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.StringTokenizer; +import java.util.TreeMap; +import java.util.TreeSet; + +/** + * GenDoc is one of back-end classes of javazic, and generates + * index.html and other html files which prints the detailed time zone + * information for each zone. + */ +class GenDoc extends BackEnd { + + private static final String docDir = "doc"; + + private static final String header1 = + "\n" + + "\n\n\n\n" + + "Java Platform, Standard Edition - TimeZone information based on "; + private static final String header3 = + "-->\n<TITLE>\n" + + "Java Platform, Standard Edition TimeZone - "; + private static final String header4 = + "\n" + + "\n\n"; + + private static final String body1 = + "\n"; + private static final String body2 = + "\n"; + + private static final String footer = + "\n"; + + + // list of time zone name and zonefile name/real time zone name + // e.g. + // key (String) : value (String) + // "America/Denver" : "America/Denver.html" (real time zone) + // "America/Shiprock" : "America/Denver" (alias) + TreeMap timezoneList = new TreeMap(); + + // list of time zone's display name and time zone name + // e.g. + // key (String) : value (String) + // "Tokyo, Asia" : "Asia/Tokyo" + // "Marengo, Indiana, America" : "America/Indiana/Marengo" + // (aliases included) + TreeMap displayNameList = new TreeMap(); + + // list of top level regions + // e.g. + // key (String) : value (String) + // "America" : "America.html" + // (including entries in America/Indiana/, America/Kentucky/, ...) + TreeMap regionList = new TreeMap(); + + // mapping list from zone name to latitude & longitude + // This list is generated from zone.tab. + // e.g. + // key (String) : value (LatitudeAndLongitude object) + // "Asia/Tokyo" : latitude=35.3916, longitude=13.9444 + // (aliases not included) + HashMap mapList = null; + + // SortedMap of zone IDs sorted by their GMT offsets. If zone's GMT + // offset will change in the future, its last known offset is + // used. + SortedMap> zonesByOffset = new TreeMap>(); + + /** + * Generates HTML document for each zone. + * @param Timezone + * @return 0 if no errors, or 1 if error occurred. + */ + int processZoneinfo(Timezone tz) { + try { + int size; + int index; + String outputDir = Main.getOutputDir(); + String zonename = tz.getName(); + String zonefile = ZoneInfoFile.getFileName(zonename) + ".html"; + List stz = tz.getLastRules(); + timezoneList.put(zonename, zonefile); + displayNameList.put(transform(zonename), zonename); + + // Populate zonesByOffset. (Zones that will change their + // GMT offsets are also added to zonesByOffset here.) + int lastKnownOffset = tz.getRawOffset(); + Set set = zonesByOffset.get(lastKnownOffset); + if (set == null) { + set = new TreeSet(); + zonesByOffset.put(lastKnownOffset, set); + } + set.add(zonename); + + /* If outputDir doesn't end with file-separator, adds it. */ + if (!outputDir.endsWith(File.separator)) { + outputDir += File.separatorChar; + } + outputDir += docDir + File.separatorChar; + + index = zonename.indexOf('/'); + if (index != -1) { + regionList.put(zonename.substring(0, index), + zonename.substring(0, index) + ".html"); + } + + /* If zonefile includes file-separator, it's treated as part of + * pathname. And make directory if necessary. + */ + index = zonefile.lastIndexOf('/'); + if (index != -1) { + zonefile.replace('/', File.separatorChar); + outputDir += zonefile.substring(0, index+1); + } + File outD = new File(outputDir); + outD.mkdirs(); + + /* If mapfile is available, add a link to the appropriate map */ + if ((mapList == null) && (Main.getMapFile() != null)) { + FileReader fr = new FileReader(Main.getMapFile()); + BufferedReader in = new BufferedReader(fr); + mapList = new HashMap(); + String line; + while ((line = in.readLine()) != null) { + // skip blank and comment lines + if (line.length() == 0 || line.charAt(0) == '#') { + continue; + } + StringTokenizer tokens = new StringTokenizer(line); + String token = tokens.nextToken(); /* We don't use the first token. */ + token = tokens.nextToken(); + LatitudeAndLongitude location = new LatitudeAndLongitude(token); + token = tokens.nextToken(); + mapList.put(token, location); + } + in.close(); + } + + /* Open zoneinfo file to write. */ + FileWriter fw = new FileWriter(outputDir + zonefile.substring(index+1)); + BufferedWriter out = new BufferedWriter(fw); + + out.write(header1 + new Date() + header3 + zonename + header4); + out.write(body1 + "" + zonename + ""); + LatitudeAndLongitude location = mapList.get(zonename); + if (location != null) { + int deg, min, sec; + + deg = location.getLatDeg(); + min = location.getLatMin(); + sec = location.getLatSec(); + if (deg < 0) { + min = -min; + sec = -sec; + } else if (min < 0) { + sec = -sec; + } + out.write("   " + + "[map]"); + } + out.write("\n

    \n"); + + List zone = tz.getZones(); + List rule = tz.getRules(); + if (rule != null && zone != null) { + out.write("\n" + + "\n" + + "\n" + + "\n" + + "\n

    " + + "Rules
    " + + "
    Zone
    \n"); + } + + /* Output Rule records. */ + if (rule != null) { + size = rule.size(); + out.write("

    \n" + + "Rules\n" + + "\n" + + "\n" + + "" + + "" + + "\n\n"); + for (int i = 0; i < size; i++) { + out.write("\n"); + StringTokenizer st = new StringTokenizer(rule.get(i).getLine()); + String s; + if (st.hasMoreTokens()) { /* RULE - truncated */ + st.nextToken(); + } + if (st.hasMoreTokens()) { /* NAME */ + out.write(""); + } + if (st.hasMoreTokens()) { /* FROM */ + out.write(""); + } + if (st.hasMoreTokens()) { /* TO */ + s = st.nextToken(); + if (s.equals("min") || s.equals("max")) { + out.write(""); + } else { + out.write(""); + } + } + if (st.hasMoreTokens()) { /* TYPE */ + out.write(""); + } + if (st.hasMoreTokens()) { /* IN */ + out.write(""); + } + if (st.hasMoreTokens()) { /* ON */ + out.write(""); + } + if (st.hasMoreTokens()) { /* AT */ + out.write(""); + } + if (st.hasMoreTokens()) { /* SAVE */ + out.write(""); + } + if (st.hasMoreTokens()) { /* LETTER/S */ + out.write(""); + } + if (st.hasMoreTokens()) { /* NOTES */ + s = st.nextToken(); + while (st.hasMoreTokens()) { + s += " " + st.nextToken(); + } + index = s.indexOf('#'); + out.write("\n"); + } else { + out.write("\n"); + } + out.write("\n"); + } + out.write("
    NAMEFROMTOTYPEINONATSAVELETTER/SNOTES
    " + st.nextToken() + "" + st.nextToken() + "" + s + "" + s + "" + st.nextToken() + "" + st.nextToken() + "" + st.nextToken() + "" + st.nextToken() + "" + st.nextToken() + "" + st.nextToken() + "" + s.substring(index+1) + " 
    \n

     

    \n"); + } + + /* Output Zone records. */ + if (zone != null) { + size = zone.size(); + out.write("

    \n" + + "Zone\n" + + "\n" + + "\n" + + "" + + "\n\n"); + for (int i = 0; i < size; i++) { + out.write("\n"); + StringTokenizer st = new StringTokenizer(zone.get(i).getLine()); + String s = st.nextToken(); + if (s.equals("Zone")) { /* NAME */ + s = st.nextToken(); + s = st.nextToken(); + } + out.write(""); /* GMTOFFSET */ + if (st.hasMoreTokens()) { /* RULES */ + out.write(""); + } + if (st.hasMoreTokens()) { /* FORMAT */ + s = st.nextToken(); + index = s.indexOf('#'); + if (index != -1) { + if (index != 0) { + out.write(""); /* FORMAT */ + s = s.substring(index+1); + } else { + out.write(""); /* FORMAT */ + } + while (st.hasMoreTokens()) { + s += " " + st.nextToken(); + } + out.write(""); /* UNTIL */ + out.write("\n\n"); /* NOTES */ + continue; + } else { + out.write(""); /* FORMAT */ + } + } + + if (st.hasMoreTokens()) { /* UNTIL */ + s = st.nextToken(); + while (st.hasMoreTokens()) { + s += " " + st.nextToken(); + } + index = s.indexOf('#'); + if (index != -1) { + if (index != 0) { + out.write(""); /* UNTIL */ + } else { + out.write(""); /* UNTIL */ + } + out.write("\n"); /* NOTES */ + } else { + out.write(""); /* UNTIL */ + out.write("\n"); /* NOTES */ + } + } else { + out.write(""); /* UNTIL */ + out.write("\n"); /* NOTES */ + } + out.write("\n"); + } + out.write("
    GMTOFFRULESFORMATUNTILNOTES
    " + s + "" + st.nextToken() + "" + s.substring(0, index-1) + + "  " + s + "
    " + s + "" + s.substring(0, index-1) + + " " + s.substring(index+1) + + "" + s + "   
    \n"); + } + out.write(body2 + footer); + + out.close(); + fw.close(); + } catch(IOException e) { + Main.panic("IO error: "+e.getMessage()); + return 1; + } + + return 0; + } + + /** + * Generates index.html and other top-level frame files. + * @param Mappings + * @return 0 if no errors, or 1 if error occurred. + */ + int generateSrc(Mappings map) { + try { + int len; + Object o[]; + String outputDir = Main.getOutputDir(); + FileWriter fw1, fw2; + BufferedWriter out1, out2; + + /* Whether alias list exists or not. */ + Map a = map.getAliases(); + if (a == null) { + Main.panic("Data not exist. (aliases)"); + return 1; + } + + timezoneList.putAll(a); + + /* If outputDir doesn't end with file-separator, adds it. */ + if (!outputDir.endsWith(File.separator)) { + outputDir += File.separatorChar; + } + outputDir += docDir + File.separatorChar; + + File outD = new File(outputDir); + outD.mkdirs(); + + /* Creates index.html */ + fw1 = new FileWriter(outputDir + "index.html", false); + out1 = new BufferedWriter(fw1); + + out1.write(header1 + new Date() + header2 + Main.getVersionName() + + header4 + + "\n" + + "\n" + + "\n" + + "\n" + + "" + + "\n" + + "\n" + + "\n" + + "<H2>\nFrame Alert\n</H2>\n\n" + + "<P>\n\n" + + "This document is designed to be viewed using the frames feature. If you see this\n" + + "message, you are using a non-frame-capable web client.\n" + + "<BR>\n" + + "Link to<A HREF=\"overview-summary.html\">Non-frame version.</A>\n" + + "\n" + footer); + + out1.close(); + fw1.close(); + + + /* Creates overview-frame.html */ + fw1 = new FileWriter(outputDir + "overview-frame.html", false); + out1 = new BufferedWriter(fw1); + + out1.write(header1 + new Date() + header2 + Main.getVersionName() + + header4 + body1 + + "\n\n" + + "\n" + + "\n
    \n" + + "JavaTM Platform
    Standard Ed.
    \n\n" + + "\n\n\n
    " + + "

    \n\nAll Time Zones Sorted By:\n
    \n" + + "  GMT offsets\n
    \n" + + "  Zone names\n
    " + + "  City names\n" + + "

    \n\nContinents and Oceans\n
    \n"); + + for (String regionKey : regionList.keySet()) { + out1.write("  " + regionKey + + "
    \n"); + + fw2 = new FileWriter(outputDir + regionList.get(regionKey), + false); + out2 = new BufferedWriter(fw2); + + out2.write(header1 + new Date() + header3 + regionKey + + header4 + body1 + "" + + regionKey + "\n
    \n\n\n\n\n
    "); + + boolean found = false; + for (String timezoneKey : timezoneList.keySet()) { + int regionIndex = timezoneKey.indexOf('/'); + if (regionIndex == -1 || + !regionKey.equals(timezoneKey.substring(0, regionIndex))) { + if (found) { + break; + } else { + continue; + } + } + + found = true; + if (a.containsKey(timezoneKey)) { + Object realName = a.get(timezoneKey); + while (a.containsKey(realName)) { + realName = a.get(realName); + } + out2.write(timezoneKey + + " (alias for " + "" + + realName + ")"); + } else { + out2.write("" + timezoneKey + + ""); + } + out2.write("
    \n"); + } + out2.write("
    \n" + body2 + footer); + + out2.close(); + fw2.close(); + } + out1.write("

    \n" + body2 + footer); + + out1.close(); + fw1.close(); + + + /* Creates allTimeZone-frame1.html (Sorted by GMT offsets) */ + fw1 = new FileWriter(outputDir + "allTimeZone-frame1.html", false); + out1 = new BufferedWriter(fw1); + + out1.write(header1 + new Date() + header2 + Main.getVersionName() + + header4 + body1 + + "Sorted by GMT offsets\n" + + "
    \n\n" + "\n" + + "\n\n\n\n\n"); + } + } + out1.write("\n\n
    \n"); + + List roi = map.getRawOffsetsIndex(); + List> roit = map.getRawOffsetsIndexTable(); + + int index = 0; + for (Integer offset : zonesByOffset.keySet()) { + int off = roi.get(index); + Set perRO = zonesByOffset.get(offset); + if (offset == off) { + // Merge aliases into zonesByOffset + perRO.addAll(roit.get(index)); + } + index++; + + for (String timezoneKey : perRO) { + out1.write("
    (" + + Time.toGMTFormat(offset.toString()) + + ")"); + + if (a.containsKey(timezoneKey)) { + Object realName = a.get(timezoneKey); + while (a.containsKey(realName)) { + realName = a.get(realName); + } + out1.write(timezoneKey + + " (alias for " + "" + realName + + ")"); + } else { + out1.write("" + timezoneKey + + ""); + } + out1.write("
    \n" + body2 + footer); + + out1.close(); + fw1.close(); + + + /* Creates allTimeZone-frame2.html (Sorted by zone names) */ + fw1 = new FileWriter(outputDir + "allTimeZone-frame2.html", false); + out1 = new BufferedWriter(fw1); + + out1.write(header1 + new Date() + header2 + Main.getVersionName() + + header4 + body1 + + "Sorted by zone names\n" + + "
    \n\n" + "\n" + + "\n\n\n
    \n"); + o = timezoneList.keySet().toArray(); + len = timezoneList.size(); + for (int i = 0; i < len; i++) { + Object timezoneKey = o[i]; + if (a.containsKey(timezoneKey)) { + Object realName = a.get(timezoneKey); + while (a.containsKey(realName)) { + realName = a.get(realName); + } + out1.write(timezoneKey + + " (alias for " + + "" + realName + + ")"); + } else { + out1.write("" + timezoneKey + + ""); + } + out1.write("
    \n"); + } + out1.write("
    \n" + body2 + footer); + + out1.close(); + fw1.close(); + + /* Creates allTimeZone-frame3.html (Sorted by city names) */ + fw1 = new FileWriter(outputDir + "allTimeZone-frame3.html", false); + out1 = new BufferedWriter(fw1); + + out1.write(header1 + new Date() + header2 + Main.getVersionName() + + header4 + body1 + + "Sorted by city names\n" + + "
    \n\n" + "\n" + + "\n\n\n
    \n"); + + Set aliasSet = a.keySet(); + len = aliasSet.size(); + String aliasNames[] = aliasSet.toArray(new String[0]); + for (int i = 0; i < len; i++) { + displayNameList.put(transform(aliasNames[i]), + aliasNames[i]); + } + + o = displayNameList.keySet().toArray(); + len = displayNameList.size(); + for (int i = 0; i < len; i++) { + Object displayName = o[i]; + Object timezoneKey = displayNameList.get(o[i]); + if (a.containsKey(timezoneKey)) { + Object realName = a.get(timezoneKey); + while (a.containsKey(realName)) { + realName = a.get(realName); + } + out1.write(displayName + + " (alias for " + + "" + realName + + ")"); + } else { + out1.write("" + displayName + + ""); + } + out1.write("
    \n"); + } + + out1.write("
    \n" + body2 + footer); + + out1.close(); + fw1.close(); + + /* Creates overview-summary.html */ + fw1 = new FileWriter(outputDir + "overview-summary.html", false); + out1 = new BufferedWriter(fw1); + + out1.write(header1 + new Date() + header2 + Main.getVersionName() + + header4 + body1 + + "

    This is the list of time zones generated from " + + Main.getVersionName() + " for Java Platform, " + + "Standard Edition. The source code can be obtained " + + "from ftp site " + + "ftp://elsie.nci.nih.gov/pub/. A total of " + + len + + " time zones and aliases are supported " + + "in this edition. For the " + + "format of rules and zones, refer to the zic " + + "(zoneinfo compiler) man page on " + + "Solaris or Linux.

    \n" + + "

    Note that the time zone data is not " + + "a public interface of the Java Platform. No " + + "applications should rely on the time zone data of " + + "this document. Time zone names and data " + + "may change without any prior notice.

    \n" + + body2 + footer); + + out1.close(); + fw1.close(); + } catch(IOException e) { + Main.panic("IO error: "+e.getMessage()); + return 1; + } + + return 0; + } + + String transform(String s) { + int index = s.lastIndexOf("/"); + + /* If the string doesn't include any delimiter, return */ + if (index == -1) { + return s; + } + + int lastIndex = index; + String str = s.substring(index+1); + do { + index = s.substring(0, lastIndex).lastIndexOf('/'); + str += ", " + s.substring(index+1, lastIndex); + lastIndex = index; + } while (index > -1); + + return str; + } + + static class LatitudeAndLongitude { + + private int latDeg, latMin, latSec, longDeg, longMin, longSec; + + LatitudeAndLongitude(String s) { + try { + // First of all, check the string has the correct format: + // either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS + + if (!s.startsWith("+") && !s.startsWith("-")) { + Main.warning("Wrong latitude&longitude data: " + s); + return; + } + int index; + if (((index = s.lastIndexOf("+")) <= 0) && + ((index = s.lastIndexOf("-")) <= 0)) { + Main.warning("Wrong latitude&longitude data: " + s); + return; + } + + if (index == 5) { + latDeg = Integer.parseInt(s.substring(1, 3)); + latMin = Integer.parseInt(s.substring(3, 5)); + latSec = 0; + } else if (index == 7) { + latDeg = Integer.parseInt(s.substring(1, 3)); + latMin = Integer.parseInt(s.substring(3, 5)); + latSec = Integer.parseInt(s.substring(5, 7)); + } else { + Main.warning("Wrong latitude&longitude data: " + s); + return; + } + if (s.startsWith("-")){ + latDeg = -latDeg; + latMin = -latMin; + latSec = -latSec; + } + + int len = s.length(); + if (index == 5 && len == 11) { + longDeg = Integer.parseInt(s.substring(index+1, index+4)); + longMin = Integer.parseInt(s.substring(index+4, index+6)); + longSec = 0; + } else if (index == 7 && len == 15) { + longDeg = Integer.parseInt(s.substring(index+1, index+4)); + longMin = Integer.parseInt(s.substring(index+4, index+6)); + longSec = Integer.parseInt(s.substring(index+6, index+8)); + } else { + Main.warning("Wrong latitude&longitude data: " + s); + return; + } + if (s.charAt(index) == '-'){ + longDeg = -longDeg; + longMin = -longMin; + longSec = -longSec; + } + } catch(Exception e) { + Main.warning("LatitudeAndLongitude() Parse error: " + s); + } + } + + int getLatDeg() { + return latDeg; + } + + int getLatMin() { + return latMin; + } + + int getLatSec() { + return latSec; + } + + int getLongDeg() { + return longDeg; + } + + int getLongMin() { + return longMin; + } + + int getLongSec() { + return longSec; + } + } +} diff --git a/jdk/test/sun/util/calendar/zi/Main.java b/jdk/test/sun/util/calendar/zi/Main.java new file mode 100644 index 00000000000..6fde7cd147d --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/Main.java @@ -0,0 +1,234 @@ +/* + * 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. + */ + +import java.util.ArrayList; +import java.util.List; + +/** + * Main class for the javazic time zone data compiler. + * + * @since 1.4 + */ +public class Main { + + private static boolean verbose = false; + static boolean outputDoc = false; + + private List ziFiles = new ArrayList(); + private static String zoneNamesFile = null; + private static String versionName = "unknown"; + private static String outputDir = "zoneinfo"; + private static String mapFile = null; + + /** + * Parses the specified arguments and sets up the variables. + * @param argv the arguments + */ + void processArgs(String[] argv) { + for (int i = 0; i < argv.length; i++) { + String arg = argv[i]; + if (arg.startsWith("-h")) { + usage(); + System.exit(0); + } else if (arg.equals("-d")) { + outputDir = argv[++i]; + } else if (arg.equals("-v")) { + verbose = true; + } else if (arg.equals("-V")) { + versionName = argv[++i]; + } else if (arg.equals("-doc")) { + outputDoc = true; + } else if (arg.equals("-map")) { + outputDoc = true; + mapFile = argv[++i]; + } else if (arg.equals("-f")) { + zoneNamesFile = argv[++i]; + } else if (arg.equals("-S")) { + try { + Zoneinfo.setYear(Integer.parseInt(argv[++i])); + } catch (Exception e) { + error("invalid year: " + argv[i]); + usage(); + System.exit(1); + } + } else { + boolean isStartYear = arg.equals("-s"); + if (isStartYear || arg.equals("-e")) { + try { + int year = Integer.parseInt(argv[++i]); + if (isStartYear) { + Zoneinfo.setStartYear(year); + } else { + Zoneinfo.setEndYear(year); + } + } catch (Exception e) { + error("invalid year: " + argv[i]); + usage(); + System.exit(1); + } + } else { + // the rest of args are zoneinfo source files + while (i < argv.length) { + ziFiles.add(argv[i++]); + } + } + } + } + } + + /** + * Parses zoneinfo source files + */ + int compile() { + int nFiles = ziFiles.size(); + int status = 0; + Mappings maps = new Mappings(); + BackEnd backend = BackEnd.getBackEnd(); + + for (int i = 0; i < nFiles; i++) { + Zoneinfo frontend = Zoneinfo.parse(ziFiles.get(i)); + + for (String key : frontend.getZones().keySet()) { + info(key); + + Timezone tz = frontend.phase2(key); + status |= backend.processZoneinfo(tz); + } + + maps.add(frontend); + } + + // special code for dealing with the conflicting name "MET" + Zone.addMET(); + + maps.resolve(); + + status |= backend.generateSrc(maps); + + return status; + } + + public static void main(String[] argv) { + Main zic = new Main(); + + /* + * Parse args + */ + zic.processArgs(argv); + + /* + * Read target zone names + */ + if (zoneNamesFile != null) { + Zone.readZoneNames(zoneNamesFile); + } + + zic.compile(); + } + + void usage() { + System.err.println("Usage: javazic [options] file...\n"+ + " -f namefile file containing zone names\n"+ + " to be generated (ie, generating subset)\n"+ + " -d dir output directory\n"+ + " -v verbose\n"+ + " -V datavers specifies the tzdata version string\n"+ + " (eg, \"tzdata2000g\")"+ + " -S year output only SimleTimeZone data of that year\n"+ + " -s year start year (default: 1900)\n"+ + " -e year end year (default: 2037)\n"+ + " -doc generates HTML documents\n"+ + " -map mapfile generates HTML documents with map information\n"+ + " file... zoneinfo source file(s)"); + } + + /** + * @return the output directory path name + */ + static String getOutputDir() { + return outputDir; + } + + /** + * @return the map file's path and name + */ + static String getMapFile() { + return mapFile; + } + + /** + * Returns the time zone data version string specified by the -V + * option. If it is not specified, "unknown" is returned. + * @return the time zone data version string + */ + static String getVersionName() { + return versionName; + } + + /** + * Prints out the specified fatal error message and calls {@link + * java.lang.System#exit System.exit(1)}. + * @param msg the fatal error message + */ + static void panic(String msg) { + printMessage("fatal error", msg); + System.exit(1); + } + + /** + * Prints out the specified error message. + * @param msg the error message + */ + static void error(String msg) { + printMessage("error", msg); + } + + /** + * Prints out the specified warning message. + * @param msg the warning message + */ + static void warning(String msg) { + printMessage("warning", msg); + } + + /** + * Prints out the informative message. + * @param msg the informative message + */ + static void info(String msg) { + if (verbose) { + printMessage(null, msg); + } + } + + private static void printMessage(String type, String msg) { + if (type != null) { + type += ": "; + } else { + type = ""; + } + System.err.println("javazic: " + type + msg); + } +} diff --git a/jdk/test/sun/util/calendar/zi/Mappings.java b/jdk/test/sun/util/calendar/zi/Mappings.java new file mode 100644 index 00000000000..2e12d8659e2 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/Mappings.java @@ -0,0 +1,195 @@ +/* + * 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. + */ + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +/** + * Mappings generates two Maps and a List which are used by + * javazic BackEnd. + * + * @since 1.4 + */ +class Mappings { + // All aliases specified by Link statements. It's alias name to + // real name mappings. + private Map aliases; + + private List rawOffsetsIndex; + + private List> rawOffsetsIndexTable; + + // Zone names to be excluded from rawOffset table. Those have GMT + // offsets to change some future time. + private List excludeList; + + /** + * Constructor creates some necessary instances. + */ + Mappings() { + aliases = new TreeMap(); + rawOffsetsIndex = new LinkedList(); + rawOffsetsIndexTable = new LinkedList>(); + } + + /** + * Generates aliases and rawOffsets tables. + * @param zi a Zoneinfo containing Zones + */ + void add(Zoneinfo zi) { + Map zones = zi.getZones(); + + for (String zoneName : zones.keySet()) { + Zone zone = zones.get(zoneName); + String zonename = zone.getName(); + int rawOffset = zone.get(zone.size()-1).getGmtOffset(); + + // If the GMT offset of this Zone will change in some + // future time, this Zone is added to the exclude list. + boolean isExcluded = false; + for (int i = 0; i < zone.size(); i++) { + ZoneRec zrec = zone.get(i); + if ((zrec.getGmtOffset() != rawOffset) + && (zrec.getUntilTime(0) > Time.getCurrentTime())) { + if (excludeList == null) { + excludeList = new ArrayList(); + } + excludeList.add(zone.getName()); + isExcluded = true; + break; + } + } + + if (!rawOffsetsIndex.contains(new Integer(rawOffset))) { + // Find the index to insert this raw offset zones + int n = rawOffsetsIndex.size(); + int i; + for (i = 0; i < n; i++) { + if (rawOffsetsIndex.get(i) > rawOffset) { + break; + } + } + rawOffsetsIndex.add(i, rawOffset); + + Set perRawOffset = new TreeSet(); + if (!isExcluded) { + perRawOffset.add(zonename); + } + rawOffsetsIndexTable.add(i, perRawOffset); + } else if (!isExcluded) { + int i = rawOffsetsIndex.indexOf(new Integer(rawOffset)); + Set perRawOffset = rawOffsetsIndexTable.get(i); + perRawOffset.add(zonename); + } + } + + Map a = zi.getAliases(); + // If there are time zone names which refer to any of the + // excluded zones, add those names to the excluded list. + if (excludeList != null) { + for (String zoneName : a.keySet()) { + String realname = a.get(zoneName); + if (excludeList.contains(realname)) { + excludeList.add(zoneName); + } + } + } + aliases.putAll(a); + } + + /** + * Adds valid aliases to one of per-RawOffset table and removes + * invalid aliases from aliases List. Aliases referring to + * excluded zones are not added to a per-RawOffset table. + */ + void resolve() { + int index = rawOffsetsIndexTable.size(); + List toBeRemoved = new ArrayList(); + for (String key : aliases.keySet()) { + boolean validname = false; + for (int j = 0; j < index; j++) { + Set perRO = rawOffsetsIndexTable.get(j); + boolean isExcluded = (excludeList == null) ? + false : excludeList.contains(key); + + if ((perRO.contains(aliases.get(key)) || isExcluded) + && Zone.isTargetZone(key)) { + validname = true; + if (!isExcluded) { + perRO.add(key); + Main.info("Alias <"+key+"> added to the list."); + } + break; + } + } + + if (!validname) { + Main.info("Alias <"+key+"> removed from the list."); + toBeRemoved.add(key); + } + } + + // Remove zones, if any, from the list. + for (String key : toBeRemoved) { + aliases.remove(key); + } + // Eliminate any alias-to-alias mappings. For example, if + // there are A->B and B->C, A->B is changed to A->C. + Map newMap = new HashMap(); + for (String key : aliases.keySet()) { + String realid = aliases.get(key); + String leaf = realid; + while (aliases.get(leaf) != null) { + leaf = aliases.get(leaf); + } + if (!realid.equals(leaf)) { + newMap.put(key, leaf); + } + } + aliases.putAll(newMap); + } + + Map getAliases() { + return(aliases); + } + + List getRawOffsetsIndex() { + return(rawOffsetsIndex); + } + + List> getRawOffsetsIndexTable() { + return(rawOffsetsIndexTable); + } + + List getExcludeList() { + return excludeList; + } +} diff --git a/jdk/test/sun/util/calendar/zi/Month.java b/jdk/test/sun/util/calendar/zi/Month.java new file mode 100644 index 00000000000..f2db5f135d1 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/Month.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2000, 2004, 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. + */ + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Month enum handles month related manipulation. + * + * @since 1.4 + */ +enum Month { + JANUARY("Jan"), + FEBRUARY("Feb"), + MARCH("Mar"), + APRIL("Apr"), + MAY("May"), + JUNE("Jun"), + JULY("Jul"), + AUGUST("Aug"), + SEPTEMBER("Sep"), + OCTOBER("Oct"), + NOVEMBER("Nov"), + DECEMBER("Dec"); + + private final String abbr; + + private static final Map abbreviations + = new HashMap(12); + + static { + for (Month m : Month.values()) { + abbreviations.put(m.abbr, m); + } + } + + private Month(String abbr) { + this.abbr = abbr; + } + + int value() { + return ordinal() + 1; + } + + /** + * Parses the specified string as a month abbreviation. + * @param name the month abbreviation + * @return the Month value + */ + static Month parse(String name) { + Month m = abbreviations.get(name); + if (m != null) { + return m; + } + return null; + } + + /** + * @param month the nunmth number (1-based) + * @return the month name in uppercase of the specified month + */ + static String toString(int month) { + if (month >= JANUARY.value() && month <= DECEMBER.value()) { + return "Calendar." + Month.values()[month - 1]; + } + throw new IllegalArgumentException("wrong month number: " + month); + } +} diff --git a/jdk/test/sun/util/calendar/zi/Rule.java b/jdk/test/sun/util/calendar/zi/Rule.java new file mode 100644 index 00000000000..8e3a1189bb9 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/Rule.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2000, 2004, 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. + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.StringTokenizer; + +/** + * Rule manipulates Rule records. + * + * @since 1.4 + */ +class Rule { + + private List list; + private String name; + + /** + * Constructs a Rule which consists of a Rule record list. The + * specified name is given to this Rule. + * @param name the Rule name + */ + Rule(String name) { + this.name = name; + list = new ArrayList(); + } + + /** + * Added a RuleRec to the Rule record list. + */ + void add(RuleRec rec) { + list.add(rec); + } + + /** + * @return the Rule name + */ + String getName() { + return name; + } + + /** + * Gets all rule records that cover the given year. + * + * @param year the year number for which the rule is applicable. + * @return rules in List that are collated in time. If no rule is found, an empty + * List is returned. + */ + List getRules(int year) { + List rules = new ArrayList(3); + for (RuleRec rec : list) { + if (year >= rec.getFromYear() && year <= rec.getToYear()) { + if ((rec.isOdd() && year % 2 == 0) || (rec.isEven() && year % 2 == 1)) + continue; + rules.add(rec); + } + } + int n = rules.size(); + if (n <= 1) { + return rules; + } + if (n == 2) { + RuleRec rec1 = rules.get(0); + RuleRec rec2 = rules.get(1); + if (rec1.getMonthNum() > rec2.getMonthNum()) { + rules.set(0, rec2); + rules.set(1, rec1); + } else if (rec1.getMonthNum() == rec2.getMonthNum()) { + // TODO: it's not accurate to ignore time types (STD, WALL, UTC) + long t1 = Time.getLocalTime(year, rec1.getMonth(), + rec1.getDay(), rec1.getTime().getTime()); + long t2 = Time.getLocalTime(year, rec2.getMonth(), + rec2.getDay(), rec2.getTime().getTime()); + if (t1 > t2) { + rules.set(0, rec2); + rules.set(1, rec1); + } + } + return rules; + } + + final int y = year; + RuleRec[] recs = new RuleRec[rules.size()]; + rules.toArray(recs); + Arrays.sort(recs, new Comparator() { + public int compare(RuleRec r1, RuleRec r2) { + int n = r1.getMonthNum() - r2.getMonthNum(); + if (n != 0) { + return n; + } + // TODO: it's not accurate to ignore time types (STD, WALL, UTC) + long t1 = Time.getLocalTime(y, r1.getMonth(), + r1.getDay(), r1.getTime().getTime()); + long t2 = Time.getLocalTime(y, r2.getMonth(), + r2.getDay(), r2.getTime().getTime()); + return (int)(t1 - t2); + } + public boolean equals(Object o) { + return this == o; + } + }); + rules.clear(); + for (int i = 0; i < n; i++) { + rules.add(recs[i]); + } + return rules; + } + + /** + * Gets rule records that have either "max" or cover the endYear + * value in its DST schedule. + * + * @return rules that contain last DST schedule. An empty + * ArrayList is returned if no last rules are found. + */ + List getLastRules() { + RuleRec start = null; + RuleRec end = null; + + for (int i = 0; i < list.size(); i++) { + RuleRec rec = list.get(i); + if (rec.isLastRule()) { + if (rec.getSave() > 0) { + start = rec; + } else { + end = rec; + } + } + } + if (start == null || end == null) { + int endYear = Zoneinfo.getEndYear(); + for (int i = 0; i < list.size(); i++) { + RuleRec rec = list.get(i); + if (endYear >= rec.getFromYear() && endYear <= rec.getToYear()) { + if (start == null && rec.getSave() > 0) { + start = rec; + } else { + if (end == null && rec.getSave() == 0) { + end = rec; + } + } + } + } + } + + List r = new ArrayList(2); + if (start == null || end == null) { + if (start != null || end != null) { + Main.warning("found last rules for "+name+" inconsistent."); + } + return r; + } + + r.add(start); + r.add(end); + return r; + } +} diff --git a/jdk/test/sun/util/calendar/zi/RuleDay.java b/jdk/test/sun/util/calendar/zi/RuleDay.java new file mode 100644 index 00000000000..a9e83aceb10 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/RuleDay.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2000, 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. + */ + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * RuleDay class represents the value of the "ON" field. The day of + * week values start from 1 following the {@link java.util.Calendar} + * convention. + * + * @since 1.4 + */ +class RuleDay { + private static final Map abbreviations = new HashMap(7); + static { + for (DayOfWeek day : DayOfWeek.values()) { + abbreviations.put(day.getAbbr(), day); + } + } + + private String dayName = null; + private DayOfWeek dow; + private boolean lastOne = false; + private int soonerOrLater = 0; + private int thanDayOfMonth; // day of month (e.g., 8 for "Sun>=8") + + RuleDay() { + } + + RuleDay(int day) { + thanDayOfMonth = day; + } + + int getDay() { + return thanDayOfMonth; + } + + /** + * @return the day of week value (1-based) + */ + int getDayOfWeekNum() { + return dow.value(); + } + + /** + * @return true if this rule day represents the last day of + * week. (e.g., lastSun). + */ + boolean isLast() { + return lastOne; + } + + /** + * @return true if this rule day represents the day of week on or + * later than (after) the {@link #getDay}. (e.g., Sun>=1) + */ + boolean isLater() { + return soonerOrLater > 0; + } + + /** + * @return true if this rule day represents the day of week on or + * earlier than (before) the {@link #getDay}. (e.g., Sun<=15) + */ + boolean isEarlier() { + return soonerOrLater < 0; + } + + /** + * @return true if this rule day represents an exact day. + */ + boolean isExact() { + return soonerOrLater == 0; + } + + /** + * Parses the "ON" field and constructs a RuleDay. + * @param day an "ON" field string (e.g., "Sun>=1") + * @return a RuleDay representing the given "ON" field + */ + static RuleDay parse(String day) { + RuleDay d = new RuleDay(); + if (day.startsWith("last")) { + d.lastOne = true; + d.dayName = day.substring(4); + d.dow = getDOW(d.dayName); + } else { + int index; + if ((index = day.indexOf(">=")) != -1) { + d.dayName = day.substring(0, index); + d.dow = getDOW(d.dayName); + d.soonerOrLater = 1; // greater or equal + d.thanDayOfMonth = Integer.parseInt(day.substring(index+2)); + } else if ((index = day.indexOf("<=")) != -1) { + d.dayName = day.substring(0, index); + d.dow = getDOW(d.dayName); + d.soonerOrLater = -1; // less or equal + d.thanDayOfMonth = Integer.parseInt(day.substring(index+2)); + } else { + // it should be an integer value. + d.thanDayOfMonth = Integer.parseInt(day); + } + } + return d; + } + + /** + * Converts this RuleDay to the SimpleTimeZone day rule. + * @return the converted SimpleTimeZone day rule + */ + int getDayForSimpleTimeZone() { + if (isLast()) { + return -1; + } + return isEarlier() ? -getDay() : getDay(); + } + + /** + * Converts this RuleDay to the SimpleTimeZone day-of-week rule. + * @return the SimpleTimeZone day-of-week rule value + */ + int getDayOfWeekForSimpleTimeZoneInt() { + if (isEarlier() || isLater()) { + return -getDayOfWeekNum(); + } + return isLast() ? getDayOfWeekNum() : 0; + } + + /** + * @return the string representation of the {@link + * #getDayOfWeekForSimpleTimeZoneInt} value + */ + String getDayOfWeekForSimpleTimeZone() { + int d = getDayOfWeekForSimpleTimeZoneInt(); + if (d == 0) { + return "0"; + } + String sign = ""; + if (d < 0) { + sign = "-"; + d = -d; + } + return sign + toString(d); + } + + private static DayOfWeek getDOW(String abbr) { + return abbreviations.get(abbr); + } + + /** + * Converts the specified day of week value to the day-of-week + * name defined in {@link java.util.Calenda}. + * @param dow 1-based day of week value + * @return the Calendar day of week name with "Calendar." prefix. + * @throws IllegalArgumentException if the specified dow value is out of range. + */ + static String toString(int dow) { + if (dow >= DayOfWeek.SUNDAY.value() && dow <= DayOfWeek.SATURDAY.value()) { + return "Calendar." + DayOfWeek.values()[dow - 1]; + } + throw new IllegalArgumentException("wrong Day_of_Week number: " + dow); + } +} diff --git a/jdk/test/sun/util/calendar/zi/RuleRec.java b/jdk/test/sun/util/calendar/zi/RuleRec.java new file mode 100644 index 00000000000..c0a578554c5 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/RuleRec.java @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2000, 2004, 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. + */ + +import java.util.StringTokenizer; + +/** + * RuleRec class represents one record of the Rule set. + * + * @since 1.4 + */ +class RuleRec { + private int fromYear; + private int toYear; + private String type; + private Month inMonth; + private RuleDay onDay; + private Time atTime; + private int save; + private String letters; + private String line; + private boolean isLastRule; + + int getFromYear() { + return fromYear; + } + + int getToYear() { + return toYear; + } + + Month getMonth() { + return inMonth; + } + + int getMonthNum() { + return inMonth.value(); + } + + RuleDay getDay() { + return onDay; + } + + Time getTime() { + return atTime; + } + + int getSave() { + return save; + } + + String getLine() { + return line; + } + + /** + * Sets the line from the text file. + * @param line the text of the line + */ + void setLine(String line) { + this.line = line; + } + + /** + * @return true if the rule type is "odd". + */ + boolean isOdd() { + return "odd".equals(type); + } + + /** + * @return true if the rule type is "even". + */ + boolean isEven() { + return "even".equals(type); + } + + /** + * Determines if this rule record is the last DST schedule rule. + * + * @return true if this rule record has "max" as TO (year). + */ + boolean isLastRule() { + return isLastRule; + } + + /** + * Determines if the unadjusted until time of the specified ZoneRec + * is the same as the transition time of this rule in the same + * year as the ZoneRec until year. + * + * @param zrec ZoneRec to compare to + * @param save the amount of daylight saving in milliseconds + * @param gmtOffset the GMT offset value in milliseconds + * @return true if the unadjusted until time is the same as rule's + * transition time. + */ + boolean isSameTransition(ZoneRec zrec, int save, int gmtOffset) { + long until, transition; + + if (zrec.getUntilTime().getType() != atTime.getType()) { + until = zrec.getLocalUntilTime(save, gmtOffset); + transition = Time.getLocalTime(zrec.getUntilYear(), + getMonth(), + getDay(), + save, + gmtOffset, + atTime); + } else { + until = zrec.getLocalUntilTime(); + transition = Time.getLocalTime(zrec.getUntilYear(), + getMonth(), + getDay(), + atTime.getTime()); + } + + return until == transition; + } + + /** + * Parses a Rule line and returns a RuleRec object. + * + * @param tokens a StringTokenizer object that should contain a + * token for the "FROM" field and the rest. + * @return a RuleRec object. + */ + static RuleRec parse(StringTokenizer tokens) { + RuleRec rec = new RuleRec(); + try { + // FROM + String token = tokens.nextToken(); + try { + rec.fromYear = Integer.parseInt(token); + } catch (NumberFormatException e) { + // it's not integer + if ("min".equals(token) || "minimum".equals(token)) { + rec.fromYear = Zoneinfo.getMinYear(); + } else if ("max".equals(token) || "maximum".equals(token)) { + rec.fromYear = Zoneinfo.getMaxYear(); + } else { + Main.panic("invalid year value: "+token); + } + } + + // TO + token = tokens.nextToken(); + rec.isLastRule = false; + try { + rec.toYear = Integer.parseInt(token); + } catch (NumberFormatException e) { + // it's not integer + if ("min".equals(token) || "minimum".equals(token)) { + rec.fromYear = Zoneinfo.getMinYear(); + } else if ("max".equals(token) || "maximum".equals(token)) { + rec.toYear = Integer.MAX_VALUE; + rec.isLastRule = true; + } else if ("only".equals(token)) { + rec.toYear = rec.fromYear; + } else { + Main.panic("invalid year value: "+token); + } + } + + // TYPE + rec.type = tokens.nextToken(); + + // IN + rec.inMonth = Month.parse(tokens.nextToken()); + + // ON + rec.onDay = RuleDay.parse(tokens.nextToken()); + + // AT + rec.atTime = Time.parse(tokens.nextToken()); + + // SAVE + rec.save = (int) Time.parse(tokens.nextToken()).getTime(); + + // LETTER/S + rec.letters = tokens.nextToken(); + } catch (Exception e) { + e.printStackTrace(); + } + return rec; + } + + /** + * Calculates the transition time of the given year under this rule. + * @param year the year value + * @param gmtOffset the GMT offset value in milliseconds + * @param save the amount of daylight save time + * @return the transition time in milliseconds of the given year in UTC. + */ + long getTransitionTime(int year, int gmtOffset, int save) { + long time = Time.getLocalTime(year, getMonth(), + getDay(), atTime.getTime()); + if (atTime.isSTD()) { + time -= gmtOffset; + } else if (atTime.isWall()) { + time -= gmtOffset + save; + } + return time; + } + + private static int getInt(StringTokenizer tokens) { + String token = tokens.nextToken(); + return Integer.parseInt(token); + } +} diff --git a/jdk/test/sun/util/calendar/zi/Simple.java b/jdk/test/sun/util/calendar/zi/Simple.java new file mode 100644 index 00000000000..b61ffeaf229 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/Simple.java @@ -0,0 +1,186 @@ +/* + * 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. + */ + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.TreeSet; + +/** + * Simple generates TimeZoneData, which had been used as internal + * data of TimeZone before J2SDK1.3. + * Since J2SDK1.4 doesn't need TimeZoneData, this class is for maintenance + * of old JDK release. + */ +class Simple extends BackEnd { + + /** + * Zone records which are applied for given year. + */ + private static Map lastZoneRecs = new HashMap<>(); + + /** + * Rule records which are applied for given year. + */ + private static Map> lastRules = new TreeMap<>(); + + /** + * zone IDs sorted by their GMT offsets. If zone's GMT + * offset will change in the future, its last known offset is + * used. + */ + private SortedMap> zonesByOffset = new TreeMap<>(); + + /** + * Sets last Rule records and Zone records for given timezone to + * each Map. + * + * @param tz Timezone object for each zone + * @return always 0 + */ + int processZoneinfo(Timezone tz) { + String zonename = tz.getName(); + + lastRules.put(zonename, tz.getLastRules()); + lastZoneRecs.put(zonename, tz.getLastZoneRec()); + + // Populate zonesByOffset. (Zones that will change their + // GMT offsets are also added to zonesByOffset here.) + int lastKnownOffset = tz.getRawOffset(); + Set set = zonesByOffset.get(lastKnownOffset); + if (set == null) { + set = new TreeSet<>(); + zonesByOffset.put(lastKnownOffset, set); + } + set.add(zonename); + + return 0; + } + + /** + * Generates TimeZoneData to output SimpleTimeZone data. + * @param map Mappings object which is generated by {@link Main#compile}. + * @return 0 if no error occurred, otherwise 1. + */ + int generateSrc(Mappings map) { + try { + File outD = new File(Main.getOutputDir()); + outD.mkdirs(); + + FileWriter fw = + new FileWriter(new File(outD, "TimeZoneData.java"), false); + BufferedWriter out = new BufferedWriter(fw); + + out.write("import java.util.SimpleTimeZone;\n\n"); + out.write(" static SimpleTimeZone zones[] = {\n"); + + Map a = map.getAliases(); + List roi = map.getRawOffsetsIndex(); + List> roit = map.getRawOffsetsIndexTable(); + + int index = 0; + for (int offset : zonesByOffset.keySet()) { + int o = roi.get(index); + Set set = zonesByOffset.get(offset); + if (offset == o) { + // Merge aliases into zonesByOffset + set.addAll(roit.get(index)); + } + index++; + + for (String key : set) { + ZoneRec zrec; + String realname; + List stz; + if ((realname = a.get(key)) != null) { + // if this alias is not targeted, ignore it. + if (!Zone.isTargetZone(key)) { + continue; + } + stz = lastRules.get(realname); + zrec = lastZoneRecs.get(realname); + } else { + stz = lastRules.get(key); + zrec = lastZoneRecs.get(key); + } + + out.write("\t//--------------------------------------------------------------------\n"); + String s = Time.toFormedString(offset); + out.write("\tnew SimpleTimeZone(" + + Time.toFormedString(offset) + ", \"" + key + "\""); + if (realname != null) { + out.write(" /* " + realname + " */"); + } + + if (stz == null) { + out.write("),\n"); + } else { + RuleRec rr0 = stz.get(0); + RuleRec rr1 = stz.get(1); + + out.write(",\n\t " + Month.toString(rr0.getMonthNum()) + + ", " + rr0.getDay().getDayForSimpleTimeZone() + ", " + + rr0.getDay().getDayOfWeekForSimpleTimeZone() + ", " + + Time.toFormedString((int)rr0.getTime().getTime()) + ", " + + rr0.getTime().getTypeForSimpleTimeZone() + ",\n" + + + "\t " + Month.toString(rr1.getMonthNum()) + ", " + + rr1.getDay().getDayForSimpleTimeZone() + ", " + + rr1.getDay().getDayOfWeekForSimpleTimeZone() + ", " + + Time.toFormedString((int)rr1.getTime().getTime())+ ", " + + rr1.getTime().getTypeForSimpleTimeZone() + ",\n" + + + "\t " + Time.toFormedString(rr0.getSave()) + "),\n"); + + out.write("\t// " + rr0.getLine() + "\n"); + out.write("\t// " + rr1.getLine() + "\n"); + } + + String zline = zrec.getLine(); + if (zline.indexOf("Zone") == -1) { + zline = "Zone " + key + "\t" + zline.trim(); + } + out.write("\t// " + zline + "\n"); + } + } + out.write(" };\n"); + + out.close(); + fw.close(); + } catch(IOException e) { + Main.panic("IO error: "+e.getMessage()); + return 1; + } + + return 0; + } +} diff --git a/jdk/test/sun/util/calendar/zi/TestZoneInfo310.java b/jdk/test/sun/util/calendar/zi/TestZoneInfo310.java new file mode 100644 index 00000000000..c9e2bd9e6f7 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/TestZoneInfo310.java @@ -0,0 +1,213 @@ +/* + * 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. + * + * 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. + */ + +/* + *@test + *@bug 8007572 + *@summary Test whether the TimeZone generated from JSR310 tzdb is the same + *as the one from the tz data from javazic + */ + +import java.io.File; +import java.lang.reflect.*; +import java.nio.file.*; +import java.util.*; +import java.util.regex.*; +import java.time.zone.*; +import java.time.ZoneId; + +public class TestZoneInfo310 { + + public static void main(String[] args) throws Throwable { + + String TESTDIR = System.getProperty("test.dir", "."); + String SRCDIR = System.getProperty("test.src", "."); + String tzdir = SRCDIR + File.separator + "tzdata"; + String tzfiles = "africa antarctica asia australasia europe northamerica pacificnew southamerica backward etcetera systemv"; + String jdk_tzdir = SRCDIR + File.separator + "tzdata_jdk"; + String jdk_tzfiles = "gmt jdk11_backward"; + String zidir = TESTDIR + File.separator + "zi"; + File fZidir = new File(zidir); + if (!fZidir.exists()) { + fZidir.mkdirs(); + } + Matcher m = Pattern.compile("tzdata(?[0-9]{4}[A-z])") + .matcher(new String(Files.readAllBytes(Paths.get(tzdir, "VERSION")), "ascii")); + String ver = m.find() ? m.group("ver") : "NULL"; + + ArrayList alist = new ArrayList<>(); + alist.add("-V"); + alist.add(ver); + alist.add("-d"); + alist.add(zidir); + for (String f : tzfiles.split(" ")) { + alist.add(tzdir + File.separator + f); + } + for (String f : jdk_tzfiles.split(" ")) { + alist.add(jdk_tzdir + File.separator + f); + } + System.out.println("Compiling tz files!"); + Main.main(alist.toArray(new String[alist.size()])); + ////////////////////////////////// + + System.out.println("testing!"); + ZoneInfoFile.ziDir = zidir; + long t0, t1; + + t0 = System.nanoTime(); + ZoneInfoOld.getTimeZone("America/Los_Angeles"); + t1 = System.nanoTime(); + System.out.printf("OLD.getZoneInfoOld()[1]=%d%n", (t1 - t0) / 1000); + + t0 = System.nanoTime(); + ZoneInfoOld.getTimeZone("America/New_York"); + t1 = System.nanoTime(); + System.out.printf("OLD.getZoneInfoOld()[2]=%d%n", (t1 - t0) / 1000); + + t0 = System.nanoTime(); + ZoneInfoOld.getTimeZone("America/Denver"); + t1 = System.nanoTime(); + System.out.printf("OLD.getZoneInfoOld()[3]=%d%n", (t1 - t0) / 1000); + + t0 = System.nanoTime(); + String[] zids_old = ZoneInfoOld.getAvailableIDs(); + t1 = System.nanoTime(); + System.out.printf("OLD.getAvailableIDs()=%d, total=%d%n", + (t1 - t0) / 1000, zids_old.length); + Arrays.sort(zids_old); + + t0 = System.nanoTime(); + ZoneId.of("America/Los_Angeles").getRules(); + t1 = System.nanoTime(); + System.out.printf("NEW.getTimeZone()[1]=%d%n", (t1 - t0) / 1000); + + t0 = System.nanoTime(); + TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); + t1 = System.nanoTime(); + System.out.printf("NEW.getTimeZone()[1]=%d%n", (t1 - t0) / 1000); + + t0 = System.nanoTime(); + tz = TimeZone.getTimeZone("America/New_York"); + t1 = System.nanoTime(); + System.out.printf("NEW.getTimeZone()[2]=%d%n", (t1 - t0) / 1000); + + t0 = System.nanoTime(); + tz = TimeZone.getTimeZone("America/Denver"); + t1 = System.nanoTime(); + System.out.printf("NEW.getTimeZone()[3]=%d%n", (t1 - t0) / 1000); + + t0 = System.nanoTime(); + String[] zids_new = TimeZone.getAvailableIDs(); + t1 = System.nanoTime(); + System.out.printf("NEW.getAvailableIDs()=%d, total=%d%n", + (t1 - t0) / 1000, zids_new.length); + Arrays.sort(zids_new); + + t0 = System.currentTimeMillis(); + for (String zid : zids_new) { + TimeZone.getTimeZone(zid); + } + t1 = System.currentTimeMillis(); + System.out.printf("NEW.TotalTZ()=%d (ms)%n", t1 - t0); + + t0 = System.currentTimeMillis(); + for (String zid : zids_old) { + ZoneInfoOld.getTimeZone(zid); + } + t1 = System.currentTimeMillis(); + System.out.printf("OLD.TotalTZ()=%d (ms)%n", t1 - t0); + + if (!Arrays.equals(zids_old, zids_new)) { + throw new RuntimeException(" FAILED: availableIds don't match"); + } + for (String zid : zids_new) { + ZoneInfoOld zi = toZoneInfoOld(TimeZone.getTimeZone(zid)); + ZoneInfoOld ziOLD = (ZoneInfoOld)ZoneInfoOld.getTimeZone(zid); + if (! zi.equalsTo(ziOLD)) { + System.out.println(zi.diffsTo(ziOLD)); + throw new RuntimeException(" FAILED: " + zid); + } + } + delete(fZidir); + + // test tzdb version + if (!ver.equals(sun.util.calendar.ZoneInfoFile.getVersion())) { + System.out.printf(" FAILED: ver=%s, expected=%s%n", + sun.util.calendar.ZoneInfoFile.getVersion(), ver); + throw new RuntimeException("Version test failed"); + } + } + + private static void delete(File f) { + if (f.isDirectory()) { + for (File f0 : f.listFiles()) { + delete(f0); + } + } + f.delete(); + } + + // to access sun.util.calendar.ZoneInfo's private fields + static Class ziClz; + static Field rawOffset; + static Field checksum; + static Field dstSavings; + static Field transitions; + static Field offsets; + static Field simpleTimeZoneParams; + static Field willGMTOffsetChange; + static { + try { + ziClz = Class.forName("sun.util.calendar.ZoneInfo"); + rawOffset = ziClz.getDeclaredField("rawOffset"); + checksum = ziClz.getDeclaredField("checksum"); + dstSavings = ziClz.getDeclaredField("dstSavings"); + transitions = ziClz.getDeclaredField("transitions"); + offsets = ziClz.getDeclaredField("offsets"); + simpleTimeZoneParams = ziClz.getDeclaredField("simpleTimeZoneParams"); + willGMTOffsetChange = ziClz.getDeclaredField("willGMTOffsetChange"); + rawOffset.setAccessible(true); + checksum.setAccessible(true); + dstSavings.setAccessible(true); + transitions.setAccessible(true); + offsets.setAccessible(true); + simpleTimeZoneParams.setAccessible(true); + willGMTOffsetChange.setAccessible(true); + } catch (Exception x) { + throw new RuntimeException(x); + } + } + + private static ZoneInfoOld toZoneInfoOld(TimeZone tz) throws Exception { + return new ZoneInfoOld(tz.getID(), + rawOffset.getInt(tz), + dstSavings.getInt(tz), + checksum.getInt(tz), + (long[])transitions.get(tz), + (int[])offsets.get(tz), + (int[])simpleTimeZoneParams.get(tz), + willGMTOffsetChange.getBoolean(tz)); + } + + +} diff --git a/jdk/test/sun/util/calendar/zi/Time.java b/jdk/test/sun/util/calendar/zi/Time.java new file mode 100644 index 00000000000..8f82e1459c5 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/Time.java @@ -0,0 +1,341 @@ +/* + * 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. + */ + +import java.util.Locale; +import sun.util.calendar.CalendarDate; +import sun.util.calendar.CalendarSystem; +import sun.util.calendar.Gregorian; + +/** + * Time class represents the "AT" field and other time related information. + * + * @since 1.4 + */ +class Time { + + static final Gregorian gcal = CalendarSystem.getGregorianCalendar(); + + // type is wall clock time + private static final int WALL = 1; + + // type is standard time + private static final int STD = 2; + + // type is UTC + private static final int UTC = 3; + + // type of representing time + private int type; + + /** + * Time from the EPOCH in milliseconds + */ + private long time; + + /** + * Current time in milliseconds + */ + private static final long currentTime = System.currentTimeMillis(); + + Time() { + time = 0L; + } + + Time(long time) { + this.time = time; + } + + void setType(int type) { + this.type = type; + } + + long getTime() { + return time; + } + + int getType() { + return type; + } + + static long getCurrentTime() { + return currentTime; + } + + /** + * @return true if the time is represented in wall-clock time. + */ + boolean isWall() { + return type == WALL; + } + + /** + * @return true if the time is represented in standard time. + */ + boolean isSTD() { + return type == STD; + } + + /** + * @return true if the time is represented in UTC time. + */ + boolean isUTC() { + return type == UTC; + } + + /** + * Converts the type to a string that represents the type in the + * SimpleTimeZone time mode. (e.g., "SimpleTimeZone.WALL_TIME"). + * @return the converted string or null if the type is undefined. + */ + String getTypeForSimpleTimeZone() { + String stz = "SimpleTimeZone."; + if (isWall()) { + return stz+"WALL_TIME"; + } + else if (isSTD()) { + return stz+"STANDARD_TIME"; + } + else if (isUTC()) { + return stz+"UTC_TIME"; + } + else { + return null; + } + } + + /** + * Converts the given Gregorian calendar field values to local time. + * Local time is represented by the amount of milliseconds from + * January 1, 1970 0:00 GMT. + * @param year the year value + * @param month the Month value + * @param day the day represented by {@link RuleDay} + * @param save the amount of daylight time in milliseconds + * @param gmtOffset the GMT offset in milliseconds + * @param time the time of the day represented by {@link Time} + * @return local time + */ + static long getLocalTime(int year, Month month, RuleDay day, int save, + int gmtOffset, Time time) { + long t = time.getTime(); + + if (time.isSTD()) + t = time.getTime() + save; + else if (time.isUTC()) + t = time.getTime() + save + gmtOffset; + + return getLocalTime(year, month, day, t); + } + + /** + * Converts the given Gregorian calendar field values to local time. + * Local time is represented by the amount of milliseconds from + * January 1, 1970 0:00 GMT. + * @param year the year value + * @param month the Month value + * @param day the day value + * @param time the time of the day in milliseconds + * @return local time + */ + static long getLocalTime(int year, Month month, int day, long time) { + CalendarDate date = gcal.newCalendarDate(null); + date.setDate(year, month.value(), day); + long millis = gcal.getTime(date); + return millis + time; + } + + /** + * Equivalent to getLocalTime(year, month, day, (long)time). + * @param year the year value + * @param month the Month value + * @param day the day value + * @param time the time of the day in milliseconds + * @return local time + */ + static long getLocalTime(int year, Month month, int day, int time) { + return getLocalTime(year, month, day, (long)time); + } + + /** + * Equivalent to {@link #getLocalTime(int, Month, RuleDay, int) + * getLocalTime(year, month, day, (int) time)}. + * @param year the year value + * @param month the Month value + * @param day the day represented by {@link RuleDay} + * @param time the time of the day represented by {@link Time} + * @return local time + */ + static long getLocalTime(int year, Month month, RuleDay day, long time) { + return getLocalTime(year, month, day, (int) time); + } + + /** + * Converts the given Gregorian calendar field values to local time. + * Local time is represented by the amount of milliseconds from + * January 1, 1970 0:00 GMT. + * @param year the year value + * @param month the Month value + * @param day the day represented by {@link RuleDay} + * @param time the time of the day represented by {@link Time} + * @return local time + */ + static long getLocalTime(int year, Month month, RuleDay day, int time) { + CalendarDate cdate = gcal.newCalendarDate(null); + int monthValue = month.value(); + + if (day.isLast()) { // e.g., "lastSun" + cdate.setDate(year, monthValue, 1); + cdate.setDayOfMonth(gcal.getMonthLength(cdate)); + cdate = gcal.getNthDayOfWeek(-1, day.getDayOfWeekNum(), cdate); + } else if (day.isLater()) { // e.g., "Sun>=1" + cdate.setDate(year, monthValue, day.getDay()); + cdate = gcal.getNthDayOfWeek(1, day.getDayOfWeekNum(), cdate); + } else if (day.isExact()) { + cdate.setDate(year, monthValue, day.getDay()); + } else if (day.isEarlier()) { // e.g., "Sun<=15" + cdate.setDate(year, monthValue, day.getDay()); + cdate = gcal.getNthDayOfWeek(-1, day.getDayOfWeekNum(), cdate); + } else { + Main.panic("invalid day type: " + day); + } + return gcal.getTime(cdate) + time; + } + + /** + * Parses the given "AT" field and constructs a Time object. + * @param the "AT" field string + * @return the Time object + */ + static Time parse(String time) { + int sign; + int index = 0; + Time tm; + + if (time.charAt(0) == '-') { + sign = -1; + index++; + } else { + sign = 1; + } + int val = 0; + int num = 0; + int countDelim = 0; + while (index < time.length()) { + char c = time.charAt(index++); + if (c == ':') { + val = val * 60 + num; + countDelim++; + num = 0; + continue; + } + int d = Character.digit(c, 10); + if (d == -1) { + --index; + break; + } + num = num * 10 + d; + } + val = val * 60 + num; + // convert val to second + for (; countDelim < 2; countDelim++) { + val *= 60; + } + tm = new Time((long)val * 1000 * sign); + if (index < time.length()) { + char c = time.charAt(index++); + if (c == 's') { + tm.setType(Time.STD); + } else if (c == 'u' || c == 'g' || c == 'z') { + tm.setType(Time.UTC); + } else if (c == 'w') { + tm.setType(Time.WALL); + } else { + Main.panic("unknown time mode: "+c); + } + } else { + tm.setType(Time.WALL); + } + return tm; + } + + /** + * Converts the given milliseconds string to a "[+-]hh:mm" string. + * @param ms the milliseconds string + */ + static String toGMTFormat(String ms) { + long sec = Long.parseLong(ms) / 1000; + char sign; + if (sec < 0) { + sign = '-'; + sec = -sec; + } else { + sign = '+'; + } + return String.format((Locale)null, "%c%02d:%02d", + sign, sec/3600, (sec%3600)/60); + } + + /** + * Converts the given millisecond value to a string for a + * SimpleTimeZone parameter. + * @param ms the millisecond value + * @return the string in a human readable form + */ + static String toFormedString(int ms) { + StringBuilder s = new StringBuilder(); + boolean minus = false; + + if (ms < 0) { + s.append("-"); + minus = true; + ms = -ms; + } else if (ms == 0) { + return "0"; + } + + int hour = ms / (60 * 60 * 1000); + ms %= (60 * 60 * 1000); + int minute = ms / (60 * 1000); + + if (hour != 0) { + if (minus && minute != 0) { + s.append("("); + } + s.append(Integer.toString(hour) + "*ONE_HOUR"); + } + + if (minute != 0) { + if (hour != 0) { + s.append("+"); + } + s.append(Integer.toString(minute) + "*ONE_MINUTE"); + if (minus && hour != 0) { + s.append(")"); + } + } + + return s.toString(); + } +} diff --git a/jdk/test/sun/util/calendar/zi/Timezone.java b/jdk/test/sun/util/calendar/zi/Timezone.java new file mode 100644 index 00000000000..04518a944f5 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/Timezone.java @@ -0,0 +1,452 @@ +/* + * Copyright (c) 2000, 2004, 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. + */ + +import java.util.ArrayList; +import java.util.List; + +/** + * Timezone represents all information of a single point of time to + * generate its time zone database. + * + * @since 1.4 + */ +class Timezone { + /** + * zone name of this time zone + */ + private String name; + + /** + * transition time values in UTC (millisecond) + */ + private List transitions; + + /** + * All offset values in millisecond + * @see sun.util.calendar.ZoneInfo + */ + private List offsets; + + /** + * Indices of GMT offset values (both raw and raw+saving) + * at transitions + */ + private List gmtOffsets; + + /** + * Indices of regular or "direct" saving time values + * at transitions + */ + private List dstOffsets; + + /** + * Zone records of this time zone + */ + private List usedZoneRecs; + + /** + * Rule records referred to by this time zone + */ + private List usedRuleRecs; + + /** + * Type of DST rules in this time zone + */ + private int dstType; + static final int UNDEF_DST = 0; // DST type not set yet + static final int NO_DST = 1; // never observed DST + static final int LAST_DST = 2; // last rule ends in DST (all year round DST-only) + static final int X_DST = 3; // used to observe DST + static final int DST = 4; // observing DST regularly + + /** + * Raw GMT offset of this time zone in the last rule + */ + private int rawOffset; + + /** + * The CRC32 value of the transitions data + */ + private int crc32; + + /** + * The last ZoneRec + */ + private ZoneRec lastZoneRec; + + /** + * The last DST rules. lastRules[0] is the DST start + * rule. lastRules[1] is the DST end rules. + */ + private List lastRules; + + /** + * The amount of DST saving value (millisecond) in the last DST + * rule. + */ + private int lastSaving; + + /** + * true if the raw offset will change in the future time. + */ + private boolean willRawOffsetChange = false; + + + /** + * Constracts a Timezone object with the given zone name. + * @param name the zone name + */ + Timezone(String name) { + this.name = name; + } + + /** + * @return the number of transitions + */ + int getNTransitions() { + if (transitions == null) { + return 0; + } + return transitions.size(); + } + + /** + * @return the zone name + */ + String getName() { + return name; + } + + /** + * Returns the list of all rule records that have been referred to + * by this time zone. + * @return the rule records list + */ + List getRules() { + return usedRuleRecs; + } + + /** + * Returns the list of all zone records that have been referred to + * by this time zone. + * @return the zone records list + */ + List getZones() { + return usedZoneRecs; + } + + /** + * @return the transition table (list) + */ + List getTransitions() { + return transitions; + } + + /** + * @return the offsets list + */ + List getOffsets() { + return offsets; + } + + /** + * @return the DST saving offsets list + */ + List getDstOffsets() { + return dstOffsets; + } + + /** + * @return the GMT offsets list + */ + List getGmtOffsets() { + return gmtOffsets; + } + + /** + * @return the checksum (crc32) value of the trasition table + */ + int getCRC32() { + return crc32; + } + + /** + * @return true if the GMT offset of this time zone would change + * after the time zone database has been generated, false, otherwise. + */ + boolean willGMTOffsetChange() { + return willRawOffsetChange; + } + + /** + * @return the last known GMT offset value in milliseconds + */ + int getRawOffset() { + return rawOffset; + } + + /** + * Sets time zone's GMT offset to offset. + * @param offset the GMT offset value in milliseconds + */ + void setRawOffset(int offset) { + rawOffset = offset; + } + + /** + * Sets time zone's GMT offset value to offset. If + * startTime is future time, then the {@link + * #willRawOffsetChange} value is set to true. + * @param offset the GMT offset value in milliseconds + * @param startTime the UTC time at which the GMT offset is in effective + */ + void setRawOffset(int offset, long startTime) { + // if this rawOffset is for the future time, let the run-time + // look for the current GMT offset. + if (startTime > Time.getCurrentTime()) { + willRawOffsetChange = true; + } + setRawOffset(offset); + } + + /** + * Adds the specified transition information to the end of the transition table. + * @param time the UTC time at which this transition happens + * @param offset the total amount of the offset from GMT in milliseconds + * @param dstOffset the amount of time in milliseconds saved at this transition + */ + void addTransition(long time, int offset, int dstOffset) { + if (transitions == null) { + transitions = new ArrayList(); + offsets = new ArrayList(); + dstOffsets = new ArrayList(); + } + transitions.add(time); + offsets.add(offset); + dstOffsets.add(dstOffset); + } + + /** + * Sets the type of historical daylight saving time + * observation. For example, China used to observed daylight + * saving time, but it no longer does. Then, X_DST is set to the + * China time zone. + * @param type the type of daylight saving time + */ + void setDSTType(int type) { + dstType = type; + } + + /** + * @return the type of historical daylight saving time + * observation. + */ + int getDSTType() { + return dstType; + } + + /** + * Adds the specified zone record to the zone records list. + * @param rec the zone record + */ + void addUsedRec(ZoneRec rec) { + if (usedZoneRecs == null) { + usedZoneRecs = new ArrayList(); + } + usedZoneRecs.add(rec); + } + + /** + * Adds the specified rule record to the rule records list. + * @param rec the rule record + */ + void addUsedRec(RuleRec rec) { + if (usedRuleRecs == null) { + usedRuleRecs = new ArrayList(); + } + // if the last used rec is the same as the given rec, avoid + // putting the same rule. + int n = usedRuleRecs.size(); + for (int i = 0; i < n; i++) { + if (usedRuleRecs.get(i).equals(rec)) { + return; + } + } + usedRuleRecs.add(rec); + } + + /** + * Sets the last zone record for this time zone. + * @param the last zone record + */ + void setLastZoneRec(ZoneRec zrec) { + lastZoneRec = zrec; + } + + /** + * @return the last zone record for this time zone. + */ + ZoneRec getLastZoneRec() { + return lastZoneRec; + } + + /** + * Sets the last rule records for this time zone. Those are used + * for generating SimpleTimeZone parameters. + * @param rules the last rule records + */ + void setLastRules(List rules) { + int n = rules.size(); + if (n > 0) { + lastRules = rules; + RuleRec rec = rules.get(0); + int offset = rec.getSave(); + if (offset > 0) { + setLastDSTSaving(offset); + } else { + System.err.println("\t No DST starting rule in the last rules."); + } + } + } + + /** + * @return the last rule records for this time zone. + */ + List getLastRules() { + return lastRules; + } + + /** + * Sets the last daylight saving amount. + * @param the daylight saving amount + */ + void setLastDSTSaving(int offset) { + lastSaving = offset; + } + + /** + * @return the last daylight saving amount. + */ + int getLastDSTSaving() { + return lastSaving; + } + + /** + * Calculates the CRC32 value from the transition table and sets + * the value to crc32. + */ + void checksum() { + if (transitions == null) { + crc32 = 0; + return; + } + Checksum sum = new Checksum(); + for (int i = 0; i < transitions.size(); i++) { + int offset = offsets.get(i); + // adjust back to make the transition in local time + sum.update(transitions.get(i) + offset); + sum.update(offset); + sum.update(dstOffsets.get(i)); + } + crc32 = (int)sum.getValue(); + } + + /** + * Removes unnecessary transitions for Java time zone support. + */ + void optimize() { + // if there is only one offset, delete all transitions. This + // could happen if only time zone abbreviations changed. + if (gmtOffsets.size() == 1) { + transitions = null; + usedRuleRecs = null; + setDSTType(NO_DST); + return; + } + for (int i = 0; i < (transitions.size() - 2); i++) { // don't remove the last one + if (transitions.get(i) == transitions.get(i+1)) { + transitions.remove(i); + offsets.remove(i); + dstOffsets.remove(i); + i--; + } + } + + for (int i = 0; i < (transitions.size() - 2); i++) { // don't remove the last one + if (offsets.get(i) == offsets.get(i+1) + && dstOffsets.get(i) == dstOffsets.get(i+1)) { + transitions.remove(i+1); + offsets.remove(i+1); + dstOffsets.remove(i+1); + i--; + } + } + } + + /** + * Stores the specified offset value from GMT in the GMT offsets + * table and returns its index. The offset value includes the base + * GMT offset and any additional daylight saving if applicable. If + * the same value as the specified offset is already in the table, + * its index is returned. + * @param offset the offset value in milliseconds + * @return the index to the offset value in the GMT offsets table. + */ + int getOffsetIndex(int offset) { + return getOffsetIndex(offset, 0); + } + + /** + * Stores the specified daylight saving value in the GMT offsets + * table and returns its index. If the same value as the specified + * offset is already in the table, its index is returned. If 0 is + * specified, it's not stored in the table and -1 is returned. + * @param offset the offset value in milliseconds + * @return the index to the specified offset value in the GMT + * offsets table, or -1 if 0 is specified. + */ + int getDstOffsetIndex(int offset) { + if (offset == 0) { + return -1; + } + return getOffsetIndex(offset, 1); + } + + private int getOffsetIndex(int offset, int index) { + if (gmtOffsets == null) { + gmtOffsets = new ArrayList(); + } + for (int i = index; i < gmtOffsets.size(); i++) { + if (offset == gmtOffsets.get(i)) { + return i; + } + } + if (gmtOffsets.size() < index) { + gmtOffsets.add(0); + } + gmtOffsets.add(offset); + return gmtOffsets.size() - 1; + } +} diff --git a/jdk/test/sun/util/calendar/zi/TzIDOldMapping.java b/jdk/test/sun/util/calendar/zi/TzIDOldMapping.java new file mode 100644 index 00000000000..e9ea6b5dfe1 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/TzIDOldMapping.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2008, 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. + */ + +import java.util.Map; +import java.util.HashMap; + +class TzIDOldMapping { + static final Map MAP = new HashMap(); + static { + String[][] oldmap = { + { "ACT", "Australia/Darwin" }, + { "AET", "Australia/Sydney" }, + { "AGT", "America/Argentina/Buenos_Aires" }, + { "ART", "Africa/Cairo" }, + { "AST", "America/Anchorage" }, + { "BET", "America/Sao_Paulo" }, + { "BST", "Asia/Dhaka" }, + { "CAT", "Africa/Harare" }, + { "CNT", "America/St_Johns" }, + { "CST", "America/Chicago" }, + { "CTT", "Asia/Shanghai" }, + { "EAT", "Africa/Addis_Ababa" }, + { "ECT", "Europe/Paris" }, + { "EST", "America/New_York" }, + { "HST", "Pacific/Honolulu" }, + { "IET", "America/Indianapolis" }, + { "IST", "Asia/Calcutta" }, + { "JST", "Asia/Tokyo" }, + { "MIT", "Pacific/Apia" }, + { "MST", "America/Denver" }, + { "NET", "Asia/Yerevan" }, + { "NST", "Pacific/Auckland" }, + { "PLT", "Asia/Karachi" }, + { "PNT", "America/Phoenix" }, + { "PRT", "America/Puerto_Rico" }, + { "PST", "America/Los_Angeles" }, + { "SST", "Pacific/Guadalcanal" }, + { "VST", "Asia/Saigon" }, + }; + for (String[] pair : oldmap) { + MAP.put(pair[0], pair[1]); + } + } +} diff --git a/jdk/test/sun/util/calendar/zi/Zone.java b/jdk/test/sun/util/calendar/zi/Zone.java new file mode 100644 index 00000000000..79520085d31 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/Zone.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2000, 2004, 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. + */ + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; + +/** + * Zone holds information corresponding to a "Zone" part of a time + * zone definition file. + * + * @since 1.4 + */ +class Zone { + // zone name (e.g., "America/Los_Angeles") + private String name; + + // zone records + private List list; + + // target zone names for this compilation + private static Set targetZones; + + /** + * Constructs a Zone with the specified zone name. + * @param name the zone name + */ + Zone(String name) { + this.name = name; + list = new ArrayList(); + } + + /** + * Reads time zone names to be generated, called "target zone + * name", from the specified text file and creats an internal hash + * table to keep those names. It's assumed that one text line + * contains a zone name or comments if it starts with + * '#'. Comments can't follow a zone name in a single line. + * @param fileName the text file name + */ + static void readZoneNames(String fileName) { + if (fileName == null) { + return; + } + BufferedReader in = null; + try { + FileReader fr = new FileReader(fileName); + in = new BufferedReader(fr); + } catch (FileNotFoundException e) { + Main.panic("can't open file: " + fileName); + } + targetZones = new HashSet(); + String line; + + try { + while ((line = in.readLine()) != null) { + line = line.trim(); + if (line.length() == 0 || line.charAt(0) == '#') { + continue; + } + if (!targetZones.add(line)) { + Main.warning("duplicated target zone name: " + line); + } + } + in.close(); + } catch (IOException e) { + Main.panic("IO error: "+e.getMessage()); + } + } + + /** + * Determines whether the specified zone is one of the target zones. + * If no target zones are specified, this method always returns + * true for any zone name. + * @param zoneName the zone name + * @return true if the specified name is a target zone. + */ + static boolean isTargetZone(String zoneName) { + if (targetZones == null) { + return true; + } + return targetZones.contains(zoneName); + } + + /** + * Forces to add "MET" to the target zone table. This is because + * there is a conflict between Java zone name "WET" and Olson zone + * name. + */ + static void addMET() { + if (targetZones != null) { + targetZones.add("MET"); + } + } + + /** + * @return the zone name + */ + String getName() { + return name; + } + + /** + * Adds the specified zone record to the zone record list. + */ + void add(ZoneRec rec) { + list.add(rec); + } + + /** + * @param index the index at which the zone record in the list is returned. + * @return the zone record specified by the index. + */ + ZoneRec get(int index) { + return list.get(index); + } + + /** + * @return the size of the zone record list + */ + int size() { + return list.size(); + } + + /** + * Resolves the reference to a rule in each zone record. + * @param zi the Zoneinfo object with which the rule reference is + * resolved. + */ + void resolve(Zoneinfo zi) { + for (int i = 0; i < list.size(); i++) { + ZoneRec rec = list.get(i); + rec.resolve(zi); + } + } +} diff --git a/jdk/test/sun/util/calendar/zi/ZoneInfoFile.java b/jdk/test/sun/util/calendar/zi/ZoneInfoFile.java new file mode 100644 index 00000000000..f0dda48c0a9 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/ZoneInfoFile.java @@ -0,0 +1,1051 @@ +/* + * 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 "Class-path" 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. + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.ref.SoftReference; +import java.nio.file.FileSystems; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import sun.util.calendar.*; + +/** + * ZoneInfoFile reads Zone information files in the + * <java.home>/lib/zi directory and provides time zone + * information in the form of a {@link ZoneInfo} object. Also, it + * reads the ZoneInfoMappings file to obtain time zone IDs information + * that is used by the {@link ZoneInfo} class. The directory layout + * and data file formats are as follows. + * + *

    Directory layout

    + * + * All zone data files and ZoneInfoMappings are put under the + * <java.home>/lib/zi directory. A path name for a given time + * zone ID is a concatenation of <java.home>/lib/zi/ and the + * time zone ID. (The file separator is replaced with the platform + * dependent value. e.g., '\' for Win32.) An example layout will look + * like as follows. + *

    + *
    + * <java.home>/lib/zi/Africa/Addis_Ababa
    + *                   /Africa/Dakar
    + *                   /America/Los_Angeles
    + *                   /Asia/Singapore
    + *                   /EET
    + *                   /Europe/Oslo
    + *                   /GMT
    + *                   /Pacific/Galapagos
    + *                       ...
    + *                   /ZoneInfoMappings
    + * 
    + *
    + * + * A zone data file has specific information of each zone. + * ZoneInfoMappings has global information of zone IDs so + * that the information can be obtained without instantiating all time + * zones. + * + *

    File format

    + * + * Two binary-file formats based on a simple Tag-Length-Value format are used + * to describe TimeZone information. The generic format of a data file is: + *

    + *
    + *    DataFile {
    + *      u1              magic[7];
    + *      u1              version;
    + *      data_item       data[];
    + *    }
    + * 
    + *
    + * where magic is a magic number identifying a file + * format, version is the format version number, and + * data is one or more data_items. The + * data_item structure is: + *
    + *
    + *    data_item {
    + *      u1              tag;
    + *      u2              length;
    + *      u1              value[length];
    + *    }
    + * 
    + *
    + * where tag indicates the data type of the item, + * length is a byte count of the following + * value that is the content of item data. + *

    + * All data is stored in the big-endian order. There is no boundary + * alignment between date items. + * + *

    1. ZoneInfo data file

    + * + * Each ZoneInfo data file consists of the following members. + *
    + *

    + *
    + *    ZoneInfoDataFile {
    + *      u1              magic[7];
    + *      u1              version;
    + *      SET OF1 {
    + *        transition            transitions2;
    + *        offset_table          offsets2;
    + *        simpletimezone        stzparams2;
    + *        raw_offset            rawoffset;
    + *        dstsaving             dst;
    + *        checksum              crc32;
    + *        gmtoffsetwillchange   gmtflag2;
    + *      }
    + *   }
    + *   1: an unordered collection of zero or one occurrences of each item
    + *   2: optional item
    + * 
    + *
    + * magic is a byte-string constant identifying the + * ZoneInfo data file. This field must be "javazi\0" + * defined as {@link #JAVAZI_LABEL}. + *

    + * version is the version number of the file format. This + * will be used for compatibility check. This field must be + * 0x01 in this version. + *

    + * transition, offset_table and + * simpletimezone have information of time transition + * from the past to the future. Therefore, these structures don't + * exist if the zone didn't change zone names and haven't applied DST in + * the past, and haven't planned to apply it. (e.g. Asia/Tokyo zone) + *

    + * raw_offset, dstsaving and checksum + * exist in every zoneinfo file. They are used by TimeZone.class indirectly. + * + *

    1.1 transition structure

    + *

    + *
    + *    transition {
    + *      u1      tag;              // 0x04 : constant
    + *      u2      length;           // byte length of whole values
    + *      s8      value[length/8];  // transitions in `long'
    + *    }
    + * 
    + *
    + * See {@link ZoneInfo#transitions ZoneInfo.transitions} about the value. + * + *

    1.2 offset_table structure

    + *

    + *
    + *    offset_table {
    + *      u1      tag;              // 0x05 : constant
    + *      u2      length;           // byte length of whole values
    + *      s4      value[length/4];  // offset values in `int'
    + *    }
    + * 
    + *
    + * + *

    1.3 simpletimezone structure

    + * See {@link ZoneInfo#simpleTimeZoneParams ZoneInfo.simpleTimeZoneParams} + * about the value. + *

    + *
    + *    simpletimezone {
    + *      u1      tag;              // 0x06 : constant
    + *      u2      length;           // byte length of whole values
    + *      s4      value[length/4];  // SimpleTimeZone parameters
    + *    }
    + * 
    + *
    + * See {@link ZoneInfo#offsets ZoneInfo.offsets} about the value. + * + *

    1.4 raw_offset structure

    + *

    + *
    + *    raw_offset {
    + *      u1      tag;              // 0x01 : constant
    + *      u2      length;           // must be 4.
    + *      s4      value;            // raw GMT offset [millisecond]
    + *    }
    + * 
    + *
    + * See {@link ZoneInfo#rawOffset ZoneInfo.rawOffset} about the value. + * + *

    1.5 dstsaving structure

    + * Value has dstSaving in seconds. + *

    + *
    + *    dstsaving {
    + *      u1      tag;              // 0x02 : constant
    + *      u2      length;           // must be 2.
    + *      s2      value;            // DST save value [second]
    + *    }
    + * 
    + *
    + * See {@link ZoneInfo#dstSavings ZoneInfo.dstSavings} about value. + * + *

    1.6 checksum structure

    + *

    + *
    + *    checksum {
    + *      u1      tag;              // 0x03 : constant
    + *      u2      length;           // must be 4.
    + *      s4      value;            // CRC32 value of transitions
    + *    }
    + * 
    + *
    + * See {@link ZoneInfo#checksum ZoneInfo.checksum}. + * + *

    1.7 gmtoffsetwillchange structure

    + * This record has a flag value for {@link ZoneInfo#rawOffsetWillChange}. + * If this record is not present in a zoneinfo file, 0 is assumed for + * the value. + *

    + *
    + *    gmtoffsetwillchange {
    + *      u1      tag;             // 0x07 : constant
    + *      u2      length;          // must be 1.
    + *      u1      value;           // 1: if the GMT raw offset will change
    + *                               // in the future, 0, otherwise.
    + *     }
    + * 
    + *
    + * + * + *

    2. ZoneInfoMappings file

    + * + * The ZoneInfoMappings file consists of the following members. + *
    + *

    + *
    + *    ZoneInfoMappings {
    + *      u1      magic[7];
    + *      u1      version;
    + *      SET OF {
    + *        versionName                   version;
    + *        zone_id_table                 zoneIDs;
    + *        raw_offset_table              rawoffsets;
    + *        raw_offset_index_table        rawoffsetindices;
    + *        alias_table                   aliases;
    + *        excluded_list                 excludedList;
    + *      }
    + *   }
    + * 
    + *
    + * + * magic is a byte-string constant which has the file type. + * This field must be "javazm\0" defined as {@link #JAVAZM_LABEL}. + *

    + * version is the version number of this file + * format. This will be used for compatibility check. This field must + * be 0x01 in this version. + *

    + * versionName shows which version of Olson's data has been used + * to generate this ZoneInfoMappings. (e.g. tzdata2000g)
    + * This field is for trouble-shooting and isn't usually used in runtime. + *

    + * zone_id_table, raw_offset_index_table and + * alias_table are general information of supported + * zones. + * + *

    2.1 zone_id_table structure

    + * The list of zone IDs included in the zi database. The list does + * not include zone IDs, if any, listed in excludedList. + *
    + *

    + *
    + *    zone_id_table {
    + *      u1      tag;              // 0x40 : constant
    + *      u2      length;           // byte length of whole values
    + *      u2      zone_id_count;
    + *      zone_id value[zone_id_count];
    + *    }
    + *
    + *    zone_id {
    + *      u1      byte_length;      // byte length of id
    + *      u1      id[byte_length];  // zone name string
    + *    }
    + * 
    + *
    + * + *

    2.2 raw_offset_table structure

    + *
    + *

    + *
    + *    raw_offset_table {
    + *      u1      tag;              // 0x41 : constant
    + *      u2      length;           // byte length of whole values
    + *      s4      value[length/4];  // raw GMT offset in milliseconds
    + *   }
    + * 
    + *
    + * + *

    2.3 raw_offset_index_table structure

    + *
    + *

    + *
    + *    raw_offset_index_table {
    + *      u1      tag;              // 0x42 : constant
    + *      u2      length;           // byte length of whole values
    + *      u1      value[length];
    + *    }
    + * 
    + *
    + * + *

    2.4 alias_table structure

    + *
    + *

    + *
    + *   alias_table {
    + *      u1      tag;              // 0x43 : constant
    + *      u2      length;           // byte length of whole values
    + *      u2      nentries;         // number of id-pairs
    + *      id_pair value[nentries];
    + *   }
    + *
    + *   id_pair {
    + *      zone_id aliasname;
    + *      zone_id ID;
    + *   }
    + * 
    + *
    + * + *

    2.5 versionName structure

    + *
    + *

    + *
    + *   versionName {
    + *      u1      tag;              // 0x44 : constant
    + *      u2      length;           // byte length of whole values
    + *      u1      value[length];
    + *   }
    + * 
    + *
    + * + *

    2.6 excludeList structure

    + * The list of zone IDs whose zones will change their GMT offsets + * (a.k.a. raw offsets) some time in the future. Those IDs must be + * added to the list of zone IDs for getAvailableIDs(). Also they must + * be examined for getAvailableIDs(int) to determine the + * current GMT offsets. + *
    + *

    + *
    + *   excluded_list {
    + *      u1      tag;              // 0x45 : constant
    + *      u2      length;           // byte length of whole values
    + *      u2      nentries;         // number of zone_ids
    + *      zone_id value[nentries];  // excluded zone IDs
    + *   }
    + * 
    + *
    + * + * @since 1.4 + */ + +public class ZoneInfoFile { + + /** + * The magic number for the ZoneInfo data file format. + */ + public static final byte[] JAVAZI_LABEL = { + (byte)'j', (byte)'a', (byte)'v', (byte)'a', (byte)'z', (byte)'i', (byte)'\0' + }; + private static final int JAVAZI_LABEL_LENGTH = JAVAZI_LABEL.length; + + /** + * The ZoneInfo data file format version number. Must increase + * one when any incompatible change has been made. + */ + public static final byte JAVAZI_VERSION = 0x01; + + /** + * Raw offset data item tag. + */ + public static final byte TAG_RawOffset = 1; + + /** + * Known last Daylight Saving Time save value data item tag. + */ + public static final byte TAG_LastDSTSaving = 2; + + /** + * Checksum data item tag. + */ + public static final byte TAG_CRC32 = 3; + + /** + * Transition data item tag. + */ + public static final byte TAG_Transition = 4; + + /** + * Offset table data item tag. + */ + public static final byte TAG_Offset = 5; + + /** + * SimpleTimeZone parameters data item tag. + */ + public static final byte TAG_SimpleTimeZone = 6; + + /** + * Raw GMT offset will change in the future. + */ + public static final byte TAG_GMTOffsetWillChange = 7; + + + /** + * The ZoneInfoMappings file name. + */ + public static final String JAVAZM_FILE_NAME = "ZoneInfoMappings"; + + /** + * The magic number for the ZoneInfoMappings file format. + */ + public static final byte[] JAVAZM_LABEL = { + (byte)'j', (byte)'a', (byte)'v', (byte)'a', (byte)'z', (byte)'m', (byte)'\0' + }; + private static final int JAVAZM_LABEL_LENGTH = JAVAZM_LABEL.length; + + /** + * The ZoneInfoMappings file format version number. Must increase + * one when any incompatible change has been made. + */ + public static final byte JAVAZM_VERSION = 0x01; + + /** + * Time zone IDs data item tag. + */ + public static final byte TAG_ZoneIDs = 64; + + /** + * Raw GMT offsets table data item tag. + */ + public static final byte TAG_RawOffsets = 65; + + /** + * Indices to the raw GMT offset table data item tag. + */ + public static final byte TAG_RawOffsetIndices = 66; + + /** + * Time zone aliases table data item tag. + */ + public static final byte TAG_ZoneAliases = 67; + + /** + * Olson's public zone information version tag. + */ + public static final byte TAG_TZDataVersion = 68; + + /** + * Excluded zones item tag. (Added in Mustang) + */ + public static final byte TAG_ExcludedZones = 69; + + private static Map zoneInfoObjects = null; + + private static final ZoneInfoOld GMT = new ZoneInfoOld("GMT", 0); + + static String ziDir; + + /** + * Converts the given time zone ID to a platform dependent path + * name. For example, "America/Los_Angeles" is converted to + * "America\Los_Angeles" on Win32. + * @return a modified ID replacing '/' with {@link + * java.io.File#separatorChar File.separatorChar} if needed. + */ + public static String getFileName(String ID) { + if (File.separatorChar == '/') { + return ID; + } + return ID.replace('/', File.separatorChar); + } + + /** + * Gets a ZoneInfo with the given GMT offset. The object + * has its ID in the format of GMT{+|-}hh:mm. + * + * @param originalId the given custom id (before normalized such as "GMT+9") + * @param gmtOffset GMT offset in milliseconds + * @return a ZoneInfo constructed with the given GMT offset + */ + public static ZoneInfoOld getCustomTimeZone(String originalId, int gmtOffset) { + String id = toCustomID(gmtOffset); + + ZoneInfoOld zi = getFromCache(id); + if (zi == null) { + zi = new ZoneInfoOld(id, gmtOffset); + zi = addToCache(id, zi); + if (!id.equals(originalId)) { + zi = addToCache(originalId, zi); + } + } + return (ZoneInfoOld) zi.clone(); + } + + public static String toCustomID(int gmtOffset) { + char sign; + int offset = gmtOffset / 60000; + + if (offset >= 0) { + sign = '+'; + } else { + sign = '-'; + offset = -offset; + } + int hh = offset / 60; + int mm = offset % 60; + + char[] buf = new char[] { 'G', 'M', 'T', sign, '0', '0', ':', '0', '0' }; + if (hh >= 10) { + buf[4] += hh / 10; + } + buf[5] += hh % 10; + if (mm != 0) { + buf[7] += mm / 10; + buf[8] += mm % 10; + } + return new String(buf); + } + + /** + * @return a ZoneInfo instance created for the specified id, or + * null if there is no time zone data file found for the specified + * id. + */ + public static ZoneInfoOld getZoneInfoOld(String id) { + //treat GMT zone as special + if ("GMT".equals(id)) + return (ZoneInfoOld) GMT.clone(); + ZoneInfoOld zi = getFromCache(id); + if (zi == null) { + Map aliases = ZoneInfoOld.getCachedAliasTable(); + if (aliases != null && aliases.get(id) != null) { + return null; + } + zi = createZoneInfoOld(id); + if (zi == null) { + return null; + } + zi = addToCache(id, zi); + } + return (ZoneInfoOld) zi.clone(); + } + + synchronized static ZoneInfoOld getFromCache(String id) { + if (zoneInfoObjects == null) { + return null; + } + return zoneInfoObjects.get(id); + } + + synchronized static ZoneInfoOld addToCache(String id, ZoneInfoOld zi) { + if (zoneInfoObjects == null) { + zoneInfoObjects = new HashMap<>(); + } else { + ZoneInfoOld zone = zoneInfoObjects.get(id); + if (zone != null) { + return zone; + } + } + zoneInfoObjects.put(id, zi); + return zi; + } + + private static ZoneInfoOld createZoneInfoOld(String id) { + byte[] buf = readZoneInfoFile(getFileName(id)); + if (buf == null) { + return null; + } + + int index = 0; + int filesize = buf.length; + int rawOffset = 0; + int dstSavings = 0; + int checksum = 0; + boolean willGMTOffsetChange = false; + long[] transitions = null; + int[] offsets = null; + int[] simpleTimeZoneParams = null; + + try { + for (index = 0; index < JAVAZI_LABEL.length; index++) { + if (buf[index] != JAVAZI_LABEL[index]) { + System.err.println("ZoneInfoOld: wrong magic number: " + id); + return null; + } + } + if (buf[index++] > JAVAZI_VERSION) { + System.err.println("ZoneInfo: incompatible version (" + + buf[index - 1] + "): " + id); + return null; + } + + while (index < filesize) { + byte tag = buf[index++]; + int len = ((buf[index++] & 0xFF) << 8) + (buf[index++] & 0xFF); + + if (filesize < index+len) { + break; + } + + switch (tag) { + case TAG_CRC32: + { + int val = buf[index++] & 0xff; + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + checksum = val; + } + break; + + case TAG_LastDSTSaving: + { + short val = (short)(buf[index++] & 0xff); + val = (short)((val << 8) + (buf[index++] & 0xff)); + dstSavings = val * 1000; + } + break; + + case TAG_RawOffset: + { + int val = buf[index++] & 0xff; + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + rawOffset = val; + } + break; + + case TAG_Transition: + { + int n = len / 8; + transitions = new long[n]; + for (int i = 0; i < n; i ++) { + long val = buf[index++] & 0xff; + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + transitions[i] = val; + } + } + break; + + case TAG_Offset: + { + int n = len / 4; + offsets = new int[n]; + for (int i = 0; i < n; i ++) { + int val = buf[index++] & 0xff; + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + offsets[i] = val; + } + } + break; + + case TAG_SimpleTimeZone: + { + if (len != 32 && len != 40) { + System.err.println("ZoneInfo: wrong SimpleTimeZone parameter size"); + return null; + } + int n = len / 4; + simpleTimeZoneParams = new int[n]; + for (int i = 0; i < n; i++) { + int val = buf[index++] & 0xff; + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + simpleTimeZoneParams[i] = val; + } + } + break; + + case TAG_GMTOffsetWillChange: + { + if (len != 1) { + System.err.println("ZoneInfo: wrong byte length for TAG_GMTOffsetWillChange"); + } + willGMTOffsetChange = buf[index++] == 1; + } + break; + + default: + System.err.println("ZoneInfo: unknown tag < " + tag + ">. ignored."); + index += len; + break; + } + } + } catch (Exception e) { + System.err.println("ZoneInfo: corrupted zoneinfo file: " + id); + return null; + } + + if (index != filesize) { + System.err.println("ZoneInfo: wrong file size: " + id); + return null; + } + + return new ZoneInfoOld(id, rawOffset, dstSavings, checksum, + transitions, offsets, simpleTimeZoneParams, + willGMTOffsetChange); + } + + private volatile static SoftReference> zoneIDs = null; + + static List getZoneIDs() { + List ids = null; + SoftReference> cache = zoneIDs; + if (cache != null) { + ids = cache.get(); + if (ids != null) { + return ids; + } + } + byte[] buf = null; + buf = getZoneInfoOldMappings(); + int index = JAVAZM_LABEL_LENGTH + 1; + int filesize = buf.length; + try { + loop: + while (index < filesize) { + byte tag = buf[index++]; + int len = ((buf[index++] & 0xFF) << 8) + (buf[index++] & 0xFF); + + switch (tag) { + case TAG_ZoneIDs: + { + int n = (buf[index++] << 8) + (buf[index++] & 0xFF); + ids = new ArrayList<>(n); + + for (int i = 0; i < n; i++) { + byte m = buf[index++]; + ids.add(new String(buf, index, m, "UTF-8")); + index += m; + } + } + break loop; + + default: + index += len; + break; + } + } + } catch (Exception e) { + System.err.println("ZoneInfoOld: corrupted " + JAVAZM_FILE_NAME); + } + + zoneIDs = new SoftReference<>(ids); + return ids; + } + + /** + * @return an alias table in HashMap where a key is an alias ID + * (e.g., "PST") and its value is a real time zone ID (e.g., + * "America/Los_Angeles"). + */ + static Map getZoneAliases() { + byte[] buf = getZoneInfoOldMappings(); + int index = JAVAZM_LABEL_LENGTH + 1; + int filesize = buf.length; + Map aliases = null; + + try { + loop: + while (index < filesize) { + byte tag = buf[index++]; + int len = ((buf[index++] & 0xFF) << 8) + (buf[index++] & 0xFF); + + switch (tag) { + case TAG_ZoneAliases: + { + int n = (buf[index++] << 8) + (buf[index++] & 0xFF); + aliases = new HashMap<>(n); + for (int i = 0; i < n; i++) { + byte m = buf[index++]; + String name = new String(buf, index, m, "UTF-8"); + index += m; + m = buf[index++]; + String realName = new String(buf, index, m, "UTF-8"); + index += m; + aliases.put(name, realName); + } + } + break loop; + + default: + index += len; + break; + } + } + } catch (Exception e) { + System.err.println("ZoneInfoOld: corrupted " + JAVAZM_FILE_NAME); + return null; + } + return aliases; + } + + private volatile static SoftReference> excludedIDs = null; + private volatile static boolean hasNoExcludeList = false; + + /** + * @return a List of zone IDs for zones that will change their GMT + * offsets in some future time. + * + * @since 1.6 + */ + static List getExcludedZones() { + if (hasNoExcludeList) { + return null; + } + + List excludeList = null; + + SoftReference> cache = excludedIDs; + if (cache != null) { + excludeList = cache.get(); + if (excludeList != null) { + return excludeList; + } + } + + byte[] buf = getZoneInfoOldMappings(); + int index = JAVAZM_LABEL_LENGTH + 1; + int filesize = buf.length; + + try { + loop: + while (index < filesize) { + byte tag = buf[index++]; + int len = ((buf[index++] & 0xFF) << 8) + (buf[index++] & 0xFF); + + switch (tag) { + case TAG_ExcludedZones: + { + int n = (buf[index++] << 8) + (buf[index++] & 0xFF); + excludeList = new ArrayList<>(); + for (int i = 0; i < n; i++) { + byte m = buf[index++]; + String name = new String(buf, index, m, "UTF-8"); + index += m; + excludeList.add(name); + } + } + break loop; + + default: + index += len; + break; + } + } + } catch (Exception e) { + System.err.println("ZoneInfoOld: corrupted " + JAVAZM_FILE_NAME); + return null; + } + + if (excludeList != null) { + excludedIDs = new SoftReference<>(excludeList); + } else { + hasNoExcludeList = true; + } + return excludeList; + } + + private volatile static SoftReference rawOffsetIndices = null; + + static byte[] getRawOffsetIndices() { + byte[] indices = null; + + SoftReference cache = rawOffsetIndices; + if (cache != null) { + indices = cache.get(); + if (indices != null) { + return indices; + } + } + + byte[] buf = getZoneInfoOldMappings(); + int index = JAVAZM_LABEL_LENGTH + 1; + int filesize = buf.length; + + try { + loop: + while (index < filesize) { + byte tag = buf[index++]; + int len = ((buf[index++] & 0xFF) << 8) + (buf[index++] & 0xFF); + + switch (tag) { + case TAG_RawOffsetIndices: + { + indices = new byte[len]; + for (int i = 0; i < len; i++) { + indices[i] = buf[index++]; + } + } + break loop; + + default: + index += len; + break; + } + } + } catch (ArrayIndexOutOfBoundsException e) { + System.err.println("ZoneInfoOld: corrupted " + JAVAZM_FILE_NAME); + } + + rawOffsetIndices = new SoftReference<>(indices); + return indices; + } + + private volatile static SoftReference rawOffsets = null; + + static int[] getRawOffsets() { + int[] offsets = null; + + SoftReference cache = rawOffsets; + if (cache != null) { + offsets = cache.get(); + if (offsets != null) { + return offsets; + } + } + + byte[] buf = getZoneInfoOldMappings(); + int index = JAVAZM_LABEL_LENGTH + 1; + int filesize = buf.length; + + try { + loop: + while (index < filesize) { + byte tag = buf[index++]; + int len = ((buf[index++] & 0xFF) << 8) + (buf[index++] & 0xFF); + + switch (tag) { + case TAG_RawOffsets: + { + int n = len/4; + offsets = new int[n]; + for (int i = 0; i < n; i++) { + int val = buf[index++] & 0xff; + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + val = (val << 8) + (buf[index++] & 0xff); + offsets[i] = val; + } + } + break loop; + + default: + index += len; + break; + } + } + } catch (ArrayIndexOutOfBoundsException e) { + System.err.println("ZoneInfoOld: corrupted " + JAVAZM_FILE_NAME); + } + + rawOffsets = new SoftReference<>(offsets); + return offsets; + } + + private volatile static SoftReference zoneInfoMappings = null; + + private static byte[] getZoneInfoOldMappings() { + byte[] data; + SoftReference cache = zoneInfoMappings; + if (cache != null) { + data = cache.get(); + if (data != null) { + return data; + } + } + data = readZoneInfoFile(JAVAZM_FILE_NAME); + if (data == null) { + throw new RuntimeException("ZoneInfoOldMapping " + + JAVAZM_FILE_NAME + " either doesn't exist or doesn't have data"); + } + + int index; + for (index = 0; index < JAVAZM_LABEL.length; index++) { + if (data[index] != JAVAZM_LABEL[index]) { + System.err.println("ZoneInfoOld: wrong magic number: " + JAVAZM_FILE_NAME); + return null; + } + } + if (data[index++] > JAVAZM_VERSION) { + System.err.println("ZoneInfoOld: incompatible version (" + + data[index - 1] + "): " + JAVAZM_FILE_NAME); + return null; + } + + zoneInfoMappings = new SoftReference<>(data); + return data; + } + + /** + * Reads the specified file under <java.home>/lib/zi into a buffer. + * @return the buffer, or null if any I/O error occurred. + */ + private static byte[] readZoneInfoFile(final String fileName) { + if (fileName.indexOf("..") >= 0) { + return null; + } + byte[] buffer = null; + File file = new File(ziDir, fileName); + try { + int filesize = (int)file.length(); + if (filesize > 0) { + FileInputStream fis = new FileInputStream(file); + buffer = new byte[filesize]; + try { + if (fis.read(buffer) != filesize) { + throw new IOException("read error on " + fileName); + } + } finally { + fis.close(); + } + } + } catch (Exception ex) { + if (!(ex instanceof FileNotFoundException) || JAVAZM_FILE_NAME.equals(fileName)) { + System.err.println("ZoneInfoOld: " + ex.getMessage()); + } + } + return buffer; + } + + private ZoneInfoFile() { + } +} diff --git a/jdk/test/sun/util/calendar/zi/ZoneInfoOld.java b/jdk/test/sun/util/calendar/zi/ZoneInfoOld.java new file mode 100644 index 00000000000..4a0a31e087d --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/ZoneInfoOld.java @@ -0,0 +1,1047 @@ +/* + * 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. + */ + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.lang.ref.SoftReference; +import java.time.ZoneOffset; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.SimpleTimeZone; +import java.util.TimeZone; + +import sun.util.calendar.CalendarSystem; +import sun.util.calendar.CalendarDate; + +/** + * ZoneInfoOld is an implementation subclass of {@link + * java.util.TimeZone TimeZone} that represents GMT offsets and + * daylight saving time transitions of a time zone. + *

    + * The daylight saving time transitions are described in the {@link + * #transitions transitions} table consisting of a chronological + * sequence of transitions of GMT offset and/or daylight saving time + * changes. Since all transitions are represented in UTC, in theory, + * ZoneInfoOld can be used with any calendar systems except + * for the {@link #getOffset(int,int,int,int,int,int) getOffset} + * method that takes Gregorian calendar date fields. + *

    + * This table covers transitions from 1900 until 2037 (as of version + * 1.4), Before 1900, it assumes that there was no daylight saving + * time and the getOffset methods always return the + * {@link #getRawOffset} value. No Local Mean Time is supported. If a + * specified date is beyond the transition table and this time zone is + * supposed to observe daylight saving time in 2037, it delegates + * operations to a {@link java.util.SimpleTimeZone SimpleTimeZone} + * object created using the daylight saving time schedule as of 2037. + *

    + * The date items, transitions, GMT offset(s), etc. are read from a database + * file. See {@link ZoneInfoFile} for details. + * @see java.util.SimpleTimeZone + * @since 1.4 + */ + +public class ZoneInfoOld extends TimeZone { + + // The constants assume no leap seconds support. + static final int SECOND_IN_MILLIS = 1000; + static final int MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60; + static final int HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60; + static final int DAY_IN_MILLIS = HOUR_IN_MILLIS * 24; + + private static final int UTC_TIME = 0; + private static final int STANDARD_TIME = 1; + private static final int WALL_TIME = 2; + + private static final long OFFSET_MASK = 0x0fL; + private static final long DST_MASK = 0xf0L; + private static final int DST_NSHIFT = 4; + // this bit field is reserved for abbreviation support + private static final long ABBR_MASK = 0xf00L; + private static final int TRANSITION_NSHIFT = 12; + + // Flag for supporting JDK backward compatible IDs, such as "EST". + static final boolean USE_OLDMAPPING; + static { + String oldmapping = System.getProperty("sun.timezone.ids.oldmapping", "false").toLowerCase(Locale.ROOT); + USE_OLDMAPPING = (oldmapping.equals("yes") || oldmapping.equals("true")); + } + + // IDs having conflicting data between Olson and JDK 1.1 + static final String[] conflictingIDs = { + "EST", "MST", "HST" + }; + + private static final CalendarSystem gcal = CalendarSystem.getGregorianCalendar(); + + /** + * The raw GMT offset in milliseconds between this zone and GMT. + * Negative offsets are to the west of Greenwich. To obtain local + * standard time, add the offset to GMT time. + * @serial + */ + int rawOffset; + + /** + * Difference in milliseconds from the original GMT offset in case + * the raw offset value has been modified by calling {@link + * #setRawOffset}. The initial value is 0. + * @serial + */ + int rawOffsetDiff = 0; + + /** + * A CRC32 value of all pairs of transition time (in milliseconds + * in long) in local time and its GMT offset (in + * seconds in int) in the chronological order. Byte + * values of each long and int are taken + * in the big endian order (i.e., MSB to LSB). + * @serial + */ + int checksum; + + /** + * The amount of time in milliseconds saved during daylight saving + * time. If useDaylight is false, this value is 0. + * @serial + */ + int dstSavings; + + /** + * This array describes transitions of GMT offsets of this time + * zone, including both raw offset changes and daylight saving + * time changes. + * A long integer consists of four bit fields. + *

      + *
    • The most significant 52-bit field represents transition + * time in milliseconds from Gregorian January 1 1970, 00:00:00 + * GMT.
    • + *
    • The next 4-bit field is reserved and must be 0.
    • + *
    • The next 4-bit field is an index value to {@link #offsets + * offsets[]} for the amount of daylight saving at the + * transition. If this value is zero, it means that no daylight + * saving, not the index value zero.
    • + *
    • The least significant 4-bit field is an index value to + * {@link #offsets offsets[]} for total GMT offset at the + * transition.
    • + *
    + * If this time zone doesn't observe daylight saving time and has + * never changed any GMT offsets in the past, this value is null. + * @serial + */ + long[] transitions; + + /** + * This array holds all unique offset values in + * milliseconds. Index values to this array are stored in the + * transitions array elements. + * @serial + */ + int[] offsets; + + /** + * SimpleTimeZone parameter values. It has to have either 8 for + * {@link java.util.SimpleTimeZone#SimpleTimeZone(int, String, + * int, int , int , int , int , int , int , int , int) the + * 11-argument SimpleTimeZone constructor} or 10 for {@link + * java.util.SimpleTimeZone#SimpleTimeZone(int, String, int, int, + * int , int , int , int , int , int , int, int, int) the + * 13-argument SimpleTimeZone constructor} parameters. + * @serial + */ + int[] simpleTimeZoneParams; + + /** + * True if the raw GMT offset value would change after the time + * zone data has been generated; false, otherwise. The default + * value is false. + * @serial + */ + boolean willGMTOffsetChange = false; + + /** + * True if the object has been modified after its instantiation. + */ + transient private boolean dirty = false; + + private static final long serialVersionUID = 2653134537216586139L; + + /** + * A constructor. + */ + public ZoneInfoOld() { + } + + /** + * A Constructor for CustomID. + */ + public ZoneInfoOld(String ID, int rawOffset) { + this(ID, rawOffset, 0, 0, null, null, null, false); + } + + /** + * Constructs a ZoneInfoOld instance. + * + * @param ID time zone name + * @param rawOffset GMT offset in milliseconds + * @param dstSavings daylight saving value in milliseconds or 0 + * (zero) if this time zone doesn't observe Daylight Saving Time. + * @param checksum CRC32 value with all transitions table entry + * values + * @param transitions transition table + * @param offsets offset value table + * @param simpleTimeZoneParams parameter values for constructing + * SimpleTimeZone + * @param willGMTOffsetChange the value of willGMTOffsetChange + */ + ZoneInfoOld(String ID, + int rawOffset, + int dstSavings, + int checksum, + long[] transitions, + int[] offsets, + int[] simpleTimeZoneParams, + boolean willGMTOffsetChange) { + setID(ID); + this.rawOffset = rawOffset; + this.dstSavings = dstSavings; + this.checksum = checksum; + this.transitions = transitions; + this.offsets = offsets; + this.simpleTimeZoneParams = simpleTimeZoneParams; + this.willGMTOffsetChange = willGMTOffsetChange; + } + + /** + * Returns the difference in milliseconds between local time and UTC + * of given time, taking into account both the raw offset and the + * effect of daylight savings. + * + * @param date the milliseconds in UTC + * @return the milliseconds to add to UTC to get local wall time + */ + public int getOffset(long date) { + return getOffsets(date, null, UTC_TIME); + } + + public int getOffsets(long utc, int[] offsets) { + return getOffsets(utc, offsets, UTC_TIME); + } + + public int getOffsetsByStandard(long standard, int[] offsets) { + return getOffsets(standard, offsets, STANDARD_TIME); + } + + public int getOffsetsByWall(long wall, int[] offsets) { + return getOffsets(wall, offsets, WALL_TIME); + } + + private int getOffsets(long date, int[] offsets, int type) { + // if dst is never observed, there is no transition. + if (transitions == null) { + int offset = getLastRawOffset(); + if (offsets != null) { + offsets[0] = offset; + offsets[1] = 0; + } + return offset; + } + + date -= rawOffsetDiff; + int index = getTransitionIndex(date, type); + + // prior to the transition table, returns the raw offset. + // FIXME: should support LMT. + if (index < 0) { + int offset = getLastRawOffset(); + if (offsets != null) { + offsets[0] = offset; + offsets[1] = 0; + } + return offset; + } + + if (index < transitions.length) { + long val = transitions[index]; + int offset = this.offsets[(int)(val & OFFSET_MASK)] + rawOffsetDiff; + if (offsets != null) { + int dst = (int)((val >>> DST_NSHIFT) & 0xfL); + int save = (dst == 0) ? 0 : this.offsets[dst]; + offsets[0] = offset - save; + offsets[1] = save; + } + return offset; + } + + // beyond the transitions, delegate to SimpleTimeZone if there + // is a rule; otherwise, return rawOffset. + SimpleTimeZone tz = getLastRule(); + if (tz != null) { + int rawoffset = tz.getRawOffset(); + long msec = date; + if (type != UTC_TIME) { + msec -= rawOffset; + } + int dstoffset = tz.getOffset(msec) - rawOffset; + + // Check if it's in a standard-to-daylight transition. + if (dstoffset > 0 && tz.getOffset(msec - dstoffset) == rawoffset) { + dstoffset = 0; + } + + if (offsets != null) { + offsets[0] = rawoffset; + offsets[1] = dstoffset; + } + return rawoffset + dstoffset; + } + int offset = getLastRawOffset(); + if (offsets != null) { + offsets[0] = offset; + offsets[1] = 0; + } + return offset; + } + + private int getTransitionIndex(long date, int type) { + int low = 0; + int high = transitions.length - 1; + + while (low <= high) { + int mid = (low + high) / 2; + long val = transitions[mid]; + long midVal = val >> TRANSITION_NSHIFT; // sign extended + if (type != UTC_TIME) { + midVal += offsets[(int)(val & OFFSET_MASK)]; // wall time + } + if (type == STANDARD_TIME) { + int dstIndex = (int)((val >>> DST_NSHIFT) & 0xfL); + if (dstIndex != 0) { + midVal -= offsets[dstIndex]; // make it standard time + } + } + + if (midVal < date) { + low = mid + 1; + } else if (midVal > date) { + high = mid - 1; + } else { + return mid; + } + } + + // if beyond the transitions, returns that index. + if (low >= transitions.length) { + return low; + } + return low - 1; + } + + /** + * Returns the difference in milliseconds between local time and + * UTC, taking into account both the raw offset and the effect of + * daylight savings, for the specified date and time. This method + * assumes that the start and end month are distinct. This method + * assumes a Gregorian calendar for calculations. + *

    + * Note: In general, clients should use + * {@link Calendar#ZONE_OFFSET Calendar.get(ZONE_OFFSET)} + + * {@link Calendar#DST_OFFSET Calendar.get(DST_OFFSET)} + * instead of calling this method. + * + * @param era The era of the given date. The value must be either + * GregorianCalendar.AD or GregorianCalendar.BC. + * @param year The year in the given date. + * @param month The month in the given date. Month is 0-based. e.g., + * 0 for January. + * @param day The day-in-month of the given date. + * @param dayOfWeek The day-of-week of the given date. + * @param millis The milliseconds in day in standard local time. + * @return The milliseconds to add to UTC to get local time. + */ + public int getOffset(int era, int year, int month, int day, + int dayOfWeek, int milliseconds) { + if (milliseconds < 0 || milliseconds >= DAY_IN_MILLIS) { + throw new IllegalArgumentException(); + } + + if (era == java.util.GregorianCalendar.BC) { // BC + year = 1 - year; + } else if (era != java.util.GregorianCalendar.AD) { + throw new IllegalArgumentException(); + } + + CalendarDate date = gcal.newCalendarDate(null); + date.setDate(year, month + 1, day); + if (gcal.validate(date) == false) { + throw new IllegalArgumentException(); + } + + // bug-for-bug compatible argument checking + if (dayOfWeek < java.util.GregorianCalendar.SUNDAY + || dayOfWeek > java.util.GregorianCalendar.SATURDAY) { + throw new IllegalArgumentException(); + } + + if (transitions == null) { + return getLastRawOffset(); + } + + long dateInMillis = gcal.getTime(date) + milliseconds; + dateInMillis -= (long) rawOffset; // make it UTC + return getOffsets(dateInMillis, null, UTC_TIME); + } + + /** + * Sets the base time zone offset from GMT. This operation + * modifies all the transitions of this ZoneInfoOld object, including + * historical ones, if applicable. + * + * @param offsetMillis the base time zone offset to GMT. + * @see getRawOffset + */ + public synchronized void setRawOffset(int offsetMillis) { + if (offsetMillis == rawOffset + rawOffsetDiff) { + return; + } + rawOffsetDiff = offsetMillis - rawOffset; + if (lastRule != null) { + lastRule.setRawOffset(offsetMillis); + } + dirty = true; + } + + /** + * Returns the GMT offset of the current date. This GMT offset + * value is not modified during Daylight Saving Time. + * + * @return the GMT offset value in milliseconds to add to UTC time + * to get local standard time + */ + public int getRawOffset() { + if (!willGMTOffsetChange) { + return rawOffset + rawOffsetDiff; + } + + int[] offsets = new int[2]; + getOffsets(System.currentTimeMillis(), offsets, UTC_TIME); + return offsets[0]; + } + + public boolean isDirty() { + return dirty; + } + + int getLastRawOffset() { + return rawOffset + rawOffsetDiff; + } + + /** + * Queries if this time zone uses Daylight Saving Time in the last known rule. + */ + public boolean useDaylightTime() { + return (simpleTimeZoneParams != null); + } + + @Override + public boolean observesDaylightTime() { + if (simpleTimeZoneParams != null) { + return true; + } + if (transitions == null) { + return false; + } + + // Look up the transition table to see if it's in DST right + // now or if there's any standard-to-daylight transition at + // any future. + long utc = System.currentTimeMillis() - rawOffsetDiff; + int index = getTransitionIndex(utc, UTC_TIME); + + // before transitions in the transition table + if (index < 0) { + return false; + } + + // the time is in the table range. + for (int i = index; i < transitions.length; i++) { + if ((transitions[i] & DST_MASK) != 0) { + return true; + } + } + // No further DST is observed. + return false; + } + + /** + * Queries if the specified date is in Daylight Saving Time. + */ + public boolean inDaylightTime(Date date) { + if (date == null) { + throw new NullPointerException(); + } + + if (transitions == null) { + return false; + } + + long utc = date.getTime() - rawOffsetDiff; + int index = getTransitionIndex(utc, UTC_TIME); + + // before transitions in the transition table + if (index < 0) { + return false; + } + + // the time is in the table range. + if (index < transitions.length) { + return (transitions[index] & DST_MASK) != 0; + } + + // beyond the transition table + SimpleTimeZone tz = getLastRule(); + if (tz != null) { + return tz.inDaylightTime(date); + } + return false; + } + + /** + * Returns the amount of time in milliseconds that the clock is advanced + * during daylight saving time is in effect in its last daylight saving time rule. + * + * @return the number of milliseconds the time is advanced with respect to + * standard time when daylight saving time is in effect. + */ + public int getDSTSavings() { + return dstSavings; + } + +// /** +// * @return the last year in the transition table or -1 if this +// * time zone doesn't observe any daylight saving time. +// */ +// public int getMaxTransitionYear() { +// if (transitions == null) { +// return -1; +// } +// long val = transitions[transitions.length - 1]; +// int offset = this.offsets[(int)(val & OFFSET_MASK)] + rawOffsetDiff; +// val = (val >> TRANSITION_NSHIFT) + offset; +// CalendarDate lastDate = Gregorian.getCalendarDate(val); +// return lastDate.getYear(); +// } + + /** + * Returns a string representation of this time zone. + * @return the string + */ + public String toString() { + return getClass().getName() + + "[id=\"" + getID() + "\"" + + ",offset=" + getLastRawOffset() + + ",dstSavings=" + dstSavings + + ",useDaylight=" + useDaylightTime() + + ",transitions=" + ((transitions != null) ? transitions.length : 0) + + ",lastRule=" + (lastRule == null ? getLastRuleInstance() : lastRule) + + "]"; + } + + /** + * Gets all available IDs supported in the Java run-time. + * + * @return an array of time zone IDs. + */ + public static String[] getAvailableIDs() { + List idList = ZoneInfoFile.getZoneIDs(); + List excluded = ZoneInfoFile.getExcludedZones(); + if (excluded != null) { + // List all zones from the idList and excluded lists + List list = new ArrayList<>(idList.size() + excluded.size()); + list.addAll(idList); + list.addAll(excluded); + idList = list; + } + String[] ids = new String[idList.size()]; + return idList.toArray(ids); + } + + /** + * Gets all available IDs that have the same value as the + * specified raw GMT offset. + * + * @param rawOffset the GMT offset in milliseconds. This + * value should not include any daylight saving time. + * + * @return an array of time zone IDs. + */ + public static String[] getAvailableIDs(int rawOffset) { + String[] result; + List matched = new ArrayList<>(); + List IDs = ZoneInfoFile.getZoneIDs(); + int[] rawOffsets = ZoneInfoFile.getRawOffsets(); + + loop: + for (int index = 0; index < rawOffsets.length; index++) { + if (rawOffsets[index] == rawOffset) { + byte[] indices = ZoneInfoFile.getRawOffsetIndices(); + for (int i = 0; i < indices.length; i++) { + if (indices[i] == index) { + matched.add(IDs.get(i++)); + while (i < indices.length && indices[i] == index) { + matched.add(IDs.get(i++)); + } + break loop; + } + } + } + } + + // We need to add any zones from the excluded zone list that + // currently have the same GMT offset as the specified + // rawOffset. The zones returned by this method may not be + // correct as of return to the caller if any GMT offset + // transition is happening during this GMT offset checking... + List excluded = ZoneInfoFile.getExcludedZones(); + if (excluded != null) { + for (String id : excluded) { + TimeZone zi = getTimeZone(id); + if (zi != null && zi.getRawOffset() == rawOffset) { + matched.add(id); + } + } + } + + result = new String[matched.size()]; + matched.toArray(result); + return result; + } + + /** + * Gets the ZoneInfoOld for the given ID. + * + * @param ID the ID for a ZoneInfoOld. See TimeZone for detail. + * + * @return the specified ZoneInfoOld object, or null if there is no + * time zone of the ID. + */ + public static TimeZone getTimeZone(String ID) { + String givenID = null; + + /* + * If old JDK compatibility is specified, get the old alias + * name. + */ + if (USE_OLDMAPPING) { + String compatibleID = TzIDOldMapping.MAP.get(ID); + if (compatibleID != null) { + givenID = ID; + ID = compatibleID; + } + } + + ZoneInfoOld zi = ZoneInfoFile.getZoneInfoOld(ID); + if (zi == null) { + // if we can't create an object for the ID, try aliases. + try { + Map map = getAliasTable(); + String alias = ID; + while ((alias = map.get(alias)) != null) { + zi = ZoneInfoFile.getZoneInfoOld(alias); + if (zi != null) { + zi.setID(ID); + zi = ZoneInfoFile.addToCache(ID, zi); + zi = (ZoneInfoOld) zi.clone(); + break; + } + } + } catch (Exception e) { + // ignore exceptions + } + } + + if (givenID != null && zi != null) { + zi.setID(givenID); + } + return zi; + } + + private transient SimpleTimeZone lastRule; + + /** + * Returns a SimpleTimeZone object representing the last GMT + * offset and DST schedule or null if this time zone doesn't + * observe DST. + */ + synchronized SimpleTimeZone getLastRule() { + if (lastRule == null) { + lastRule = getLastRuleInstance(); + } + return lastRule; + } + + /** + * Returns a SimpleTimeZone object that represents the last + * known daylight saving time rules. + * + * @return a SimpleTimeZone object or null if this time zone + * doesn't observe DST. + */ + public SimpleTimeZone getLastRuleInstance() { + if (simpleTimeZoneParams == null) { + return null; + } + if (simpleTimeZoneParams.length == 10) { + return new SimpleTimeZone(getLastRawOffset(), getID(), + simpleTimeZoneParams[0], + simpleTimeZoneParams[1], + simpleTimeZoneParams[2], + simpleTimeZoneParams[3], + simpleTimeZoneParams[4], + simpleTimeZoneParams[5], + simpleTimeZoneParams[6], + simpleTimeZoneParams[7], + simpleTimeZoneParams[8], + simpleTimeZoneParams[9], + dstSavings); + } + return new SimpleTimeZone(getLastRawOffset(), getID(), + simpleTimeZoneParams[0], + simpleTimeZoneParams[1], + simpleTimeZoneParams[2], + simpleTimeZoneParams[3], + simpleTimeZoneParams[4], + simpleTimeZoneParams[5], + simpleTimeZoneParams[6], + simpleTimeZoneParams[7], + dstSavings); + } + + /** + * Returns a copy of this ZoneInfoOld. + */ + public Object clone() { + ZoneInfoOld zi = (ZoneInfoOld) super.clone(); + zi.lastRule = null; + return zi; + } + + /** + * Returns a hash code value calculated from the GMT offset and + * transitions. + * @return a hash code of this time zone + */ + public int hashCode() { + return getLastRawOffset() ^ checksum; + } + + /** + * Compares the equity of two ZoneInfoOld objects. + * + * @param obj the object to be compared with + * @return true if given object is same as this ZoneInfoOld object, + * false otherwise. + */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof ZoneInfoOld)) { + return false; + } + ZoneInfoOld that = (ZoneInfoOld) obj; + return (getID().equals(that.getID()) + && (getLastRawOffset() == that.getLastRawOffset()) + && (checksum == that.checksum)); + } + + /** + * Returns true if this zone has the same raw GMT offset value and + * transition table as another zone info. If the specified + * TimeZone object is not a ZoneInfoOld instance, this method returns + * true if the specified TimeZone object has the same raw GMT + * offset value with no daylight saving time. + * + * @param other the ZoneInfoOld object to be compared with + * @return true if the given TimeZone has the same + * GMT offset and transition information; false, otherwise. + */ + public boolean hasSameRules(TimeZone other) { + if (this == other) { + return true; + } + if (other == null) { + return false; + } + if (!(other instanceof ZoneInfoOld)) { + if (getRawOffset() != other.getRawOffset()) { + return false; + } + // if both have the same raw offset and neither observes + // DST, they have the same rule. + if ((transitions == null) + && (useDaylightTime() == false) + && (other.useDaylightTime() == false)) { + return true; + } + return false; + } + if (getLastRawOffset() != ((ZoneInfoOld)other).getLastRawOffset()) { + return false; + } + return (checksum == ((ZoneInfoOld)other).checksum); + } + + private static SoftReference> aliasTable; + + static Map getCachedAliasTable() { + Map aliases = null; + + SoftReference> cache = aliasTable; + if (cache != null) { + aliases = cache.get(); + } + return aliases; + } + + /** + * Returns a Map from alias time zone IDs to their standard + * time zone IDs. + * + * @return the Map that holds the mappings from alias time zone IDs + * to their standard time zone IDs, or null if + * ZoneInfoOldMappings file is not available. + */ + public synchronized static Map getAliasTable() { + Map aliases = getCachedAliasTable(); + if (aliases == null) { + aliases = ZoneInfoFile.getZoneAliases(); + if (aliases != null) { + if (!USE_OLDMAPPING) { + // Remove the conflicting IDs from the alias table. + for (String key : conflictingIDs) { + aliases.remove(key); + } + } + aliasTable = new SoftReference>(aliases); + } + } + return aliases; + } + + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + // We don't know how this object from 1.4.x or earlier has + // been mutated. So it should always be marked as `dirty'. + dirty = true; + } + + ////////////////////////////////////////////////////////////// + public boolean equalsTo(ZoneInfoOld other) { + return (getID().equals(other.getID()) + && (getLastRawOffset() == other.getLastRawOffset()) + && (dstSavings == other.dstSavings) + && (willGMTOffsetChange == other.willGMTOffsetChange) + && (checksum == other.checksum) + && equalsTransOffsets(other) + && (Arrays.equals(simpleTimeZoneParams, other.simpleTimeZoneParams) || + getLastRule().equals(other.getLastRule()))); + } + + private boolean equalsTransOffsets(ZoneInfoOld other) { + if (transitions == null) { + return (other.transitions == null && + Arrays.equals(offsets, other.offsets)); + } + if (other.transitions == null || + transitions.length != other.transitions.length) { + return false; + } + // if offsets and other.offsets have different order + // the last 4-bit in trans are different. + for (int i = 0; i < transitions.length; i++) { + long val = transitions[i]; + int dst = (int)((val >>> DST_NSHIFT) & 0xfL); + int save = (dst == 0) ? 0 : offsets[dst] / 1000; + int off = offsets[(int)(val & OFFSET_MASK)]/1000; + long second = (val >> TRANSITION_NSHIFT)/1000; + + val = other.transitions[i]; + int dstO = (int)((val >>> DST_NSHIFT) & 0xfL); + int saveO = (dstO == 0) ? 0 : other.offsets[dstO] / 1000; + int offO = other.offsets[(int)(val & OFFSET_MASK)]/1000; + long secondO = (val >> TRANSITION_NSHIFT)/1000; + if ((dst == 0) != (dstO == 0) || save != saveO || off != offO || second != secondO) + return false; + } + return true; + } + + private int transToString(long val, int off_old, int[] offsets, StringBuilder sb) { + int dst = (int)((val >>> DST_NSHIFT) & 0xfL); + int save = (dst == 0) ? 0 : offsets[dst] / 1000; + int off = offsets[(int)(val & OFFSET_MASK)]/1000; + long second = (val >> TRANSITION_NSHIFT)/1000; + ZoneOffset offset_old = ZoneOffset.ofTotalSeconds(off_old); + ZoneOffset offset = ZoneOffset.ofTotalSeconds(off); + sb.append(" " + LocalDateTime.ofEpochSecond(second, 0, offset_old)); + + sb.append(" [utc=" + second + + " raw=" + Long.toHexString(val >> TRANSITION_NSHIFT) + + ", offset=" + off + "/" + offset + ", saving=" + save + "]"); + return off; + } + + public String diffsTo(ZoneInfoOld other) { + + int rawOffset0 = other.rawOffset; + int checksum0 = other.checksum; + int dstSavings0 = other.dstSavings; + long[] transitions0 = other.transitions; + int[] offsets0 = other.offsets; + int[] simpleTimeZoneParams0 = other.simpleTimeZoneParams; + boolean willGMTOffsetChange0 = other.willGMTOffsetChange; + + + //return getClass().getName() + + StringBuilder sb = new StringBuilder(); + sb.append("******************************\n" + + getID() + " : " + other.getID()); + // ROC is excluded by ZoneInfoOld + if ("ROC".equals(getID())) { + return sb.toString(); + } + if (rawOffset != rawOffset0 || + dstSavings != dstSavings0 || + checksum != checksum0 || + willGMTOffsetChange != willGMTOffsetChange0 || + (simpleTimeZoneParams != null ) != (simpleTimeZoneParams0 != null) || + (transitions != null && transitions0 != null && + transitions.length != transitions0.length)) + { + sb.append("\n offset=" + getLastRawOffset() + + ",dstSavings=" + dstSavings + + ",useDaylight=" + useDaylightTime() + + ",transitions=" + ((transitions != null) ? transitions.length : 0) + + ",offsets=" + ((offsets != null) ? offsets.length : 0) + + ",checksum=" + checksum + + ",gmtChanged=" + willGMTOffsetChange) + .append("\n[NG]offset=" + rawOffset0 + + ",dstSavings=" + dstSavings0 + + ",useDaylight=" + (simpleTimeZoneParams != null) + + ",transitions=" + ((transitions0 != null) ? transitions0.length : 0) + + ",offsets=" + ((offsets0 != null) ? offsets0.length : 0) + + ",checksum=" + checksum0 + + ",gmtChanged=" + willGMTOffsetChange0 + + ""); + } + // offsets + if (!Arrays.equals(offsets, offsets0)) { + sb.append("\n offset.len=" + ((offsets != null)? offsets.length : "null") + + " " + ((offsets0 != null)? offsets0.length : "null")); + if (offsets != null && offsets0.length != 0) { + int len = Math.min(offsets.length, offsets0.length); + int i = 0; + for (i = 0; i < len; i++) { + sb.append("\n " + + ZoneOffset.ofTotalSeconds(offsets[i]/1000) + " " + + ZoneOffset.ofTotalSeconds(offsets0[i]/1000)); + } + for (; i < offsets0.length; i++) { + sb.append("\n " + ZoneOffset.ofTotalSeconds(offsets0[i]/1000)); + } + } + } + // trans + int offset = 0; + int offset0 = 0; + if (!equalsTransOffsets(other)) { + sb.append("\n -------------"); + if ((transitions == null) != (transitions0 == null)) { + sb.append("\n (NG) Different trans(null) :" + + transitions + ", " + transitions0); + if (transitions != null) { + for (int i = 0; i < transitions.length; i++) { + sb.append("\n (NG)"); + offset = transToString(transitions[i], offset, offsets, sb); + } + } + } else { + if (transitions.length != transitions0.length) { + sb.append("\n (NG) Different trans size :" + + transitions.length + ", " + transitions0.length); + } + int length = Math.min(transitions.length, transitions0.length); + for (int i = 0; i < length; i++) { + // sb.append("\n[" + i + "] "); + // offset = transToString(transitions[i], offset, offsets, sb); + long val = transitions[i]; + int dst = (int)((val >>> DST_NSHIFT) & 0xfL); + int save = (dst == 0) ? 0 : offsets[dst] / 1000; + int off = offsets[(int)(val & OFFSET_MASK)]/1000; + long second = (val >> TRANSITION_NSHIFT)/1000; + sb.append("\n "); + offset = transToString(transitions[i], offset, offsets, sb); + if (transitions0 == null || i >= transitions0.length) { + sb.append("\n "); + offset = transToString(transitions[i], offset, offsets, sb); + sb.append("\n (NG) trans0 is null or < trans.length"); + } else { + long val0 = transitions0[i]; + int dst0 = (int)((val0 >>> DST_NSHIFT) & 0xfL); + int save0 = (dst0 == 0) ? 0 : offsets0[dst0] / 1000; + int off0 = offsets0[(int)(val0 & OFFSET_MASK)]/1000; + long second0 = (val0 >> TRANSITION_NSHIFT)/1000; + if (save != save0 || off != off0 || second != second0) { + sb.append("\n (NG)"); + } else { + sb.append("\n (OK)"); + } + offset0 = transToString(transitions0[i], offset0, offsets0, sb); + sb.append("\n -----"); + } + } + } + } + SimpleTimeZone stz = getLastRuleInstance(); + if (stz != null) { + SimpleTimeZone stz0 = other.getLastRule(); + if (!stz.hasSameRules(stz0)) { + sb.append("\n -------------") + .append("\n SimpleTimeZone (NG)") + .append("\n stz=" + stz) + .append("\n stz0=" + stz0); + } + } + sb.append("\n -------------"); + return sb.toString(); + } +} diff --git a/jdk/test/sun/util/calendar/zi/ZoneRec.java b/jdk/test/sun/util/calendar/zi/ZoneRec.java new file mode 100644 index 00000000000..e96346f4e2a --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/ZoneRec.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2000, 2004, 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. + */ + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; + +/** + * ZoneRec hold information of time zone corresponding to each text + * line of the "Zone" part. + * + * @since 1.4 + */ +class ZoneRec { + private int gmtOffset; + private String ruleName; + private int directSave; + private Rule ruleRef; + private String format; + private boolean hasUntil; + private int untilYear; + private Month untilMonth; + private RuleDay untilDay; + private Time untilTime; + private long untilInMillis; + private String line; + + /** + * @return the "UNTIL" value in milliseconds + */ + Time getUntilTime() { + return untilTime; + } + + /** + * @return the GMT offset value in milliseconds + */ + int getGmtOffset() { + return gmtOffset; + } + + /** + * @return the rule name to which this zone record refers + */ + String getRuleName() { + return ruleName; + } + + /** + * @return the amount of saving time directly defined in the + * "RULES/SAVE" field. + */ + int getDirectSave() { + return directSave; + } + + /** + * @return true if this zone record has a reference to a rule + */ + boolean hasRuleReference() { + return ruleRef != null; + } + + /** + * Returns the "FORMAT" field string of this zone record. This + * @return the "FORMAT" field + */ + String getFormat() { + return format; + } + + /** + * @return the year in the "UNTIL" field + */ + int getUntilYear() { + return untilYear; + } + + /** + * Returns the "UNTIL" field value in milliseconds from Janurary + * 1, 1970 0:00 GMT. + * @param currentSave the amount of daylight saving in + * milliseconds that is used to adjust wall-clock time. + * @return the milliseconds value of the "UNTIL" field + */ + long getUntilTime(int currentSave) { + if (untilTime.isWall()) { + return untilInMillis - currentSave; + } + return untilInMillis; + } + + /** + * Returns the "UNTIL" time in milliseconds without adjusting GMT + * offsets or daylight saving. + * @return local "UNTIL" time in milliseconds + */ + long getLocalUntilTime() { + return Time.getLocalTime(untilYear, + untilMonth, + untilDay, + untilTime.getTime()); + } + + /** + * Returns the "UNTIL" time in milliseconds with adjusting GMT offsets and daylight saving. + * @return the "UNTIL" time after the adjustment + */ + long getLocalUntilTime(int save, int gmtOffset) { + return Time.getLocalTime(untilYear, + untilMonth, + untilDay, + save, + gmtOffset, + untilTime); + } + + /** + * @return the text line of this zone record + */ + String getLine() { + return line; + } + + /** + * Sets the specified text line to this zone record + */ + void setLine(String line) { + this.line = line; + } + + /** + * @return true if this zone record has the "UNTIL" field + */ + boolean hasUntil() { + return this.hasUntil; + } + + /** + * Adjusts the "UNTIL" time to GMT offset if this zone record has + * it. untilTime is not adjusted to daylight saving + * in this method. + */ + void adjustTime() { + if (!hasUntil()) { + return; + } + if (untilTime.isSTD() || untilTime.isWall()) { + // adjust to gmt offset only here. adjust to real + // wall-clock time when tracking rules + untilInMillis -= gmtOffset; + } + } + + /** + * @return the reference to the Rule object + */ + Rule getRuleRef() { + return ruleRef; + } + + /** + * Resolves the reference to a Rule and adjusts its "UNTIL" time + * to GMT offset. + */ + void resolve(Zoneinfo zi) { + if (ruleName != null && (!"-".equals(ruleName))) { + ruleRef = zi.getRule(ruleName); + } + adjustTime(); + } + + /** + * Parses a Zone text line that is described by a StringTokenizer. + * @param tokens represents tokens of a Zone text line + * @return the zone record produced by parsing the text + */ + static ZoneRec parse(StringTokenizer tokens) { + ZoneRec rec = new ZoneRec(); + try { + rec.gmtOffset = (int) Time.parse(tokens.nextToken()).getTime(); + String token = tokens.nextToken(); + char c = token.charAt(0); + if (c >= '0' && c <= '9') { + rec.directSave = (int) Time.parse(token).getTime(); + } else { + rec.ruleName = token; + } + rec.format = tokens.nextToken(); + if (tokens.hasMoreTokens()) { + rec.hasUntil = true; + rec.untilYear = Integer.parseInt(tokens.nextToken()); + if (tokens.hasMoreTokens()) { + rec.untilMonth = Month.parse(tokens.nextToken()); + } else { + rec.untilMonth = Month.JANUARY; + } + if (tokens.hasMoreTokens()) { + rec.untilDay = RuleDay.parse(tokens.nextToken()); + } else { + rec.untilDay = new RuleDay(1); + } + if (tokens.hasMoreTokens()) { + rec.untilTime = Time.parse(tokens.nextToken()); + } else { + rec.untilTime = Time.parse("0:00"); + } + rec.untilInMillis = rec.getLocalUntilTime(); + } + } catch (Exception e) { + // TODO: error reporting + e.printStackTrace(); + } + return rec; + } + + private static void panic(String msg) { + Main.panic(msg); + } +} diff --git a/jdk/test/sun/util/calendar/zi/Zoneinfo.java b/jdk/test/sun/util/calendar/zi/Zoneinfo.java new file mode 100644 index 00000000000..93242eb4013 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/Zoneinfo.java @@ -0,0 +1,567 @@ +/* + * 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. + */ + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +/** + * Zoneinfo provides javazic compiler front-end functionality. + * @since 1.4 + */ +class Zoneinfo { + + private static final int minYear = 1900; + private static final int maxYear = 2037; + private static final long minTime = Time.getLocalTime(minYear, Month.JANUARY, 1, 0); + private static int startYear = minYear; + private static int endYear = maxYear; + + /** + * True if javazic should generate a list of SimpleTimeZone + * instances for the SimpleTimeZone-based time zone support. + */ + static boolean isYearForTimeZoneDataSpecified = false; + + /** + * Zone name to Zone mappings + */ + private Map zones; + + /** + * Rule name to Rule mappings + */ + private Map rules; + + /** + * Alias name to real name mappings + */ + private Map aliases; + + /** + * Constracts a Zoneinfo. + */ + Zoneinfo() { + zones = new HashMap(); + rules = new HashMap(); + aliases = new HashMap(); + } + + /** + * Adds the given zone to the list of Zones. + * @param zone Zone to be added to the list. + */ + void add(Zone zone) { + String name = zone.getName(); + zones.put(name, zone); + } + + /** + * Adds the given rule to the list of Rules. + * @param rule Rule to be added to the list. + */ + void add(Rule rule) { + String name = rule.getName(); + rules.put(name, rule); + } + + /** + * Puts the specifid name pair to the alias table. + * @param name1 an alias time zone name + * @param name2 the real time zone of the alias name + */ + void putAlias(String name1, String name2) { + aliases.put(name1, name2); + } + + /** + * Sets the given year for SimpleTimeZone list output. + * This method is called when the -S option is specified. + * @param year the year for which SimpleTimeZone list should be generated + */ + static void setYear(int year) { + setStartYear(year); + setEndYear(year); + isYearForTimeZoneDataSpecified = true; + } + + /** + * Sets the start year. + * @param year the start year value + * @throws IllegalArgumentException if the specified year value is + * smaller than the minimum year or greater than the end year. + */ + static void setStartYear(int year) { + if (year < minYear || year > endYear) { + throw new IllegalArgumentException("invalid start year specified: " + year); + } + startYear = year; + } + + /** + * @return the start year value + */ + static int getStartYear() { + return startYear; + } + + /** + * Sets the end year. + * @param year the end year value + * @throws IllegalArgumentException if the specified year value is + * smaller than the start year or greater than the maximum year. + */ + static void setEndYear(int year) { + if (year < startYear || year > maxYear) { + throw new IllegalArgumentException(); + } + endYear = year; + } + + /** + * @return the end year value + */ + static int getEndYear() { + return endYear; + } + + /** + * @return the minimum year value + */ + static int getMinYear() { + return minYear; + } + + /** + * @return the maximum year value + */ + static int getMaxYear() { + return maxYear; + } + + /** + * @return the alias table + */ + Map getAliases() { + return aliases; + } + + /** + * @return the Zone list + */ + Map getZones() { + return zones; + } + + /** + * @return a Zone specified by name. + * @param name a zone name + */ + Zone getZone(String name) { + return zones.get(name); + } + + /** + * @return a Rule specified by name. + * @param name a rule name + */ + Rule getRule(String name) { + return rules.get(name); + } + + private static String line; + + private static int lineNum; + + /** + * Parses the specified time zone data file and creates a Zoneinfo + * that has all Rules, Zones and Links (aliases) information. + * @param fname the time zone data file name + * @return a Zoneinfo object + */ + static Zoneinfo parse(String fname) { + BufferedReader in = null; + try { + FileReader fr = new FileReader(fname); + in = new BufferedReader(fr); + } catch (FileNotFoundException e) { + panic("can't open file: "+fname); + } + Zoneinfo zi = new Zoneinfo(); + boolean continued = false; + Zone zone = null; + String l; + lineNum = 0; + + try { + while ((line = in.readLine()) != null) { + lineNum++; + // skip blank and comment lines + if (line.length() == 0 || line.charAt(0) == '#') { + continue; + } + + // trim trailing comments + int rindex = line.lastIndexOf('#'); + if (rindex != -1) { + // take the data part of the line + l = line.substring(0, rindex); + } else { + l = line; + } + + StringTokenizer tokens = new StringTokenizer(l); + if (!tokens.hasMoreTokens()) { + continue; + } + String token = tokens.nextToken(); + + if (continued || "Zone".equals(token)) { + if (zone == null) { + if (!tokens.hasMoreTokens()) { + panic("syntax error: zone no more token"); + } + token = tokens.nextToken(); + // if the zone name is in "GMT+hh" or "GMT-hh" + // format, ignore it due to spec conflict. + if (token.startsWith("GMT+") || token.startsWith("GMT-")) { + continue; + } + zone = new Zone(token); + } else { + // no way to push the current token back... + tokens = new StringTokenizer(l); + } + + ZoneRec zrec = ZoneRec.parse(tokens); + zrec.setLine(line); + zone.add(zrec); + if ((continued = zrec.hasUntil()) == false) { + if (Zone.isTargetZone(zone.getName())) { + // zone.resolve(zi); + zi.add(zone); + } + zone = null; + } + } else if ("Rule".equals(token)) { + if (!tokens.hasMoreTokens()) { + panic("syntax error: rule no more token"); + } + token = tokens.nextToken(); + Rule rule = zi.getRule(token); + if (rule == null) { + rule = new Rule(token); + zi.add(rule); + } + RuleRec rrec = RuleRec.parse(tokens); + rrec.setLine(line); + rule.add(rrec); + } else if ("Link".equals(token)) { + // Link + try { + String name1 = tokens.nextToken(); + String name2 = tokens.nextToken(); + + // if the zone name is in "GMT+hh" or "GMT-hh" + // format, ignore it due to spec conflict with + // custom time zones. Also, ignore "ROC" for + // PC-ness. + if (name2.startsWith("GMT+") || name2.startsWith("GMT-") + || "ROC".equals(name2)) { + continue; + } + zi.putAlias(name2, name1); + } catch (Exception e) { + panic("syntax error: no more token for Link"); + } + } + } + in.close(); + } catch (IOException ex) { + panic("IO error: " + ex.getMessage()); + } + + return zi; + } + + /** + * Interprets a zone and constructs a Timezone object that + * contains enough information on GMT offsets and DST schedules to + * generate a zone info database. + * + * @param zoneName the zone name for which a Timezone object is + * constructed. + * + * @return a Timezone object that contains all GMT offsets and DST + * rules information. + */ + Timezone phase2(String zoneName) { + Timezone tz = new Timezone(zoneName); + Zone zone = getZone(zoneName); + zone.resolve(this); + + // TODO: merge phase2's for the regular and SimpleTimeZone ones. + if (isYearForTimeZoneDataSpecified) { + ZoneRec zrec = zone.get(zone.size()-1); + tz.setLastZoneRec(zrec); + tz.setRawOffset(zrec.getGmtOffset()); + if (zrec.hasRuleReference()) { + /* + * This part assumes that the specified year is covered by + * the rules referred to by the last zone record. + */ + List rrecs = zrec.getRuleRef().getRules(startYear); + + if (rrecs.size() == 2) { + // make sure that one is a start rule and the other is + // an end rule. + RuleRec r0 = rrecs.get(0); + RuleRec r1 = rrecs.get(1); + if (r0.getSave() == 0 && r1.getSave() > 0) { + rrecs.set(0, r1); + rrecs.set(1, r0); + } else if (!(r0.getSave() > 0 && r1.getSave() == 0)) { + rrecs = null; + Main.error(zoneName + ": rules for " + startYear + " not found."); + } + } else { + rrecs = null; + } + if (rrecs != null) { + tz.setLastRules(rrecs); + } + } + return tz; + } + + int gmtOffset; + int year = minYear; + int fromYear = year; + long fromTime = Time.getLocalTime(startYear, + Month.JANUARY, + 1, 0); + + // take the index 0 for the GMT offset of the last zone record + ZoneRec zrec = zone.get(zone.size()-1); + tz.getOffsetIndex(zrec.getGmtOffset()); + + int currentSave = 0; + boolean usedZone; + for (int zindex = 0; zindex < zone.size(); zindex++) { + zrec = zone.get(zindex); + usedZone = false; + gmtOffset = zrec.getGmtOffset(); + int stdOffset = zrec.getDirectSave(); + + // If this is the last zone record, take the last rule info. + if (!zrec.hasUntil()) { + tz.setRawOffset(gmtOffset, fromTime); + if (zrec.hasRuleReference()) { + tz.setLastRules(zrec.getRuleRef().getLastRules()); + } else if (stdOffset != 0) { + // in case the last rule is all year round DST-only + // (Asia/Amman once announced this rule.) + tz.setLastDSTSaving(stdOffset); + } + } + if (!zrec.hasRuleReference()) { + if (!zrec.hasUntil() || zrec.getUntilTime(stdOffset) >= fromTime) { + tz.addTransition(fromTime, + tz.getOffsetIndex(gmtOffset+stdOffset), + tz.getDstOffsetIndex(stdOffset)); + usedZone = true; + } + currentSave = stdOffset; + // optimization in case the last rule is fixed. + if (!zrec.hasUntil()) { + if (tz.getNTransitions() > 0) { + if (stdOffset == 0) { + tz.setDSTType(Timezone.X_DST); + } else { + tz.setDSTType(Timezone.LAST_DST); + } + long time = Time.getLocalTime(maxYear, + Month.JANUARY, 1, 0); + time -= zrec.getGmtOffset(); + tz.addTransition(time, + tz.getOffsetIndex(gmtOffset+stdOffset), + tz.getDstOffsetIndex(stdOffset)); + tz.addUsedRec(zrec); + } else { + tz.setDSTType(Timezone.NO_DST); + } + break; + } + } else { + Rule rule = zrec.getRuleRef(); + boolean fromTimeUsed = false; + currentSave = 0; + year_loop: + for (year = getMinYear(); year <= endYear; year++) { + if (zrec.hasUntil() && year > zrec.getUntilYear()) { + break; + } + List rules = rule.getRules(year); + if (rules.size() > 0) { + for (int i = 0; i < rules.size(); i++) { + RuleRec rrec = rules.get(i); + long transition = rrec.getTransitionTime(year, + gmtOffset, + currentSave); + if (zrec.hasUntil()) { + if (transition >= zrec.getUntilTime(currentSave)) { + break year_loop; + } + } + + if (fromTimeUsed == false) { + if (fromTime <= transition) { + fromTimeUsed = true; + + if (fromTime != minTime) { + int prevsave; + + ZoneRec prevzrec = zone.get(zindex - 1); + + // See if until time in the previous + // ZoneRec is the same thing as the + // local time in the next rule. + // (examples are Asia/Ashkhabad in 1991, + // Europe/Riga in 1989) + + if (i > 0) { + prevsave = rules.get(i-1).getSave(); + } else { + List prevrules = rule.getRules(year-1); + + if (prevrules.size() > 0) { + prevsave = prevrules.get(prevrules.size()-1).getSave(); + } else { + prevsave = 0; + } + } + + if (rrec.isSameTransition(prevzrec, prevsave, gmtOffset)) { + currentSave = rrec.getSave(); + tz.addTransition(fromTime, + tz.getOffsetIndex(gmtOffset+currentSave), + tz.getDstOffsetIndex(currentSave)); + tz.addUsedRec(rrec); + usedZone = true; + continue; + } + if (!prevzrec.hasRuleReference() + || rule != prevzrec.getRuleRef() + || (rule == prevzrec.getRuleRef() + && gmtOffset != prevzrec.getGmtOffset())) { + int save = (fromTime == transition) ? rrec.getSave() : currentSave; + tz.addTransition(fromTime, + tz.getOffsetIndex(gmtOffset+save), + tz.getDstOffsetIndex(save)); + tz.addUsedRec(rrec); + usedZone = true; + } + } else { // fromTime == minTime + int save = rrec.getSave(); + tz.addTransition(minTime, + tz.getOffsetIndex(gmtOffset), + tz.getDstOffsetIndex(0)); + + tz.addTransition(transition, + tz.getOffsetIndex(gmtOffset+save), + tz.getDstOffsetIndex(save)); + + tz.addUsedRec(rrec); + usedZone = true; + } + } else if (year == fromYear && i == rules.size()-1) { + int save = rrec.getSave(); + tz.addTransition(fromTime, + tz.getOffsetIndex(gmtOffset+save), + tz.getDstOffsetIndex(save)); + } + } + + currentSave = rrec.getSave(); + if (fromTime < transition) { + tz.addTransition(transition, + tz.getOffsetIndex(gmtOffset+currentSave), + tz.getDstOffsetIndex(currentSave)); + tz.addUsedRec(rrec); + usedZone = true; + } + } + } else { + if (year == fromYear) { + tz.addTransition(fromTime, + tz.getOffsetIndex(gmtOffset+currentSave), + tz.getDstOffsetIndex(currentSave)); + fromTimeUsed = true; + } + if (year == endYear && !zrec.hasUntil()) { + if (tz.getNTransitions() > 0) { + // Assume that this Zone stopped DST + tz.setDSTType(Timezone.X_DST); + long time = Time.getLocalTime(maxYear, Month.JANUARY, + 1, 0); + time -= zrec.getGmtOffset(); + tz.addTransition(time, + tz.getOffsetIndex(gmtOffset), + tz.getDstOffsetIndex(0)); + usedZone = true; + } else { + tz.setDSTType(Timezone.NO_DST); + } + } + } + } + } + if (usedZone) { + tz.addUsedRec(zrec); + } + if (zrec.hasUntil() && zrec.getUntilTime(currentSave) > fromTime) { + fromTime = zrec.getUntilTime(currentSave); + fromYear = zrec.getUntilYear(); + year = zrec.getUntilYear(); + } + } + + if (tz.getDSTType() == Timezone.UNDEF_DST) { + tz.setDSTType(Timezone.DST); + } + tz.optimize(); + tz.checksum(); + return tz; + } + + private static void panic(String msg) { + Main.panic(msg); + } +} diff --git a/jdk/test/sun/util/calendar/zi/tzdata/VERSION b/jdk/test/sun/util/calendar/zi/tzdata/VERSION new file mode 100644 index 00000000000..85db871ccf3 --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/tzdata/VERSION @@ -0,0 +1,24 @@ +# +# 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. +# +tzdata2012i diff --git a/jdk/test/sun/util/calendar/zi/tzdata/africa b/jdk/test/sun/util/calendar/zi/tzdata/africa new file mode 100644 index 00000000000..7db9b3d269d --- /dev/null +++ b/jdk/test/sun/util/calendar/zi/tzdata/africa @@ -0,0 +1,1186 @@ +# +# 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. +# +#

    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# This data is by no means authoritative; if you think you know better,
    +# go ahead and edit the file (and please send any changes to
    +# tz@elsie.nci.nih.gov for general use in the future).
    +
    +# From Paul Eggert (2006-03-22):
    +#
    +# A good source for time zone historical data outside the U.S. is
    +# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
    +# San Diego: ACS Publications, Inc. (2003).
    +#
    +# Gwillim Law writes that a good source
    +# for recent time zone data is the International Air Transport
    +# Association's Standard Schedules Information Manual (IATA SSIM),
    +# published semiannually.  Law sent in several helpful summaries
    +# of the IATA's data after 1990.
    +#
    +# Except where otherwise noted, Shanks & Pottenger is the source for
    +# entries through 1990, and IATA SSIM is the source for entries afterwards.
    +#
    +# Another source occasionally used is Edward W. Whitman, World Time Differences,
    +# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
    +# I found in the UCLA library.
    +#
    +# A reliable and entertaining source about time zones is
    +# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
    +#
    +# Previous editions of this database used WAT, CAT, SAT, and EAT
    +# for +0:00 through +3:00, respectively,
    +# but Mark R V Murray reports that
    +# `SAST' is the official abbreviation for +2:00 in the country of South Africa,
    +# `CAT' is commonly used for +2:00 in countries north of South Africa, and
    +# `WAT' is probably the best name for +1:00, as the common phrase for
    +# the area that includes Nigeria is ``West Africa''.
    +# He has heard of ``Western Sahara Time'' for +0:00 but can find no reference.
    +#
    +# To make things confusing, `WAT' seems to have been used for -1:00 long ago;
    +# I'd guess that this was because people needed _some_ name for -1:00,
    +# and at the time, far west Africa was the only major land area in -1:00.
    +# This usage is now obsolete, as the last use of -1:00 on the African
    +# mainland seems to have been 1976 in Western Sahara.
    +#
    +# To summarize, the following abbreviations seem to have some currency:
    +#	-1:00	WAT	West Africa Time (no longer used)
    +#	 0:00	GMT	Greenwich Mean Time
    +#	 2:00	CAT	Central Africa Time
    +#	 2:00	SAST	South Africa Standard Time
    +# and Murray suggests the following abbreviation:
    +#	 1:00	WAT	West Africa Time
    +# I realize that this leads to `WAT' being used for both -1:00 and 1:00
    +# for times before 1976, but this is the best I can think of
    +# until we get more information.
    +#
    +# I invented the following abbreviations; corrections are welcome!
    +#	 2:00	WAST	West Africa Summer Time
    +#	 2:30	BEAT	British East Africa Time (no longer used)
    +#	 2:45	BEAUT	British East Africa Unified Time (no longer used)
    +#	 3:00	CAST	Central Africa Summer Time (no longer used)
    +#	 3:00	SAST	South Africa Summer Time (no longer used)
    +#	 3:00	EAT	East Africa Time
    +#	 4:00	EAST	East Africa Summer Time (no longer used)
    +
    +# Algeria
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Algeria	1916	only	-	Jun	14	23:00s	1:00	S
    +Rule	Algeria	1916	1919	-	Oct	Sun>=1	23:00s	0	-
    +Rule	Algeria	1917	only	-	Mar	24	23:00s	1:00	S
    +Rule	Algeria	1918	only	-	Mar	 9	23:00s	1:00	S
    +Rule	Algeria	1919	only	-	Mar	 1	23:00s	1:00	S
    +Rule	Algeria	1920	only	-	Feb	14	23:00s	1:00	S
    +Rule	Algeria	1920	only	-	Oct	23	23:00s	0	-
    +Rule	Algeria	1921	only	-	Mar	14	23:00s	1:00	S
    +Rule	Algeria	1921	only	-	Jun	21	23:00s	0	-
    +Rule	Algeria	1939	only	-	Sep	11	23:00s	1:00	S
    +Rule	Algeria	1939	only	-	Nov	19	 1:00	0	-
    +Rule	Algeria	1944	1945	-	Apr	Mon>=1	 2:00	1:00	S
    +Rule	Algeria	1944	only	-	Oct	 8	 2:00	0	-
    +Rule	Algeria	1945	only	-	Sep	16	 1:00	0	-
    +Rule	Algeria	1971	only	-	Apr	25	23:00s	1:00	S
    +Rule	Algeria	1971	only	-	Sep	26	23:00s	0	-
    +Rule	Algeria	1977	only	-	May	 6	 0:00	1:00	S
    +Rule	Algeria	1977	only	-	Oct	21	 0:00	0	-
    +Rule	Algeria	1978	only	-	Mar	24	 1:00	1:00	S
    +Rule	Algeria	1978	only	-	Sep	22	 3:00	0	-
    +Rule	Algeria	1980	only	-	Apr	25	 0:00	1:00	S
    +Rule	Algeria	1980	only	-	Oct	31	 2:00	0	-
    +# Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
    +# more precise 0:09:21.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Algiers	0:12:12 -	LMT	1891 Mar 15 0:01
    +			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
    +			0:00	Algeria	WE%sT	1940 Feb 25 2:00
    +			1:00	Algeria	CE%sT	1946 Oct  7
    +			0:00	-	WET	1956 Jan 29
    +			1:00	-	CET	1963 Apr 14
    +			0:00	Algeria	WE%sT	1977 Oct 21
    +			1:00	Algeria	CE%sT	1979 Oct 26
    +			0:00	Algeria	WE%sT	1981 May
    +			1:00	-	CET
    +
    +# Angola
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Luanda	0:52:56	-	LMT	1892
    +			0:52:04	-	AOT	1911 May 26 # Angola Time
    +			1:00	-	WAT
    +
    +# Benin
    +# Whitman says they switched to 1:00 in 1946, not 1934;
    +# go with Shanks & Pottenger.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Africa/Porto-Novo	0:10:28	-	LMT	1912
    +			0:00	-	GMT	1934 Feb 26
    +			1:00	-	WAT
    +
    +# Botswana
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Gaborone	1:43:40 -	LMT	1885
    +			2:00	-	CAT	1943 Sep 19 2:00
    +			2:00	1:00	CAST	1944 Mar 19 2:00
    +			2:00	-	CAT
    +
    +# Burkina Faso
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Africa/Ouagadougou	-0:06:04 -	LMT	1912
    +			 0:00	-	GMT
    +
    +# Burundi
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Africa/Bujumbura	1:57:28	-	LMT	1890
    +			2:00	-	CAT
    +
    +# Cameroon
    +# Whitman says they switched to 1:00 in 1920; go with Shanks & Pottenger.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Douala	0:38:48	-	LMT	1912
    +			1:00	-	WAT
    +
    +# Cape Verde
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Atlantic/Cape_Verde -1:34:04 -	LMT	1907			# Praia
    +			-2:00	-	CVT	1942 Sep
    +			-2:00	1:00	CVST	1945 Oct 15
    +			-2:00	-	CVT	1975 Nov 25 2:00
    +			-1:00	-	CVT
    +
    +# Central African Republic
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Bangui	1:14:20	-	LMT	1912
    +			1:00	-	WAT
    +
    +# Chad
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Ndjamena	1:00:12 -	LMT	1912
    +			1:00	-	WAT	1979 Oct 14
    +			1:00	1:00	WAST	1980 Mar  8
    +			1:00	-	WAT
    +
    +# Comoros
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Indian/Comoro	2:53:04 -	LMT	1911 Jul   # Moroni, Gran Comoro
    +			3:00	-	EAT
    +
    +# Democratic Republic of Congo
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Africa/Kinshasa	1:01:12 -	LMT	1897 Nov 9
    +			1:00	-	WAT
    +Zone Africa/Lubumbashi	1:49:52 -	LMT	1897 Nov 9
    +			2:00	-	CAT
    +
    +# Republic of the Congo
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Africa/Brazzaville	1:01:08 -	LMT	1912
    +			1:00	-	WAT
    +
    +# Cote D'Ivoire
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Abidjan	-0:16:08 -	LMT	1912
    +			 0:00	-	GMT
    +
    +# Djibouti
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Djibouti	2:52:36 -	LMT	1911 Jul
    +			3:00	-	EAT
    +
    +###############################################################################
    +
    +# Egypt
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Egypt	1940	only	-	Jul	15	0:00	1:00	S
    +Rule	Egypt	1940	only	-	Oct	 1	0:00	0	-
    +Rule	Egypt	1941	only	-	Apr	15	0:00	1:00	S
    +Rule	Egypt	1941	only	-	Sep	16	0:00	0	-
    +Rule	Egypt	1942	1944	-	Apr	 1	0:00	1:00	S
    +Rule	Egypt	1942	only	-	Oct	27	0:00	0	-
    +Rule	Egypt	1943	1945	-	Nov	 1	0:00	0	-
    +Rule	Egypt	1945	only	-	Apr	16	0:00	1:00	S
    +Rule	Egypt	1957	only	-	May	10	0:00	1:00	S
    +Rule	Egypt	1957	1958	-	Oct	 1	0:00	0	-
    +Rule	Egypt	1958	only	-	May	 1	0:00	1:00	S
    +Rule	Egypt	1959	1981	-	May	 1	1:00	1:00	S
    +Rule	Egypt	1959	1965	-	Sep	30	3:00	0	-
    +Rule	Egypt	1966	1994	-	Oct	 1	3:00	0	-
    +Rule	Egypt	1982	only	-	Jul	25	1:00	1:00	S
    +Rule	Egypt	1983	only	-	Jul	12	1:00	1:00	S
    +Rule	Egypt	1984	1988	-	May	 1	1:00	1:00	S
    +Rule	Egypt	1989	only	-	May	 6	1:00	1:00	S
    +Rule	Egypt	1990	1994	-	May	 1	1:00	1:00	S
    +# IATA (after 1990) says transitions are at 0:00.
    +# Go with IATA starting in 1995, except correct 1995 entry from 09-30 to 09-29.
    +
    +# From Alexander Krivenyshev (2011-04-20):
    +# "...Egypt's interim cabinet decided on Wednesday to cancel daylight
    +# saving time after a poll posted on its website showed the majority of
    +# Egyptians would approve the cancellation."
    +#
    +# Egypt to cancel daylight saving time
    +# 
    +# http://www.almasryalyoum.com/en/node/407168
    +# 
    +# or
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_egypt04.html
    +# 
    +Rule	Egypt	1995	2010	-	Apr	lastFri	 0:00s	1:00	S
    +Rule	Egypt	1995	2005	-	Sep	lastThu	23:00s	0	-
    +# From Steffen Thorsen (2006-09-19):
    +# The Egyptian Gazette, issue 41,090 (2006-09-18), page 1, reports:
    +# Egypt will turn back clocks by one hour at the midnight of Thursday
    +# after observing the daylight saving time since May.
    +# http://news.gom.com.eg/gazette/pdf/2006/09/18/01.pdf
    +Rule	Egypt	2006	only	-	Sep	21	23:00s	0	-
    +# From Dirk Losch (2007-08-14):
    +# I received a mail from an airline which says that the daylight
    +# saving time in Egypt will end in the night of 2007-09-06 to 2007-09-07.
    +# From Jesper Norgaard Welen (2007-08-15): [The following agree:]
    +# http://www.nentjes.info/Bill/bill5.htm
    +# http://www.timeanddate.com/worldclock/city.html?n=53
    +# From Steffen Thorsen (2007-09-04): The official information...:
    +# http://www.sis.gov.eg/En/EgyptOnline/Miscellaneous/000002/0207000000000000001580.htm
    +Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
    +# From Abdelrahman Hassan (2007-09-06):
    +# Due to the Hijri (lunar Islamic calendar) year being 11 days shorter
    +# than the year of the Gregorian calendar, Ramadan shifts earlier each
    +# year. This year it will be observed September 13 (September is quite
    +# hot in Egypt), and the idea is to make fasting easier for workers by
    +# shifting business hours one hour out of daytime heat. Consequently,
    +# unless discontinued, next DST may end Thursday 28 August 2008.
    +# From Paul Eggert (2007-08-17):
    +# For lack of better info, assume the new rule is last Thursday in August.
    +
    +# From Petr Machata (2009-04-06):
    +# The following appeared in Red Hat bugzilla[1] (edited):
    +#
    +# > $ zdump -v /usr/share/zoneinfo/Africa/Cairo | grep 2009
    +# > /usr/share/zoneinfo/Africa/Cairo  Thu Apr 23 21:59:59 2009 UTC = Thu =
    +# Apr 23
    +# > 23:59:59 2009 EET isdst=0 gmtoff=7200
    +# > /usr/share/zoneinfo/Africa/Cairo  Thu Apr 23 22:00:00 2009 UTC = Fri =
    +# Apr 24
    +# > 01:00:00 2009 EEST isdst=1 gmtoff=10800
    +# > /usr/share/zoneinfo/Africa/Cairo  Thu Aug 27 20:59:59 2009 UTC = Thu =
    +# Aug 27
    +# > 23:59:59 2009 EEST isdst=1 gmtoff=10800
    +# > /usr/share/zoneinfo/Africa/Cairo  Thu Aug 27 21:00:00 2009 UTC = Thu =
    +# Aug 27
    +# > 23:00:00 2009 EET isdst=0 gmtoff=7200
    +#
    +# > end date should be Thu Sep 24 2009 (Last Thursday in September at 23:59=
    +# :59)
    +# > http://support.microsoft.com/kb/958729/
    +#
    +# timeanddate[2] and another site I've found[3] also support that.
    +#
    +# [1] 
    +# https://bugzilla.redhat.com/show_bug.cgi?id=492263
    +# 
    +# [2] 
    +# http://www.timeanddate.com/worldclock/clockchange.html?n=53
    +# 
    +# [3] 
    +# http://wwp.greenwichmeantime.com/time-zone/africa/egypt/
    +# 
    +
    +# From Arthur David Olson (2009-04-20):
    +# In 2009 (and for the next several years), Ramadan ends before the fourth
    +# Thursday in September; Egypt is expected to revert to the last Thursday
    +# in September.
    +
    +# From Steffen Thorsen (2009-08-11):
    +# We have been able to confirm the August change with the Egyptian Cabinet
    +# Information and Decision Support Center:
    +# 
    +# http://www.timeanddate.com/news/time/egypt-dst-ends-2009.html
    +# 
    +#
    +# The Middle East News Agency
    +# 
    +# http://www.mena.org.eg/index.aspx
    +# 
    +# also reports "Egypt starts winter time on August 21"
    +# today in article numbered "71, 11/08/2009 12:25 GMT."
    +# Only the title above is available without a subscription to their service,
    +# and can be found by searching for "winter" in their search engine
    +# (at least today).
    +
    +# From Alexander Krivenyshev (2010-07-20):
    +# According to News from Egypt -  Al-Masry Al-Youm Egypt's cabinet has
    +# decided that Daylight Saving Time will not be used in Egypt during
    +# Ramadan.
    +#
    +# Arabic translation:
    +# "Clocks to go back during Ramadan--and then forward again"
    +# 
    +# http://www.almasryalyoum.com/en/news/clocks-go-back-during-ramadan-and-then-forward-again
    +# 
    +# or
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_egypt02.html
    +# 
    +
    +Rule	Egypt	2008	only	-	Aug	lastThu	23:00s	0	-
    +Rule	Egypt	2009	only	-	Aug	20	23:00s	0	-
    +Rule	Egypt	2010	only	-	Aug	11	0:00	0	-
    +Rule	Egypt	2010	only	-	Sep	10	0:00	1:00	S
    +Rule	Egypt	2010	only	-	Sep	lastThu	23:00s	0	-
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Cairo	2:05:00 -	LMT	1900 Oct
    +			2:00	Egypt	EE%sT
    +
    +# Equatorial Guinea
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Malabo	0:35:08 -	LMT	1912
    +			0:00	-	GMT	1963 Dec 15
    +			1:00	-	WAT
    +
    +# Eritrea
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Asmara	2:35:32 -	LMT	1870
    +			2:35:32	-	AMT	1890	      # Asmara Mean Time
    +			2:35:20	-	ADMT	1936 May 5    # Adis Dera MT
    +			3:00	-	EAT
    +
    +# Ethiopia
    +# From Paul Eggert (2006-03-22):
    +# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time zones
    +# between 1870 and 1890, and that they merged to 38E50 (2:35:20) in 1890.
    +# We'll guess that 38E50 is for Adis Dera.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Africa/Addis_Ababa	2:34:48 -	LMT	1870
    +			2:35:20	-	ADMT	1936 May 5    # Adis Dera MT
    +			3:00	-	EAT
    +
    +# Gabon
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Africa/Libreville	0:37:48 -	LMT	1912
    +			1:00	-	WAT
    +
    +# Gambia
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Banjul	-1:06:36 -	LMT	1912
    +			-1:06:36 -	BMT	1935	# Banjul Mean Time
    +			-1:00	-	WAT	1964
    +			 0:00	-	GMT
    +
    +# Ghana
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +# Whitman says DST was observed from 1931 to ``the present'';
    +# go with Shanks & Pottenger.
    +Rule	Ghana	1936	1942	-	Sep	 1	0:00	0:20	GHST
    +Rule	Ghana	1936	1942	-	Dec	31	0:00	0	GMT
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Accra	-0:00:52 -	LMT	1918
    +			 0:00	Ghana	%s
    +
    +# Guinea
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Conakry	-0:54:52 -	LMT	1912
    +			 0:00	-	GMT	1934 Feb 26
    +			-1:00	-	WAT	1960
    +			 0:00	-	GMT
    +
    +# Guinea-Bissau
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Bissau	-1:02:20 -	LMT	1911 May 26
    +			-1:00	-	WAT	1975
    +			 0:00	-	GMT
    +
    +# Kenya
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Nairobi	2:27:16	-	LMT	1928 Jul
    +			3:00	-	EAT	1930
    +			2:30	-	BEAT	1940
    +			2:45	-	BEAUT	1960
    +			3:00	-	EAT
    +
    +# Lesotho
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Maseru	1:50:00 -	LMT	1903 Mar
    +			2:00	-	SAST	1943 Sep 19 2:00
    +			2:00	1:00	SAST	1944 Mar 19 2:00
    +			2:00	-	SAST
    +
    +# Liberia
    +# From Paul Eggert (2006-03-22):
    +# In 1972 Liberia was the last country to switch
    +# from a UTC offset that was not a multiple of 15 or 20 minutes.
    +# Howse reports that it was in honor of their president's birthday.
    +# Shank & Pottenger report the date as May 1, whereas Howse reports Jan;
    +# go with Shanks & Pottenger.
    +# For Liberia before 1972, Shanks & Pottenger report -0:44, whereas Howse and
    +# Whitman each report -0:44:30; go with the more precise figure.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Monrovia	-0:43:08 -	LMT	1882
    +			-0:43:08 -	MMT	1919 Mar # Monrovia Mean Time
    +			-0:44:30 -	LRT	1972 May # Liberia Time
    +			 0:00	-	GMT
    +
    +###############################################################################
    +
    +# Libya
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Libya	1951	only	-	Oct	14	2:00	1:00	S
    +Rule	Libya	1952	only	-	Jan	 1	0:00	0	-
    +Rule	Libya	1953	only	-	Oct	 9	2:00	1:00	S
    +Rule	Libya	1954	only	-	Jan	 1	0:00	0	-
    +Rule	Libya	1955	only	-	Sep	30	0:00	1:00	S
    +Rule	Libya	1956	only	-	Jan	 1	0:00	0	-
    +Rule	Libya	1982	1984	-	Apr	 1	0:00	1:00	S
    +Rule	Libya	1982	1985	-	Oct	 1	0:00	0	-
    +Rule	Libya	1985	only	-	Apr	 6	0:00	1:00	S
    +Rule	Libya	1986	only	-	Apr	 4	0:00	1:00	S
    +Rule	Libya	1986	only	-	Oct	 3	0:00	0	-
    +Rule	Libya	1987	1989	-	Apr	 1	0:00	1:00	S
    +Rule	Libya	1987	1989	-	Oct	 1	0:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Tripoli	0:52:44 -	LMT	1920
    +			1:00	Libya	CE%sT	1959
    +			2:00	-	EET	1982
    +			1:00	Libya	CE%sT	1990 May  4
    +# The following entries are from Shanks & Pottenger;
    +# the IATA SSIM data contain some obvious errors.
    +			2:00	-	EET	1996 Sep 30
    +			1:00	-	CET	1997 Apr  4
    +			1:00	1:00	CEST	1997 Oct  4
    +			2:00	-	EET
    +
    +# Madagascar
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Indian/Antananarivo 3:10:04 -	LMT	1911 Jul
    +			3:00	-	EAT	1954 Feb 27 23:00s
    +			3:00	1:00	EAST	1954 May 29 23:00s
    +			3:00	-	EAT
    +
    +# Malawi
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Blantyre	2:20:00 -	LMT	1903 Mar
    +			2:00	-	CAT
    +
    +# Mali
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Bamako	-0:32:00 -	LMT	1912
    +			 0:00	-	GMT	1934 Feb 26
    +			-1:00	-	WAT	1960 Jun 20
    +			 0:00	-	GMT
    +
    +# Mauritania
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Africa/Nouakchott	-1:03:48 -	LMT	1912
    +			 0:00	-	GMT	1934 Feb 26
    +			-1:00	-	WAT	1960 Nov 28
    +			 0:00	-	GMT
    +
    +# Mauritius
    +
    +# From Steffen Thorsen (2008-06-25):
    +# Mauritius plans to observe DST from 2008-11-01 to 2009-03-31 on a trial
    +# basis....
    +# It seems that Mauritius observed daylight saving time from 1982-10-10 to
    +# 1983-03-20 as well, but that was not successful....
    +# http://www.timeanddate.com/news/time/mauritius-daylight-saving-time.html
    +
    +# From Alex Krivenyshev (2008-06-25):
    +# http://economicdevelopment.gov.mu/portal/site/Mainhomepage/menuitem.a42b24128104d9845dabddd154508a0c/?content_id=0a7cee8b5d69a110VgnVCM1000000a04a8c0RCRD
    +
    +# From Arthur David Olson (2008-06-30):
    +# The www.timeanddate.com article cited by Steffen Thorsen notes that "A
    +# final decision has yet to be made on the times that daylight saving
    +# would begin and end on these dates." As a place holder, use midnight.
    +
    +# From Paul Eggert (2008-06-30):
    +# Follow Thorsen on DST in 1982/1983, instead of Shanks & Pottenger.
    +
    +# From Steffen Thorsen (2008-07-10):
    +# According to
    +# 
    +# http://www.lexpress.mu/display_article.php?news_id=111216
    +# 
    +# (in French), Mauritius will start and end their DST a few days earlier
    +# than previously announced (2008-11-01 to 2009-03-31).  The new start
    +# date is 2008-10-26 at 02:00 and the new end date is 2009-03-27 (no time
    +# given, but it is probably at either 2 or 3 wall clock time).
    +#
    +# A little strange though, since the article says that they moved the date
    +# to align itself with Europe and USA which also change time on that date,
    +# but that means they have not paid attention to what happened in
    +# USA/Canada last year (DST ends first Sunday in November). I also wonder
    +# why that they end on a Friday, instead of aligning with Europe which
    +# changes two days later.
    +
    +# From Alex Krivenyshev (2008-07-11):
    +# Seems that English language article "The revival of daylight saving
    +# time:  Energy conservation?"-# No. 16578 (07/11/2008) was originally
    +# published on Monday, June 30, 2008...
    +#
    +# I guess that article in French "Le gouvernement avance l'introduction
    +# de l'heure d'ete" stating that DST in Mauritius starting on October 26
    +# and ending on March 27, 2009 is the most recent one.
    +# ...
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_mauritius02.html
    +# 
    +
    +# From Riad M. Hossen Ally (2008-08-03):
    +# The Government of Mauritius weblink
    +# 
    +# http://www.gov.mu/portal/site/pmosite/menuitem.4ca0efdee47462e7440a600248a521ca/?content_id=4728ca68b2a5b110VgnVCM1000000a04a8c0RCRD
    +# 
    +# Cabinet Decision of July 18th, 2008 states as follows:
    +#
    +# 4. ...Cabinet has agreed to the introduction into the National Assembly
    +# of the Time Bill which provides for the introduction of summer time in
    +# Mauritius. The summer time period which will be of one hour ahead of
    +# the standard time, will be aligned with that in Europe and the United
    +# States of America. It will start at two o'clock in the morning on the
    +# last Sunday of October and will end at two o'clock in the morning on
    +# the last Sunday of March the following year. The summer time for the
    +# year 2008 - 2009 will, therefore, be effective as from 26 October 2008
    +# and end on 29 March 2009.
    +
    +# From Ed Maste (2008-10-07):
    +# THE TIME BILL (No. XXVII of 2008) Explanatory Memorandum states the
    +# beginning / ending of summer time is 2 o'clock standard time in the
    +# morning of the last Sunday of October / last Sunday of March.
    +# 
    +# http://www.gov.mu/portal/goc/assemblysite/file/bill2708.pdf
    +# 
    +
    +# From Steffen Thorsen (2009-06-05):
    +# According to several sources, Mauritius will not continue to observe
    +# DST the coming summer...
    +#
    +# Some sources, in French:
    +# 
    +# http://www.defimedia.info/news/946/Rashid-Beebeejaun-:-%C2%AB-L%E2%80%99heure-d%E2%80%99%C3%A9t%C3%A9-ne-sera-pas-appliqu%C3%A9e-cette-ann%C3%A9e-%C2%BB
    +# 
    +# 
    +# http://lexpress.mu/Story/3398~Beebeejaun---Les-objectifs-d-%C3%A9conomie-d-%C3%A9nergie-de-l-heure-d-%C3%A9t%C3%A9-ont-%C3%A9t%C3%A9-atteints-
    +# 
    +#
    +# Our wrap-up:
    +# 
    +# http://www.timeanddate.com/news/time/mauritius-dst-will-not-repeat.html
    +# 
    +
    +# From Arthur David Olson (2009-07-11):
    +# The "mauritius-dst-will-not-repeat" wrapup includes this:
    +# "The trial ended on March 29, 2009, when the clocks moved back by one hour
    +# at 2am (or 02:00) local time..."
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule Mauritius	1982	only	-	Oct	10	0:00	1:00	S
    +Rule Mauritius	1983	only	-	Mar	21	0:00	0	-
    +Rule Mauritius	2008	only	-	Oct	lastSun	2:00	1:00	S
    +Rule Mauritius	2009	only	-	Mar	lastSun	2:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Indian/Mauritius	3:50:00 -	LMT	1907		# Port Louis
    +			4:00 Mauritius	MU%sT	# Mauritius Time
    +# Agalega Is, Rodriguez
    +# no information; probably like Indian/Mauritius
    +
    +# Mayotte
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
    +			3:00	-	EAT
    +
    +# Morocco
    +# See the `europe' file for Spanish Morocco (Africa/Ceuta).
    +
    +# From Alex Krivenyshev (2008-05-09):
    +# Here is an article that Morocco plan to introduce Daylight Saving Time between
    +# 1 June, 2008 and 27 September, 2008.
    +#
    +# "... Morocco is to save energy by adjusting its clock during summer so it will
    +# be one hour ahead of GMT between 1 June and 27 September, according to
    +# Communication Minister and Gov ernment Spokesman, Khalid Naciri...."
    +#
    +# 
    +# http://www.worldtimezone.net/dst_news/dst_news_morocco01.html
    +# 
    +# OR
    +# 
    +# http://en.afrik.com/news11892.html
    +# 
    +
    +# From Alex Krivenyshev (2008-05-09):
    +# The Morocco time change can be confirmed on Morocco web site Maghreb Arabe Presse:
    +# 
    +# http://www.map.ma/eng/sections/box3/morocco_shifts_to_da/view
    +# 
    +#
    +# Morocco shifts to daylight time on June 1st through September 27, Govt.
    +# spokesman.
    +
    +# From Patrice Scattolin (2008-05-09):
    +# According to this article:
    +# 
    +# http://www.avmaroc.com/actualite/heure-dete-comment-a127896.html
    +# 
    +# (and republished here:
    +# 
    +# http://www.actu.ma/heure-dete-comment_i127896_0.html
    +# 
    +# )
    +# the changes occurs at midnight:
    +#
    +# saturday night may 31st at midnight (which in french is to be
    +# intrepreted as the night between saturday and sunday)
    +# sunday night the 28th  at midnight
    +#
    +# Seeing that the 28th is monday, I am guessing that she intends to say
    +# the midnight of the 28th which is the midnight between sunday and
    +# monday, which jives with other sources that say that it's inclusive
    +# june1st to sept 27th.
    +#
    +# The decision was taken by decree *2-08-224 *but I can't find the decree
    +# published on the web.
    +#
    +# It's also confirmed here:
    +# 
    +# http://www.maroc.ma/NR/exeres/FACF141F-D910-44B0-B7FA-6E03733425D1.htm
    +# 
    +# on a government portal as being  between june 1st and sept 27th (not yet
    +# posted in english).
    +#
    +# The following google query will generate many relevant hits:
    +# 
    +# http://www.google.com/search?hl=en&q=Conseil+de+gouvernement+maroc+heure+avance&btnG=Search
    +# 
    +
    +# From Alex Krivenyshev (2008-05-09):
    +# Is Western Sahara (part which administrated by Morocco) going to follow
    +# Morocco DST changes?  Any information?  What about other part of
    +# Western Sahara - under administration of POLISARIO Front (also named
    +# SADR Saharawi Arab Democratic Republic)?
    +
    +# From Arthur David Olson (2008-05-09):
    +# XXX--guess that it is only Morocco for now; guess only 2008 for now.
    +
    +# From Steffen Thorsen (2008-08-27):
    +# Morocco will change the clocks back on the midnight between August 31
    +# and September 1. They originally planned to observe DST to near the end
    +# of September:
    +#
    +# One article about it (in French):
    +# 
    +# http://www.menara.ma/fr/Actualites/Maroc/Societe/ci.retour_a_l_heure_gmt_a_partir_du_dimanche_31_aout_a_minuit_officiel_.default
    +# 
    +#
    +# We have some further details posted here:
    +# 
    +# http://www.timeanddate.com/news/time/morocco-ends-dst-early-2008.html
    +# 
    +
    +# From Steffen Thorsen (2009-03-17):
    +# Morocco will observe DST from 2009-06-01 00:00 to 2009-08-21 00:00 according
    +# to many sources, such as
    +# 
    +# http://news.marweb.com/morocco/entertainment/morocco-daylight-saving.html
    +# 
    +# 
    +# http://www.medi1sat.ma/fr/depeche.aspx?idp=2312
    +# 
    +# (French)
    +#
    +# Our summary:
    +# 
    +# http://www.timeanddate.com/news/time/morocco-starts-dst-2009.html
    +# 
    +
    +# From Alexander Krivenyshev (2009-03-17):
    +# Here is a link to official document from Royaume du Maroc Premier Ministre,
    +# Ministere de la Modernisation des Secteurs Publics
    +#
    +# Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 june 1967)
    +# concerning the amendment of the legal time, the Ministry of Modernization of
    +# Public Sectors announced that the official time in the Kingdom will be
    +# advanced 60 minutes from Sunday 31 May 2009 at midnight.
    +#
    +# 
    +# http://www.mmsp.gov.ma/francais/Actualites_fr/PDF_Actualites_Fr/HeureEte_FR.pdf
    +# 
    +#
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_morocco03.html
    +# 
    +
    +# From Steffen Thorsen (2010-04-13):
    +# Several news media in Morocco report that the Ministry of Modernization
    +# of Public Sectors has announced that Morocco will have DST from
    +# 2010-05-02 to 2010-08-08.
    +#
    +# Example:
    +# 
    +# http://www.lavieeco.com/actualites/4099-le-maroc-passera-a-l-heure-d-ete-gmt1-le-2-mai.html
    +# 
    +# (French)
    +# Our page:
    +# 
    +# http://www.timeanddate.com/news/time/morocco-starts-dst-2010.html
    +# 
    +
    +# From Dan Abitol (2011-03-30):
    +# ...Rules for Africa/Casablanca are the following (24h format)
    +# The 3rd april 2011 at 00:00:00, [it] will be 3rd april 1:00:00
    +# The 31th july 2011 at 00:59:59,  [it] will be 31th July 00:00:00
    +# ...Official links of change in morocco
    +# The change was broadcast on the FM Radio
    +# I ve called ANRT (telecom regulations in Morocco) at
    +# +212.537.71.84.00
    +# 
    +# http://www.anrt.net.ma/fr/
    +# 
    +# They said that
    +# 
    +# http://www.map.ma/fr/sections/accueil/l_heure_legale_au_ma/view
    +# 
    +# is the official publication to look at.
    +# They said that the decision was already taken.
    +#
    +# More articles in the press
    +# 
    +# http://www.yabiladi.com/articles/details/5058/secret-l-heure-d-ete-maroc-lev
    +# 
    +# e.html
    +# 
    +# http://www.lematin.ma/Actualite/Express/Article.asp?id=148923
    +# 
    +# 
    +# http://www.lavieeco.com/actualite/Le-Maroc-passe-sur-GMT%2B1-a-partir-de-dim
    +# anche-prochain-5538.html
    +# 
    +
    +# From Petr Machata (2011-03-30):
    +# They have it written in English here:
    +# 
    +# http://www.map.ma/eng/sections/home/morocco_to_spring_fo/view
    +# 
    +#
    +# It says there that "Morocco will resume its standard time on July 31,
    +# 2011 at midnight." Now they don't say whether they mean midnight of
    +# wall clock time (i.e. 11pm UTC), but that's what I would assume. It has
    +# also been like that in the past.
    +
    +# From Alexander Krivenyshev (2012-03-09):
    +# According to Infomédiaire web site from Morocco (infomediaire.ma),
    +# on March 9, 2012, (in French) Heure légale:
    +# Le Maroc adopte officiellement l'heure d'été
    +# 
    +# http://www.infomediaire.ma/news/maroc/heure-l%C3%A9gale-le-maroc-adopte-officiellement-lheure-d%C3%A9t%C3%A9
    +# 
    +# Governing Council adopted draft decree, that Morocco DST starts on
    +# the last Sunday of March (March 25, 2012) and ends on
    +# last Sunday of September (September 30, 2012)
    +# except the month of Ramadan.
    +# or (brief)
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_morocco06.html
    +# 
    +
    +# From Arthur David Olson (2012-03-10):
    +# The infomediaire.ma source indicates that the system is to be in
    +# effect every year. It gives 03H00 as the "fall back" time of day;
    +# it lacks a "spring forward" time of day; assume 2:00 XXX.
    +# Wait on specifying the Ramadan exception for details about
    +# start date, start time of day, end date, and end time of day XXX.
    +
    +# From Christophe Tropamer (2012-03-16):
    +# Seen Morocco change again:
    +# 
    +# http://www.le2uminutes.com/actualite.php
    +# 
    +# "...à partir du dernier dimance d'avril et non fins mars,
    +# comme annoncé précédemment."
    +
    +# From Milamber Space Network (2012-07-17):
    +# The official return to GMT is announced by the Moroccan government:
    +# 
    +# http://www.mmsp.gov.ma/fr/actualites.aspx?id=288 [in French]
    +# 
    +#
    +# Google translation, lightly edited:
    +# Back to the standard time of the Kingdom (GMT)
    +# Pursuant to Decree No. 2-12-126 issued on 26 Jumada (I) 1433 (April 18,
    +# 2012) and in accordance with the order of Mr. President of the
    +# Government No. 3-47-12 issued on 24 Sha'ban (11 July 2012), the Ministry
    +# of Public Service and Administration Modernization announces the return
    +# of the legal time of the Kingdom (GMT) from Friday, July 20, 2012 until
    +# Monday, August 20, 2012.  So the time will be delayed by 60 minutes from
    +# 3:00 am Friday, July 20, 2012 and will again be advanced by 60 minutes
    +# August 20, 2012 from 2:00 am.
    +
    +# RULE	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +
    +Rule	Morocco	1939	only	-	Sep	12	 0:00	1:00	S
    +Rule	Morocco	1939	only	-	Nov	19	 0:00	0	-
    +Rule	Morocco	1940	only	-	Feb	25	 0:00	1:00	S
    +Rule	Morocco	1945	only	-	Nov	18	 0:00	0	-
    +Rule	Morocco	1950	only	-	Jun	11	 0:00	1:00	S
    +Rule	Morocco	1950	only	-	Oct	29	 0:00	0	-
    +Rule	Morocco	1967	only	-	Jun	 3	12:00	1:00	S
    +Rule	Morocco	1967	only	-	Oct	 1	 0:00	0	-
    +Rule	Morocco	1974	only	-	Jun	24	 0:00	1:00	S
    +Rule	Morocco	1974	only	-	Sep	 1	 0:00	0	-
    +Rule	Morocco	1976	1977	-	May	 1	 0:00	1:00	S
    +Rule	Morocco	1976	only	-	Aug	 1	 0:00	0	-
    +Rule	Morocco	1977	only	-	Sep	28	 0:00	0	-
    +Rule	Morocco	1978	only	-	Jun	 1	 0:00	1:00	S
    +Rule	Morocco	1978	only	-	Aug	 4	 0:00	0	-
    +Rule	Morocco	2008	only	-	Jun	 1	 0:00	1:00	S
    +Rule	Morocco	2008	only	-	Sep	 1	 0:00	0	-
    +Rule	Morocco	2009	only	-	Jun	 1	 0:00	1:00	S
    +Rule	Morocco	2009	only	-	Aug	 21	 0:00	0	-
    +Rule	Morocco	2010	only	-	May	 2	 0:00	1:00	S
    +Rule	Morocco	2010	only	-	Aug	 8	 0:00	0	-
    +Rule	Morocco	2011	only	-	Apr	 3	 0:00	1:00	S
    +Rule	Morocco	2011	only	-	Jul	 31	 0	0	-
    +Rule	Morocco	2012	max	-	Apr	 lastSun 2:00	1:00	S
    +Rule	Morocco	2012	max	-	Sep	 lastSun 3:00	0	-
    +Rule	Morocco	2012	only	-	Jul	 20	 3:00	0	-
    +Rule	Morocco	2012	only	-	Aug	 20	 2:00	1:00	S
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Africa/Casablanca	-0:30:20 -	LMT	1913 Oct 26
    +			 0:00	Morocco	WE%sT	1984 Mar 16
    +			 1:00	-	CET	1986
    +			 0:00	Morocco	WE%sT
    +# Western Sahara
    +Zone Africa/El_Aaiun	-0:52:48 -	LMT	1934 Jan
    +			-1:00	-	WAT	1976 Apr 14
    +			 0:00	-	WET
    +
    +# Mozambique
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Maputo	2:10:20 -	LMT	1903 Mar
    +			2:00	-	CAT
    +
    +# Namibia
    +# The 1994-04-03 transition is from Shanks & Pottenger.
    +# Shanks & Pottenger report no DST after 1998-04; go with IATA.
    +
    +# From Petronella Sibeene (2007-03-30) in
    +# :
    +# While the entire country changes its time, Katima Mulilo and other
    +# settlements in Caprivi unofficially will not because the sun there
    +# rises and sets earlier compared to other regions.  Chief of
    +# Forecasting Riaan van Zyl explained that the far eastern parts of
    +# the country are close to 40 minutes earlier in sunrise than the rest
    +# of the country.
    +#
    +# From Paul Eggert (2007-03-31):
    +# Apparently the Caprivi Strip informally observes Botswana time, but
    +# we have no details.  In the meantime people there can use Africa/Gaborone.
    +
    +# RULE	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Namibia	1994	max	-	Sep	Sun>=1	2:00	1:00	S
    +Rule	Namibia	1995	max	-	Apr	Sun>=1	2:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Windhoek	1:08:24 -	LMT	1892 Feb 8
    +			1:30	-	SWAT	1903 Mar	# SW Africa Time
    +			2:00	-	SAST	1942 Sep 20 2:00
    +			2:00	1:00	SAST	1943 Mar 21 2:00
    +			2:00	-	SAST	1990 Mar 21 # independence
    +			2:00	-	CAT	1994 Apr  3
    +			1:00	Namibia	WA%sT
    +
    +# Niger
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Niamey	 0:08:28 -	LMT	1912
    +			-1:00	-	WAT	1934 Feb 26
    +			 0:00	-	GMT	1960
    +			 1:00	-	WAT
    +
    +# Nigeria
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Lagos	0:13:36 -	LMT	1919 Sep
    +			1:00	-	WAT
    +
    +# Reunion
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Indian/Reunion	3:41:52 -	LMT	1911 Jun	# Saint-Denis
    +			4:00	-	RET	# Reunion Time
    +#
    +# Scattered Islands (Iles Eparses) administered from Reunion are as follows.
    +# The following information about them is taken from
    +# Iles Eparses (www.outre-mer.gouv.fr/domtom/ile.htm, 1997-07-22, in French;
    +# no longer available as of 1999-08-17).
    +# We have no info about their time zone histories.
    +#
    +# Bassas da India - uninhabited
    +# Europa Island - inhabited from 1905 to 1910 by two families
    +# Glorioso Is - inhabited until at least 1958
    +# Juan de Nova - uninhabited
    +# Tromelin - inhabited until at least 1958
    +
    +# Rwanda
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Kigali	2:00:16 -	LMT	1935 Jun
    +			2:00	-	CAT
    +
    +# St Helena
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Atlantic/St_Helena	-0:22:48 -	LMT	1890		# Jamestown
    +			-0:22:48 -	JMT	1951	# Jamestown Mean Time
    +			 0:00	-	GMT
    +# The other parts of the St Helena territory are similar:
    +#	Tristan da Cunha: on GMT, say Whitman and the CIA
    +#	Ascension: on GMT, says usno1995 and the CIA
    +#	Gough (scientific station since 1955; sealers wintered previously):
    +#		on GMT, says the CIA
    +#	Inaccessible, Nightingale: no information, but probably GMT
    +
    +# Sao Tome and Principe
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Sao_Tome	 0:26:56 -	LMT	1884
    +			-0:36:32 -	LMT	1912	# Lisbon Mean Time
    +			 0:00	-	GMT
    +
    +# Senegal
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Dakar	-1:09:44 -	LMT	1912
    +			-1:00	-	WAT	1941 Jun
    +			 0:00	-	GMT
    +
    +# Seychelles
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Indian/Mahe	3:41:48 -	LMT	1906 Jun	# Victoria
    +			4:00	-	SCT	# Seychelles Time
    +# From Paul Eggert (2001-05-30):
    +# Aldabra, Farquhar, and Desroches, originally dependencies of the
    +# Seychelles, were transferred to the British Indian Ocean Territory
    +# in 1965 and returned to Seychelles control in 1976.  We don't know
    +# whether this affected their time zone, so omit this for now.
    +# Possibly the islands were uninhabited.
    +
    +# Sierra Leone
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +# Whitman gives Mar 31 - Aug 31 for 1931 on; go with Shanks & Pottenger.
    +Rule	SL	1935	1942	-	Jun	 1	0:00	0:40	SLST
    +Rule	SL	1935	1942	-	Oct	 1	0:00	0	WAT
    +Rule	SL	1957	1962	-	Jun	 1	0:00	1:00	SLST
    +Rule	SL	1957	1962	-	Sep	 1	0:00	0	GMT
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Freetown	-0:53:00 -	LMT	1882
    +			-0:53:00 -	FMT	1913 Jun # Freetown Mean Time
    +			-1:00	SL	%s	1957
    +			 0:00	SL	%s
    +
    +# Somalia
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Africa/Mogadishu	3:01:28 -	LMT	1893 Nov
    +			3:00	-	EAT	1931
    +			2:30	-	BEAT	1957
    +			3:00	-	EAT
    +
    +# South Africa
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	SA	1942	1943	-	Sep	Sun>=15	2:00	1:00	-
    +Rule	SA	1943	1944	-	Mar	Sun>=15	2:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Africa/Johannesburg 1:52:00 -	LMT	1892 Feb 8
    +			1:30	-	SAST	1903 Mar
    +			2:00	SA	SAST
    +# Marion and Prince Edward Is
    +# scientific station since 1947
    +# no information
    +
    +# Sudan
    +#
    +# From 
    +# Sudan News Agency (2000-01-13)
    +# , also reported by Michael De Beukelaer-Dossche via Steffen Thorsen:
    +# Clocks will be moved ahead for 60 minutes all over the Sudan as of noon
    +# Saturday....  This was announced Thursday by Caretaker State Minister for
    +# Manpower Abdul-Rahman Nur-Eddin.
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Sudan	1970	only	-	May	 1	0:00	1:00	S
    +Rule	Sudan	1970	1985	-	Oct	15	0:00	0	-
    +Rule	Sudan	1971	only	-	Apr	30	0:00	1:00	S
    +Rule	Sudan	1972	1985	-	Apr	lastSun	0:00	1:00	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Khartoum	2:10:08 -	LMT	1931
    +			2:00	Sudan	CA%sT	2000 Jan 15 12:00
    +			3:00	-	EAT
    +
    +# South Sudan
    +Zone	Africa/Juba	2:06:24 -	LMT	1931
    +			2:00	Sudan	CA%sT	2000 Jan 15 12:00
    +			3:00	-	EAT
    +
    +# Swaziland
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Mbabane	2:04:24 -	LMT	1903 Mar
    +			2:00	-	SAST
    +
    +# Tanzania
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Africa/Dar_es_Salaam 2:37:08 -	LMT	1931
    +			3:00	-	EAT	1948
    +			2:45	-	BEAUT	1961
    +			3:00	-	EAT
    +
    +# Togo
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Lome	0:04:52 -	LMT	1893
    +			0:00	-	GMT
    +
    +# Tunisia
    +
    +# From Gwillim Law (2005-04-30):
    +# My correspondent, Risto Nykanen, has alerted me to another adoption of DST,
    +# this time in Tunisia.  According to Yahoo France News
    +# , in a story attributed to AP
    +# and dated 2005-04-26, "Tunisia has decided to advance its official time by
    +# one hour, starting on Sunday, May 1.  Henceforth, Tunisian time will be
    +# UTC+2 instead of UTC+1.  The change will take place at 23:00 UTC next
    +# Saturday."  (My translation)
    +#
    +# From Oscar van Vlijmen (2005-05-02):
    +# LaPresse, the first national daily newspaper ...
    +# 
    +# ... DST for 2005: on: Sun May 1 0h standard time, off: Fri Sept. 30,
    +# 1h standard time.
    +#
    +# From Atef Loukil (2006-03-28):
    +# The daylight saving time will be the same each year:
    +# Beginning      : the last Sunday of March at 02:00
    +# Ending         : the last Sunday of October at 03:00 ...
    +# http://www.tap.info.tn/en/index.php?option=com_content&task=view&id=1188&Itemid=50
    +
    +# From Steffen Thorsen (2009-03-16):
    +# According to several news sources, Tunisia will not observe DST this year.
    +# (Arabic)
    +# 
    +# http://www.elbashayer.com/?page=viewn&nid=42546
    +# 
    +# 
    +# http://www.babnet.net/kiwidetail-15295.asp
    +# 
    +#
    +# We have also confirmed this with the US embassy in Tunisia.
    +# We have a wrap-up about this on the following page:
    +# 
    +# http://www.timeanddate.com/news/time/tunisia-cancels-dst-2009.html
    +# 
    +
    +# From Alexander Krivenyshev (2009-03-17):
    +# Here is a link to Tunis Afrique Presse News Agency
    +#
    +# Standard time to be kept the whole year long (tap.info.tn):
    +#
    +# (in English)
    +# 
    +# http://www.tap.info.tn/en/index.php?option=com_content&task=view&id=26813&Itemid=157
    +# 
    +#
    +# (in Arabic)
    +# 
    +# http://www.tap.info.tn/ar/index.php?option=com_content&task=view&id=61240&Itemid=1
    +# 
    +
    +# From Arthur David Olson (2009--3-18):
    +# The Tunis Afrique Presse News Agency notice contains this: "This measure is due to the fact
    +# that the fasting month of ramadan coincides with the period concerned by summer time.
    +# Therefore, the standard time will be kept unchanged the whole year long."
    +# So foregoing DST seems to be an exception (albeit one that may be repeated in the  future).
    +
    +# From Alexander Krivenyshev (2010-03-27):
    +# According to some news reports Tunis confirmed not to use DST in 2010
    +#
    +# (translation):
    +# "The Tunisian government has decided to abandon DST, which was scheduled on
    +# Sunday...
    +# Tunisian authorities had suspended the DST for the first time last year also
    +# coincided with the month of Ramadan..."
    +#
    +# (in Arabic)
    +# 
    +# http://www.moheet.com/show_news.aspx?nid=358861&pg=1
    +# 
    +# http://www.almadenahnews.com/newss/news.php?c=118&id=38036
    +# or
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_tunis02.html
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Tunisia	1939	only	-	Apr	15	23:00s	1:00	S
    +Rule	Tunisia	1939	only	-	Nov	18	23:00s	0	-
    +Rule	Tunisia	1940	only	-	Feb	25	23:00s	1:00	S
    +Rule	Tunisia	1941	only	-	Oct	 6	 0:00	0	-
    +Rule	Tunisia	1942	only	-	Mar	 9	 0:00	1:00	S
    +Rule	Tunisia	1942	only	-	Nov	 2	 3:00	0	-
    +Rule	Tunisia	1943	only	-	Mar	29	 2:00	1:00	S
    +Rule	Tunisia	1943	only	-	Apr	17	 2:00	0	-
    +Rule	Tunisia	1943	only	-	Apr	25	 2:00	1:00	S
    +Rule	Tunisia	1943	only	-	Oct	 4	 2:00	0	-
    +Rule	Tunisia	1944	1945	-	Apr	Mon>=1	 2:00	1:00	S
    +Rule	Tunisia	1944	only	-	Oct	 8	 0:00	0	-
    +Rule	Tunisia	1945	only	-	Sep	16	 0:00	0	-
    +Rule	Tunisia	1977	only	-	Apr	30	 0:00s	1:00	S
    +Rule	Tunisia	1977	only	-	Sep	24	 0:00s	0	-
    +Rule	Tunisia	1978	only	-	May	 1	 0:00s	1:00	S
    +Rule	Tunisia	1978	only	-	Oct	 1	 0:00s	0	-
    +Rule	Tunisia	1988	only	-	Jun	 1	 0:00s	1:00	S
    +Rule	Tunisia	1988	1990	-	Sep	lastSun	 0:00s	0	-
    +Rule	Tunisia	1989	only	-	Mar	26	 0:00s	1:00	S
    +Rule	Tunisia	1990	only	-	May	 1	 0:00s	1:00	S
    +Rule	Tunisia	2005	only	-	May	 1	 0:00s	1:00	S
    +Rule	Tunisia	2005	only	-	Sep	30	 1:00s	0	-
    +Rule	Tunisia	2006	2008	-	Mar	lastSun	 2:00s	1:00	S
    +Rule	Tunisia	2006	2008	-	Oct	lastSun	 2:00s	0	-
    +
    +# Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
    +# more precise 0:09:21.
    +# Shanks & Pottenger say the 1911 switch was on Mar 9; go with Howse's Mar 11.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Tunis	0:40:44 -	LMT	1881 May 12
    +			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
    +			1:00	Tunisia	CE%sT
    +
    +# Uganda
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Kampala	2:09:40 -	LMT	1928 Jul
    +			3:00	-	EAT	1930
    +			2:30	-	BEAT	1948
    +			2:45	-	BEAUT	1957
    +			3:00	-	EAT
    +
    +# Zambia
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Lusaka	1:53:08 -	LMT	1903 Mar
    +			2:00	-	CAT
    +
    +# Zimbabwe
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Africa/Harare	2:04:12 -	LMT	1903 Mar
    +			2:00	-	CAT
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/antarctica b/jdk/test/sun/util/calendar/zi/tzdata/antarctica
    new file mode 100644
    index 00000000000..64b71d5c052
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/antarctica
    @@ -0,0 +1,436 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# From Paul Eggert (1999-11-15):
    +# To keep things manageable, we list only locations occupied year-round; see
    +# 
    +# COMNAP - Stations and Bases
    +# 
    +# and
    +# 
    +# Summary of the Peri-Antarctic Islands (1998-07-23)
    +# 
    +# for information.
    +# Unless otherwise specified, we have no time zone information.
    +#
    +# Except for the French entries,
    +# I made up all time zone abbreviations mentioned here; corrections welcome!
    +# FORMAT is `zzz' and GMTOFF is 0 for locations while uninhabited.
    +
    +# These rules are stolen from the `southamerica' file.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	ArgAQ	1964	1966	-	Mar	 1	0:00	0	-
    +Rule	ArgAQ	1964	1966	-	Oct	15	0:00	1:00	S
    +Rule	ArgAQ	1967	only	-	Apr	 2	0:00	0	-
    +Rule	ArgAQ	1967	1968	-	Oct	Sun>=1	0:00	1:00	S
    +Rule	ArgAQ	1968	1969	-	Apr	Sun>=1	0:00	0	-
    +Rule	ArgAQ	1974	only	-	Jan	23	0:00	1:00	S
    +Rule	ArgAQ	1974	only	-	May	 1	0:00	0	-
    +Rule	ChileAQ	1972	1986	-	Mar	Sun>=9	3:00u	0	-
    +Rule	ChileAQ	1974	1987	-	Oct	Sun>=9	4:00u	1:00	S
    +Rule	ChileAQ	1987	only	-	Apr	12	3:00u	0	-
    +Rule	ChileAQ	1988	1989	-	Mar	Sun>=9	3:00u	0	-
    +Rule	ChileAQ	1988	only	-	Oct	Sun>=1	4:00u	1:00	S
    +Rule	ChileAQ	1989	only	-	Oct	Sun>=9	4:00u	1:00	S
    +Rule	ChileAQ	1990	only	-	Mar	18	3:00u	0	-
    +Rule	ChileAQ	1990	only	-	Sep	16	4:00u	1:00	S
    +Rule	ChileAQ	1991	1996	-	Mar	Sun>=9	3:00u	0	-
    +Rule	ChileAQ	1991	1997	-	Oct	Sun>=9	4:00u	1:00	S
    +Rule	ChileAQ	1997	only	-	Mar	30	3:00u	0	-
    +Rule	ChileAQ	1998	only	-	Mar	Sun>=9	3:00u	0	-
    +Rule	ChileAQ	1998	only	-	Sep	27	4:00u	1:00	S
    +Rule	ChileAQ	1999	only	-	Apr	 4	3:00u	0	-
    +Rule	ChileAQ	1999	2010	-	Oct	Sun>=9	4:00u	1:00	S
    +Rule	ChileAQ	2000	2007	-	Mar	Sun>=9	3:00u	0	-
    +# N.B.: the end of March 29 in Chile is March 30 in Universal time,
    +# which is used below in specifying the transition.
    +Rule	ChileAQ	2008	only	-	Mar	30	3:00u	0	-
    +Rule	ChileAQ	2009	only	-	Mar	Sun>=9	3:00u	0	-
    +Rule	ChileAQ	2010	only	-	Apr	Sun>=1	3:00u	0	-
    +Rule	ChileAQ	2011	only	-	May	Sun>=2	3:00u	0	-
    +Rule	ChileAQ	2011	only	-	Aug	Sun>=16	4:00u	1:00	S
    +Rule	ChileAQ	2012	only	-	Apr	Sun>=23	3:00u	0	-
    +Rule	ChileAQ	2012	only	-	Sep	Sun>=2	4:00u	1:00	S
    +Rule	ChileAQ	2013	max	-	Mar	Sun>=9	3:00u	0	-
    +Rule	ChileAQ	2013	max	-	Oct	Sun>=9	4:00u	1:00	S
    +
    +# These rules are stolen from the `australasia' file.
    +Rule	AusAQ	1917	only	-	Jan	 1	0:01	1:00	-
    +Rule	AusAQ	1917	only	-	Mar	25	2:00	0	-
    +Rule	AusAQ	1942	only	-	Jan	 1	2:00	1:00	-
    +Rule	AusAQ	1942	only	-	Mar	29	2:00	0	-
    +Rule	AusAQ	1942	only	-	Sep	27	2:00	1:00	-
    +Rule	AusAQ	1943	1944	-	Mar	lastSun	2:00	0	-
    +Rule	AusAQ	1943	only	-	Oct	 3	2:00	1:00	-
    +Rule	ATAQ	1967	only	-	Oct	Sun>=1	2:00s	1:00	-
    +Rule	ATAQ	1968	only	-	Mar	lastSun	2:00s	0	-
    +Rule	ATAQ	1968	1985	-	Oct	lastSun	2:00s	1:00	-
    +Rule	ATAQ	1969	1971	-	Mar	Sun>=8	2:00s	0	-
    +Rule	ATAQ	1972	only	-	Feb	lastSun	2:00s	0	-
    +Rule	ATAQ	1973	1981	-	Mar	Sun>=1	2:00s	0	-
    +Rule	ATAQ	1982	1983	-	Mar	lastSun	2:00s	0	-
    +Rule	ATAQ	1984	1986	-	Mar	Sun>=1	2:00s	0	-
    +Rule	ATAQ	1986	only	-	Oct	Sun>=15	2:00s	1:00	-
    +Rule	ATAQ	1987	1990	-	Mar	Sun>=15	2:00s	0	-
    +Rule	ATAQ	1987	only	-	Oct	Sun>=22	2:00s	1:00	-
    +Rule	ATAQ	1988	1990	-	Oct	lastSun	2:00s	1:00	-
    +Rule	ATAQ	1991	1999	-	Oct	Sun>=1	2:00s	1:00	-
    +Rule	ATAQ	1991	2005	-	Mar	lastSun	2:00s	0	-
    +Rule	ATAQ	2000	only	-	Aug	lastSun	2:00s	1:00	-
    +Rule	ATAQ	2001	max	-	Oct	Sun>=1	2:00s	1:00	-
    +Rule	ATAQ	2006	only	-	Apr	Sun>=1	2:00s	0	-
    +Rule	ATAQ	2007	only	-	Mar	lastSun	2:00s	0	-
    +Rule	ATAQ	2008	max	-	Apr	Sun>=1	2:00s	0	-
    +
    +# Argentina - year-round bases
    +# Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
    +# Esperanza, San Martin Land, -6323-05659, since 1952-12-17
    +# Jubany, Potter Peninsula, King George Island, -6414-0602320, since 1982-01
    +# Marambio, Seymour I, -6414-05637, since 1969-10-29
    +# Orcadas, Laurie I, -6016-04444, since 1904-02-22
    +# San Martin, Debenham I, -6807-06708, since 1951-03-21
    +#	(except 1960-03 / 1976-03-21)
    +
    +# Australia - territories
    +# Heard Island, McDonald Islands (uninhabited)
    +#	previously sealers and scientific personnel wintered
    +#	
    +#	Margaret Turner reports
    +#	 (1999-09-30) that they're UTC+5, with no DST;
    +#	presumably this is when they have visitors.
    +#
    +# year-round bases
    +# Casey, Bailey Peninsula, -6617+11032, since 1969
    +# Davis, Vestfold Hills, -6835+07759, since 1957-01-13
    +#	(except 1964-11 - 1969-02)
    +# Mawson, Holme Bay, -6736+06253, since 1954-02-13
    +
    +# From Steffen Thorsen (2009-03-11):
    +# Three Australian stations in Antarctica have changed their time zone:
    +# Casey moved from UTC+8 to UTC+11
    +# Davis moved from UTC+7 to UTC+5
    +# Mawson moved from UTC+6 to UTC+5
    +# The changes occurred on 2009-10-18 at 02:00 (local times).
    +#
    +# Government source: (Australian Antarctic Division)
    +# 
    +# http://www.aad.gov.au/default.asp?casid=37079
    +# 
    +#
    +# We have more background information here:
    +# 
    +# http://www.timeanddate.com/news/time/antarctica-new-times.html
    +# 
    +
    +# From Steffen Thorsen (2010-03-10):
    +# We got these changes from the Australian Antarctic Division:
    +# - Macquarie Island will stay on UTC+11 for winter and therefore not
    +# switch back from daylight savings time when other parts of Australia do
    +# on 4 April.
    +#
    +# - Casey station reverted to its normal time of UTC+8 on 5 March 2010.
    +# The change to UTC+11 is being considered as a regular summer thing but
    +# has not been decided yet.
    +#
    +# - Davis station will revert to its normal time of UTC+7 at 10 March 2010
    +# 20:00 UTC.
    +#
    +# - Mawson station stays on UTC+5.
    +#
    +# In addition to the Rule changes for Casey/Davis, it means that Macquarie
    +# will no longer be like Hobart and will have to have its own Zone created.
    +#
    +# Background:
    +# 
    +# http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
    +# 
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Antarctica/Casey	0	-	zzz	1969
    +			8:00	-	WST	2009 Oct 18 2:00
    +						# Western (Aus) Standard Time
    +			11:00	-	CAST	2010 Mar 5 2:00
    +						# Casey Time
    +			8:00	-	WST	2011 Oct 28 2:00
    +			11:00	-	CAST	2012 Feb 21 17:00u
    +			8:00	-	WST
    +Zone Antarctica/Davis	0	-	zzz	1957 Jan 13
    +			7:00	-	DAVT	1964 Nov # Davis Time
    +			0	-	zzz	1969 Feb
    +			7:00	-	DAVT	2009 Oct 18 2:00
    +			5:00	-	DAVT	2010 Mar 10 20:00u
    +			7:00	-	DAVT	2011 Oct 28 2:00
    +			5:00	-	DAVT	2012 Feb 21 20:00u
    +			7:00	-	DAVT
    +Zone Antarctica/Mawson	0	-	zzz	1954 Feb 13
    +			6:00	-	MAWT	2009 Oct 18 2:00
    +						# Mawson Time
    +			5:00	-	MAWT
    +Zone Antarctica/Macquarie 0	-	zzz	1911
    +			10:00	-	EST	1916 Oct 1 2:00
    +			10:00	1:00	EST	1917 Feb
    +			10:00	AusAQ	EST	1967
    +			10:00	ATAQ	EST	2010 Apr 4 3:00
    +			11:00	-	MIST	# Macquarie Island Time
    +# References:
    +# 
    +# Casey Weather (1998-02-26)
    +# 
    +# 
    +# Davis Station, Antarctica (1998-02-26)
    +# 
    +# 
    +# Mawson Station, Antarctica (1998-02-25)
    +# 
    +
    +# Brazil - year-round base
    +# Comandante Ferraz, King George Island, -6205+05824, since 1983/4
    +
    +# Chile - year-round bases and towns
    +# Escudero, South Shetland Is, -621157-0585735, since 1994
    +# Presidente Eduadro Frei, King George Island, -6214-05848, since 1969-03-07
    +# General Bernardo O'Higgins, Antarctic Peninsula, -6319-05704, since 1948-02
    +# Capitan Arturo Prat, -6230-05941
    +# Villa Las Estrellas (a town), around the Frei base, since 1984-04-09
    +# These locations have always used Santiago time; use TZ='America/Santiago'.
    +
    +# China - year-round bases
    +# Great Wall, King George Island, -6213-05858, since 1985-02-20
    +# Zhongshan, Larsemann Hills, Prydz Bay, -6922+07623, since 1989-02-26
    +
    +# France - year-round bases
    +#
    +# From Antoine Leca (1997-01-20):
    +# Time data are from Nicole Pailleau at the IFRTP
    +# (French Institute for Polar Research and Technology).
    +# She confirms that French Southern Territories and Terre Adelie bases
    +# don't observe daylight saving time, even if Terre Adelie supplies came
    +# from Tasmania.
    +#
    +# French Southern Territories with year-round inhabitants
    +#
    +# Martin-de-Vivies Base, Amsterdam Island, -374105+0773155, since 1950
    +# Alfred-Faure Base, Crozet Islands, -462551+0515152, since 1964
    +# Port-aux-Francais, Kerguelen Islands, -492110+0701303, since 1951;
    +#	whaling & sealing station operated 1908/1914, 1920/1929, and 1951/1956
    +#
    +# St Paul Island - near Amsterdam, uninhabited
    +#	fishing stations operated variously 1819/1931
    +#
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Indian/Kerguelen	0	-	zzz	1950	# Port-aux-Francais
    +			5:00	-	TFT	# ISO code TF Time
    +#
    +# year-round base in the main continent
    +# Dumont-d'Urville, Ile des Petrels, -6640+14001, since 1956-11
    +#
    +# Another base at Port-Martin, 50km east, began operation in 1947.
    +# It was destroyed by fire on 1952-01-14.
    +#
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Antarctica/DumontDUrville 0 -	zzz	1947
    +			10:00	-	PMT	1952 Jan 14 # Port-Martin Time
    +			0	-	zzz	1956 Nov
    +			10:00	-	DDUT	# Dumont-d'Urville Time
    +# Reference:
    +# 
    +# Dumont d'Urville Station (2005-12-05)
    +# 
    +
    +# Germany - year-round base
    +# Georg von Neumayer, -7039-00815
    +
    +# India - year-round base
    +# Dakshin Gangotri, -7005+01200
    +
    +# Japan - year-round bases
    +# Dome Fuji, -7719+03942
    +# Syowa, -690022+0393524
    +#
    +# From Hideyuki Suzuki (1999-02-06):
    +# In all Japanese stations, +0300 is used as the standard time.
    +#
    +# Syowa station, which is the first antarctic station of Japan,
    +# was established on 1957-01-29.  Since Syowa station is still the main
    +# station of Japan, it's appropriate for the principal location.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Antarctica/Syowa	0	-	zzz	1957 Jan 29
    +			3:00	-	SYOT	# Syowa Time
    +# See:
    +# 
    +# NIPR Antarctic Research Activities (1999-08-17)
    +# 
    +
    +# S Korea - year-round base
    +# King Sejong, King George Island, -6213-05847, since 1988
    +
    +# New Zealand - claims
    +# Balleny Islands (never inhabited)
    +# Scott Island (never inhabited)
    +#
    +# year-round base
    +# Scott, Ross Island, since 1957-01, is like Antarctica/McMurdo.
    +#
    +# These rules for New Zealand are stolen from the `australasia' file.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	NZAQ	1974	only	-	Nov	 3	2:00s	1:00	D
    +Rule	NZAQ	1975	1988	-	Oct	lastSun	2:00s	1:00	D
    +Rule	NZAQ	1989	only	-	Oct	 8	2:00s	1:00	D
    +Rule	NZAQ	1990	2006	-	Oct	Sun>=1	2:00s	1:00	D
    +Rule	NZAQ	1975	only	-	Feb	23	2:00s	0	S
    +Rule	NZAQ	1976	1989	-	Mar	Sun>=1	2:00s	0	S
    +Rule	NZAQ	1990	2007	-	Mar	Sun>=15	2:00s	0	S
    +Rule	NZAQ	2007	max	-	Sep	lastSun	2:00s	1:00	D
    +Rule	NZAQ	2008	max	-	Apr	Sun>=1	2:00s	0	S
    +
    +# Norway - territories
    +# Bouvet (never inhabited)
    +#
    +# claims
    +# Peter I Island (never inhabited)
    +
    +# Poland - year-round base
    +# Arctowski, King George Island, -620945-0582745, since 1977
    +
    +# Russia - year-round bases
    +# Bellingshausen, King George Island, -621159-0585337, since 1968-02-22
    +# Mirny, Davis coast, -6633+09301, since 1956-02
    +# Molodezhnaya, Alasheyev Bay, -6740+04551,
    +#	year-round from 1962-02 to 1999-07-01
    +# Novolazarevskaya, Queen Maud Land, -7046+01150,
    +#	year-round from 1960/61 to 1992
    +
    +# Vostok, since 1957-12-16, temporarily closed 1994-02/1994-11
    +# 
    +# From Craig Mundell (1994-12-15):
    +# Vostok, which is one of the Russian stations, is set on the same
    +# time as Moscow, Russia.
    +#
    +# From Lee Hotz (2001-03-08):
    +# I queried the folks at Columbia who spent the summer at Vostok and this is
    +# what they had to say about time there:
    +# ``in the US Camp (East Camp) we have been on New Zealand (McMurdo)
    +# time, which is 12 hours ahead of GMT. The Russian Station Vostok was
    +# 6 hours behind that (although only 2 miles away, i.e. 6 hours ahead
    +# of GMT). This is a time zone I think two hours east of Moscow. The
    +# natural time zone is in between the two: 8 hours ahead of GMT.''
    +#
    +# From Paul Eggert (2001-05-04):
    +# This seems to be hopelessly confusing, so I asked Lee Hotz about it
    +# in person.  He said that some Antartic locations set their local
    +# time so that noon is the warmest part of the day, and that this
    +# changes during the year and does not necessarily correspond to mean
    +# solar noon.  So the Vostok time might have been whatever the clocks
    +# happened to be during their visit.  So we still don't really know what time
    +# it is at Vostok.  But we'll guess UTC+6.
    +#
    +Zone Antarctica/Vostok	0	-	zzz	1957 Dec 16
    +			6:00	-	VOST	# Vostok time
    +
    +# S Africa - year-round bases
    +# Marion Island, -4653+03752
    +# Sanae, -7141-00250
    +
    +# UK
    +#
    +# British Antarctic Territories (BAT) claims
    +# South Orkney Islands
    +#	scientific station from 1903
    +#	whaling station at Signy I 1920/1926
    +# South Shetland Islands
    +#
    +# year-round bases
    +# Bird Island, South Georgia, -5400-03803, since 1983
    +# Deception Island, -6259-06034, whaling station 1912/1931,
    +#	scientific station 1943/1967,
    +#	previously sealers and a scientific expedition wintered by accident,
    +#	and a garrison was deployed briefly
    +# Halley, Coates Land, -7535-02604, since 1956-01-06
    +#	Halley is on a moving ice shelf and is periodically relocated
    +#	so that it is never more than 10km from its nominal location.
    +# Rothera, Adelaide Island, -6734-6808, since 1976-12-01
    +#
    +# From Paul Eggert (2002-10-22)
    +#  says Rothera is -03 all year.
    +#
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Antarctica/Rothera	0	-	zzz	1976 Dec  1
    +			-3:00	-	ROTT	# Rothera time
    +
    +# Uruguay - year round base
    +# Artigas, King George Island, -621104-0585107
    +
    +# USA - year-round bases
    +#
    +# Palmer, Anvers Island, since 1965 (moved 2 miles in 1968)
    +#
    +# From Ethan Dicks (1996-10-06):
    +# It keeps the same time as Punta Arenas, Chile, because, just like us
    +# and the South Pole, that's the other end of their supply line....
    +# I verified with someone who was there that since 1980,
    +# Palmer has followed Chile.  Prior to that, before the Falklands War,
    +# Palmer used to be supplied from Argentina.
    +#
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Antarctica/Palmer	0	-	zzz	1965
    +			-4:00	ArgAQ	AR%sT	1969 Oct 5
    +			-3:00	ArgAQ	AR%sT	1982 May
    +			-4:00	ChileAQ	CL%sT
    +#
    +#
    +# McMurdo, Ross Island, since 1955-12
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Antarctica/McMurdo	0	-	zzz	1956
    +			12:00	NZAQ	NZ%sT
    +#
    +# Amundsen-Scott, South Pole, continuously occupied since 1956-11-20
    +#
    +# From Paul Eggert (1996-09-03):
    +# Normally it wouldn't have a separate entry, since it's like the
    +# larger Antarctica/McMurdo since 1970, but it's too famous to omit.
    +#
    +# From Chris Carrier (1996-06-27):
    +# Siple, the first commander of the South Pole station,
    +# stated that he would have liked to have kept GMT at the station,
    +# but that he found it more convenient to keep GMT+12
    +# as supplies for the station were coming from McMurdo Sound,
    +# which was on GMT+12 because New Zealand was on GMT+12 all year
    +# at that time (1957).  (Source: Siple's book 90 degrees SOUTH.)
    +#
    +# From Susan Smith
    +# http://www.cybertours.com/whs/pole10.html
    +# (1995-11-13 16:24:56 +1300, no longer available):
    +# We use the same time as McMurdo does.
    +# And they use the same time as Christchurch, NZ does....
    +# One last quirk about South Pole time.
    +# All the electric clocks are usually wrong.
    +# Something about the generators running at 60.1hertz or something
    +# makes all of the clocks run fast.  So every couple of days,
    +# we have to go around and set them back 5 minutes or so.
    +# Maybe if we let them run fast all of the time, we'd get to leave here sooner!!
    +#
    +Link	Antarctica/McMurdo	Antarctica/South_Pole
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/asia b/jdk/test/sun/util/calendar/zi/tzdata/asia
    new file mode 100644
    index 00000000000..9ef3ef8df54
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/asia
    @@ -0,0 +1,2738 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# This data is by no means authoritative; if you think you know better,
    +# go ahead and edit the file (and please send any changes to
    +# tz@elsie.nci.nih.gov for general use in the future).
    +
    +# From Paul Eggert (2006-03-22):
    +#
    +# A good source for time zone historical data outside the U.S. is
    +# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
    +# San Diego: ACS Publications, Inc. (2003).
    +#
    +# Gwillim Law writes that a good source
    +# for recent time zone data is the International Air Transport
    +# Association's Standard Schedules Information Manual (IATA SSIM),
    +# published semiannually.  Law sent in several helpful summaries
    +# of the IATA's data after 1990.
    +#
    +# Except where otherwise noted, Shanks & Pottenger is the source for
    +# entries through 1990, and IATA SSIM is the source for entries afterwards.
    +#
    +# Another source occasionally used is Edward W. Whitman, World Time Differences,
    +# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
    +# I found in the UCLA library.
    +#
    +# A reliable and entertaining source about time zones is
    +# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
    +#
    +# I invented the abbreviations marked `*' in the following table;
    +# the rest are from earlier versions of this file, or from other sources.
    +# Corrections are welcome!
    +#	     std  dst
    +#	     LMT	Local Mean Time
    +#	2:00 EET  EEST	Eastern European Time
    +#	2:00 IST  IDT	Israel
    +#	3:00 AST  ADT	Arabia*
    +#	3:30 IRST IRDT	Iran
    +#	4:00 GST	Gulf*
    +#	5:30 IST	India
    +#	7:00 ICT	Indochina*
    +#	7:00 WIT	west Indonesia
    +#	8:00 CIT	central Indonesia
    +#	8:00 CST	China
    +#	9:00 CJT	Central Japanese Time (1896/1937)*
    +#	9:00 EIT	east Indonesia
    +#	9:00 JST  JDT	Japan
    +#	9:00 KST  KDT	Korea
    +#	9:30 CST	(Australian) Central Standard Time
    +#
    +# See the `europe' file for Russia and Turkey in Asia.
    +
    +# From Guy Harris:
    +# Incorporates data for Singapore from Robert Elz' asia 1.1, as well as
    +# additional information from Tom Yap, Sun Microsystems Intercontinental
    +# Technical Support (including a page from the Official Airline Guide -
    +# Worldwide Edition).  The names for time zones are guesses.
    +
    +###############################################################################
    +
    +# These rules are stolen from the `europe' file.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	EUAsia	1981	max	-	Mar	lastSun	 1:00u	1:00	S
    +Rule	EUAsia	1979	1995	-	Sep	lastSun	 1:00u	0	-
    +Rule	EUAsia	1996	max	-	Oct	lastSun	 1:00u	0	-
    +Rule E-EurAsia	1981	max	-	Mar	lastSun	 0:00	1:00	S
    +Rule E-EurAsia	1979	1995	-	Sep	lastSun	 0:00	0	-
    +Rule E-EurAsia	1996	max	-	Oct	lastSun	 0:00	0	-
    +Rule RussiaAsia	1981	1984	-	Apr	1	 0:00	1:00	S
    +Rule RussiaAsia	1981	1983	-	Oct	1	 0:00	0	-
    +Rule RussiaAsia	1984	1991	-	Sep	lastSun	 2:00s	0	-
    +Rule RussiaAsia	1985	1991	-	Mar	lastSun	 2:00s	1:00	S
    +Rule RussiaAsia	1992	only	-	Mar	lastSat	23:00	1:00	S
    +Rule RussiaAsia	1992	only	-	Sep	lastSat	23:00	0	-
    +Rule RussiaAsia	1993	max	-	Mar	lastSun	 2:00s	1:00	S
    +Rule RussiaAsia	1993	1995	-	Sep	lastSun	 2:00s	0	-
    +Rule RussiaAsia	1996	max	-	Oct	lastSun	 2:00s	0	-
    +
    +# Afghanistan
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Kabul	4:36:48 -	LMT	1890
    +			4:00	-	AFT	1945
    +			4:30	-	AFT
    +
    +# Armenia
    +# From Paul Eggert (2006-03-22):
    +# Shanks & Pottenger have Yerevan switching to 3:00 (with Russian DST)
    +# in spring 1991, then to 4:00 with no DST in fall 1995, then
    +# readopting Russian DST in 1997.  Go with Shanks & Pottenger, even
    +# when they disagree with others.  Edgar Der-Danieliantz
    +# reported (1996-05-04) that Yerevan probably wouldn't use DST
    +# in 1996, though it did use DST in 1995.  IATA SSIM (1991/1998) reports that
    +# Armenia switched from 3:00 to 4:00 in 1998 and observed DST after 1991,
    +# but started switching at 3:00s in 1998.
    +
    +# From Arthur David Olson (2011-06-15):
    +# While Russia abandoned DST in 2011, Armenia may choose to
    +# follow Russia's "old" rules.
    +
    +# From Alexander Krivenyshev (2012-02-10):
    +# According to News Armenia, on Feb 9, 2012,
    +# http://newsarmenia.ru/society/20120209/42609695.html
    +#
    +# The Armenia National Assembly adopted final reading of Amendments to the
    +# Law "On procedure of calculation time on the territory of the Republic of
    +# Armenia" according to which Armenia [is] abolishing Daylight Saving Time.
    +# or
    +# (brief)
    +# http://www.worldtimezone.com/dst_news/dst_news_armenia03.html
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Yerevan	2:58:00 -	LMT	1924 May  2
    +			3:00	-	YERT	1957 Mar    # Yerevan Time
    +			4:00 RussiaAsia YER%sT	1991 Mar 31 2:00s
    +			3:00	1:00	YERST	1991 Sep 23 # independence
    +			3:00 RussiaAsia	AM%sT	1995 Sep 24 2:00s
    +			4:00	-	AMT	1997
    +			4:00 RussiaAsia	AM%sT	2012 Mar 25 2:00s
    +			4:00	-	AMT
    +
    +# Azerbaijan
    +# From Rustam Aliyev of the Azerbaijan Internet Forum (2005-10-23):
    +# According to the resolution of Cabinet of Ministers, 1997
    +# Resolution available at: http://aif.az/docs/daylight_res.pdf
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Azer	1997	max	-	Mar	lastSun	 4:00	1:00	S
    +Rule	Azer	1997	max	-	Oct	lastSun	 5:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Baku	3:19:24 -	LMT	1924 May  2
    +			3:00	-	BAKT	1957 Mar    # Baku Time
    +			4:00 RussiaAsia BAK%sT	1991 Mar 31 2:00s
    +			3:00	1:00	BAKST	1991 Aug 30 # independence
    +			3:00 RussiaAsia	AZ%sT	1992 Sep lastSat 23:00
    +			4:00	-	AZT	1996 # Azerbaijan time
    +			4:00	EUAsia	AZ%sT	1997
    +			4:00	Azer	AZ%sT
    +
    +# Bahrain
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
    +			4:00	-	GST	1972 Jun
    +			3:00	-	AST
    +
    +# Bangladesh
    +# From Alexander Krivenyshev (2009-05-13):
    +# According to newspaper Asian Tribune (May 6, 2009) Bangladesh may introduce
    +# Daylight Saving Time from June 16 to Sept 30
    +#
    +# Bangladesh to introduce daylight saving time likely from June 16
    +# 
    +# http://www.asiantribune.com/?q=node/17288
    +# 
    +# or
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_bangladesh02.html
    +# 
    +#
    +# "... Bangladesh government has decided to switch daylight saving time from
    +# June
    +# 16 till September 30 in a bid to ensure maximum use of daylight to cope with
    +# crippling power crisis. "
    +#
    +# The switch will remain in effect from June 16 to Sept 30 (2009) but if
    +# implemented the next year, it will come in force from April 1, 2010
    +
    +# From Steffen Thorsen (2009-06-02):
    +# They have finally decided now, but changed the start date to midnight between
    +# the 19th and 20th, and they have not set the end date yet.
    +#
    +# Some sources:
    +# 
    +# http://in.reuters.com/article/southAsiaNews/idINIndia-40017620090601
    +# 
    +# 
    +# http://bdnews24.com/details.php?id=85889&cid=2
    +# 
    +#
    +# Our wrap-up:
    +# 
    +# http://www.timeanddate.com/news/time/bangladesh-daylight-saving-2009.html
    +# 
    +
    +# From A. N. M. Kamrus Saadat (2009-06-15):
    +# Finally we've got the official mail regarding DST start time where DST start
    +# time is mentioned as Jun 19 2009, 23:00 from BTRC (Bangladesh
    +# Telecommunication Regulatory Commission).
    +#
    +# No DST end date has been announced yet.
    +
    +# From Alexander Krivenyshev (2009-09-25):
    +# Bangladesh won't go back to Standard Time from October 1, 2009,
    +# instead it will continue DST measure till the cabinet makes a fresh decision.
    +#
    +# Following report by same newspaper-"The Daily Star Friday":
    +# "DST change awaits cabinet decision-Clock won't go back by 1-hr from Oct 1"
    +# 
    +# http://www.thedailystar.net/newDesign/news-details.php?nid=107021
    +# 
    +# or
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html
    +# 
    +
    +# From Steffen Thorsen (2009-10-13):
    +# IANS (Indo-Asian News Service) now reports:
    +# Bangladesh has decided that the clock advanced by an hour to make
    +# maximum use of daylight hours as an energy saving measure would
    +# "continue for an indefinite period."
    +#
    +# One of many places where it is published:
    +# 
    +# http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html
    +# 
    +
    +# From Alexander Krivenyshev (2009-12-24):
    +# According to Bangladesh newspaper "The Daily Star,"
    +# Bangladesh will change its clock back to Standard Time on Dec 31, 2009.
    +#
    +# Clock goes back 1-hr on Dec 31 night.
    +# 
    +# http://www.thedailystar.net/newDesign/news-details.php?nid=119228
    +# 
    +# and
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_bangladesh05.html
    +# 
    +#
    +# "...The government yesterday decided to put the clock back by one hour
    +# on December 31 midnight and the new time will continue until March 31,
    +# 2010 midnight. The decision came at a cabinet meeting at the Prime
    +# Minister's Office last night..."
    +
    +# From Alexander Krivenyshev (2010-03-22):
    +# According to Bangladesh newspaper "The Daily Star,"
    +# Cabinet cancels Daylight Saving Time
    +# 
    +# http://www.thedailystar.net/newDesign/latest_news.php?nid=22817
    +# 
    +# or
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_bangladesh06.html
    +# 
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Dhaka	2009	only	-	Jun	19	23:00	1:00	S
    +Rule	Dhaka	2009	only	-	Dec	31	23:59	0	-
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Dhaka	6:01:40 -	LMT	1890
    +			5:53:20	-	HMT	1941 Oct    # Howrah Mean Time?
    +			6:30	-	BURT	1942 May 15 # Burma Time
    +			5:30	-	IST	1942 Sep
    +			6:30	-	BURT	1951 Sep 30
    +			6:00	-	DACT	1971 Mar 26 # Dacca Time
    +			6:00	-	BDT	2009
    +			6:00	Dhaka	BD%sT
    +
    +# Bhutan
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Thimphu	5:58:36 -	LMT	1947 Aug 15 # or Thimbu
    +			5:30	-	IST	1987 Oct
    +			6:00	-	BTT	# Bhutan Time
    +
    +# British Indian Ocean Territory
    +# Whitman and the 1995 CIA time zone map say 5:00, but the
    +# 1997 and later maps say 6:00.  Assume the switch occurred in 1996.
    +# We have no information as to when standard time was introduced;
    +# assume it occurred in 1907, the same year as Mauritius (which
    +# then contained the Chagos Archipelago).
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Indian/Chagos	4:49:40	-	LMT	1907
    +			5:00	-	IOT	1996 # BIOT Time
    +			6:00	-	IOT
    +
    +# Brunei
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar   # Bandar Seri Begawan
    +			7:30	-	BNT	1933
    +			8:00	-	BNT
    +
    +# Burma / Myanmar
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Rangoon	6:24:40 -	LMT	1880		# or Yangon
    +			6:24:36	-	RMT	1920	   # Rangoon Mean Time?
    +			6:30	-	BURT	1942 May   # Burma Time
    +			9:00	-	JST	1945 May 3
    +			6:30	-	MMT		   # Myanmar Time
    +
    +# Cambodia
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Phnom_Penh	6:59:40 -	LMT	1906 Jun  9
    +			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
    +			7:00	-	ICT	1912 May
    +			8:00	-	ICT	1931 May
    +			7:00	-	ICT
    +
    +# China
    +
    +# From Guy Harris:
    +# People's Republic of China.  Yes, they really have only one time zone.
    +
    +# From Bob Devine (1988-01-28):
    +# No they don't.  See TIME mag, 1986-02-17 p.52.  Even though
    +# China is across 4 physical time zones, before Feb 1, 1986 only the
    +# Peking (Bejing) time zone was recognized.  Since that date, China
    +# has two of 'em -- Peking's and Urumqi (named after the capital of
    +# the Xinjiang Uyghur Autonomous Region).  I don't know about DST for it.
    +#
    +# . . .I just deleted the DST table and this editor makes it too
    +# painful to suck in another copy..  So, here is what I have for
    +# DST start/end dates for Peking's time zone (info from AP):
    +#
    +#     1986 May 4 - Sept 14
    +#     1987 mid-April - ??
    +
    +# From U. S. Naval Observatory (1989-01-19):
    +# CHINA               8 H  AHEAD OF UTC  ALL OF CHINA, INCL TAIWAN
    +# CHINA               9 H  AHEAD OF UTC  APR 17 - SEP 10
    +
    +# From Paul Eggert (2006-03-22):
    +# Shanks & Pottenger write that China (except for Hong Kong and Macau)
    +# has had a single time zone since 1980 May 1, observing summer DST
    +# from 1986 through 1991; this contradicts Devine's
    +# note about Time magazine, though apparently _something_ happened in 1986.
    +# Go with Shanks & Pottenger for now.  I made up names for the other
    +# pre-1980 time zones.
    +
    +# From Shanks & Pottenger:
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Shang	1940	only	-	Jun	 3	0:00	1:00	D
    +Rule	Shang	1940	1941	-	Oct	 1	0:00	0	S
    +Rule	Shang	1941	only	-	Mar	16	0:00	1:00	D
    +Rule	PRC	1986	only	-	May	 4	0:00	1:00	D
    +Rule	PRC	1986	1991	-	Sep	Sun>=11	0:00	0	S
    +Rule	PRC	1987	1991	-	Apr	Sun>=10	0:00	1:00	D
    +
    +# From Anthony Fok (2001-12-20):
    +# BTW, I did some research on-line and found some info regarding these five
    +# historic timezones from some Taiwan websites.  And yes, there are official
    +# Chinese names for these locales (before 1949).
    +#
    +# From Jesper Norgaard Welen (2006-07-14):
    +# I have investigated the timezones around 1970 on the
    +# http://www.astro.com/atlas site [with provinces and county
    +# boundaries summarized below]....  A few other exceptions were two
    +# counties on the Sichuan side of the Xizang-Sichuan border,
    +# counties Dege and Baiyu which lies on the Sichuan side and are
    +# therefore supposed to be GMT+7, Xizang region being GMT+6, but Dege
    +# county is GMT+8 according to astro.com while Baiyu county is GMT+6
    +# (could be true), for the moment I am assuming that those two
    +# counties are mistakes in the astro.com data.
    +
    +# From Paul Eggert (2008-02-11):
    +# I just now checked Google News for western news sources that talk
    +# about China's single time zone, and couldn't find anything before 1986
    +# talking about China being in one time zone.  (That article was: Jim
    +# Mann, "A clumsy embrace for another western custom: China on daylight
    +# time--sort of", Los Angeles Times, 1986-05-05.  By the way, this
    +# article confirms the tz database's data claiming that China began
    +# observing daylight saving time in 1986.
    +#
    +# From Thomas S. Mullaney (2008-02-11):
    +# I think you're combining two subjects that need to treated
    +# separately: daylight savings (which, you're correct, wasn't
    +# implemented until the 1980s) and the unified time zone centered near
    +# Beijing (which was implemented in 1949). Briefly, there was also a
    +# "Lhasa Time" in Tibet and "Urumqi Time" in Xinjiang. The first was
    +# ceased, and the second eventually recognized (again, in the 1980s).
    +#
    +# From Paul Eggert (2008-06-30):
    +# There seems to be a good chance China switched to a single time zone in 1949
    +# rather than in 1980 as Shanks & Pottenger have it, but we don't have a
    +# reliable documentary source saying so yet, so for now we still go with
    +# Shanks & Pottenger.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +# Changbai Time ("Long-white Time", Long-white = Heilongjiang area)
    +# Heilongjiang (except Mohe county), Jilin
    +Zone	Asia/Harbin	8:26:44	-	LMT	1928 # or Haerbin
    +			8:30	-	CHAT	1932 Mar # Changbai Time
    +			8:00	-	CST	1940
    +			9:00	-	CHAT	1966 May
    +			8:30	-	CHAT	1980 May
    +			8:00	PRC	C%sT
    +# Zhongyuan Time ("Central plain Time")
    +# most of China
    +Zone	Asia/Shanghai	8:05:52	-	LMT	1928
    +			8:00	Shang	C%sT	1949
    +			8:00	PRC	C%sT
    +# Long-shu Time (probably due to Long and Shu being two names of that area)
    +# Guangxi, Guizhou, Hainan, Ningxia, Sichuan, Shaanxi, and Yunnan;
    +# most of Gansu; west Inner Mongolia; west Qinghai; and the Guangdong
    +# counties Deqing, Enping, Kaiping, Luoding, Taishan, Xinxing,
    +# Yangchun, Yangjiang, Yu'nan, and Yunfu.
    +Zone	Asia/Chongqing	7:06:20	-	LMT	1928 # or Chungking
    +			7:00	-	LONT	1980 May # Long-shu Time
    +			8:00	PRC	C%sT
    +# Xin-zang Time ("Xinjiang-Tibet Time")
    +# The Gansu counties Aksay, Anxi, Dunhuang, Subei; west Qinghai;
    +# the Guangdong counties  Xuwen, Haikang, Suixi, Lianjiang,
    +# Zhanjiang, Wuchuan, Huazhou, Gaozhou, Maoming, Dianbai, and Xinyi;
    +# east Tibet, including Lhasa, Chamdo, Shigaise, Jimsar, Shawan and Hutubi;
    +# east Xinjiang, including Urumqi, Turpan, Karamay, Korla, Minfeng, Jinghe,
    +# Wusu, Qiemo, Xinyan, Wulanwusu, Jinghe, Yumin, Tacheng, Tuoli, Emin,
    +# Shihezi, Changji, Yanqi, Heshuo, Tuokexun, Tulufan, Shanshan, Hami,
    +# Fukang, Kuitun, Kumukuli, Miquan, Qitai, and Turfan.
    +Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
    +			6:00	-	URUT	1980 May # Urumqi Time
    +			8:00	PRC	C%sT
    +# Kunlun Time
    +# West Tibet, including Pulan, Aheqi, Shufu, Shule;
    +# West Xinjiang, including Aksu, Atushi, Yining, Hetian, Cele, Luopu, Nileke,
    +# Zhaosu, Tekesi, Gongliu, Chabuchaer, Huocheng, Bole, Pishan, Suiding,
    +# and Yarkand.
    +
    +# From Luther Ma (2009-10-17):
    +# Almost all (>99.9%) ethnic Chinese (properly ethnic Han) living in
    +# Xinjiang use Chinese Standard Time. Some are aware of Xinjiang time,
    +# but have no need of it. All planes, trains, and schools function on
    +# what is called "Beijing time." When Han make an appointment in Chinese
    +# they implicitly use Beijing time.
    +#
    +# On the other hand, ethnic Uyghurs, who make up about half the
    +# population of Xinjiang, typically use "Xinjiang time" which is two
    +# hours behind Beijing time, or UTC +0600. The government of the Xinjiang
    +# Uyghur Autonomous Region, (XAUR, or just Xinjiang for short) as well as
    +# local governments such as the Urumqi city government use both times in
    +# publications, referring to what is popularly called Xinjiang time as
    +# "Urumqi time." When Uyghurs make an appointment in the Uyghur language
    +# they almost invariably use Xinjiang time.
    +#
    +# (Their ethnic Han compatriots would typically have no clue of its
    +# widespread use, however, because so extremely few of them are fluent in
    +# Uyghur, comparable to the number of Anglo-Americans fluent in Navajo.)
    +#
    +# (...As with the rest of China there was a brief interval ending in 1990
    +# or 1991 when summer time was in use.  The confusion was severe, with
    +# the province not having dual times but four times in use at the same
    +# time. Some areas remained on standard Xinjiang time or Beijing time and
    +# others moving their clocks ahead.)
    +#
    +# ...an example of an official website using of Urumqi time.
    +#
    +# The first few lines of the Google translation of
    +# 
    +# http://www.fjysgl.gov.cn/show.aspx?id=2379&cid=39
    +# 
    +# (retrieved 2009-10-13)
    +# > Urumqi fire seven people are missing the alleged losses of at least
    +# > 500 million yuan
    +# >
    +# > (Reporter Dong Liu) the day before 20:20 or so (Urumqi Time 18:20),
    +# > Urumqi City Department of International Plaza Luther Qiantang River
    +# > burst fire. As of yesterday, 18:30, Urumqi City Fire officers and men
    +# > have worked continuously for 22 hours...
    +
    +# From Luther Ma (2009-11-19):
    +# With the risk of being redundant to previous answers these are the most common
    +# English "transliterations" (w/o using non-English symbols):
    +#
    +# 1. Wulumuqi...
    +# 2. Kashi...
    +# 3. Urumqi...
    +# 4. Kashgar...
    +# ...
    +# 5. It seems that Uyghurs in Urumqi has been using Xinjiang since at least the
    +# 1960's. I know of one Han, now over 50, who grew up in the surrounding
    +# countryside and used Xinjiang time as a child.
    +#
    +# 6. Likewise for Kashgar and the rest of south Xinjiang I don't know of any
    +# start date for Xinjiang time.
    +#
    +# Without having access to local historical records, nor the ability to legally
    +# publish them, I would go with October 1, 1949, when Xinjiang became the Uyghur
    +# Autonomous Region under the PRC. (Before that Uyghurs, of course, would also
    +# not be using Beijing time, but some local time.)
    +
    +Zone	Asia/Kashgar	5:03:56	-	LMT	1928 # or Kashi or Kaxgar
    +			5:30	-	KAST	1940	 # Kashgar Time
    +			5:00	-	KAST	1980 May
    +			8:00	PRC	C%sT
    +
    +
    +# From Lee Yiu Chung (2009-10-24):
    +# I found there are some mistakes for the...DST rule for Hong
    +# Kong. [According] to the DST record from Hong Kong Observatory (actually,
    +# it is not [an] observatory, but the official meteorological agency of HK,
    +# and also serves as the official timing agency), there are some missing
    +# and incorrect rules. Although the exact switch over time is missing, I
    +# think 3:30 is correct. The official DST record for Hong Kong can be
    +# obtained from
    +# 
    +# http://www.hko.gov.hk/gts/time/Summertime.htm
    +# .
    +
    +# From Arthur David Olson (2009-10-28):
    +# Here are the dates given at
    +# 
    +# http://www.hko.gov.hk/gts/time/Summertime.htm
    +# 
    +# as of 2009-10-28:
    +# Year        Period
    +# 1941        1 Apr to 30 Sep
    +# 1942        Whole year
    +# 1943        Whole year
    +# 1944        Whole year
    +# 1945        Whole year
    +# 1946        20 Apr to 1 Dec
    +# 1947        13 Apr to 30 Dec
    +# 1948        2 May to 31 Oct
    +# 1949        3 Apr to 30 Oct
    +# 1950        2 Apr to 29 Oct
    +# 1951        1 Apr to 28 Oct
    +# 1952        6 Apr to 25 Oct
    +# 1953        5 Apr to 1 Nov
    +# 1954        21 Mar to 31 Oct
    +# 1955        20 Mar to 6 Nov
    +# 1956        18 Mar to 4 Nov
    +# 1957        24 Mar to 3 Nov
    +# 1958        23 Mar to 2 Nov
    +# 1959        22 Mar to 1 Nov
    +# 1960        20 Mar to 6 Nov
    +# 1961        19 Mar to 5 Nov
    +# 1962        18 Mar to 4 Nov
    +# 1963        24 Mar to 3 Nov
    +# 1964        22 Mar to 1 Nov
    +# 1965        18 Apr to 17 Oct
    +# 1966        17 Apr to 16 Oct
    +# 1967        16 Apr to 22 Oct
    +# 1968        21 Apr to 20 Oct
    +# 1969        20 Apr to 19 Oct
    +# 1970        19 Apr to 18 Oct
    +# 1971        18 Apr to 17 Oct
    +# 1972        16 Apr to 22 Oct
    +# 1973        22 Apr to 21 Oct
    +# 1973/74     30 Dec 73 to 20 Oct 74
    +# 1975        20 Apr to 19 Oct
    +# 1976        18 Apr to 17 Oct
    +# 1977        Nil
    +# 1978        Nil
    +# 1979        13 May to 21 Oct
    +# 1980 to Now Nil
    +# The page does not give start or end times of day.
    +# The page does not give a start date for 1942.
    +# The page does not givw an end date for 1945.
    +# The Japanese occupation of Hong Kong began on 1941-12-25.
    +# The Japanese surrender of Hong Kong was signed 1945-09-15.
    +# For lack of anything better, use start of those days as the transition times.
    +
    +# Hong Kong (Xianggang)
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	HK	1941	only	-	Apr	1	3:30	1:00	S
    +Rule	HK	1941	only	-	Sep	30	3:30	0	-
    +Rule	HK	1946	only	-	Apr	20	3:30	1:00	S
    +Rule	HK	1946	only	-	Dec	1	3:30	0	-
    +Rule	HK	1947	only	-	Apr	13	3:30	1:00	S
    +Rule	HK	1947	only	-	Dec	30	3:30	0	-
    +Rule	HK	1948	only	-	May	2	3:30	1:00	S
    +Rule	HK	1948	1951	-	Oct	lastSun	3:30	0	-
    +Rule	HK	1952	only	-	Oct	25	3:30	0	-
    +Rule	HK	1949	1953	-	Apr	Sun>=1	3:30	1:00	S
    +Rule	HK	1953	only	-	Nov	1	3:30	0	-
    +Rule	HK	1954	1964	-	Mar	Sun>=18	3:30	1:00	S
    +Rule	HK	1954	only	-	Oct	31	3:30	0	-
    +Rule	HK	1955	1964	-	Nov	Sun>=1	3:30	0	-
    +Rule	HK	1965	1976	-	Apr	Sun>=16	3:30	1:00	S
    +Rule	HK	1965	1976	-	Oct	Sun>=16	3:30	0	-
    +Rule	HK	1973	only	-	Dec	30	3:30	1:00	S
    +Rule	HK	1979	only	-	May	Sun>=8	3:30	1:00	S
    +Rule	HK	1979	only	-	Oct	Sun>=16	3:30	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Hong_Kong	7:36:36 -	LMT	1904 Oct 30
    +			8:00	HK	HK%sT	1941 Dec 25
    +			9:00	-	JST	1945 Sep 15
    +			8:00	HK	HK%sT
    +
    +###############################################################################
    +
    +# Taiwan
    +
    +# Shanks & Pottenger write that Taiwan observed DST during 1945, when it
    +# was still controlled by Japan.  This is hard to believe, but we don't
    +# have any other information.
    +
    +# From smallufo (2010-04-03):
    +# According to Taiwan's CWB,
    +# 
    +# http://www.cwb.gov.tw/V6/astronomy/cdata/summert.htm
    +# 
    +# Taipei has DST in 1979 between July 1st and Sep 30.
    +
    +# From Arthur David Olson (2010-04-07):
    +# Here's Google's translation of the table at the bottom of the "summert.htm" page:
    +# Decade 	                                                    Name                      Start and end date
    +# Republic of China 34 years to 40 years (AD 1945-1951 years) Summer Time               May 1 to September 30
    +# 41 years of the Republic of China (AD 1952)                 Daylight Saving Time      March 1 to October 31
    +# Republic of China 42 years to 43 years (AD 1953-1954 years) Daylight Saving Time      April 1 to October 31
    +# In the 44 years to 45 years (AD 1955-1956 years)            Daylight Saving Time      April 1 to September 30
    +# Republic of China 46 years to 48 years (AD 1957-1959)       Summer Time               April 1 to September 30
    +# Republic of China 49 years to 50 years (AD 1960-1961)       Summer Time               June 1 to September 30
    +# Republic of China 51 years to 62 years (AD 1962-1973 years) Stop Summer Time
    +# Republic of China 63 years to 64 years (1974-1975 AD)       Daylight Saving Time      April 1 to September 30
    +# Republic of China 65 years to 67 years (1976-1978 AD)       Stop Daylight Saving Time
    +# Republic of China 68 years (AD 1979)                        Daylight Saving Time      July 1 to September 30
    +# Republic of China since 69 years (AD 1980)                  Stop Daylight Saving Time
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Taiwan	1945	1951	-	May	1	0:00	1:00	D
    +Rule	Taiwan	1945	1951	-	Oct	1	0:00	0	S
    +Rule	Taiwan	1952	only	-	Mar	1	0:00	1:00	D
    +Rule	Taiwan	1952	1954	-	Nov	1	0:00	0	S
    +Rule	Taiwan	1953	1959	-	Apr	1	0:00	1:00	D
    +Rule	Taiwan	1955	1961	-	Oct	1	0:00	0	S
    +Rule	Taiwan	1960	1961	-	Jun	1	0:00	1:00	D
    +Rule	Taiwan	1974	1975	-	Apr	1	0:00	1:00	D
    +Rule	Taiwan	1974	1975	-	Oct	1	0:00	0	S
    +Rule	Taiwan	1979	only	-	Jun	30	0:00	1:00	D
    +Rule	Taiwan	1979	only	-	Sep	30	0:00	0	S
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Taipei	8:06:00 -	LMT	1896 # or Taibei or T'ai-pei
    +			8:00	Taiwan	C%sT
    +
    +# Macau (Macao, Aomen)
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Macau	1961	1962	-	Mar	Sun>=16	3:30	1:00	S
    +Rule	Macau	1961	1964	-	Nov	Sun>=1	3:30	0	-
    +Rule	Macau	1963	only	-	Mar	Sun>=16	0:00	1:00	S
    +Rule	Macau	1964	only	-	Mar	Sun>=16	3:30	1:00	S
    +Rule	Macau	1965	only	-	Mar	Sun>=16	0:00	1:00	S
    +Rule	Macau	1965	only	-	Oct	31	0:00	0	-
    +Rule	Macau	1966	1971	-	Apr	Sun>=16	3:30	1:00	S
    +Rule	Macau	1966	1971	-	Oct	Sun>=16	3:30	0	-
    +Rule	Macau	1972	1974	-	Apr	Sun>=15	0:00	1:00	S
    +Rule	Macau	1972	1973	-	Oct	Sun>=15	0:00	0	-
    +Rule	Macau	1974	1977	-	Oct	Sun>=15	3:30	0	-
    +Rule	Macau	1975	1977	-	Apr	Sun>=15	3:30	1:00	S
    +Rule	Macau	1978	1980	-	Apr	Sun>=15	0:00	1:00	S
    +Rule	Macau	1978	1980	-	Oct	Sun>=15	0:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Macau	7:34:20 -	LMT	1912
    +			8:00	Macau	MO%sT	1999 Dec 20 # return to China
    +			8:00	PRC	C%sT
    +
    +
    +###############################################################################
    +
    +# Cyprus
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Cyprus	1975	only	-	Apr	13	0:00	1:00	S
    +Rule	Cyprus	1975	only	-	Oct	12	0:00	0	-
    +Rule	Cyprus	1976	only	-	May	15	0:00	1:00	S
    +Rule	Cyprus	1976	only	-	Oct	11	0:00	0	-
    +Rule	Cyprus	1977	1980	-	Apr	Sun>=1	0:00	1:00	S
    +Rule	Cyprus	1977	only	-	Sep	25	0:00	0	-
    +Rule	Cyprus	1978	only	-	Oct	2	0:00	0	-
    +Rule	Cyprus	1979	1997	-	Sep	lastSun	0:00	0	-
    +Rule	Cyprus	1981	1998	-	Mar	lastSun	0:00	1:00	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Nicosia	2:13:28 -	LMT	1921 Nov 14
    +			2:00	Cyprus	EE%sT	1998 Sep
    +			2:00	EUAsia	EE%sT
    +# IATA SSIM (1998-09) has Cyprus using EU rules for the first time.
    +
    +# Classically, Cyprus belongs to Asia; e.g. see Herodotus, Histories, I.72.
    +# However, for various reasons many users expect to find it under Europe.
    +Link	Asia/Nicosia	Europe/Nicosia
    +
    +# Georgia
    +# From Paul Eggert (1994-11-19):
    +# Today's _Economist_ (p 60) reports that Georgia moved its clocks forward
    +# an hour recently, due to a law proposed by Zurab Murvanidze,
    +# an MP who went on a hunger strike for 11 days to force discussion about it!
    +# We have no details, but we'll guess they didn't move the clocks back in fall.
    +#
    +# From Mathew Englander, quoting AP (1996-10-23 13:05-04):
    +# Instead of putting back clocks at the end of October, Georgia
    +# will stay on daylight savings time this winter to save energy,
    +# President Eduard Shevardnadze decreed Wednesday.
    +#
    +# From the BBC via Joseph S. Myers (2004-06-27):
    +#
    +# Georgia moved closer to Western Europe on Sunday...  The former Soviet
    +# republic has changed its time zone back to that of Moscow.  As a result it
    +# is now just four hours ahead of Greenwich Mean Time, rather than five hours
    +# ahead.  The switch was decreed by the pro-Western president of Georgia,
    +# Mikhail Saakashvili, who said the change was partly prompted by the process
    +# of integration into Europe.
    +
    +# From Teimuraz Abashidze (2005-11-07):
    +# Government of Georgia ... decided to NOT CHANGE daylight savings time on
    +# [Oct.] 30, as it was done before during last more than 10 years.
    +# Currently, we are in fact GMT +4:00, as before 30 October it was GMT
    +# +3:00.... The problem is, there is NO FORMAL LAW or governmental document
    +# about it.  As far as I can find, I was told, that there is no document,
    +# because we just DIDN'T ISSUE document about switching to winter time....
    +# I don't know what can be done, especially knowing that some years ago our
    +# DST rules where changed THREE TIMES during one month.
    +
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Tbilisi	2:59:16 -	LMT	1880
    +			2:59:16	-	TBMT	1924 May  2 # Tbilisi Mean Time
    +			3:00	-	TBIT	1957 Mar    # Tbilisi Time
    +			4:00 RussiaAsia TBI%sT	1991 Mar 31 2:00s
    +			3:00	1:00	TBIST	1991 Apr  9 # independence
    +			3:00 RussiaAsia GE%sT	1992 # Georgia Time
    +			3:00 E-EurAsia	GE%sT	1994 Sep lastSun
    +			4:00 E-EurAsia	GE%sT	1996 Oct lastSun
    +			4:00	1:00	GEST	1997 Mar lastSun
    +			4:00 E-EurAsia	GE%sT	2004 Jun 27
    +			3:00 RussiaAsia	GE%sT	2005 Mar lastSun 2:00
    +			4:00	-	GET
    +
    +# East Timor
    +
    +# See Indonesia for the 1945 transition.
    +
    +# From Joao Carrascalao, brother of the former governor of East Timor, in
    +# 
    +# East Timor may be late for its millennium
    +#  (1999-12-26/31):
    +# Portugal tried to change the time forward in 1974 because the sun
    +# rises too early but the suggestion raised a lot of problems with the
    +# Timorese and I still don't think it would work today because it
    +# conflicts with their way of life.
    +
    +# From Paul Eggert (2000-12-04):
    +# We don't have any record of the above attempt.
    +# Most likely our records are incomplete, but we have no better data.
    +
    +# 
    +# From Manoel de Almeida e Silva, Deputy Spokesman for the UN Secretary-General
    +# (2000-08-16):
    +# The Cabinet of the East Timor Transition Administration decided
    +# today to advance East Timor's time by one hour.  The time change,
    +# which will be permanent, with no seasonal adjustment, will happen at
    +# midnight on Saturday, September 16.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Dili	8:22:20 -	LMT	1912
    +			8:00	-	TLT	1942 Feb 21 23:00 # E Timor Time
    +			9:00	-	JST	1945 Sep 23
    +			9:00	-	TLT	1976 May  3
    +			8:00	-	CIT	2000 Sep 17 00:00
    +			9:00	-	TLT
    +
    +# India
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Kolkata	5:53:28 -	LMT	1880	# Kolkata
    +			5:53:20	-	HMT	1941 Oct    # Howrah Mean Time?
    +			6:30	-	BURT	1942 May 15 # Burma Time
    +			5:30	-	IST	1942 Sep
    +			5:30	1:00	IST	1945 Oct 15
    +			5:30	-	IST
    +# The following are like Asia/Kolkata:
    +#	Andaman Is
    +#	Lakshadweep (Laccadive, Minicoy and Amindivi Is)
    +#	Nicobar Is
    +
    +# Indonesia
    +#
    +# From Gwillim Law (2001-05-28), overriding Shanks & Pottenger:
    +# 
    +# says that Indonesia's time zones changed on 1988-01-01.  Looking at some
    +# time zone maps, I think that must refer to Western Borneo (Kalimantan Barat
    +# and Kalimantan Tengah) switching from UTC+8 to UTC+7.
    +#
    +# From Paul Eggert (2007-03-10):
    +# Here is another correction to Shanks & Pottenger.
    +# JohnTWB writes that Japanese forces did not surrender control in
    +# Indonesia until 1945-09-01 00:00 at the earliest (in Jakarta) and
    +# other formal surrender ceremonies were September 9, 11, and 13, plus
    +# September 12 for the regional surrender to Mountbatten in Singapore.
    +# These would be the earliest possible times for a change.
    +# Regimes horaires pour le monde entier, by Henri Le Corre, (Editions
    +# Traditionnelles, 1987, Paris) says that Java and Madura switched
    +# from JST to UTC+07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura
    +# (Hollandia).  For now, assume all Indonesian locations other than Jayapura
    +# switched on 1945-09-23.
    +#
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Asia/Jakarta	7:07:12 -	LMT	1867 Aug 10
    +# Shanks & Pottenger say the next transition was at 1924 Jan 1 0:13,
    +# but this must be a typo.
    +			7:07:12	-	JMT	1923 Dec 31 23:47:12 # Jakarta
    +			7:20	-	JAVT	1932 Nov	 # Java Time
    +			7:30	-	WIT	1942 Mar 23
    +			9:00	-	JST	1945 Sep 23
    +			7:30	-	WIT	1948 May
    +			8:00	-	WIT	1950 May
    +			7:30	-	WIT	1964
    +			7:00	-	WIT
    +Zone Asia/Pontianak	7:17:20	-	LMT	1908 May
    +			7:17:20	-	PMT	1932 Nov    # Pontianak MT
    +			7:30	-	WIT	1942 Jan 29
    +			9:00	-	JST	1945 Sep 23
    +			7:30	-	WIT	1948 May
    +			8:00	-	WIT	1950 May
    +			7:30	-	WIT	1964
    +			8:00	-	CIT	1988 Jan  1
    +			7:00	-	WIT
    +Zone Asia/Makassar	7:57:36 -	LMT	1920
    +			7:57:36	-	MMT	1932 Nov    # Macassar MT
    +			8:00	-	CIT	1942 Feb  9
    +			9:00	-	JST	1945 Sep 23
    +			8:00	-	CIT
    +Zone Asia/Jayapura	9:22:48 -	LMT	1932 Nov
    +			9:00	-	EIT	1944 Sep  1
    +			9:30	-	CST	1964
    +			9:00	-	EIT
    +
    +# Iran
    +
    +# From Roozbeh Pournader (2003-03-15):
    +# This is an English translation of what I just found (originally in Persian).
    +# The Gregorian dates in brackets are mine:
    +#
    +#	Official Newspaper No. 13548-1370/6/25 [1991-09-16]
    +#	No. 16760/T233 H				1370/6/10 [1991-09-01]
    +#
    +#	The Rule About Change of the Official Time of the Country
    +#
    +#	The Board of Ministers, in the meeting dated 1370/5/23 [1991-08-14],
    +#	based on the suggestion number 2221/D dated 1370/4/22 [1991-07-13]
    +#	of the Country's Organization for Official and Employment Affairs,
    +#	and referring to the law for equating the working hours of workers
    +#	and officers in the whole country dated 1359/4/23 [1980-07-14], and
    +#	for synchronizing the official times of the country, agreed that:
    +#
    +#	The official time of the country will should move forward one hour
    +#	at the 24[:00] hours of the first day of Farvardin and should return
    +#	to its previous state at the 24[:00] hours of the 30th day of
    +#	Shahrivar.
    +#
    +#	First Deputy to the President - Hassan Habibi
    +#
    +# From personal experience, that agrees with what has been followed
    +# for at least the last 5 years.  Before that, for a few years, the
    +# date used was the first Thursday night of Farvardin and the last
    +# Thursday night of Shahrivar, but I can't give exact dates....
    +# I have also changed the abbreviations to what is considered correct
    +# here in Iran, IRST for regular time and IRDT for daylight saving time.
    +#
    +# From Roozbeh Pournader (2005-04-05):
    +# The text of the Iranian law, in effect since 1925, clearly mentions
    +# that the true solar year is the measure, and there is no arithmetic
    +# leap year calculation involved.  There has never been any serious
    +# plan to change that law....
    +#
    +# From Paul Eggert (2006-03-22):
    +# Go with Shanks & Pottenger before Sept. 1991, and with Pournader thereafter.
    +# I used Ed Reingold's cal-persia in GNU Emacs 21.2 to check Persian dates,
    +# stopping after 2037 when 32-bit time_t's overflow.
    +# That cal-persia used Birashk's approximation, which disagrees with the solar
    +# calendar predictions for the year 2025, so I corrected those dates by hand.
    +#
    +# From Oscar van Vlijmen (2005-03-30), writing about future
    +# discrepancies between cal-persia and the Iranian calendar:
    +# For 2091 solar-longitude-after yields 2091-03-20 08:40:07.7 UT for
    +# the vernal equinox and that gets so close to 12:00 some local
    +# Iranian time that the definition of the correct location needs to be
    +# known exactly, amongst other factors.  2157 is even closer:
    +# 2157-03-20 08:37:15.5 UT.  But the Gregorian year 2025 should give
    +# no interpretation problem whatsoever.  By the way, another instant
    +# in the near future where there will be a discrepancy between
    +# arithmetical and astronomical Iranian calendars will be in 2058:
    +# vernal equinox on 2058-03-20 09:03:05.9 UT.  The Java version of
    +# Reingold's/Dershowitz' calculator gives correctly the Gregorian date
    +# 2058-03-21 for 1 Farvardin 1437 (astronomical).
    +#
    +# From Steffen Thorsen (2006-03-22):
    +# Several of my users have reported that Iran will not observe DST anymore:
    +# http://www.irna.ir/en/news/view/line-17/0603193812164948.htm
    +#
    +# From Reuters (2007-09-16), with a heads-up from Jesper Norgaard Welen:
    +# ... the Guardian Council ... approved a law on Sunday to re-introduce
    +# daylight saving time ...
    +# http://uk.reuters.com/article/oilRpt/idUKBLA65048420070916
    +#
    +# From Roozbeh Pournader (2007-11-05):
    +# This is quoted from Official Gazette of the Islamic Republic of
    +# Iran, Volume 63, Number 18242, dated Tuesday 1386/6/24
    +# [2007-10-16]. I am doing the best translation I can:...
    +# The official time of the country will be moved forward for one hour
    +# on the 24 hours of the first day of the month of Farvardin and will
    +# be changed back to its previous state on the 24 hours of the
    +# thirtieth day of Shahrivar.
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Iran	1978	1980	-	Mar	21	0:00	1:00	D
    +Rule	Iran	1978	only	-	Oct	21	0:00	0	S
    +Rule	Iran	1979	only	-	Sep	19	0:00	0	S
    +Rule	Iran	1980	only	-	Sep	23	0:00	0	S
    +Rule	Iran	1991	only	-	May	 3	0:00	1:00	D
    +Rule	Iran	1992	1995	-	Mar	22	0:00	1:00	D
    +Rule	Iran	1991	1995	-	Sep	22	0:00	0	S
    +Rule	Iran	1996	only	-	Mar	21	0:00	1:00	D
    +Rule	Iran	1996	only	-	Sep	21	0:00	0	S
    +Rule	Iran	1997	1999	-	Mar	22	0:00	1:00	D
    +Rule	Iran	1997	1999	-	Sep	22	0:00	0	S
    +Rule	Iran	2000	only	-	Mar	21	0:00	1:00	D
    +Rule	Iran	2000	only	-	Sep	21	0:00	0	S
    +Rule	Iran	2001	2003	-	Mar	22	0:00	1:00	D
    +Rule	Iran	2001	2003	-	Sep	22	0:00	0	S
    +Rule	Iran	2004	only	-	Mar	21	0:00	1:00	D
    +Rule	Iran	2004	only	-	Sep	21	0:00	0	S
    +Rule	Iran	2005	only	-	Mar	22	0:00	1:00	D
    +Rule	Iran	2005	only	-	Sep	22	0:00	0	S
    +Rule	Iran	2008	only	-	Mar	21	0:00	1:00	D
    +Rule	Iran	2008	only	-	Sep	21	0:00	0	S
    +Rule	Iran	2009	2011	-	Mar	22	0:00	1:00	D
    +Rule	Iran	2009	2011	-	Sep	22	0:00	0	S
    +Rule	Iran	2012	only	-	Mar	21	0:00	1:00	D
    +Rule	Iran	2012	only	-	Sep	21	0:00	0	S
    +Rule	Iran	2013	2015	-	Mar	22	0:00	1:00	D
    +Rule	Iran	2013	2015	-	Sep	22	0:00	0	S
    +Rule	Iran	2016	only	-	Mar	21	0:00	1:00	D
    +Rule	Iran	2016	only	-	Sep	21	0:00	0	S
    +Rule	Iran	2017	2019	-	Mar	22	0:00	1:00	D
    +Rule	Iran	2017	2019	-	Sep	22	0:00	0	S
    +Rule	Iran	2020	only	-	Mar	21	0:00	1:00	D
    +Rule	Iran	2020	only	-	Sep	21	0:00	0	S
    +Rule	Iran	2021	2023	-	Mar	22	0:00	1:00	D
    +Rule	Iran	2021	2023	-	Sep	22	0:00	0	S
    +Rule	Iran	2024	only	-	Mar	21	0:00	1:00	D
    +Rule	Iran	2024	only	-	Sep	21	0:00	0	S
    +Rule	Iran	2025	2027	-	Mar	22	0:00	1:00	D
    +Rule	Iran	2025	2027	-	Sep	22	0:00	0	S
    +Rule	Iran	2028	2029	-	Mar	21	0:00	1:00	D
    +Rule	Iran	2028	2029	-	Sep	21	0:00	0	S
    +Rule	Iran	2030	2031	-	Mar	22	0:00	1:00	D
    +Rule	Iran	2030	2031	-	Sep	22	0:00	0	S
    +Rule	Iran	2032	2033	-	Mar	21	0:00	1:00	D
    +Rule	Iran	2032	2033	-	Sep	21	0:00	0	S
    +Rule	Iran	2034	2035	-	Mar	22	0:00	1:00	D
    +Rule	Iran	2034	2035	-	Sep	22	0:00	0	S
    +Rule	Iran	2036	2037	-	Mar	21	0:00	1:00	D
    +Rule	Iran	2036	2037	-	Sep	21	0:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Tehran	3:25:44	-	LMT	1916
    +			3:25:44	-	TMT	1946	# Tehran Mean Time
    +			3:30	-	IRST	1977 Nov
    +			4:00	Iran	IR%sT	1979
    +			3:30	Iran	IR%sT
    +
    +
    +# Iraq
    +#
    +# From Jonathan Lennox (2000-06-12):
    +# An article in this week's Economist ("Inside the Saddam-free zone", p. 50 in
    +# the U.S. edition) on the Iraqi Kurds contains a paragraph:
    +# "The three northern provinces ... switched their clocks this spring and
    +# are an hour ahead of Baghdad."
    +#
    +# But Rives McDow (2000-06-18) quotes a contact in Iraqi-Kurdistan as follows:
    +# In the past, some Kurdish nationalists, as a protest to the Iraqi
    +# Government, did not adhere to daylight saving time.  They referred
    +# to daylight saving as Saddam time.  But, as of today, the time zone
    +# in Iraqi-Kurdistan is on standard time with Baghdad, Iraq.
    +#
    +# So we'll ignore the Economist's claim.
    +
    +# From Steffen Thorsen (2008-03-10):
    +# The cabinet in Iraq abolished DST last week, according to the following
    +# news sources (in Arabic):
    +# 
    +# http://www.aljeeran.net/wesima_articles/news-20080305-98602.html
    +# 
    +# 
    +# http://www.aswataliraq.info/look/article.tpl?id=2047&IdLanguage=17&IdPublication=4&NrArticle=71743&NrIssue=1&NrSection=10
    +# 
    +#
    +# We have published a short article in English about the change:
    +# 
    +# http://www.timeanddate.com/news/time/iraq-dumps-daylight-saving.html
    +# 
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Iraq	1982	only	-	May	1	0:00	1:00	D
    +Rule	Iraq	1982	1984	-	Oct	1	0:00	0	S
    +Rule	Iraq	1983	only	-	Mar	31	0:00	1:00	D
    +Rule	Iraq	1984	1985	-	Apr	1	0:00	1:00	D
    +Rule	Iraq	1985	1990	-	Sep	lastSun	1:00s	0	S
    +Rule	Iraq	1986	1990	-	Mar	lastSun	1:00s	1:00	D
    +# IATA SSIM (1991/1996) says Apr 1 12:01am UTC; guess the `:01' is a typo.
    +# Shanks & Pottenger say Iraq did not observe DST 1992/1997; ignore this.
    +#
    +Rule	Iraq	1991	2007	-	Apr	 1	3:00s	1:00	D
    +Rule	Iraq	1991	2007	-	Oct	 1	3:00s	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Baghdad	2:57:40	-	LMT	1890
    +			2:57:36	-	BMT	1918	    # Baghdad Mean Time?
    +			3:00	-	AST	1982 May
    +			3:00	Iraq	A%sT
    +
    +
    +###############################################################################
    +
    +# Israel
    +
    +# From Ephraim Silverberg (2001-01-11):
    +#
    +# I coined "IST/IDT" circa 1988.  Until then there were three
    +# different abbreviations in use:
    +#
    +# JST  Jerusalem Standard Time [Danny Braniss, Hebrew University]
    +# IZT  Israel Zonal (sic) Time [Prof. Haim Papo, Technion]
    +# EEST Eastern Europe Standard Time [used by almost everyone else]
    +#
    +# Since timezones should be called by country and not capital cities,
    +# I ruled out JST.  As Israel is in Asia Minor and not Eastern Europe,
    +# EEST was equally unacceptable.  Since "zonal" was not compatible with
    +# any other timezone abbreviation, I felt that 'IST' was the way to go
    +# and, indeed, it has received almost universal acceptance in timezone
    +# settings in Israeli computers.
    +#
    +# In any case, I am happy to share timezone abbreviations with India,
    +# high on my favorite-country list (and not only because my wife's
    +# family is from India).
    +
    +# From Shanks & Pottenger:
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Zion	1940	only	-	Jun	 1	0:00	1:00	D
    +Rule	Zion	1942	1944	-	Nov	 1	0:00	0	S
    +Rule	Zion	1943	only	-	Apr	 1	2:00	1:00	D
    +Rule	Zion	1944	only	-	Apr	 1	0:00	1:00	D
    +Rule	Zion	1945	only	-	Apr	16	0:00	1:00	D
    +Rule	Zion	1945	only	-	Nov	 1	2:00	0	S
    +Rule	Zion	1946	only	-	Apr	16	2:00	1:00	D
    +Rule	Zion	1946	only	-	Nov	 1	0:00	0	S
    +Rule	Zion	1948	only	-	May	23	0:00	2:00	DD
    +Rule	Zion	1948	only	-	Sep	 1	0:00	1:00	D
    +Rule	Zion	1948	1949	-	Nov	 1	2:00	0	S
    +Rule	Zion	1949	only	-	May	 1	0:00	1:00	D
    +Rule	Zion	1950	only	-	Apr	16	0:00	1:00	D
    +Rule	Zion	1950	only	-	Sep	15	3:00	0	S
    +Rule	Zion	1951	only	-	Apr	 1	0:00	1:00	D
    +Rule	Zion	1951	only	-	Nov	11	3:00	0	S
    +Rule	Zion	1952	only	-	Apr	20	2:00	1:00	D
    +Rule	Zion	1952	only	-	Oct	19	3:00	0	S
    +Rule	Zion	1953	only	-	Apr	12	2:00	1:00	D
    +Rule	Zion	1953	only	-	Sep	13	3:00	0	S
    +Rule	Zion	1954	only	-	Jun	13	0:00	1:00	D
    +Rule	Zion	1954	only	-	Sep	12	0:00	0	S
    +Rule	Zion	1955	only	-	Jun	11	2:00	1:00	D
    +Rule	Zion	1955	only	-	Sep	11	0:00	0	S
    +Rule	Zion	1956	only	-	Jun	 3	0:00	1:00	D
    +Rule	Zion	1956	only	-	Sep	30	3:00	0	S
    +Rule	Zion	1957	only	-	Apr	29	2:00	1:00	D
    +Rule	Zion	1957	only	-	Sep	22	0:00	0	S
    +Rule	Zion	1974	only	-	Jul	 7	0:00	1:00	D
    +Rule	Zion	1974	only	-	Oct	13	0:00	0	S
    +Rule	Zion	1975	only	-	Apr	20	0:00	1:00	D
    +Rule	Zion	1975	only	-	Aug	31	0:00	0	S
    +Rule	Zion	1985	only	-	Apr	14	0:00	1:00	D
    +Rule	Zion	1985	only	-	Sep	15	0:00	0	S
    +Rule	Zion	1986	only	-	May	18	0:00	1:00	D
    +Rule	Zion	1986	only	-	Sep	 7	0:00	0	S
    +Rule	Zion	1987	only	-	Apr	15	0:00	1:00	D
    +Rule	Zion	1987	only	-	Sep	13	0:00	0	S
    +Rule	Zion	1988	only	-	Apr	 9	0:00	1:00	D
    +Rule	Zion	1988	only	-	Sep	 3	0:00	0	S
    +
    +# From Ephraim Silverberg
    +# (1997-03-04, 1998-03-16, 1998-12-28, 2000-01-17, 2000-07-25, 2004-12-22,
    +# and 2005-02-17):
    +
    +# According to the Office of the Secretary General of the Ministry of
    +# Interior, there is NO set rule for Daylight-Savings/Standard time changes.
    +# One thing is entrenched in law, however: that there must be at least 150
    +# days of daylight savings time annually.  From 1993-1998, the change to
    +# daylight savings time was on a Friday morning from midnight IST to
    +# 1 a.m IDT; up until 1998, the change back to standard time was on a
    +# Saturday night from midnight daylight savings time to 11 p.m. standard
    +# time.  1996 is an exception to this rule where the change back to standard
    +# time took place on Sunday night instead of Saturday night to avoid
    +# conflicts with the Jewish New Year.  In 1999, the change to
    +# daylight savings time was still on a Friday morning but from
    +# 2 a.m. IST to 3 a.m. IDT; furthermore, the change back to standard time
    +# was also on a Friday morning from 2 a.m. IDT to 1 a.m. IST for
    +# 1999 only.  In the year 2000, the change to daylight savings time was
    +# similar to 1999, but although the change back will be on a Friday, it
    +# will take place from 1 a.m. IDT to midnight IST.  Starting in 2001, all
    +# changes to/from will take place at 1 a.m. old time, but now there is no
    +# rule as to what day of the week it will take place in as the start date
    +# (except in 2003) is the night after the Passover Seder (i.e. the eve
    +# of the 16th of Nisan in the lunar Hebrew calendar) and the end date
    +# (except in 2002) is three nights before Yom Kippur [Day of Atonement]
    +# (the eve of the 7th of Tishrei in the lunar Hebrew calendar).
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Zion	1989	only	-	Apr	30	0:00	1:00	D
    +Rule	Zion	1989	only	-	Sep	 3	0:00	0	S
    +Rule	Zion	1990	only	-	Mar	25	0:00	1:00	D
    +Rule	Zion	1990	only	-	Aug	26	0:00	0	S
    +Rule	Zion	1991	only	-	Mar	24	0:00	1:00	D
    +Rule	Zion	1991	only	-	Sep	 1	0:00	0	S
    +Rule	Zion	1992	only	-	Mar	29	0:00	1:00	D
    +Rule	Zion	1992	only	-	Sep	 6	0:00	0	S
    +Rule	Zion	1993	only	-	Apr	 2	0:00	1:00	D
    +Rule	Zion	1993	only	-	Sep	 5	0:00	0	S
    +
    +# The dates for 1994-1995 were obtained from Office of the Spokeswoman for the
    +# Ministry of Interior, Jerusalem, Israel.  The spokeswoman can be reached by
    +# calling the office directly at 972-2-6701447 or 972-2-6701448.
    +
    +# Rule	NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
    +Rule	Zion	1994	only	-	Apr	 1	0:00	1:00	D
    +Rule	Zion	1994	only	-	Aug	28	0:00	0	S
    +Rule	Zion	1995	only	-	Mar	31	0:00	1:00	D
    +Rule	Zion	1995	only	-	Sep	 3	0:00	0	S
    +
    +# The dates for 1996 were determined by the Minister of Interior of the
    +# time, Haim Ramon.  The official announcement regarding 1996-1998
    +# (with the dates for 1997-1998 no longer being relevant) can be viewed at:
    +#
    +#   ftp://ftp.cs.huji.ac.il/pub/tz/announcements/1996-1998.ramon.ps.gz
    +#
    +# The dates for 1997-1998 were altered by his successor, Rabbi Eli Suissa.
    +#
    +# The official announcements for the years 1997-1999 can be viewed at:
    +#
    +#   ftp://ftp.cs.huji.ac.il/pub/tz/announcements/YYYY.ps.gz
    +#
    +#       where YYYY is the relevant year.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Zion	1996	only	-	Mar	15	0:00	1:00	D
    +Rule	Zion	1996	only	-	Sep	16	0:00	0	S
    +Rule	Zion	1997	only	-	Mar	21	0:00	1:00	D
    +Rule	Zion	1997	only	-	Sep	14	0:00	0	S
    +Rule	Zion	1998	only	-	Mar	20	0:00	1:00	D
    +Rule	Zion	1998	only	-	Sep	 6	0:00	0	S
    +Rule	Zion	1999	only	-	Apr	 2	2:00	1:00	D
    +Rule	Zion	1999	only	-	Sep	 3	2:00	0	S
    +
    +# The Knesset Interior Committee has changed the dates for 2000 for
    +# the third time in just over a year and have set new dates for the
    +# years 2001-2004 as well.
    +#
    +# The official announcement for the start date of 2000 can be viewed at:
    +#
    +#	ftp://ftp.cs.huji.ac.il/pub/tz/announcements/2000-start.ps.gz
    +#
    +# The official announcement for the end date of 2000 and the dates
    +# for the years 2001-2004 can be viewed at:
    +#
    +#	ftp://ftp.cs.huji.ac.il/pub/tz/announcements/2000-2004.ps.gz
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Zion	2000	only	-	Apr	14	2:00	1:00	D
    +Rule	Zion	2000	only	-	Oct	 6	1:00	0	S
    +Rule	Zion	2001	only	-	Apr	 9	1:00	1:00	D
    +Rule	Zion	2001	only	-	Sep	24	1:00	0	S
    +Rule	Zion	2002	only	-	Mar	29	1:00	1:00	D
    +Rule	Zion	2002	only	-	Oct	 7	1:00	0	S
    +Rule	Zion	2003	only	-	Mar	28	1:00	1:00	D
    +Rule	Zion	2003	only	-	Oct	 3	1:00	0	S
    +Rule	Zion	2004	only	-	Apr	 7	1:00	1:00	D
    +Rule	Zion	2004	only	-	Sep	22	1:00	0	S
    +
    +# The proposed law agreed upon by the Knesset Interior Committee on
    +# 2005-02-14 is that, for 2005 and beyond, DST starts at 02:00 the
    +# last Friday before April 2nd (i.e. the last Friday in March or April
    +# 1st itself if it falls on a Friday) and ends at 02:00 on the Saturday
    +# night _before_ the fast of Yom Kippur.
    +#
    +# Those who can read Hebrew can view the announcement at:
    +#
    +#	ftp://ftp.cs.huji.ac.il/pub/tz/announcements/2005+beyond.ps
    +
    +# From Paul Eggert (2012-10-26):
    +# I used Ephraim Silverberg's dst-israel.el program
    +#  (2005-02-20)
    +# along with Ed Reingold's cal-hebrew in GNU Emacs 21.4,
    +# to generate the transitions from 2005 through 2012.
    +# (I replaced "lastFri" with "Fri>=26" by hand.)
    +# The spring transitions all correspond to the following Rule:
    +#
    +# Rule	Zion	2005	2012	-	Mar	Fri>=26	2:00	1:00	D
    +#
    +# but older zic implementations (e.g., Solaris 8) do not support
    +# "Fri>=26" to mean April 1 in years like 2005, so for now we list the
    +# springtime transitions explicitly.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Zion	2005	only	-	Apr	 1	2:00	1:00	D
    +Rule	Zion	2005	only	-	Oct	 9	2:00	0	S
    +Rule	Zion	2006	2010	-	Mar	Fri>=26	2:00	1:00	D
    +Rule	Zion	2006	only	-	Oct	 1	2:00	0	S
    +Rule	Zion	2007	only	-	Sep	16	2:00	0	S
    +Rule	Zion	2008	only	-	Oct	 5	2:00	0	S
    +Rule	Zion	2009	only	-	Sep	27	2:00	0	S
    +Rule	Zion	2010	only	-	Sep	12	2:00	0	S
    +Rule	Zion	2011	only	-	Apr	 1	2:00	1:00	D
    +Rule	Zion	2011	only	-	Oct	 2	2:00	0	S
    +Rule	Zion	2012	only	-	Mar	Fri>=26	2:00	1:00	D
    +Rule	Zion	2012	only	-	Sep	23	2:00	0	S
    +
    +# From Ephraim Silverberg (2012-10-18):
    +
    +# Yesterday, the Interior Ministry Committee, after more than a year
    +# past, approved sending the proposed June 2011 changes to the Time
    +# Decree Law back to the Knesset for second and third (final) votes
    +# before the upcoming elections on Jan. 22, 2013.  Hence, although the
    +# changes are not yet law, they are expected to be so before February 2013.
    +#
    +# As of 2013, DST starts at 02:00 on the Friday before the last Sunday in March.
    +# DST ends at 02:00 on the first Sunday after October 1, unless it occurs on the
    +# second day of the Jewish Rosh Hashana holiday, in which case DST ends a day
    +# later (i.e. at 02:00 the first Monday after October 2).
    +# [Rosh Hashana holidays are factored in until 2100.]
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Zion	2013	max	-	Mar	Fri>=23	2:00	1:00	D
    +Rule	Zion	2013	2026	-	Oct	Sun>=2	2:00	0	S
    +Rule	Zion	2027	only	-	Oct	Mon>=3	2:00	0	S
    +Rule	Zion	2028	max	-	Oct	Sun>=2	2:00	0	S
    +# The following rules are commented out for now, as they break older
    +# versions of zic that support only signed 32-bit timestamps, i.e.,
    +# through 2038-01-19 03:14:07 UTC.
    +#Rule	Zion	2028	2053	-	Oct	Sun>=2	2:00	0	S
    +#Rule	Zion	2054	only	-	Oct	Mon>=3	2:00	0	S
    +#Rule	Zion	2055	2080	-	Oct	Sun>=2	2:00	0	S
    +#Rule	Zion	2081	only	-	Oct	Mon>=3	2:00	0	S
    +#Rule	Zion	2082	max	-	Oct	Sun>=2	2:00	0	S
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Jerusalem	2:20:56 -	LMT	1880
    +			2:20:40	-	JMT	1918	# Jerusalem Mean Time?
    +			2:00	Zion	I%sT
    +
    +
    +
    +###############################################################################
    +
    +# Japan
    +
    +# `9:00' and `JST' is from Guy Harris.
    +
    +# From Paul Eggert (1995-03-06):
    +# Today's _Asahi Evening News_ (page 4) reports that Japan had
    +# daylight saving between 1948 and 1951, but ``the system was discontinued
    +# because the public believed it would lead to longer working hours.''
    +
    +# From Mayumi Negishi in the 2005-08-10 Japan Times
    +# :
    +# Occupation authorities imposed daylight-saving time on Japan on
    +# [1948-05-01]....  But lack of prior debate and the execution of
    +# daylight-saving time just three days after the bill was passed generated
    +# deep hatred of the concept....  The Diet unceremoniously passed a bill to
    +# dump the unpopular system in October 1951, less than a month after the San
    +# Francisco Peace Treaty was signed.  (A government poll in 1951 showed 53%
    +# of the Japanese wanted to scrap daylight-saving time, as opposed to 30% who
    +# wanted to keep it.)
    +
    +# From Paul Eggert (2006-03-22):
    +# Shanks & Pottenger write that DST in Japan during those years was as follows:
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Japan	1948	only	-	May	Sun>=1	2:00	1:00	D
    +Rule	Japan	1948	1951	-	Sep	Sat>=8	2:00	0	S
    +Rule	Japan	1949	only	-	Apr	Sun>=1	2:00	1:00	D
    +Rule	Japan	1950	1951	-	May	Sun>=1	2:00	1:00	D
    +# but the only locations using it (for birth certificates, presumably, since
    +# their audience is astrologers) were US military bases.  For now, assume
    +# that for most purposes daylight-saving time was observed; otherwise, what
    +# would have been the point of the 1951 poll?
    +
    +# From Hideyuki Suzuki (1998-11-09):
    +# 'Tokyo' usually stands for the former location of Tokyo Astronomical
    +# Observatory: E 139 44' 40".90 (9h 18m 58s.727), N 35 39' 16".0.
    +# This data is from 'Rika Nenpyou (Chronological Scientific Tables) 1996'
    +# edited by National Astronomical Observatory of Japan....
    +# JST (Japan Standard Time) has been used since 1888-01-01 00:00 (JST).
    +# The law is enacted on 1886-07-07.
    +
    +# From Hideyuki Suzuki (1998-11-16):
    +# The ordinance No. 51 (1886) established "standard time" in Japan,
    +# which stands for the time on E 135 degree.
    +# In the ordinance No. 167 (1895), "standard time" was renamed to "central
    +# standard time".  And the same ordinance also established "western standard
    +# time", which stands for the time on E 120 degree....  But "western standard
    +# time" was abolished in the ordinance No. 529 (1937).  In the ordinance No.
    +# 167, there is no mention regarding for what place western standard time is
    +# standard....
    +#
    +# I wrote "ordinance" above, but I don't know how to translate.
    +# In Japanese it's "chokurei", which means ordinance from emperor.
    +
    +# Shanks & Pottenger claim JST in use since 1896, and that a few
    +# places (e.g. Ishigaki) use +0800; go with Suzuki.  Guess that all
    +# ordinances took effect on Jan 1.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Tokyo	9:18:59	-	LMT	1887 Dec 31 15:00u
    +			9:00	-	JST	1896
    +			9:00	-	CJT	1938
    +			9:00	Japan	J%sT
    +# Since 1938, all Japanese possessions have been like Asia/Tokyo.
    +
    +# Jordan
    +#
    +# From 
    +# Jordan Week (1999-07-01)  via Steffen Thorsen (1999-09-09):
    +# Clocks in Jordan were forwarded one hour on Wednesday at midnight,
    +# in accordance with the government's decision to implement summer time
    +# all year round.
    +#
    +# From 
    +# Jordan Week (1999-09-30)  via Steffen Thorsen (1999-11-09):
    +# Winter time starts today Thursday, 30 September. Clocks will be turned back
    +# by one hour.  This is the latest government decision and it's final!
    +# The decision was taken because of the increase in working hours in
    +# government's departments from six to seven hours.
    +#
    +# From Paul Eggert (2005-11-22):
    +# Starting 2003 transitions are from Steffen Thorsen's web site timeanddate.com.
    +#
    +# From Steffen Thorsen (2005-11-23):
    +# For Jordan I have received multiple independent user reports every year
    +# about DST end dates, as the end-rule is different every year.
    +#
    +# From Steffen Thorsen (2006-10-01), after a heads-up from Hilal Malawi:
    +# http://www.petranews.gov.jo/nepras/2006/Sep/05/4000.htm
    +# "Jordan will switch to winter time on Friday, October 27".
    +#
    +
    +# From Phil Pizzey (2009-04-02):
    +# ...I think I may have spotted an error in the timezone data for
    +# Jordan.
    +# The current (2009d) asia file shows Jordan going to daylight
    +# saving
    +# time on the last Thursday in March.
    +#
    +# Rule  Jordan      2000  max	-  Mar   lastThu     0:00s 1:00  S
    +#
    +# However timeanddate.com, which I usually find reliable, shows Jordan
    +# going to daylight saving time on the last Friday in March since 2002.
    +# Please see
    +# 
    +# http://www.timeanddate.com/worldclock/timezone.html?n=11
    +# 
    +
    +# From Steffen Thorsen (2009-04-02):
    +# This single one might be good enough, (2009-03-24, Arabic):
    +# 
    +# http://petra.gov.jo/Artical.aspx?Lng=2&Section=8&Artical=95279
    +# 
    +#
    +# Google's translation:
    +#
    +# > The Council of Ministers decided in 2002 to adopt the principle of timely
    +# > submission of the summer at 60 minutes as of midnight on the last Thursday
    +# > of the month of March of each year.
    +#
    +# So - this means the midnight between Thursday and Friday since 2002.
    +
    +# From Arthur David Olson (2009-04-06):
    +# We still have Jordan switching to DST on Thursdays in 2000 and 2001.
    +
    +# From Steffen Thorsen (2012-10-25):
    +# Yesterday the government in Jordan announced that they will not
    +# switch back to standard time this winter, so the will stay on DST
    +# until about the same time next year (at least).
    +# http://www.petra.gov.jo/Public_News/Nws_NewsDetails.aspx?NewsID=88950
    +#
    +# From Paul Eggert (2012-10-25):
    +# For now, assume this is just a one-year measure.  If it becomes
    +# permanent, we should move Jordan from EET to AST effective tomorrow.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Jordan	1973	only	-	Jun	6	0:00	1:00	S
    +Rule	Jordan	1973	1975	-	Oct	1	0:00	0	-
    +Rule	Jordan	1974	1977	-	May	1	0:00	1:00	S
    +Rule	Jordan	1976	only	-	Nov	1	0:00	0	-
    +Rule	Jordan	1977	only	-	Oct	1	0:00	0	-
    +Rule	Jordan	1978	only	-	Apr	30	0:00	1:00	S
    +Rule	Jordan	1978	only	-	Sep	30	0:00	0	-
    +Rule	Jordan	1985	only	-	Apr	1	0:00	1:00	S
    +Rule	Jordan	1985	only	-	Oct	1	0:00	0	-
    +Rule	Jordan	1986	1988	-	Apr	Fri>=1	0:00	1:00	S
    +Rule	Jordan	1986	1990	-	Oct	Fri>=1	0:00	0	-
    +Rule	Jordan	1989	only	-	May	8	0:00	1:00	S
    +Rule	Jordan	1990	only	-	Apr	27	0:00	1:00	S
    +Rule	Jordan	1991	only	-	Apr	17	0:00	1:00	S
    +Rule	Jordan	1991	only	-	Sep	27	0:00	0	-
    +Rule	Jordan	1992	only	-	Apr	10	0:00	1:00	S
    +Rule	Jordan	1992	1993	-	Oct	Fri>=1	0:00	0	-
    +Rule	Jordan	1993	1998	-	Apr	Fri>=1	0:00	1:00	S
    +Rule	Jordan	1994	only	-	Sep	Fri>=15	0:00	0	-
    +Rule	Jordan	1995	1998	-	Sep	Fri>=15	0:00s	0	-
    +Rule	Jordan	1999	only	-	Jul	 1	0:00s	1:00	S
    +Rule	Jordan	1999	2002	-	Sep	lastFri	0:00s	0	-
    +Rule	Jordan	2000	2001	-	Mar	lastThu	0:00s	1:00	S
    +Rule	Jordan	2002	max	-	Mar	lastThu	24:00	1:00	S
    +Rule	Jordan	2003	only	-	Oct	24	0:00s	0	-
    +Rule	Jordan	2004	only	-	Oct	15	0:00s	0	-
    +Rule	Jordan	2005	only	-	Sep	lastFri	0:00s	0	-
    +Rule	Jordan	2006	2011	-	Oct	lastFri	0:00s	0	-
    +Rule	Jordan	2013	max	-	Oct	lastFri	0:00s	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Amman	2:23:44 -	LMT	1931
    +			2:00	Jordan	EE%sT
    +
    +
    +# Kazakhstan
    +
    +# From Paul Eggert (1996-11-22):
    +# Andrew Evtichov (1996-04-13) writes that Kazakhstan
    +# stayed in sync with Moscow after 1990, and that Aqtobe (formerly Aktyubinsk)
    +# and Aqtau (formerly Shevchenko) are the largest cities in their zones.
    +# Guess that Aqtau and Aqtobe diverged in 1995, since that's the first time
    +# IATA SSIM mentions a third time zone in Kazakhstan.
    +
    +# From Paul Eggert (2006-03-22):
    +# German Iofis, ELSI, Almaty (2001-10-09) reports that Kazakhstan uses
    +# RussiaAsia rules, instead of switching at 00:00 as the IATA has it.
    +# Go with Shanks & Pottenger, who have them always using RussiaAsia rules.
    +# Also go with the following claims of Shanks & Pottenger:
    +#
    +# - Kazakhstan did not observe DST in 1991.
    +# - Qyzylorda switched from +5:00 to +6:00 on 1992-01-19 02:00.
    +# - Oral switched from +5:00 to +4:00 in spring 1989.
    +
    +# 
    +# From Kazakhstan Embassy's News Bulletin #11 (2005-03-21):
    +# 
    +# The Government of Kazakhstan passed a resolution March 15 abolishing
    +# daylight saving time citing lack of economic benefits and health
    +# complications coupled with a decrease in productivity.
    +#
    +# From Branislav Kojic (in Astana) via Gwillim Law (2005-06-28):
    +# ... what happened was that the former Kazakhstan Eastern time zone
    +# was "blended" with the Central zone.  Therefore, Kazakhstan now has
    +# two time zones, and difference between them is one hour.  The zone
    +# closer to UTC is the former Western zone (probably still called the
    +# same), encompassing four provinces in the west: Aqtobe, Atyrau,
    +# Mangghystau, and West Kazakhstan.  The other zone encompasses
    +# everything else....  I guess that would make Kazakhstan time zones
    +# de jure UTC+5 and UTC+6 respectively.
    +
    +#
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +#
    +# Almaty (formerly Alma-Ata), representing most locations in Kazakhstan
    +Zone	Asia/Almaty	5:07:48 -	LMT	1924 May  2 # or Alma-Ata
    +			5:00	-	ALMT	1930 Jun 21 # Alma-Ata Time
    +			6:00 RussiaAsia ALM%sT	1991
    +			6:00	-	ALMT	1992
    +			6:00 RussiaAsia	ALM%sT	2005 Mar 15
    +			6:00	-	ALMT
    +# Qyzylorda (aka Kyzylorda, Kizilorda, Kzyl-Orda, etc.)
    +Zone	Asia/Qyzylorda	4:21:52 -	LMT	1924 May  2
    +			4:00	-	KIZT	1930 Jun 21 # Kizilorda Time
    +			5:00	-	KIZT	1981 Apr  1
    +			5:00	1:00	KIZST	1981 Oct  1
    +			6:00	-	KIZT	1982 Apr  1
    +			5:00 RussiaAsia	KIZ%sT	1991
    +			5:00	-	KIZT	1991 Dec 16 # independence
    +			5:00	-	QYZT	1992 Jan 19 2:00
    +			6:00 RussiaAsia	QYZ%sT	2005 Mar 15
    +			6:00	-	QYZT
    +# Aqtobe (aka Aktobe, formerly Akt'ubinsk)
    +Zone	Asia/Aqtobe	3:48:40	-	LMT	1924 May  2
    +			4:00	-	AKTT	1930 Jun 21 # Aktyubinsk Time
    +			5:00	-	AKTT	1981 Apr  1
    +			5:00	1:00	AKTST	1981 Oct  1
    +			6:00	-	AKTT	1982 Apr  1
    +			5:00 RussiaAsia	AKT%sT	1991
    +			5:00	-	AKTT	1991 Dec 16 # independence
    +			5:00 RussiaAsia	AQT%sT	2005 Mar 15 # Aqtobe Time
    +			5:00	-	AQTT
    +# Mangghystau
    +# Aqtau was not founded until 1963, but it represents an inhabited region,
    +# so include time stamps before 1963.
    +Zone	Asia/Aqtau	3:21:04	-	LMT	1924 May  2
    +			4:00	-	FORT	1930 Jun 21 # Fort Shevchenko T
    +			5:00	-	FORT	1963
    +			5:00	-	SHET	1981 Oct  1 # Shevchenko Time
    +			6:00	-	SHET	1982 Apr  1
    +			5:00 RussiaAsia	SHE%sT	1991
    +			5:00	-	SHET	1991 Dec 16 # independence
    +			5:00 RussiaAsia	AQT%sT	1995 Mar lastSun 2:00 # Aqtau Time
    +			4:00 RussiaAsia	AQT%sT	2005 Mar 15
    +			5:00	-	AQTT
    +# West Kazakhstan
    +Zone	Asia/Oral	3:25:24	-	LMT	1924 May  2 # or Ural'sk
    +			4:00	-	URAT	1930 Jun 21 # Ural'sk time
    +			5:00	-	URAT	1981 Apr  1
    +			5:00	1:00	URAST	1981 Oct  1
    +			6:00	-	URAT	1982 Apr  1
    +			5:00 RussiaAsia	URA%sT	1989 Mar 26 2:00
    +			4:00 RussiaAsia	URA%sT	1991
    +			4:00	-	URAT	1991 Dec 16 # independence
    +			4:00 RussiaAsia	ORA%sT	2005 Mar 15 # Oral Time
    +			5:00	-	ORAT
    +
    +# Kyrgyzstan (Kirgizstan)
    +# Transitions through 1991 are from Shanks & Pottenger.
    +
    +# From Paul Eggert (2005-08-15):
    +# According to an article dated today in the Kyrgyzstan Development Gateway
    +# 
    +# Kyrgyzstan is canceling the daylight saving time system.  I take the article
    +# to mean that they will leave their clocks at 6 hours ahead of UTC.
    +# From Malik Abdugaliev (2005-09-21):
    +# Our government cancels daylight saving time 6th of August 2005.
    +# From 2005-08-12 our GMT-offset is +6, w/o any daylight saving.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Kyrgyz	1992	1996	-	Apr	Sun>=7	0:00s	1:00	S
    +Rule	Kyrgyz	1992	1996	-	Sep	lastSun	0:00	0	-
    +Rule	Kyrgyz	1997	2005	-	Mar	lastSun	2:30	1:00	S
    +Rule	Kyrgyz	1997	2004	-	Oct	lastSun	2:30	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Bishkek	4:58:24 -	LMT	1924 May  2
    +			5:00	-	FRUT	1930 Jun 21 # Frunze Time
    +			6:00 RussiaAsia FRU%sT	1991 Mar 31 2:00s
    +			5:00	1:00	FRUST	1991 Aug 31 2:00 # independence
    +			5:00	Kyrgyz	KG%sT	2005 Aug 12    # Kyrgyzstan Time
    +			6:00	-	KGT
    +
    +###############################################################################
    +
    +# Korea (North and South)
    +
    +# From Annie I. Bang (2006-07-10) in
    +# :
    +# The Ministry of Commerce, Industry and Energy has already
    +# commissioned a research project [to reintroduce DST] and has said
    +# the system may begin as early as 2008....  Korea ran a daylight
    +# saving program from 1949-61 but stopped it during the 1950-53 Korean War.
    +
    +# From Shanks & Pottenger:
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	ROK	1960	only	-	May	15	0:00	1:00	D
    +Rule	ROK	1960	only	-	Sep	13	0:00	0	S
    +Rule	ROK	1987	1988	-	May	Sun>=8	0:00	1:00	D
    +Rule	ROK	1987	1988	-	Oct	Sun>=8	0:00	0	S
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Seoul	8:27:52	-	LMT	1890
    +			8:30	-	KST	1904 Dec
    +			9:00	-	KST	1928
    +			8:30	-	KST	1932
    +			9:00	-	KST	1954 Mar 21
    +			8:00	ROK	K%sT	1961 Aug 10
    +			8:30	-	KST	1968 Oct
    +			9:00	ROK	K%sT
    +Zone	Asia/Pyongyang	8:23:00 -	LMT	1890
    +			8:30	-	KST	1904 Dec
    +			9:00	-	KST	1928
    +			8:30	-	KST	1932
    +			9:00	-	KST	1954 Mar 21
    +			8:00	-	KST	1961 Aug 10
    +			9:00	-	KST
    +
    +###############################################################################
    +
    +# Kuwait
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +# From the Arab Times (2007-03-14):
    +# The Civil Service Commission (CSC) has approved a proposal forwarded
    +# by MP Ahmad Baqer on implementing the daylight saving time (DST) in
    +# Kuwait starting from April until the end of Sept this year, reports Al-Anba.
    +# .
    +# From Paul Eggert (2007-03-29):
    +# We don't know the details, or whether the approval means it'll happen,
    +# so for now we assume no DST.
    +Zone	Asia/Kuwait	3:11:56 -	LMT	1950
    +			3:00	-	AST
    +
    +# Laos
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Vientiane	6:50:24 -	LMT	1906 Jun  9 # or Viangchan
    +			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
    +			7:00	-	ICT	1912 May
    +			8:00	-	ICT	1931 May
    +			7:00	-	ICT
    +
    +# Lebanon
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Lebanon	1920	only	-	Mar	28	0:00	1:00	S
    +Rule	Lebanon	1920	only	-	Oct	25	0:00	0	-
    +Rule	Lebanon	1921	only	-	Apr	3	0:00	1:00	S
    +Rule	Lebanon	1921	only	-	Oct	3	0:00	0	-
    +Rule	Lebanon	1922	only	-	Mar	26	0:00	1:00	S
    +Rule	Lebanon	1922	only	-	Oct	8	0:00	0	-
    +Rule	Lebanon	1923	only	-	Apr	22	0:00	1:00	S
    +Rule	Lebanon	1923	only	-	Sep	16	0:00	0	-
    +Rule	Lebanon	1957	1961	-	May	1	0:00	1:00	S
    +Rule	Lebanon	1957	1961	-	Oct	1	0:00	0	-
    +Rule	Lebanon	1972	only	-	Jun	22	0:00	1:00	S
    +Rule	Lebanon	1972	1977	-	Oct	1	0:00	0	-
    +Rule	Lebanon	1973	1977	-	May	1	0:00	1:00	S
    +Rule	Lebanon	1978	only	-	Apr	30	0:00	1:00	S
    +Rule	Lebanon	1978	only	-	Sep	30	0:00	0	-
    +Rule	Lebanon	1984	1987	-	May	1	0:00	1:00	S
    +Rule	Lebanon	1984	1991	-	Oct	16	0:00	0	-
    +Rule	Lebanon	1988	only	-	Jun	1	0:00	1:00	S
    +Rule	Lebanon	1989	only	-	May	10	0:00	1:00	S
    +Rule	Lebanon	1990	1992	-	May	1	0:00	1:00	S
    +Rule	Lebanon	1992	only	-	Oct	4	0:00	0	-
    +Rule	Lebanon	1993	max	-	Mar	lastSun	0:00	1:00	S
    +Rule	Lebanon	1993	1998	-	Sep	lastSun	0:00	0	-
    +Rule	Lebanon	1999	max	-	Oct	lastSun	0:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Beirut	2:22:00 -	LMT	1880
    +			2:00	Lebanon	EE%sT
    +
    +# Malaysia
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	NBorneo	1935	1941	-	Sep	14	0:00	0:20	TS # one-Third Summer
    +Rule	NBorneo	1935	1941	-	Dec	14	0:00	0	-
    +#
    +# peninsular Malaysia
    +# The data here are taken from Mok Ly Yng (2003-10-30)
    +# .
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Asia/Kuala_Lumpur	6:46:46 -	LMT	1901 Jan  1
    +			6:55:25	-	SMT	1905 Jun  1 # Singapore M.T.
    +			7:00	-	MALT	1933 Jan  1 # Malaya Time
    +			7:00	0:20	MALST	1936 Jan  1
    +			7:20	-	MALT	1941 Sep  1
    +			7:30	-	MALT	1942 Feb 16
    +			9:00	-	JST	1945 Sep 12
    +			7:30	-	MALT	1982 Jan  1
    +			8:00	-	MYT	# Malaysia Time
    +# Sabah & Sarawak
    +# From Paul Eggert (2006-03-22):
    +# The data here are mostly from Shanks & Pottenger, but the 1942, 1945 and 1982
    +# transition dates are from Mok Ly Yng.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Asia/Kuching	7:21:20	-	LMT	1926 Mar
    +			7:30	-	BORT	1933	# Borneo Time
    +			8:00	NBorneo	BOR%sT	1942 Feb 16
    +			9:00	-	JST	1945 Sep 12
    +			8:00	-	BORT	1982 Jan  1
    +			8:00	-	MYT
    +
    +# Maldives
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
    +			4:54:00	-	MMT	1960	# Male Mean Time
    +			5:00	-	MVT		# Maldives Time
    +
    +# Mongolia
    +
    +# Shanks & Pottenger say that Mongolia has three time zones, but
    +# usno1995 and the CIA map Standard Time Zones of the World (2005-03)
    +# both say that it has just one.
    +
    +# From Oscar van Vlijmen (1999-12-11):
    +# 
    +# General Information Mongolia
    +#  (1999-09)
    +# "Time: Mongolia has two time zones. Three westernmost provinces of
    +# Bayan-Ulgii, Uvs, and Hovd are one hour earlier than the capital city, and
    +# the rest of the country follows the Ulaanbaatar time, which is UTC/GMT plus
    +# eight hours."
    +
    +# From Rives McDow (1999-12-13):
    +# Mongolia discontinued the use of daylight savings time in 1999; 1998
    +# being the last year it was implemented.  The dates of implementation I am
    +# unsure of, but most probably it was similar to Russia, except for the time
    +# of implementation may have been different....
    +# Some maps in the past have indicated that there was an additional time
    +# zone in the eastern part of Mongolia, including the provinces of Dornod,
    +# Suhbaatar, and possibly Khentij.
    +
    +# From Paul Eggert (1999-12-15):
    +# Naming and spelling is tricky in Mongolia.
    +# We'll use Hovd (also spelled Chovd and Khovd) to represent the west zone;
    +# the capital of the Hovd province is sometimes called Hovd, sometimes Dund-Us,
    +# and sometimes Jirgalanta (with variant spellings), but the name Hovd
    +# is good enough for our purposes.
    +
    +# From Rives McDow (2001-05-13):
    +# In addition to Mongolia starting daylight savings as reported earlier
    +# (adopted DST on 2001-04-27 02:00 local time, ending 2001-09-28),
    +# there are three time zones.
    +#
    +# Provinces [at 7:00]: Bayan-ulgii, Uvs, Khovd, Zavkhan, Govi-Altai
    +# Provinces [at 8:00]: Khovsgol, Bulgan, Arkhangai, Khentii, Tov,
    +#	Bayankhongor, Ovorkhangai, Dundgovi, Dornogovi, Omnogovi
    +# Provinces [at 9:00]: Dornod, Sukhbaatar
    +#
    +# [The province of Selenge is omitted from the above lists.]
    +
    +# From Ganbold Ts., Ulaanbaatar (2004-04-17):
    +# Daylight saving occurs at 02:00 local time last Saturday of March.
    +# It will change back to normal at 02:00 local time last Saturday of
    +# September.... As I remember this rule was changed in 2001.
    +#
    +# From Paul Eggert (2004-04-17):
    +# For now, assume Rives McDow's informant got confused about Friday vs
    +# Saturday, and that his 2001 dates should have 1 added to them.
    +
    +# From Paul Eggert (2005-07-26):
    +# We have wildly conflicting information about Mongolia's time zones.
    +# Bill Bonnet (2005-05-19) reports that the US Embassy in Ulaanbaatar says
    +# there is only one time zone and that DST is observed, citing Microsoft
    +# Windows XP as the source.  Risto Nykanen (2005-05-16) reports that
    +# travelmongolia.org says there are two time zones (UTC+7, UTC+8) with no DST.
    +# Oscar van Vlijmen (2005-05-20) reports that the Mongolian Embassy in
    +# Washington, DC says there are two time zones, with DST observed.
    +# He also found
    +# 
    +# which also says that there is DST, and which has a comment by "Toddius"
    +# (2005-03-31 06:05 +0700) saying "Mongolia actually has 3.5 time zones.
    +# The West (OLGII) is +7 GMT, most of the country is ULAT is +8 GMT
    +# and some Eastern provinces are +9 GMT but Sukhbaatar Aimag is SUHK +8.5 GMT.
    +# The SUKH timezone is new this year, it is one of the few things the
    +# parliament passed during the tumultuous winter session."
    +# For now, let's ignore this information, until we have more confirmation.
    +
    +# From Ganbold Ts. (2007-02-26):
    +# Parliament of Mongolia has just changed the daylight-saving rule in February.
    +# They decided not to adopt daylight-saving time....
    +# http://www.mongolnews.mn/index.php?module=unuudur&sec=view&id=15742
    +
    +# From Deborah Goldsmith (2008-03-30):
    +# We received a bug report claiming that the tz database UTC offset for
    +# Asia/Choibalsan (GMT+09:00) is incorrect, and that it should be GMT
    +# +08:00 instead. Different sources appear to disagree with the tz
    +# database on this, e.g.:
    +#
    +# 
    +# http://www.timeanddate.com/worldclock/city.html?n=1026
    +# 
    +# 
    +# http://www.worldtimeserver.com/current_time_in_MN.aspx
    +# 
    +#
    +# both say GMT+08:00.
    +
    +# From Steffen Thorsen (2008-03-31):
    +# eznis airways, which operates several domestic flights, has a flight
    +# schedule here:
    +# 
    +# http://www.eznis.com/Container.jsp?id=112
    +# 
    +# (click the English flag for English)
    +#
    +# There it appears that flights between Choibalsan and Ulaanbatar arrive
    +# about 1:35 - 1:50 hours later in local clock time, no matter the
    +# direction, while Ulaanbaatar-Khvod takes 2 hours in the Eastern
    +# direction and 3:35 back, which indicates that Ulaanbatar and Khvod are
    +# in different time zones (like we know about), while Choibalsan and
    +# Ulaanbatar are in the same time zone (correction needed).
    +
    +# From Arthur David Olson (2008-05-19):
    +# Assume that Choibalsan is indeed offset by 8:00.
    +# XXX--in the absence of better information, assume that transition
    +# was at the start of 2008-03-31 (the day of Steffen Thorsen's report);
    +# this is almost surely wrong.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Mongol	1983	1984	-	Apr	1	0:00	1:00	S
    +Rule	Mongol	1983	only	-	Oct	1	0:00	0	-
    +# Shanks & Pottenger and IATA SSIM say 1990s switches occurred at 00:00,
    +# but McDow says the 2001 switches occurred at 02:00.  Also, IATA SSIM
    +# (1996-09) says 1996-10-25.  Go with Shanks & Pottenger through 1998.
    +#
    +# Shanks & Pottenger say that the Sept. 1984 through Sept. 1990 switches
    +# in Choibalsan (more precisely, in Dornod and Sukhbaatar) took place
    +# at 02:00 standard time, not at 00:00 local time as in the rest of
    +# the country.  That would be odd, and possibly is a result of their
    +# correction of 02:00 (in the previous edition) not being done correctly
    +# in the latest edition; so ignore it for now.
    +
    +Rule	Mongol	1985	1998	-	Mar	lastSun	0:00	1:00	S
    +Rule	Mongol	1984	1998	-	Sep	lastSun	0:00	0	-
    +# IATA SSIM (1999-09) says Mongolia no longer observes DST.
    +Rule	Mongol	2001	only	-	Apr	lastSat	2:00	1:00	S
    +Rule	Mongol	2001	2006	-	Sep	lastSat	2:00	0	-
    +Rule	Mongol	2002	2006	-	Mar	lastSat	2:00	1:00	S
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +# Hovd, a.k.a. Chovd, Dund-Us, Dzhargalant, Khovd, Jirgalanta
    +Zone	Asia/Hovd	6:06:36 -	LMT	1905 Aug
    +			6:00	-	HOVT	1978	# Hovd Time
    +			7:00	Mongol	HOV%sT
    +# Ulaanbaatar, a.k.a. Ulan Bataar, Ulan Bator, Urga
    +Zone	Asia/Ulaanbaatar 7:07:32 -	LMT	1905 Aug
    +			7:00	-	ULAT	1978	# Ulaanbaatar Time
    +			8:00	Mongol	ULA%sT
    +# Choibalsan, a.k.a. Bajan Tuemen, Bajan Tumen, Chojbalsan,
    +# Choybalsan, Sanbejse, Tchoibalsan
    +Zone	Asia/Choibalsan	7:38:00 -	LMT	1905 Aug
    +			7:00	-	ULAT	1978
    +			8:00	-	ULAT	1983 Apr
    +			9:00	Mongol	CHO%sT	2008 Mar 31 # Choibalsan Time
    +			8:00	Mongol	CHO%sT
    +
    +# Nepal
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Kathmandu	5:41:16 -	LMT	1920
    +			5:30	-	IST	1986
    +			5:45	-	NPT	# Nepal Time
    +
    +# Oman
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Muscat	3:54:20 -	LMT	1920
    +			4:00	-	GST
    +
    +# Pakistan
    +
    +# From Rives McDow (2002-03-13):
    +# I have been advised that Pakistan has decided to adopt dst on a
    +# TRIAL basis for one year, starting 00:01 local time on April 7, 2002
    +# and ending at 00:01 local time October 6, 2002.  This is what I was
    +# told, but I believe that the actual time of change may be 00:00; the
    +# 00:01 was to make it clear which day it was on.
    +
    +# From Paul Eggert (2002-03-15):
    +# Jesper Norgaard found this URL:
    +# http://www.pak.gov.pk/public/news/app/app06_dec.htm
    +# (dated 2001-12-06) which says that the Cabinet adopted a scheme "to
    +# advance the clocks by one hour on the night between the first
    +# Saturday and Sunday of April and revert to the original position on
    +# 15th October each year".  This agrees with McDow's 04-07 at 00:00,
    +# but disagrees about the October transition, and makes it sound like
    +# it's not on a trial basis.  Also, the "between the first Saturday
    +# and Sunday of April" phrase, if taken literally, means that the
    +# transition takes place at 00:00 on the first Sunday on or after 04-02.
    +
    +# From Paul Eggert (2003-02-09):
    +# DAWN  reported on 2002-10-05
    +# that 2002 DST ended that day at midnight.  Go with McDow for now.
    +
    +# From Steffen Thorsen (2003-03-14):
    +# According to http://www.dawn.com/2003/03/07/top15.htm
    +# there will be no DST in Pakistan this year:
    +#
    +# ISLAMABAD, March 6: Information and Media Development Minister Sheikh
    +# Rashid Ahmed on Thursday said the cabinet had reversed a previous
    +# decision to advance clocks by one hour in summer and put them back by
    +# one hour in winter with the aim of saving light hours and energy.
    +#
    +# The minister told a news conference that the experiment had rather
    +# shown 8 per cent higher consumption of electricity.
    +
    +# From Alex Krivenyshev (2008-05-15):
    +#
    +# Here is an article that Pakistan plan to introduce Daylight Saving Time
    +# on June 1, 2008 for 3 months.
    +#
    +# "... The federal cabinet on Wednesday announced a new conservation plan to help
    +# reduce load shedding by approving the closure of commercial centres at 9pm and
    +# moving clocks forward by one hour for the next three months.
    +# ...."
    +#
    +# 
    +# http://www.worldtimezone.net/dst_news/dst_news_pakistan01.html
    +# 
    +# OR
    +# 
    +# http://www.dailytimes.com.pk/default.asp?page=2008%5C05%5C15%5Cstory_15-5-2008_pg1_4
    +# 
    +
    +# From Arthur David Olson (2008-05-19):
    +# XXX--midnight transitions is a guess; 2008 only is a guess.
    +
    +# From Alexander Krivenyshev (2008-08-28):
    +# Pakistan government has decided to keep the watches one-hour advanced
    +# for another 2 months--plan to return to Standard Time on October 31
    +# instead of August 31.
    +#
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_pakistan02.html
    +# 
    +# OR
    +# 
    +# http://dailymailnews.com/200808/28/news/dmbrn03.html
    +# 
    +
    +# From Alexander Krivenyshev (2009-04-08):
    +# Based on previous media reports that "... proposed plan to
    +# advance clocks by one hour from May 1 will cause disturbance
    +# to the working schedules rather than bringing discipline in
    +# official working."
    +# 
    +# http://www.thenews.com.pk/daily_detail.asp?id=171280
    +# 
    +#
    +# recent news that instead of May 2009 - Pakistan plan to
    +# introduce DST from April 15, 2009
    +#
    +# FYI: Associated Press Of Pakistan
    +# April 08, 2009
    +# Cabinet okays proposal to advance clocks by one hour from April 15
    +# 
    +# http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=73043&Itemid=1
    +# 
    +#
    +# or
    +#
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_pakistan05.html
    +# 
    +#
    +# ....
    +# The Federal Cabinet on Wednesday approved the proposal to
    +# advance clocks in the country by one hour from April 15 to
    +# conserve energy"
    +
    +# From Steffen Thorsen (2009-09-17):
    +# "The News International," Pakistan reports that: "The Federal
    +# Government has decided to restore the previous time by moving the
    +# clocks backward by one hour from October 1. A formal announcement to
    +# this effect will be made after the Prime Minister grants approval in
    +# this regard."
    +# 
    +# http://www.thenews.com.pk/updates.asp?id=87168
    +# 
    +
    +# From Alexander Krivenyshev (2009-09-28):
    +# According to Associated Press Of Pakistan, it is confirmed that
    +# Pakistan clocks across the country would be turned back by an hour from October
    +# 1, 2009.
    +#
    +# "Clocks to go back one hour from 1 Oct"
    +# 
    +# http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2
    +# 
    +# or
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm
    +# 
    +
    +# From Steffen Thorsen (2009-09-29):
    +# Alexander Krivenyshev wrote:
    +# > According to Associated Press Of Pakistan, it is confirmed that
    +# > Pakistan clocks across the country would be turned back by an hour from October
    +# > 1, 2009.
    +#
    +# Now they seem to have changed their mind, November 1 is the new date:
    +# 
    +# http://www.thenews.com.pk/top_story_detail.asp?Id=24742
    +# 
    +# "The country's clocks will be reversed by one hour on November 1.
    +# Officials of Federal Ministry for Interior told this to Geo News on
    +# Monday."
    +#
    +# And more importantly, it seems that these dates will be kept every year:
    +# "It has now been decided that clocks will be wound forward by one hour
    +# on April 15 and reversed by an hour on November 1 every year without
    +# obtaining prior approval, the officials added."
    +#
    +# We have confirmed this year's end date with both with the Ministry of
    +# Water and Power and the Pakistan Electric Power Company:
    +# 
    +# http://www.timeanddate.com/news/time/pakistan-ends-dst09.html
    +# 
    +
    +# From Christoph Goehre (2009-10-01):
    +# [T]he German Consulate General in Karachi reported me today that Pakistan
    +# will go back to standard time on 1st of November.
    +
    +# From Steffen Thorsen (2010-03-26):
    +# Steffen Thorsen wrote:
    +# > On Thursday (2010-03-25) it was announced that DST would start in
    +# > Pakistan on 2010-04-01.
    +# >
    +# > Then today, the president said that they might have to revert the
    +# > decision if it is not supported by the parliament. So at the time
    +# > being, it seems unclear if DST will be actually observed or not - but
    +# > April 1 could be a more likely date than April 15.
    +# Now, it seems that the decision to not observe DST in final:
    +#
    +# "Govt Withdraws Plan To Advance Clocks"
    +# 
    +# http://www.apakistannews.com/govt-withdraws-plan-to-advance-clocks-172041
    +# 
    +#
    +# "People laud PM's announcement to end DST"
    +# 
    +# http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=99374&Itemid=2
    +# 
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule Pakistan	2002	only	-	Apr	Sun>=2	0:01	1:00	S
    +Rule Pakistan	2002	only	-	Oct	Sun>=2	0:01	0	-
    +Rule Pakistan	2008	only	-	Jun	1	0:00	1:00	S
    +Rule Pakistan	2008	only	-	Nov	1	0:00	0	-
    +Rule Pakistan	2009	only	-	Apr	15	0:00	1:00	S
    +Rule Pakistan	2009	only	-	Nov	1	0:00	0	-
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Karachi	4:28:12 -	LMT	1907
    +			5:30	-	IST	1942 Sep
    +			5:30	1:00	IST	1945 Oct 15
    +			5:30	-	IST	1951 Sep 30
    +			5:00	-	KART	1971 Mar 26 # Karachi Time
    +			5:00 Pakistan	PK%sT	# Pakistan Time
    +
    +# Palestine
    +
    +# From Amos Shapir (1998-02-15):
    +#
    +# From 1917 until 1948-05-15, all of Palestine, including the parts now
    +# known as the Gaza Strip and the West Bank, was under British rule.
    +# Therefore the rules given for Israel for that period, apply there too...
    +#
    +# The Gaza Strip was under Egyptian rule between 1948-05-15 until 1967-06-05
    +# (except a short occupation by Israel from 1956-11 till 1957-03, but no
    +# time zone was affected then).  It was never formally annexed to Egypt,
    +# though.
    +#
    +# The rest of Palestine was under Jordanian rule at that time, formally
    +# annexed in 1950 as the West Bank (and the word "Trans" was dropped from
    +# the country's previous name of "the Hashemite Kingdom of the
    +# Trans-Jordan").  So the rules for Jordan for that time apply.  Major
    +# towns in that area are Nablus (Shchem), El-Halil (Hebron), Ramallah, and
    +# East Jerusalem.
    +#
    +# Both areas were occupied by Israel in June 1967, but not annexed (except
    +# for East Jerusalem).  They were on Israel time since then; there might
    +# have been a Military Governor's order about time zones, but I'm not aware
    +# of any (such orders may have been issued semi-annually whenever summer
    +# time was in effect, but maybe the legal aspect of time was just neglected).
    +#
    +# The Palestinian Authority was established in 1993, and got hold of most
    +# towns in the West Bank and Gaza by 1995.  I know that in order to
    +# demonstrate...independence, they have been switching to
    +# summer time and back on a different schedule than Israel's, but I don't
    +# know when this was started, or what algorithm is used (most likely the
    +# Jordanian one).
    +#
    +# To summarize, the table should probably look something like that:
    +#
    +# Area \ when | 1918-1947 | 1948-1967 | 1967-1995 | 1996-
    +# ------------+-----------+-----------+-----------+-----------
    +# Israel      | Zion      | Zion      | Zion      | Zion
    +# West bank   | Zion      | Jordan    | Zion      | Jordan
    +# Gaza        | Zion      | Egypt     | Zion      | Jordan
    +#
    +# I guess more info may be available from the PA's web page (if/when they
    +# have one).
    +
    +# From Paul Eggert (2006-03-22):
    +# Shanks & Pottenger write that Gaza did not observe DST until 1957, but go
    +# with Shapir and assume that it observed DST from 1940 through 1947,
    +# and that it used Jordanian rules starting in 1996.
    +# We don't yet need a separate entry for the West Bank, since
    +# the only differences between it and Gaza that we know about
    +# occurred before our cutoff date of 1970.
    +# However, as we get more information, we may need to add entries
    +# for parts of the West Bank as they transitioned from Israel's rules
    +# to Palestine's rules.  If you have more info about this, please
    +# send it to tz@elsie.nci.nih.gov for incorporation into future editions.
    +
    +# From IINS News Service - Israel - 1998-03-23 10:38:07 Israel time,
    +# forwarded by Ephraim Silverberg:
    +#
    +# Despite the fact that Israel changed over to daylight savings time
    +# last week, the PLO Authority (PA) has decided not to turn its clocks
    +# one-hour forward at this time.  As a sign of independence from Israeli rule,
    +# the PA has decided to implement DST in April.
    +
    +# From Paul Eggert (1999-09-20):
    +# Daoud Kuttab writes in
    +# 
    +# Holiday havoc
    +#  (Jerusalem Post, 1999-04-22) that
    +# the Palestinian National Authority changed to DST on 1999-04-15.
    +# I vaguely recall that they switch back in October (sorry, forgot the source).
    +# For now, let's assume that the spring switch was at 24:00,
    +# and that they switch at 0:00 on the 3rd Fridays of April and October.
    +
    +# From Paul Eggert (2005-11-22):
    +# Starting 2004 transitions are from Steffen Thorsen's web site timeanddate.com.
    +
    +# From Steffen Thorsen (2005-11-23):
    +# A user from Gaza reported that Gaza made the change early because of
    +# the Ramadan.  Next year Ramadan will be even earlier, so I think
    +# there is a good chance next year's end date will be around two weeks
    +# earlier--the same goes for Jordan.
    +
    +# From Steffen Thorsen (2006-08-17):
    +# I was informed by a user in Bethlehem that in Bethlehem it started the
    +# same day as Israel, and after checking with other users in the area, I
    +# was informed that they started DST one day after Israel.  I was not
    +# able to find any authoritative sources at the time, nor details if
    +# Gaza changed as well, but presumed Gaza to follow the same rules as
    +# the West Bank.
    +
    +# From Steffen Thorsen (2006-09-26):
    +# according to the Palestine News Network (2006-09-19):
    +# http://english.pnn.ps/index.php?option=com_content&task=view&id=596&Itemid=5
    +# > The Council of Ministers announced that this year its winter schedule
    +# > will begin early, as of midnight Thursday.  It is also time to turn
    +# > back the clocks for winter.  Friday will begin an hour late this week.
    +# I guess it is likely that next year's date will be moved as well,
    +# because of the Ramadan.
    +
    +# From Jesper Norgaard Welen (2007-09-18):
    +# According to Steffen Thorsen's web site the Gaza Strip and the rest of the
    +# Palestinian territories left DST early on 13.th. of September at 2:00.
    +
    +# From Paul Eggert (2007-09-20):
    +# My understanding is that Gaza and the West Bank disagree even over when
    +# the weekend is (Thursday+Friday versus Friday+Saturday), so I'd be a bit
    +# surprised if they agreed about DST.  But for now, assume they agree.
    +# For lack of better information, predict that future changes will be
    +# the 2nd Thursday of September at 02:00.
    +
    +# From Alexander Krivenyshev (2008-08-28):
    +# Here is an article, that Mideast running on different clocks at Ramadan.
    +#
    +# Gaza Strip (as Egypt) ended DST at midnight Thursday (Aug 28, 2008), while
    +# the West Bank will end Daylight Saving Time at midnight Sunday (Aug 31, 2008).
    +#
    +# 
    +# http://www.guardian.co.uk/world/feedarticle/7759001
    +# 
    +# 
    +# http://www.abcnews.go.com/International/wireStory?id=5676087
    +# 
    +# or
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_gazastrip01.html
    +# 
    +
    +# From Alexander Krivenyshev (2009-03-26):
    +# According to the Palestine News Network (arabic.pnn.ps), Palestinian
    +# government decided to start Daylight Time on Thursday night March
    +# 26 and continue until the night of 27 September 2009.
    +#
    +# (in Arabic)
    +# 
    +# http://arabic.pnn.ps/index.php?option=com_content&task=view&id=50850
    +# 
    +#
    +# or
    +# (English translation)
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_westbank01.html
    +# 
    +
    +# From Steffen Thorsen (2009-08-31):
    +# Palestine's Council of Ministers announced that they will revert back to
    +# winter time on Friday, 2009-09-04.
    +#
    +# One news source:
    +# 
    +# http://www.safa.ps/ara/?action=showdetail&seid=4158
    +# 
    +# (Palestinian press agency, Arabic),
    +# Google translate: "Decided that the Palestinian government in Ramallah
    +# headed by Salam Fayyad, the start of work in time for the winter of
    +# 2009, starting on Friday approved the fourth delay Sept. clock sixty
    +# minutes per hour as of Friday morning."
    +#
    +# We are not sure if Gaza will do the same, last year they had a different
    +# end date, we will keep this page updated:
    +# 
    +# http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html
    +# 
    +
    +# From Alexander Krivenyshev (2009-09-02):
    +# Seems that Gaza Strip will go back to Winter Time same date as West Bank.
    +#
    +# According to Palestinian Ministry Of Interior, West Bank and Gaza Strip plan
    +# to change time back to Standard time on September 4, 2009.
    +#
    +# "Winter time unite the West Bank and Gaza"
    +# (from Palestinian National Authority):
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html
    +# 
    +
    +# From Alexander Krivenyshev (2010-03-19):
    +# According to Voice of Palestine DST will last for 191 days, from March
    +# 26, 2010 till "the last Sunday before the tenth day of Tishri
    +# (October), each year" (October 03, 2010?)
    +#
    +# 
    +# http://palvoice.org/forums/showthread.php?t=245697
    +# 
    +# (in Arabic)
    +# or
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_westbank03.html
    +# 
    +
    +# From Steffen Thorsen (2010-03-24):
    +# ...Ma'an News Agency reports that Hamas cabinet has decided it will
    +# start one day later, at 12:01am. Not sure if they really mean 12:01am or
    +# noon though:
    +#
    +# 
    +# http://www.maannews.net/eng/ViewDetails.aspx?ID=271178
    +# 
    +# (Ma'an News Agency)
    +# "At 12:01am Friday, clocks in Israel and the West Bank will change to
    +# 1:01am, while Gaza clocks will change at 12:01am Saturday morning."
    +
    +# From Steffen Thorsen (2010-08-11):
    +# According to several sources, including
    +# 
    +# http://www.maannews.net/eng/ViewDetails.aspx?ID=306795
    +# 
    +# the clocks were set back one hour at 2010-08-11 00:00:00 local time in
    +# Gaza and the West Bank.
    +# Some more background info:
    +# 
    +# http://www.timeanddate.com/news/time/westbank-gaza-end-dst-2010.html
    +# 
    +
    +# From Steffen Thorsen (2011-08-26):
    +# Gaza and the West Bank did go back to standard time in the beginning of
    +# August, and will now enter daylight saving time again on 2011-08-30
    +# 00:00 (so two periods of DST in 2011). The pause was because of
    +# Ramadan.
    +#
    +# 
    +# http://www.maannews.net/eng/ViewDetails.aspx?ID=416217
    +# 
    +# Additional info:
    +# 
    +# http://www.timeanddate.com/news/time/palestine-dst-2011.html
    +# 
    +
    +# From Alexander Krivenyshev (2011-08-27):
    +# According to the article in The Jerusalem Post:
    +# "...Earlier this month, the Palestinian government in the West Bank decided to
    +# move to standard time for 30 days, during Ramadan. The Palestinians in the
    +# Gaza Strip accepted the change and also moved their clocks one hour back.
    +# The Hamas government said on Saturday that it won't observe summertime after
    +# the Muslim feast of Id al-Fitr, which begins on Tuesday..."
    +# ...
    +# 
    +# http://www.jpost.com/MiddleEast/Article.aspx?id=235650
    +# 
    +# or
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_gazastrip05.html
    +# 
    +# The rules for Egypt are stolen from the `africa' file.
    +
    +# From Steffen Thorsen (2011-09-30):
    +# West Bank did end Daylight Saving Time this morning/midnight (2011-09-30
    +# 00:00).
    +# So West Bank and Gaza now have the same time again.
    +#
    +# Many sources, including:
    +# 
    +# http://www.maannews.net/eng/ViewDetails.aspx?ID=424808
    +# 
    +
    +# From Steffen Thorsen (2012-03-26):
    +# Palestinian news sources tell that both Gaza and West Bank will start DST
    +# on Friday (Thursday midnight, 2012-03-29 24:00).
    +# Some of many sources in Arabic:
    +# 
    +# http://www.samanews.com/index.php?act=Show&id=122638
    +# 
    +#
    +# 
    +# http://safa.ps/details/news/74352/%D8%A8%D8%AF%D8%A1-%D8%A7%D9%84%D8%AA%D9%88%D9%82%D9%8A%D8%AA-%D8%A7%D9%84%D8%B5%D9%8A%D9%81%D9%8A-%D8%A8%D8%A7%D9%84%D8%B6%D9%81%D8%A9-%D9%88%D8%BA%D8%B2%D8%A9-%D9%84%D9%8A%D9%84%D8%A9-%D8%A7%D9%84%D8%AC%D9%85%D8%B9%D8%A9.html
    +# 
    +#
    +# Our brief summary:
    +# 
    +# http://www.timeanddate.com/news/time/gaza-west-bank-dst-2012.html
    +# 
    +
    +# From Arthur David Olson (2012-03-27):
    +# The timeanddate article for 2012 says that "the end date has not yet been
    +# announced" and that "Last year, both...paused daylight saving time during...
    +# Ramadan. It is not yet known [for] 2012."
    +# For now, assume both switch back on the last Friday in September. XXX
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule EgyptAsia	1957	only	-	May	10	0:00	1:00	S
    +Rule EgyptAsia	1957	1958	-	Oct	 1	0:00	0	-
    +Rule EgyptAsia	1958	only	-	May	 1	0:00	1:00	S
    +Rule EgyptAsia	1959	1967	-	May	 1	1:00	1:00	S
    +Rule EgyptAsia	1959	1965	-	Sep	30	3:00	0	-
    +Rule EgyptAsia	1966	only	-	Oct	 1	3:00	0	-
    +
    +Rule Palestine	1999	2005	-	Apr	Fri>=15	0:00	1:00	S
    +Rule Palestine	1999	2003	-	Oct	Fri>=15	0:00	0	-
    +Rule Palestine	2004	only	-	Oct	 1	1:00	0	-
    +Rule Palestine	2005	only	-	Oct	 4	2:00	0	-
    +Rule Palestine	2006	2008	-	Apr	 1	0:00	1:00	S
    +Rule Palestine	2006	only	-	Sep	22	0:00	0	-
    +Rule Palestine	2007	only	-	Sep	Thu>=8	2:00	0	-
    +Rule Palestine	2008	only	-	Aug	lastFri	0:00	0	-
    +Rule Palestine	2009	only	-	Mar	lastFri	0:00	1:00	S
    +Rule Palestine	2009	only	-	Sep	Fri>=1	2:00	0	-
    +Rule Palestine	2010	only	-	Mar	lastSat	0:01	1:00	S
    +Rule Palestine	2010	only	-	Aug	11	0:00	0	-
    +
    +# From Arthur David Olson (2011-09-20):
    +# 2011 transitions per http://www.timeanddate.com as of 2011-09-20.
    +# From Paul Eggert (2012-10-12):
    +# 2012 transitions per http://www.timeanddate.com as of 2012-10-12.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Gaza	2:17:52	-	LMT	1900 Oct
    +			2:00	Zion	EET	1948 May 15
    +			2:00 EgyptAsia	EE%sT	1967 Jun  5
    +			2:00	Zion	I%sT	1996
    +			2:00	Jordan	EE%sT	1999
    +			2:00 Palestine	EE%sT	2011 Apr  2 12:01
    +			2:00	1:00	EEST	2011 Aug  1
    +			2:00	-	EET	2012 Mar 30
    +			2:00	1:00	EEST	2012 Sep 21 1:00
    +			2:00	-	EET
    +
    +Zone	Asia/Hebron	2:20:23	-	LMT	1900 Oct
    +			2:00	Zion	EET	1948 May 15
    +			2:00 EgyptAsia	EE%sT	1967 Jun  5
    +			2:00	Zion	I%sT	1996
    +			2:00	Jordan	EE%sT	1999
    +			2:00 Palestine	EE%sT	2008 Aug
    +			2:00 	1:00	EEST	2008 Sep
    +			2:00 Palestine	EE%sT	2011 Apr  1 12:01
    +			2:00	1:00	EEST	2011 Aug  1
    +			2:00	-	EET	2011 Aug 30
    +			2:00	1:00	EEST	2011 Sep 30 3:00
    +			2:00	-	EET	2012 Mar 30
    +			2:00	1:00	EEST	2012 Sep 21 1:00
    +			2:00	-	EET
    +
    +# Paracel Is
    +# no information
    +
    +# Philippines
    +# On 1844-08-16, Narciso Claveria, governor-general of the
    +# Philippines, issued a proclamation announcing that 1844-12-30 was to
    +# be immediately followed by 1845-01-01.  Robert H. van Gent has a
    +# transcript of the decree in .
    +# The rest of the data are from Shanks & Pottenger.
    +
    +# From Paul Eggert (2006-04-25):
    +# Tomorrow's Manila Standard reports that the Philippines Department of
    +# Trade and Industry is considering adopting DST this June when the
    +# rainy season begins.  See
    +# .
    +# For now, we'll ignore this, since it's not definite and we lack details.
    +#
    +# From Jesper Norgaard Welen (2006-04-26):
    +# ... claims that Philippines had DST last time in 1990:
    +# http://story.philippinetimes.com/p.x/ct/9/id/145be20cc6b121c0/cid/3e5bbccc730d258c/
    +# [a story dated 2006-04-25 by Cris Larano of Dow Jones Newswires,
    +# but no details]
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Phil	1936	only	-	Nov	1	0:00	1:00	S
    +Rule	Phil	1937	only	-	Feb	1	0:00	0	-
    +Rule	Phil	1954	only	-	Apr	12	0:00	1:00	S
    +Rule	Phil	1954	only	-	Jul	1	0:00	0	-
    +Rule	Phil	1978	only	-	Mar	22	0:00	1:00	S
    +Rule	Phil	1978	only	-	Sep	21	0:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Manila	-15:56:00 -	LMT	1844 Dec 31
    +			8:04:00 -	LMT	1899 May 11
    +			8:00	Phil	PH%sT	1942 May
    +			9:00	-	JST	1944 Nov
    +			8:00	Phil	PH%sT
    +
    +# Qatar
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Qatar	3:26:08 -	LMT	1920	# Al Dawhah / Doha
    +			4:00	-	GST	1972 Jun
    +			3:00	-	AST
    +
    +# Saudi Arabia
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Riyadh	3:06:52 -	LMT	1950
    +			3:00	-	AST
    +
    +# Singapore
    +# The data here are taken from Mok Ly Yng (2003-10-30)
    +# .
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
    +			6:55:25	-	SMT	1905 Jun  1 # Singapore M.T.
    +			7:00	-	MALT	1933 Jan  1 # Malaya Time
    +			7:00	0:20	MALST	1936 Jan  1
    +			7:20	-	MALT	1941 Sep  1
    +			7:30	-	MALT	1942 Feb 16
    +			9:00	-	JST	1945 Sep 12
    +			7:30	-	MALT	1965 Aug  9 # independence
    +			7:30	-	SGT	1982 Jan  1 # Singapore Time
    +			8:00	-	SGT
    +
    +# Spratly Is
    +# no information
    +
    +# Sri Lanka
    +# From Paul Eggert (1996-09-03):
    +# "Sri Lanka advances clock by an hour to avoid blackout"
    +# (www.virtual-pc.com/lankaweb/news/items/240596-2.html, 1996-05-24,
    +# no longer available as of 1999-08-17)
    +# reported ``the country's standard time will be put forward by one hour at
    +# midnight Friday (1830 GMT) `in the light of the present power crisis'.''
    +#
    +# From Dharmasiri Senanayake, Sri Lanka Media Minister (1996-10-24), as quoted
    +# by Shamindra in
    +# 
    +# Daily News - Hot News Section (1996-10-26)
    +# :
    +# With effect from 12.30 a.m. on 26th October 1996
    +# Sri Lanka will be six (06) hours ahead of GMT.
    +
    +# From Jesper Norgaard Welen (2006-04-14), quoting Sri Lanka News Online
    +#  (2006-04-13):
    +# 0030 hrs on April 15, 2006 (midnight of April 14, 2006 +30 minutes)
    +# at present, become 2400 hours of April 14, 2006 (midnight of April 14, 2006).
    +
    +# From Peter Apps and Ranga Sirila of Reuters (2006-04-12) in:
    +# 
    +# [The Tamil Tigers] never accepted the original 1996 time change and simply
    +# kept their clocks set five and a half hours ahead of Greenwich Mean
    +# Time (GMT), in line with neighbor India.
    +# From Paul Eggert (2006-04-18):
    +# People who live in regions under Tamil control can use [TZ='Asia/Kolkata'],
    +# as that zone has agreed with the Tamil areas since our cutoff date of 1970.
    +
    +# From K Sethu (2006-04-25):
    +# I think the abbreviation LKT originated from the world of computers at
    +# the time of or subsequent to the time zone changes by SL Government
    +# twice in 1996 and probably SL Government or its standardization
    +# agencies never declared an abbreviation as a national standard.
    +#
    +# I recollect before the recent change the government annoucemments
    +# mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka
    +# Time and no mention was made about the abbreviation.
    +#
    +# If we look at Sri Lanka Department of Government's "Official News
    +# Website of Sri Lanka" ... http://www.news.lk/ we can see that they
    +# use SLT as abbreviation in time stamp at the beginning of each news
    +# item....
    +#
    +# Within Sri Lanka I think LKT is well known among computer users and
    +# adminsitrators.  In my opinion SLT may not be a good choice because the
    +# nation's largest telcom / internet operator Sri Lanka Telcom is well
    +# known by that abbreviation - simply as SLT (there IP domains are
    +# slt.lk and sltnet.lk).
    +#
    +# But if indeed our government has adopted SLT as standard abbreviation
    +# (that we have not known so far) then  it is better that it be used for
    +# all computers.
    +
    +# From Paul Eggert (2006-04-25):
    +# One possibility is that we wait for a bit for the dust to settle down
    +# and then see what people actually say in practice.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Colombo	5:19:24 -	LMT	1880
    +			5:19:32	-	MMT	1906	# Moratuwa Mean Time
    +			5:30	-	IST	1942 Jan  5
    +			5:30	0:30	IHST	1942 Sep
    +			5:30	1:00	IST	1945 Oct 16 2:00
    +			5:30	-	IST	1996 May 25 0:00
    +			6:30	-	LKT	1996 Oct 26 0:30
    +			6:00	-	LKT	2006 Apr 15 0:30
    +			5:30	-	IST
    +
    +# Syria
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Syria	1920	1923	-	Apr	Sun>=15	2:00	1:00	S
    +Rule	Syria	1920	1923	-	Oct	Sun>=1	2:00	0	-
    +Rule	Syria	1962	only	-	Apr	29	2:00	1:00	S
    +Rule	Syria	1962	only	-	Oct	1	2:00	0	-
    +Rule	Syria	1963	1965	-	May	1	2:00	1:00	S
    +Rule	Syria	1963	only	-	Sep	30	2:00	0	-
    +Rule	Syria	1964	only	-	Oct	1	2:00	0	-
    +Rule	Syria	1965	only	-	Sep	30	2:00	0	-
    +Rule	Syria	1966	only	-	Apr	24	2:00	1:00	S
    +Rule	Syria	1966	1976	-	Oct	1	2:00	0	-
    +Rule	Syria	1967	1978	-	May	1	2:00	1:00	S
    +Rule	Syria	1977	1978	-	Sep	1	2:00	0	-
    +Rule	Syria	1983	1984	-	Apr	9	2:00	1:00	S
    +Rule	Syria	1983	1984	-	Oct	1	2:00	0	-
    +Rule	Syria	1986	only	-	Feb	16	2:00	1:00	S
    +Rule	Syria	1986	only	-	Oct	9	2:00	0	-
    +Rule	Syria	1987	only	-	Mar	1	2:00	1:00	S
    +Rule	Syria	1987	1988	-	Oct	31	2:00	0	-
    +Rule	Syria	1988	only	-	Mar	15	2:00	1:00	S
    +Rule	Syria	1989	only	-	Mar	31	2:00	1:00	S
    +Rule	Syria	1989	only	-	Oct	1	2:00	0	-
    +Rule	Syria	1990	only	-	Apr	1	2:00	1:00	S
    +Rule	Syria	1990	only	-	Sep	30	2:00	0	-
    +Rule	Syria	1991	only	-	Apr	 1	0:00	1:00	S
    +Rule	Syria	1991	1992	-	Oct	 1	0:00	0	-
    +Rule	Syria	1992	only	-	Apr	 8	0:00	1:00	S
    +Rule	Syria	1993	only	-	Mar	26	0:00	1:00	S
    +Rule	Syria	1993	only	-	Sep	25	0:00	0	-
    +# IATA SSIM (1998-02) says 1998-04-02;
    +# (1998-09) says 1999-03-29 and 1999-09-29; (1999-02) says 1999-04-02,
    +# 2000-04-02, and 2001-04-02; (1999-09) says 2000-03-31 and 2001-03-31;
    +# (2006) says 2006-03-31 and 2006-09-22;
    +# for now ignore all these claims and go with Shanks & Pottenger,
    +# except for the 2006-09-22 claim (which seems right for Ramadan).
    +Rule	Syria	1994	1996	-	Apr	 1	0:00	1:00	S
    +Rule	Syria	1994	2005	-	Oct	 1	0:00	0	-
    +Rule	Syria	1997	1998	-	Mar	lastMon	0:00	1:00	S
    +Rule	Syria	1999	2006	-	Apr	 1	0:00	1:00	S
    +# From Stephen Colebourne (2006-09-18):
    +# According to IATA data, Syria will change DST on 21st September [21:00 UTC]
    +# this year [only]....  This is probably related to Ramadan, like Egypt.
    +Rule	Syria	2006	only	-	Sep	22	0:00	0	-
    +# From Paul Eggert (2007-03-29):
    +# Today the AP reported "Syria will switch to summertime at midnight Thursday."
    +# http://www.iht.com/articles/ap/2007/03/29/africa/ME-GEN-Syria-Time-Change.php
    +Rule	Syria	2007	only	-	Mar	lastFri	0:00	1:00	S
    +# From Jesper Norgard (2007-10-27):
    +# The sister center ICARDA of my work CIMMYT is confirming that Syria DST will
    +# not take place 1.st November at 0:00 o'clock but 1.st November at 24:00 or
    +# rather Midnight between Thursday and Friday. This does make more sence than
    +# having it between Wednesday and Thursday (two workdays in Syria) since the
    +# weekend in Syria is not Saturday and Sunday, but Friday and Saturday. So now
    +# it is implemented at midnight of the last workday before weekend...
    +#
    +# From Steffen Thorsen (2007-10-27):
    +# Jesper Norgaard Welen wrote:
    +#
    +# > "Winter local time in Syria will be observed at midnight of Thursday 1
    +# > November 2007, and the clock will be put back 1 hour."
    +#
    +# I found confirmation on this in this gov.sy-article (Arabic):
    +# http://wehda.alwehda.gov.sy/_print_veiw.asp?FileName=12521710520070926111247
    +#
    +# which using Google's translate tools says:
    +# Council of Ministers also approved the commencement of work on
    +# identifying the winter time as of Friday, 2/11/2007 where the 60th
    +# minute delay at midnight Thursday 1/11/2007.
    +Rule	Syria	2007	only	-	Nov	 Fri>=1	0:00	0	-
    +
    +# From Stephen Colebourne (2008-03-17):
    +# For everyone's info, I saw an IATA time zone change for [Syria] for
    +# this month (March 2008) in the last day or so...This is the data IATA
    +# are now using:
    +# Country     Time Standard   --- DST Start ---   --- DST End ---  DST
    +# Name        Zone Variation   Time    Date        Time    Date
    +# Variation
    +# Syrian Arab
    +# Republic    SY    +0200      2200  03APR08       2100  30SEP08   +0300
    +#                              2200  02APR09       2100  30SEP09   +0300
    +#                              2200  01APR10       2100  30SEP10   +0300
    +
    +# From Arthur David Olson (2008-03-17):
    +# Here's a link to English-language coverage by the Syrian Arab News
    +# Agency (SANA)...
    +# 
    +# http://www.sana.sy/eng/21/2008/03/11/165173.htm
    +# ...which reads (in part) "The Cabinet approved the suggestion of the
    +# Ministry of Electricity to begin daylight savings time on Friday April
    +# 4th, advancing clocks one hour ahead on midnight of Thursday April 3rd."
    +# Since Syria is two hours east of UTC, the 2200 and 2100 transition times
    +# shown above match up with midnight in Syria.
    +
    +# From Arthur David Olson (2008-03-18):
    +# My buest guess at a Syrian rule is "the Friday nearest April 1";
    +# coding that involves either using a "Mar Fri>=29" construct that old time zone
    +# compilers can't handle  or having multiple Rules (a la Israel).
    +# For now, use "Apr Fri>=1", and go with IATA on a uniform Sep 30 end.
    +
    +# From Steffen Thorsen (2008-10-07):
    +# Syria has now officially decided to end DST on 2008-11-01 this year,
    +# according to the following article in the Syrian Arab News Agency (SANA).
    +#
    +# The article is in Arabic, and seems to tell that they will go back to
    +# winter time on 2008-11-01 at 00:00 local daylight time (delaying/setting
    +# clocks back 60 minutes).
    +#
    +# 
    +# http://sana.sy/ara/2/2008/10/07/195459.htm
    +# 
    +
    +# From Steffen Thorsen (2009-03-19):
    +# Syria will start DST on 2009-03-27 00:00 this year according to many sources,
    +# two examples:
    +#
    +# 
    +# http://www.sana.sy/eng/21/2009/03/17/217563.htm
    +# 
    +# (English, Syrian Arab News # Agency)
    +# 
    +# http://thawra.alwehda.gov.sy/_View_news2.asp?FileName=94459258720090318012209
    +# 
    +# (Arabic, gov-site)
    +#
    +# We have not found any sources saying anything about when DST ends this year.
    +#
    +# Our summary
    +# 
    +# http://www.timeanddate.com/news/time/syria-dst-starts-march-27-2009.html
    +# 
    +
    +# From Steffen Thorsen (2009-10-27):
    +# The Syrian Arab News Network on 2009-09-29 reported that Syria will
    +# revert back to winter (standard) time on midnight between Thursday
    +# 2009-10-29 and Friday 2009-10-30:
    +# 
    +# http://www.sana.sy/ara/2/2009/09/29/247012.htm (Arabic)
    +# 
    +
    +# From Arthur David Olson (2009-10-28):
    +# We'll see if future DST switching times turn out to be end of the last
    +# Thursday of the month or the start of the last Friday of the month or
    +# something else. For now, use the start of the last Friday.
    +
    +# From Steffen Thorsen (2010-03-17):
    +# The "Syrian News Station" reported on 2010-03-16 that the Council of
    +# Ministers has decided that Syria will start DST on midnight Thursday
    +# 2010-04-01: (midnight between Thursday and Friday):
    +# 
    +# http://sns.sy/sns/?path=news/read/11421 (Arabic)
    +# 
    +
    +# From Steffen Thorsen (2012-03-26):
    +# Today, Syria's government announced that they will start DST early on Friday
    +# (00:00). This is a bit earlier than the past two years.
    +#
    +# From Syrian Arab News Agency, in Arabic:
    +# 
    +# http://www.sana.sy/ara/2/2012/03/26/408215.htm
    +# 
    +#
    +# Our brief summary:
    +# 
    +# http://www.timeanddate.com/news/time/syria-dst-2012.html
    +# 
    +
    +# From Arthur David Olson (2012-03-27):
    +# Assume last Friday in March going forward XXX.
    +
    +Rule	Syria	2008	only	-	Apr	Fri>=1	0:00	1:00	S
    +Rule	Syria	2008	only	-	Nov	1	0:00	0	-
    +Rule	Syria	2009	only	-	Mar	lastFri	0:00	1:00	S
    +Rule	Syria	2010	2011	-	Apr	Fri>=1	0:00	1:00	S
    +Rule	Syria	2012	max	-	Mar	lastFri	0:00	1:00	S
    +Rule	Syria	2009	max	-	Oct	lastFri	0:00	0	-
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Damascus	2:25:12 -	LMT	1920	# Dimashq
    +			2:00	Syria	EE%sT
    +
    +# Tajikistan
    +# From Shanks & Pottenger.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Dushanbe	4:35:12 -	LMT	1924 May  2
    +			5:00	-	DUST	1930 Jun 21 # Dushanbe Time
    +			6:00 RussiaAsia DUS%sT	1991 Mar 31 2:00s
    +			5:00	1:00	DUSST	1991 Sep  9 2:00s
    +			5:00	-	TJT		    # Tajikistan Time
    +
    +# Thailand
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Bangkok	6:42:04	-	LMT	1880
    +			6:42:04	-	BMT	1920 Apr # Bangkok Mean Time
    +			7:00	-	ICT
    +
    +# Turkmenistan
    +# From Shanks & Pottenger.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Ashgabat	3:53:32 -	LMT	1924 May  2 # or Ashkhabad
    +			4:00	-	ASHT	1930 Jun 21 # Ashkhabad Time
    +			5:00 RussiaAsia	ASH%sT	1991 Mar 31 2:00
    +			4:00 RussiaAsia	ASH%sT	1991 Oct 27 # independence
    +			4:00 RussiaAsia	TM%sT	1992 Jan 19 2:00
    +			5:00	-	TMT
    +
    +# United Arab Emirates
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Dubai	3:41:12 -	LMT	1920
    +			4:00	-	GST
    +
    +# Uzbekistan
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Samarkand	4:27:12 -	LMT	1924 May  2
    +			4:00	-	SAMT	1930 Jun 21 # Samarkand Time
    +			5:00	-	SAMT	1981 Apr  1
    +			5:00	1:00	SAMST	1981 Oct  1
    +			6:00	-	TAST	1982 Apr  1 # Tashkent Time
    +			5:00 RussiaAsia	SAM%sT	1991 Sep  1 # independence
    +			5:00 RussiaAsia	UZ%sT	1992
    +			5:00	-	UZT
    +Zone	Asia/Tashkent	4:37:12 -	LMT	1924 May  2
    +			5:00	-	TAST	1930 Jun 21 # Tashkent Time
    +			6:00 RussiaAsia	TAS%sT	1991 Mar 31 2:00
    +			5:00 RussiaAsia	TAS%sT	1991 Sep  1 # independence
    +			5:00 RussiaAsia	UZ%sT	1992
    +			5:00	-	UZT
    +
    +# Vietnam
    +
    +# From Arthur David Olson (2008-03-18):
    +# The English-language name of Vietnam's most populous city is "Ho Chi Min City";
    +# we use Ho_Chi_Minh below to avoid a name of more than 14 characters.
    +
    +# From Shanks & Pottenger:
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Ho_Chi_Minh	7:06:40 -	LMT	1906 Jun  9
    +			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
    +			7:00	-	ICT	1912 May
    +			8:00	-	ICT	1931 May
    +			7:00	-	ICT
    +
    +# Yemen
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Asia/Aden	3:00:48	-	LMT	1950
    +			3:00	-	AST
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/australasia b/jdk/test/sun/util/calendar/zi/tzdata/australasia
    new file mode 100644
    index 00000000000..7f83448f3fb
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/australasia
    @@ -0,0 +1,1742 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# This file also includes Pacific islands.
    +
    +# Notes are at the end of this file
    +
    +###############################################################################
    +
    +# Australia
    +
    +# Please see the notes below for the controversy about "EST" versus "AEST" etc.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Aus	1917	only	-	Jan	 1	0:01	1:00	-
    +Rule	Aus	1917	only	-	Mar	25	2:00	0	-
    +Rule	Aus	1942	only	-	Jan	 1	2:00	1:00	-
    +Rule	Aus	1942	only	-	Mar	29	2:00	0	-
    +Rule	Aus	1942	only	-	Sep	27	2:00	1:00	-
    +Rule	Aus	1943	1944	-	Mar	lastSun	2:00	0	-
    +Rule	Aus	1943	only	-	Oct	 3	2:00	1:00	-
    +# Go with Whitman and the Australian National Standards Commission, which
    +# says W Australia didn't use DST in 1943/1944.  Ignore Whitman's claim that
    +# 1944/1945 was just like 1943/1944.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +# Northern Territory
    +Zone Australia/Darwin	 8:43:20 -	LMT	1895 Feb
    +			 9:00	-	CST	1899 May
    +			 9:30	Aus	CST
    +# Western Australia
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	AW	1974	only	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AW	1975	only	-	Mar	Sun>=1	2:00s	0	-
    +Rule	AW	1983	only	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AW	1984	only	-	Mar	Sun>=1	2:00s	0	-
    +Rule	AW	1991	only	-	Nov	17	2:00s	1:00	-
    +Rule	AW	1992	only	-	Mar	Sun>=1	2:00s	0	-
    +Rule	AW	2006	only	-	Dec	 3	2:00s	1:00	-
    +Rule	AW	2007	2009	-	Mar	lastSun	2:00s	0	-
    +Rule	AW	2007	2008	-	Oct	lastSun	2:00s	1:00	-
    +Zone Australia/Perth	 7:43:24 -	LMT	1895 Dec
    +			 8:00	Aus	WST	1943 Jul
    +			 8:00	AW	WST
    +Zone Australia/Eucla	 8:35:28 -	LMT	1895 Dec
    +			 8:45	Aus	CWST	1943 Jul
    +			 8:45	AW	CWST
    +
    +# Queensland
    +#
    +# From Alex Livingston (1996-11-01):
    +# I have heard or read more than once that some resort islands off the coast
    +# of Queensland chose to keep observing daylight-saving time even after
    +# Queensland ceased to.
    +#
    +# From Paul Eggert (1996-11-22):
    +# IATA SSIM (1993-02/1994-09) say that the Holiday Islands (Hayman, Lindeman,
    +# Hamilton) observed DST for two years after the rest of Queensland stopped.
    +# Hamilton is the largest, but there is also a Hamilton in Victoria,
    +# so use Lindeman.
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	AQ	1971	only	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AQ	1972	only	-	Feb	lastSun	2:00s	0	-
    +Rule	AQ	1989	1991	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AQ	1990	1992	-	Mar	Sun>=1	2:00s	0	-
    +Rule	Holiday	1992	1993	-	Oct	lastSun	2:00s	1:00	-
    +Rule	Holiday	1993	1994	-	Mar	Sun>=1	2:00s	0	-
    +Zone Australia/Brisbane	10:12:08 -	LMT	1895
    +			10:00	Aus	EST	1971
    +			10:00	AQ	EST
    +Zone Australia/Lindeman  9:55:56 -	LMT	1895
    +			10:00	Aus	EST	1971
    +			10:00	AQ	EST	1992 Jul
    +			10:00	Holiday	EST
    +
    +# South Australia
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	AS	1971	1985	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AS	1986	only	-	Oct	19	2:00s	1:00	-
    +Rule	AS	1987	2007	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AS	1972	only	-	Feb	27	2:00s	0	-
    +Rule	AS	1973	1985	-	Mar	Sun>=1	2:00s	0	-
    +Rule	AS	1986	1990	-	Mar	Sun>=15	2:00s	0	-
    +Rule	AS	1991	only	-	Mar	3	2:00s	0	-
    +Rule	AS	1992	only	-	Mar	22	2:00s	0	-
    +Rule	AS	1993	only	-	Mar	7	2:00s	0	-
    +Rule	AS	1994	only	-	Mar	20	2:00s	0	-
    +Rule	AS	1995	2005	-	Mar	lastSun	2:00s	0	-
    +Rule	AS	2006	only	-	Apr	2	2:00s	0	-
    +Rule	AS	2007	only	-	Mar	lastSun	2:00s	0	-
    +Rule	AS	2008	max	-	Apr	Sun>=1	2:00s	0	-
    +Rule	AS	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Australia/Adelaide	9:14:20 -	LMT	1895 Feb
    +			9:00	-	CST	1899 May
    +			9:30	Aus	CST	1971
    +			9:30	AS	CST
    +
    +# Tasmania
    +#
    +# From Paul Eggert (2005-08-16):
    +# 
    +# says King Island didn't observe DST from WWII until late 1971.
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	AT	1967	only	-	Oct	Sun>=1	2:00s	1:00	-
    +Rule	AT	1968	only	-	Mar	lastSun	2:00s	0	-
    +Rule	AT	1968	1985	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AT	1969	1971	-	Mar	Sun>=8	2:00s	0	-
    +Rule	AT	1972	only	-	Feb	lastSun	2:00s	0	-
    +Rule	AT	1973	1981	-	Mar	Sun>=1	2:00s	0	-
    +Rule	AT	1982	1983	-	Mar	lastSun	2:00s	0	-
    +Rule	AT	1984	1986	-	Mar	Sun>=1	2:00s	0	-
    +Rule	AT	1986	only	-	Oct	Sun>=15	2:00s	1:00	-
    +Rule	AT	1987	1990	-	Mar	Sun>=15	2:00s	0	-
    +Rule	AT	1987	only	-	Oct	Sun>=22	2:00s	1:00	-
    +Rule	AT	1988	1990	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AT	1991	1999	-	Oct	Sun>=1	2:00s	1:00	-
    +Rule	AT	1991	2005	-	Mar	lastSun	2:00s	0	-
    +Rule	AT	2000	only	-	Aug	lastSun	2:00s	1:00	-
    +Rule	AT	2001	max	-	Oct	Sun>=1	2:00s	1:00	-
    +Rule	AT	2006	only	-	Apr	Sun>=1	2:00s	0	-
    +Rule	AT	2007	only	-	Mar	lastSun	2:00s	0	-
    +Rule	AT	2008	max	-	Apr	Sun>=1	2:00s	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Australia/Hobart	9:49:16	-	LMT	1895 Sep
    +			10:00	-	EST	1916 Oct 1 2:00
    +			10:00	1:00	EST	1917 Feb
    +			10:00	Aus	EST	1967
    +			10:00	AT	EST
    +Zone Australia/Currie	9:35:28	-	LMT	1895 Sep
    +			10:00	-	EST	1916 Oct 1 2:00
    +			10:00	1:00	EST	1917 Feb
    +			10:00	Aus	EST	1971 Jul
    +			10:00	AT	EST
    +
    +# Victoria
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	AV	1971	1985	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AV	1972	only	-	Feb	lastSun	2:00s	0	-
    +Rule	AV	1973	1985	-	Mar	Sun>=1	2:00s	0	-
    +Rule	AV	1986	1990	-	Mar	Sun>=15	2:00s	0	-
    +Rule	AV	1986	1987	-	Oct	Sun>=15	2:00s	1:00	-
    +Rule	AV	1988	1999	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AV	1991	1994	-	Mar	Sun>=1	2:00s	0	-
    +Rule	AV	1995	2005	-	Mar	lastSun	2:00s	0	-
    +Rule	AV	2000	only	-	Aug	lastSun	2:00s	1:00	-
    +Rule	AV	2001	2007	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AV	2006	only	-	Apr	Sun>=1	2:00s	0	-
    +Rule	AV	2007	only	-	Mar	lastSun	2:00s	0	-
    +Rule	AV	2008	max	-	Apr	Sun>=1	2:00s	0	-
    +Rule	AV	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Australia/Melbourne 9:39:52 -	LMT	1895 Feb
    +			10:00	Aus	EST	1971
    +			10:00	AV	EST
    +
    +# New South Wales
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	AN	1971	1985	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AN	1972	only	-	Feb	27	2:00s	0	-
    +Rule	AN	1973	1981	-	Mar	Sun>=1	2:00s	0	-
    +Rule	AN	1982	only	-	Apr	Sun>=1	2:00s	0	-
    +Rule	AN	1983	1985	-	Mar	Sun>=1	2:00s	0	-
    +Rule	AN	1986	1989	-	Mar	Sun>=15	2:00s	0	-
    +Rule	AN	1986	only	-	Oct	19	2:00s	1:00	-
    +Rule	AN	1987	1999	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AN	1990	1995	-	Mar	Sun>=1	2:00s	0	-
    +Rule	AN	1996	2005	-	Mar	lastSun	2:00s	0	-
    +Rule	AN	2000	only	-	Aug	lastSun	2:00s	1:00	-
    +Rule	AN	2001	2007	-	Oct	lastSun	2:00s	1:00	-
    +Rule	AN	2006	only	-	Apr	Sun>=1	2:00s	0	-
    +Rule	AN	2007	only	-	Mar	lastSun	2:00s	0	-
    +Rule	AN	2008	max	-	Apr	Sun>=1	2:00s	0	-
    +Rule	AN	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Australia/Sydney	10:04:52 -	LMT	1895 Feb
    +			10:00	Aus	EST	1971
    +			10:00	AN	EST
    +Zone Australia/Broken_Hill 9:25:48 -	LMT	1895 Feb
    +			10:00	-	EST	1896 Aug 23
    +			9:00	-	CST	1899 May
    +			9:30	Aus	CST	1971
    +			9:30	AN	CST	2000
    +			9:30	AS	CST
    +
    +# Lord Howe Island
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	LH	1981	1984	-	Oct	lastSun	2:00	1:00	-
    +Rule	LH	1982	1985	-	Mar	Sun>=1	2:00	0	-
    +Rule	LH	1985	only	-	Oct	lastSun	2:00	0:30	-
    +Rule	LH	1986	1989	-	Mar	Sun>=15	2:00	0	-
    +Rule	LH	1986	only	-	Oct	19	2:00	0:30	-
    +Rule	LH	1987	1999	-	Oct	lastSun	2:00	0:30	-
    +Rule	LH	1990	1995	-	Mar	Sun>=1	2:00	0	-
    +Rule	LH	1996	2005	-	Mar	lastSun	2:00	0	-
    +Rule	LH	2000	only	-	Aug	lastSun	2:00	0:30	-
    +Rule	LH	2001	2007	-	Oct	lastSun	2:00	0:30	-
    +Rule	LH	2006	only	-	Apr	Sun>=1	2:00	0	-
    +Rule	LH	2007	only	-	Mar	lastSun	2:00	0	-
    +Rule	LH	2008	max	-	Apr	Sun>=1	2:00	0	-
    +Rule	LH	2008	max	-	Oct	Sun>=1	2:00	0:30	-
    +Zone Australia/Lord_Howe 10:36:20 -	LMT	1895 Feb
    +			10:00	-	EST	1981 Mar
    +			10:30	LH	LHST
    +
    +# Australian miscellany
    +#
    +# Ashmore Is, Cartier
    +# no indigenous inhabitants; only seasonal caretakers
    +# no times are set
    +#
    +# Coral Sea Is
    +# no indigenous inhabitants; only meteorologists
    +# no times are set
    +#
    +# Macquarie
    +# permanent occupation (scientific station) since 1948;
    +# sealing and penguin oil station operated 1888/1917
    +# like Australia/Hobart
    +
    +# Christmas
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Indian/Christmas	7:02:52 -	LMT	1895 Feb
    +			7:00	-	CXT	# Christmas Island Time
    +
    +# Cook Is
    +# From Shanks & Pottenger:
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Cook	1978	only	-	Nov	12	0:00	0:30	HS
    +Rule	Cook	1979	1991	-	Mar	Sun>=1	0:00	0	-
    +Rule	Cook	1979	1990	-	Oct	lastSun	0:00	0:30	HS
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Rarotonga	-10:39:04 -	LMT	1901		# Avarua
    +			-10:30	-	CKT	1978 Nov 12	# Cook Is Time
    +			-10:00	Cook	CK%sT
    +
    +# Cocos
    +# These islands were ruled by the Ross family from about 1830 to 1978.
    +# We don't know when standard time was introduced; for now, we guess 1900.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Indian/Cocos	6:27:40	-	LMT	1900
    +			6:30	-	CCT	# Cocos Islands Time
    +
    +# Fiji
    +# From Alexander Krivenyshev (2009-11-10):
    +# According to Fiji Broadcasting Corporation,  Fiji plans to re-introduce DST
    +# from November 29th 2009  to April 25th 2010.
    +#
    +# "Daylight savings to commence this month"
    +# 
    +# http://www.radiofiji.com.fj/fullstory.php?id=23719
    +# 
    +# or
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_fiji01.html
    +# 
    +
    +# From Steffen Thorsen (2009-11-10):
    +# The Fiji Government has posted some more details about the approved
    +# amendments:
    +# 
    +# http://www.fiji.gov.fj/publish/page_16198.shtml
    +# 
    +
    +# From Steffen Thorsen (2010-03-03):
    +# The Cabinet in Fiji has decided to end DST about a month early, on
    +# 2010-03-28 at 03:00.
    +# The plan is to observe DST again, from 2010-10-24 to sometime in March
    +# 2011 (last Sunday a good guess?).
    +#
    +# Official source:
    +# 
    +# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=1096:3310-cabinet-approves-change-in-daylight-savings-dates&catid=49:cabinet-releases&Itemid=166
    +# 
    +#
    +# A bit more background info here:
    +# 
    +# http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html
    +# 
    +
    +# From Alexander Krivenyshev (2010-10-24):
    +# According to Radio Fiji and Fiji Times online, Fiji will end DST 3
    +# weeks earlier than expected - on March 6, 2011, not March 27, 2011...
    +# Here is confirmation from Government of the Republic of the Fiji Islands,
    +# Ministry of Information (fiji.gov.fj) web site:
    +# 
    +# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155
    +# 
    +# or
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_fiji04.html
    +# 
    +
    +# From Steffen Thorsen (2011-10-03):
    +# Now the dates have been confirmed, and at least our start date
    +# assumption was correct (end date was one week wrong).
    +#
    +# 
    +# www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155
    +# 
    +# which says
    +# Members of the public are reminded to change their time to one hour in
    +# advance at 2am to 3am on October 23, 2011 and one hour back at 3am to
    +# 2am on February 26 next year.
    +
    +# From Ken Rylander (2011-10-24)
    +# Another change to the Fiji DST end date. In the TZ database the end date for
    +# Fiji DST 2012, is currently Feb 26. This has been changed to Jan 22.
    +#
    +# 
    +# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=5017:amendments-to-daylight-savings&catid=71:press-releases&Itemid=155
    +# 
    +# states:
    +#
    +# The end of daylight saving scheduled initially for the 26th of February 2012
    +# has been brought forward to the 22nd of January 2012.
    +# The commencement of daylight saving will remain unchanged and start
    +# on the  23rd of October, 2011.
    +
    +# From the Fiji Government Online Portal (2012-08-21) via Steffen Thorsen:
    +# The Minister for Labour, Industrial Relations and Employment Mr Jone Usamate
    +# today confirmed that Fiji will start daylight savings at 2 am on Sunday 21st
    +# October 2012 and end at 3 am on Sunday 20th January 2013.
    +# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=6702&catid=71&Itemid=155
    +#
    +# From Paul Eggert (2012-08-31):
    +# For now, guess a pattern of the penultimate Sundays in October and January.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Fiji	1998	1999	-	Nov	Sun>=1	2:00	1:00	S
    +Rule	Fiji	1999	2000	-	Feb	lastSun	3:00	0	-
    +Rule	Fiji	2009	only	-	Nov	29	2:00	1:00	S
    +Rule	Fiji	2010	only	-	Mar	lastSun	3:00	0	-
    +Rule	Fiji	2010	max	-	Oct	Sun>=18	2:00	1:00	S
    +Rule	Fiji	2011	only	-	Mar	Sun>=1	3:00	0	-
    +Rule	Fiji	2012	max	-	Jan	Sun>=18	3:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Pacific/Fiji	11:53:40 -	LMT	1915 Oct 26	# Suva
    +			12:00	Fiji	FJ%sT	# Fiji Time
    +
    +# French Polynesia
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Pacific/Gambier	 -8:59:48 -	LMT	1912 Oct	# Rikitea
    +			 -9:00	-	GAMT	# Gambier Time
    +Zone	Pacific/Marquesas -9:18:00 -	LMT	1912 Oct
    +			 -9:30	-	MART	# Marquesas Time
    +Zone	Pacific/Tahiti	 -9:58:16 -	LMT	1912 Oct	# Papeete
    +			-10:00	-	TAHT	# Tahiti Time
    +# Clipperton (near North America) is administered from French Polynesia;
    +# it is uninhabited.
    +
    +# Guam
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Pacific/Guam	-14:21:00 -	LMT	1844 Dec 31
    +			 9:39:00 -	LMT	1901		# Agana
    +			10:00	-	GST	2000 Dec 23	# Guam
    +			10:00	-	ChST	# Chamorro Standard Time
    +
    +# Kiribati
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Tarawa	 11:32:04 -	LMT	1901		# Bairiki
    +			 12:00	-	GILT		 # Gilbert Is Time
    +Zone Pacific/Enderbury	-11:24:20 -	LMT	1901
    +			-12:00	-	PHOT	1979 Oct # Phoenix Is Time
    +			-11:00	-	PHOT	1995
    +			 13:00	-	PHOT
    +Zone Pacific/Kiritimati	-10:29:20 -	LMT	1901
    +			-10:40	-	LINT	1979 Oct # Line Is Time
    +			-10:00	-	LINT	1995
    +			 14:00	-	LINT
    +
    +# N Mariana Is
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Saipan	-14:17:00 -	LMT	1844 Dec 31
    +			 9:43:00 -	LMT	1901
    +			 9:00	-	MPT	1969 Oct # N Mariana Is Time
    +			10:00	-	MPT	2000 Dec 23
    +			10:00	-	ChST	# Chamorro Standard Time
    +
    +# Marshall Is
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Majuro	11:24:48 -	LMT	1901
    +			11:00	-	MHT	1969 Oct # Marshall Islands Time
    +			12:00	-	MHT
    +Zone Pacific/Kwajalein	11:09:20 -	LMT	1901
    +			11:00	-	MHT	1969 Oct
    +			-12:00	-	KWAT	1993 Aug 20	# Kwajalein Time
    +			12:00	-	MHT
    +
    +# Micronesia
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Chuuk	10:07:08 -	LMT	1901
    +			10:00	-	CHUT			# Chuuk Time
    +Zone Pacific/Pohnpei	10:32:52 -	LMT	1901		# Kolonia
    +			11:00	-	PONT			# Pohnpei Time
    +Zone Pacific/Kosrae	10:51:56 -	LMT	1901
    +			11:00	-	KOST	1969 Oct	# Kosrae Time
    +			12:00	-	KOST	1999
    +			11:00	-	KOST
    +
    +# Nauru
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Pacific/Nauru	11:07:40 -	LMT	1921 Jan 15	# Uaobe
    +			11:30	-	NRT	1942 Mar 15	# Nauru Time
    +			9:00	-	JST	1944 Aug 15
    +			11:30	-	NRT	1979 May
    +			12:00	-	NRT
    +
    +# New Caledonia
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	NC	1977	1978	-	Dec	Sun>=1	0:00	1:00	S
    +Rule	NC	1978	1979	-	Feb	27	0:00	0	-
    +Rule	NC	1996	only	-	Dec	 1	2:00s	1:00	S
    +# Shanks & Pottenger say the following was at 2:00; go with IATA.
    +Rule	NC	1997	only	-	Mar	 2	2:00s	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Pacific/Noumea	11:05:48 -	LMT	1912 Jan 13
    +			11:00	NC	NC%sT
    +
    +
    +###############################################################################
    +
    +# New Zealand
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	NZ	1927	only	-	Nov	 6	2:00	1:00	S
    +Rule	NZ	1928	only	-	Mar	 4	2:00	0	M
    +Rule	NZ	1928	1933	-	Oct	Sun>=8	2:00	0:30	S
    +Rule	NZ	1929	1933	-	Mar	Sun>=15	2:00	0	M
    +Rule	NZ	1934	1940	-	Apr	lastSun	2:00	0	M
    +Rule	NZ	1934	1940	-	Sep	lastSun	2:00	0:30	S
    +Rule	NZ	1946	only	-	Jan	 1	0:00	0	S
    +# Since 1957 Chatham has been 45 minutes ahead of NZ, but there's no
    +# convenient notation for this so we must duplicate the Rule lines.
    +Rule	NZ	1974	only	-	Nov	Sun>=1	2:00s	1:00	D
    +Rule	Chatham	1974	only	-	Nov	Sun>=1	2:45s	1:00	D
    +Rule	NZ	1975	only	-	Feb	lastSun	2:00s	0	S
    +Rule	Chatham	1975	only	-	Feb	lastSun	2:45s	0	S
    +Rule	NZ	1975	1988	-	Oct	lastSun	2:00s	1:00	D
    +Rule	Chatham	1975	1988	-	Oct	lastSun	2:45s	1:00	D
    +Rule	NZ	1976	1989	-	Mar	Sun>=1	2:00s	0	S
    +Rule	Chatham	1976	1989	-	Mar	Sun>=1	2:45s	0	S
    +Rule	NZ	1989	only	-	Oct	Sun>=8	2:00s	1:00	D
    +Rule	Chatham	1989	only	-	Oct	Sun>=8	2:45s	1:00	D
    +Rule	NZ	1990	2006	-	Oct	Sun>=1	2:00s	1:00	D
    +Rule	Chatham	1990	2006	-	Oct	Sun>=1	2:45s	1:00	D
    +Rule	NZ	1990	2007	-	Mar	Sun>=15	2:00s	0	S
    +Rule	Chatham	1990	2007	-	Mar	Sun>=15	2:45s	0	S
    +Rule	NZ	2007	max	-	Sep	lastSun	2:00s	1:00	D
    +Rule	Chatham	2007	max	-	Sep	lastSun	2:45s	1:00	D
    +Rule	NZ	2008	max	-	Apr	Sun>=1	2:00s	0	S
    +Rule	Chatham	2008	max	-	Apr	Sun>=1	2:45s	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Auckland	11:39:04 -	LMT	1868 Nov  2
    +			11:30	NZ	NZ%sT	1946 Jan  1
    +			12:00	NZ	NZ%sT
    +Zone Pacific/Chatham	12:13:48 -	LMT	1957 Jan  1
    +			12:45	Chatham	CHA%sT
    +
    +
    +# Auckland Is
    +# uninhabited; Maori and Moriori, colonial settlers, pastoralists, sealers,
    +# and scientific personnel have wintered
    +
    +# Campbell I
    +# minor whaling stations operated 1909/1914
    +# scientific station operated 1941/1995;
    +# previously whalers, sealers, pastoralists, and scientific personnel wintered
    +# was probably like Pacific/Auckland
    +
    +###############################################################################
    +
    +
    +# Niue
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Pacific/Niue	-11:19:40 -	LMT	1901		# Alofi
    +			-11:20	-	NUT	1951	# Niue Time
    +			-11:30	-	NUT	1978 Oct 1
    +			-11:00	-	NUT
    +
    +# Norfolk
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Pacific/Norfolk	11:11:52 -	LMT	1901		# Kingston
    +			11:12	-	NMT	1951	# Norfolk Mean Time
    +			11:30	-	NFT		# Norfolk Time
    +
    +# Palau (Belau)
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Palau	8:57:56 -	LMT	1901		# Koror
    +			9:00	-	PWT	# Palau Time
    +
    +# Papua New Guinea
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Port_Moresby 9:48:40 -	LMT	1880
    +			9:48:32	-	PMMT	1895	# Port Moresby Mean Time
    +			10:00	-	PGT		# Papua New Guinea Time
    +
    +# Pitcairn
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Pitcairn	-8:40:20 -	LMT	1901		# Adamstown
    +			-8:30	-	PNT	1998 Apr 27 00:00
    +			-8:00	-	PST	# Pitcairn Standard Time
    +
    +# American Samoa
    +Zone Pacific/Pago_Pago	 12:37:12 -	LMT	1879 Jul  5
    +			-11:22:48 -	LMT	1911
    +			-11:30	-	SAMT	1950		# Samoa Time
    +			-11:00	-	NST	1967 Apr	# N=Nome
    +			-11:00	-	BST	1983 Nov 30	# B=Bering
    +			-11:00	-	SST			# S=Samoa
    +
    +# Samoa
    +
    +# From Steffen Thorsen (2009-10-16):
    +# We have been in contact with the government of Samoa again, and received
    +# the following info:
    +#
    +# "Cabinet has now approved Daylight Saving to be effected next year
    +# commencing from the last Sunday of September 2010 and conclude first
    +# Sunday of April 2011."
    +#
    +# Background info:
    +# 
    +# http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html
    +# 
    +#
    +# Samoa's Daylight Saving Time Act 2009 is available here, but does not
    +# contain any dates:
    +# 
    +# http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf
    +# 
    +
    +# From Laupue Raymond Hughes (2010-10-07):
    +# Please see
    +# 
    +# http://www.mcil.gov.ws
    +# ,
    +# the Ministry of Commerce, Industry and Labour (sideframe) "Last Sunday
    +# September 2010 (26/09/10) - adjust clocks forward from 12:00 midnight
    +# to 01:00am and First Sunday April 2011 (03/04/11) - adjust clocks
    +# backwards from 1:00am to 12:00am"
    +
    +# From Laupue Raymond Hughes (2011-03-07):
    +# I believe this will be posted shortly on the website
    +# 
    +# www.mcil.gov.ws
    +# 
    +#
    +# PUBLIC NOTICE ON DAYLIGHT SAVING TIME
    +#
    +# Pursuant to the Daylight Saving Act 2009 and Cabinets decision,
    +# businesses and the general public are hereby advised that daylight
    +# saving time is on the first Saturday of April 2011 (02/04/11).
    +#
    +# The public is therefore advised that when the standard time strikes
    +# the hour of four oclock (4.00am or 0400 Hours) on the 2nd April 2011,
    +# then all instruments used to measure standard time are to be
    +# adjusted/changed to three oclock (3:00am or 0300Hrs).
    +#
    +# Margaret Fruean ACTING CHIEF EXECUTIVE OFFICER MINISTRY OF COMMERCE,
    +# INDUSTRY AND LABOUR 28th February 2011
    +
    +# From David Zuelke (2011-05-09):
    +# Subject: Samoa to move timezone from east to west of international date line
    +#
    +# 
    +# http://www.morningstar.co.uk/uk/markets/newsfeeditem.aspx?id=138501958347963
    +# 
    +
    +# From Mark Sim-Smith (2011-08-17):
    +# I have been in contact with Leilani Tuala Warren from the Samoa Law
    +# Reform Commission, and she has sent me a copy of the Bill that she
    +# confirmed has been passed...Most of the sections are about maps rather
    +# than the time zone change, but I'll paste the relevant bits below. But
    +# the essence is that at midnight 29 Dec (UTC-11 I suppose), Samoa
    +# changes from UTC-11 to UTC+13:
    +#
    +# International Date Line Bill 2011
    +#
    +# AN ACT to provide for the change to standard time in Samoa and to make
    +# consequential amendments to the position of the International Date
    +# Line, and for related purposes.
    +#
    +# BE IT ENACTED by the Legislative Assembly of Samoa in Parliament
    +# assembled as follows:
    +#
    +# 1. Short title and commencement-(1) This Act may be cited as the
    +# International Date Line Act 2011. (2) Except for section 5(3) this Act
    +# commences at 12 o'clock midnight, on Thursday 29th December 2011. (3)
    +# Section 5(3) commences on the date of assent by the Head of State.
    +#
    +# [snip]
    +#
    +# 3. Interpretation - [snip] "Samoa standard time" in this Act and any
    +# other statute of Samoa which refers to 'Samoa standard time' means the
    +# time 13 hours in advance of Co-ordinated Universal Time.
    +#
    +# 4. Samoa standard time - (1) Upon the commencement of this Act, Samoa
    +# standard time shall be set at 13 hours in advance of Co-ordinated
    +# Universal Time for the whole of Samoa. (2) All references to Samoa's
    +# time zone and to Samoa standard time in Samoa in all legislation and
    +# instruments after the commencement of this Act shall be references to
    +# Samoa standard time as provided for in this Act. (3) Nothing in this
    +# Act affects the provisions of the Daylight Saving Act 2009, except that
    +# it defines Samoa standard time....
    +
    +# From Laupue Raymond Hughes (2011-09-02):
    +# 
    +# http://www.mcil.gov.ws/mcil_publications.html
    +# 
    +#
    +# here is the official website publication for Samoa DST and dateline change
    +#
    +# DST
    +# Year	End	Time	Start	Time
    +# 2011	- - -	- - -	24 September	3:00am to 4:00am
    +# 2012	01 April	4:00am to 3:00am	- - -	- - -
    +#
    +# Dateline Change skip Friday 30th Dec 2011
    +# Thursday 29th December 2011	23:59:59 Hours
    +# Saturday 31st December 2011	00:00:00 Hours
    +#
    +# Clarification by Tim Parenti (2012-01-03):
    +# Although Samoa has used Daylight Saving Time in the 2010-2011 and 2011-2012
    +# seasons, there is not yet any indication that this trend will continue on
    +# a regular basis. For now, we have explicitly listed the transitions below.
    +#
    +# From Nicky (2012-09-10):
    +# Daylight Saving Time commences on Sunday 30th September 2012 and
    +# ends on Sunday 7th of April 2013.
    +#
    +# Please find link below for more information.
    +# http://www.mcil.gov.ws/mcil_publications.html
    +#
    +# That publication also includes dates for Summer of 2013/4 as well
    +# which give the impression of a pattern in selecting dates for the
    +# future, so for now, we will guess this will continue.
    +
    +# Western Samoa
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	WS	2012	max	-	Sep	lastSun	3:00	1	D
    +Rule	WS	2012	max	-	Apr	Sun>=1	4:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Apia	 12:33:04 -	LMT	1879 Jul  5
    +			-11:26:56 -	LMT	1911
    +			-11:30	-	SAMT	1950		# Samoa Time
    +			-11:00	-	WST	2010 Sep 26
    +			-11:00	1:00	WSDT	2011 Apr 2 4:00
    +			-11:00	-	WST	2011 Sep 24 3:00
    +			-11:00	1:00	WSDT	2011 Dec 30
    +			 13:00	1:00	WSDT	2012 Apr Sun>=1 4:00
    +			 13:00	WS	WS%sT
    +
    +# Solomon Is
    +# excludes Bougainville, for which see Papua New Guinea
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct	# Honiara
    +			11:00	-	SBT	# Solomon Is Time
    +
    +# Tokelau Is
    +#
    +# From Gwillim Law (2011-12-29)
    +# A correspondent informed me that Tokelau, like Samoa, will be skipping
    +# December 31 this year ...
    +#
    +# From Steffen Thorsen (2012-07-25)
    +# ... we double checked by calling hotels and offices based in Tokelau asking
    +# about the time there, and they all told a time that agrees with UTC+13....
    +# Shanks says UTC-10 from 1901 [but] ... there is a good chance the change
    +# actually was to UTC-11 back then.
    +#
    +# From Paul Eggert (2012-07-25)
    +# A Google Books snippet of Appendix to the Journals of the House of
    +# Representatives of New Zealand, Session 1948,
    +# , page 65, says Tokelau
    +# was "11 hours slow on G.M.T."  Go with Thorsen and assume Shanks & Pottenger
    +# are off by an hour starting in 1901.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Pacific/Fakaofo	-11:24:56 -	LMT	1901
    +			-11:00	-	TKT 2011 Dec 30	# Tokelau Time
    +			13:00	-	TKT
    +
    +# Tonga
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Tonga	1999	only	-	Oct	 7	2:00s	1:00	S
    +Rule	Tonga	2000	only	-	Mar	19	2:00s	0	-
    +Rule	Tonga	2000	2001	-	Nov	Sun>=1	2:00	1:00	S
    +Rule	Tonga	2001	2002	-	Jan	lastSun	2:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Tongatapu	12:19:20 -	LMT	1901
    +			12:20	-	TOT	1941 # Tonga Time
    +			13:00	-	TOT	1999
    +			13:00	Tonga	TO%sT
    +
    +# Tuvalu
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Funafuti	11:56:52 -	LMT	1901
    +			12:00	-	TVT	# Tuvalu Time
    +
    +
    +# US minor outlying islands
    +
    +# Howland, Baker
    +# Howland was mined for guano by American companies 1857-1878 and British
    +# 1886-1891; Baker was similar but exact dates are not known.
    +# Inhabited by civilians 1935-1942; U.S. military bases 1943-1944;
    +# uninhabited thereafter.
    +# Howland observed Hawaii Standard Time (UTC-10:30) in 1937;
    +# see page 206 of Elgen M. Long and Marie K. Long,
    +# Amelia Earhart: the Mystery Solved, Simon & Schuster (2000).
    +# So most likely Howland and Baker observed Hawaii Time from 1935
    +# until they were abandoned after the war.
    +
    +# Jarvis
    +# Mined for guano by American companies 1857-1879 and British 1883?-1891?.
    +# Inhabited by civilians 1935-1942; IGY scientific base 1957-1958;
    +# uninhabited thereafter.
    +# no information; was probably like Pacific/Kiritimati
    +
    +# Johnston
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Pacific/Johnston	-10:00	-	HST
    +
    +# Kingman
    +# uninhabited
    +
    +# Midway
    +#
    +# From Mark Brader (2005-01-23):
    +# [Fallacies and Fantasies of Air Transport History, by R.E.G. Davies,
    +# published 1994 by Paladwr Press, McLean, VA, USA; ISBN 0-9626483-5-3]
    +# reproduced a Pan American Airways timeables from 1936, for their weekly
    +# "Orient Express" flights between San Francisco and Manila, and connecting
    +# flights to Chicago and the US East Coast.  As it uses some time zone
    +# designations that I've never seen before:....
    +# Fri. 6:30A Lv. HONOLOLU (Pearl Harbor), H.I.   H.L.T. Ar. 5:30P Sun.
    +#  "   3:00P Ar. MIDWAY ISLAND . . . . . . . . . M.L.T. Lv. 6:00A  "
    +#
    +Zone Pacific/Midway	-11:49:28 -	LMT	1901
    +			-11:00	-	NST	1956 Jun  3
    +			-11:00	1:00	NDT	1956 Sep  2
    +			-11:00	-	NST	1967 Apr	# N=Nome
    +			-11:00	-	BST	1983 Nov 30	# B=Bering
    +			-11:00	-	SST			# S=Samoa
    +
    +# Palmyra
    +# uninhabited since World War II; was probably like Pacific/Kiritimati
    +
    +# Wake
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Pacific/Wake	11:06:28 -	LMT	1901
    +			12:00	-	WAKT	# Wake Time
    +
    +
    +# Vanuatu
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Vanuatu	1983	only	-	Sep	25	0:00	1:00	S
    +Rule	Vanuatu	1984	1991	-	Mar	Sun>=23	0:00	0	-
    +Rule	Vanuatu	1984	only	-	Oct	23	0:00	1:00	S
    +Rule	Vanuatu	1985	1991	-	Sep	Sun>=23	0:00	1:00	S
    +Rule	Vanuatu	1992	1993	-	Jan	Sun>=23	0:00	0	-
    +Rule	Vanuatu	1992	only	-	Oct	Sun>=23	0:00	1:00	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Pacific/Efate	11:13:16 -	LMT	1912 Jan 13		# Vila
    +			11:00	Vanuatu	VU%sT	# Vanuatu Time
    +
    +# Wallis and Futuna
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Pacific/Wallis	12:15:20 -	LMT	1901
    +			12:00	-	WFT	# Wallis & Futuna Time
    +
    +###############################################################################
    +
    +# NOTES
    +
    +# This data is by no means authoritative; if you think you know better,
    +# go ahead and edit the file (and please send any changes to
    +# tz@elsie.nci.nih.gov for general use in the future).
    +
    +# From Paul Eggert (2006-03-22):
    +# A good source for time zone historical data outside the U.S. is
    +# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
    +# San Diego: ACS Publications, Inc. (2003).
    +#
    +# Gwillim Law writes that a good source
    +# for recent time zone data is the International Air Transport
    +# Association's Standard Schedules Information Manual (IATA SSIM),
    +# published semiannually.  Law sent in several helpful summaries
    +# of the IATA's data after 1990.
    +#
    +# Except where otherwise noted, Shanks & Pottenger is the source for
    +# entries through 1990, and IATA SSIM is the source for entries afterwards.
    +#
    +# Another source occasionally used is Edward W. Whitman, World Time Differences,
    +# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
    +# I found in the UCLA library.
    +#
    +# A reliable and entertaining source about time zones is
    +# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
    +#
    +# I invented the abbreviations marked `*' in the following table;
    +# the rest are from earlier versions of this file, or from other sources.
    +# Corrections are welcome!
    +#		std dst
    +#		LMT	Local Mean Time
    +#	  8:00	WST WST	Western Australia
    +#	  8:45	CWST CWST Central Western Australia*
    +#	  9:00	JST	Japan
    +#	  9:30	CST CST	Central Australia
    +#	 10:00	EST EST	Eastern Australia
    +#	 10:00	ChST	Chamorro
    +#	 10:30	LHST LHST Lord Howe*
    +#	 11:30	NZMT NZST New Zealand through 1945
    +#	 12:00	NZST NZDT New Zealand 1946-present
    +#	 12:45	CHAST CHADT Chatham*
    +#	-11:00	SST	Samoa
    +#	-10:00	HST	Hawaii
    +#	- 8:00	PST	Pitcairn*
    +#
    +# See the `northamerica' file for Hawaii.
    +# See the `southamerica' file for Easter I and the Galapagos Is.
    +
    +###############################################################################
    +
    +# Australia
    +
    +# From Paul Eggert (2005-12-08):
    +# 
    +# Implementation Dates of Daylight Saving Time within Australia
    +#  summarizes daylight saving issues in Australia.
    +
    +# From Arthur David Olson (2005-12-12):
    +# 
    +# Lawlink NSW:Daylight Saving in New South Wales
    +#  covers New South Wales in particular.
    +
    +# From John Mackin (1991-03-06):
    +# We in Australia have _never_ referred to DST as `daylight' time.
    +# It is called `summer' time.  Now by a happy coincidence, `summer'
    +# and `standard' happen to start with the same letter; hence, the
    +# abbreviation does _not_ change...
    +# The legislation does not actually define abbreviations, at least
    +# in this State, but the abbreviation is just commonly taken to be the
    +# initials of the phrase, and the legislation here uniformly uses
    +# the phrase `summer time' and does not use the phrase `daylight
    +# time'.
    +# Announcers on the Commonwealth radio network, the ABC (for Australian
    +# Broadcasting Commission), use the phrases `Eastern Standard Time'
    +# or `Eastern Summer Time'.  (Note, though, that as I say in the
    +# current australasia file, there is really no such thing.)  Announcers
    +# on its overseas service, Radio Australia, use the same phrases
    +# prefixed by the word `Australian' when referring to local times;
    +# time announcements on that service, naturally enough, are made in UTC.
    +
    +# From Arthur David Olson (1992-03-08):
    +# Given the above, what's chosen for year-round use is:
    +#	CST	for any place operating at a GMTOFF of 9:30
    +#	WST	for any place operating at a GMTOFF of 8:00
    +#	EST	for any place operating at a GMTOFF of 10:00
    +
    +# From Chuck Soper (2006-06-01):
    +# I recently found this Australian government web page on time zones:
    +# 
    +# And this government web page lists time zone names and abbreviations:
    +# 
    +
    +# From Paul Eggert (2001-04-05), summarizing a long discussion about "EST"
    +# versus "AEST" etc.:
    +#
    +# I see the following points of dispute:
    +#
    +# * How important are unique time zone abbreviations?
    +#
    +#   Here I tend to agree with the point (most recently made by Chris
    +#   Newman) that unique abbreviations should not be essential for proper
    +#   operation of software.  We have other instances of ambiguity
    +#   (e.g. "IST" denoting both "Israel Standard Time" and "Indian
    +#   Standard Time"), and they are not likely to go away any time soon.
    +#   In the old days, some software mistakenly relied on unique
    +#   abbreviations, but this is becoming less true with time, and I don't
    +#   think it's that important to cater to such software these days.
    +#
    +#   On the other hand, there is another motivation for unambiguous
    +#   abbreviations: it cuts down on human confusion.  This is
    +#   particularly true for Australia, where "EST" can mean one thing for
    +#   time T and a different thing for time T plus 1 second.
    +#
    +# * Does the relevant legislation indicate which abbreviations should be used?
    +#
    +#   Here I tend to think that things are a mess, just as they are in
    +#   many other countries.  We Americans are currently disagreeing about
    +#   which abbreviation to use for the newly legislated Chamorro Standard
    +#   Time, for example.
    +#
    +#   Personally, I would prefer to use common practice; I would like to
    +#   refer to legislation only for examples of common practice, or as a
    +#   tiebreaker.
    +#
    +# * Do Australians more often use "Eastern Daylight Time" or "Eastern
    +#   Summer Time"?  Do they typically prefix the time zone names with
    +#   the word "Australian"?
    +#
    +#   My own impression is that both "Daylight Time" and "Summer Time" are
    +#   common and are widely understood, but that "Summer Time" is more
    +#   popular; and that the leading "A" is also common but is omitted more
    +#   often than not.  I just used AltaVista advanced search and got the
    +#   following count of page hits:
    +#
    +#     1,103 "Eastern Summer Time" AND domain:au
    +#       971 "Australian Eastern Summer Time" AND domain:au
    +#       613 "Eastern Daylight Time" AND domain:au
    +#       127 "Australian Eastern Daylight Time" AND domain:au
    +#
    +#   Here "Summer" seems quite a bit more popular than "Daylight",
    +#   particularly when we know the time zone is Australian and not US,
    +#   say.  The "Australian" prefix seems to be popular for Eastern Summer
    +#   Time, but unpopular for Eastern Daylight Time.
    +#
    +#   For abbreviations, tools like AltaVista are less useful because of
    +#   ambiguity.  Many hits are not really time zones, unfortunately, and
    +#   many hits denote US time zones and not Australian ones.  But here
    +#   are the hit counts anyway:
    +#
    +#     161,304 "EST" and domain:au
    +#      25,156 "EDT" and domain:au
    +#      18,263 "AEST" and domain:au
    +#      10,416 "AEDT" and domain:au
    +#
    +#      14,538 "CST" and domain:au
    +#       5,728 "CDT" and domain:au
    +#         176 "ACST" and domain:au
    +#          29 "ACDT" and domain:au
    +#
    +#       7,539 "WST" and domain:au
    +#          68 "AWST" and domain:au
    +#
    +#   This data suggest that Australians tend to omit the "A" prefix in
    +#   practice.  The situation for "ST" versus "DT" is less clear, given
    +#   the ambiguities involved.
    +#
    +# * How do Australians feel about the abbreviations in the tz database?
    +#
    +#   If you just count Australians on this list, I count 2 in favor and 3
    +#   against.  One of the "against" votes (David Keegel) counseled delay,
    +#   saying that both AEST/AEDT and EST/EST are widely used and
    +#   understood in Australia.
    +
    +# From Paul Eggert (1995-12-19):
    +# Shanks & Pottenger report 2:00 for all autumn changes in Australia and NZ.
    +# Mark Prior writes that his newspaper
    +# reports that NSW's fall 1995 change will occur at 2:00,
    +# but Robert Elz says it's been 3:00 in Victoria since 1970
    +# and perhaps the newspaper's `2:00' is referring to standard time.
    +# For now we'll continue to assume 2:00s for changes since 1960.
    +
    +# From Eric Ulevik (1998-01-05):
    +#
    +# Here are some URLs to Australian time legislation. These URLs are stable,
    +# and should probably be included in the data file. There are probably more
    +# relevant entries in this database.
    +#
    +# NSW (including LHI and Broken Hill):
    +# 
    +# Standard Time Act 1987 (updated 1995-04-04)
    +# 
    +# ACT
    +# 
    +# Standard Time and Summer Time Act 1972
    +# 
    +# SA
    +# 
    +# Standard Time Act, 1898
    +# 
    +
    +# From David Grosz (2005-06-13):
    +# It was announced last week that Daylight Saving would be extended by
    +# one week next year to allow for the 2006 Commonwealth Games.
    +# Daylight Saving is now to end for next year only on the first Sunday
    +# in April instead of the last Sunday in March.
    +#
    +# From Gwillim Law (2005-06-14):
    +# I did some Googling and found that all of those states (and territory) plan
    +# to extend DST together in 2006.
    +# ACT: http://www.cmd.act.gov.au/mediareleases/fileread.cfm?file=86.txt
    +# New South Wales: http://www.thecouriermail.news.com.au/common/story_page/0,5936,15538869%255E1702,00.html
    +# South Australia: http://www.news.com.au/story/0,10117,15555031-1246,00.html
    +# Tasmania: http://www.media.tas.gov.au/release.php?id=14772
    +# Victoria: I wasn't able to find anything separate, but the other articles
    +# allude to it.
    +# But not Queensland
    +# http://www.news.com.au/story/0,10117,15564030-1248,00.html.
    +
    +# Northern Territory
    +
    +# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
    +# # The NORTHERN TERRITORY..  [ Courtesy N.T. Dept of the Chief Minister ]
    +# #					[ Nov 1990 ]
    +# #	N.T. have never utilised any DST due to sub-tropical/tropical location.
    +# ...
    +# Zone        Australia/North         9:30    -       CST
    +
    +# From Bradley White (1991-03-04):
    +# A recent excerpt from an Australian newspaper...
    +# the Northern Territory do[es] not have daylight saving.
    +
    +# Western Australia
    +
    +# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
    +# #  The state of WESTERN AUSTRALIA..  [ Courtesy W.A. dept Premier+Cabinet ]
    +# #						[ Nov 1990 ]
    +# #	W.A. suffers from a great deal of public and political opposition to
    +# #	DST in principle. A bill is brought before parliament in most years, but
    +# #	usually defeated either in the upper house, or in party caucus
    +# #	before reaching parliament.
    +# ...
    +# Zone	Australia/West		8:00	AW	%sST
    +# ...
    +# Rule	AW	1974	only	-	Oct	lastSun	2:00	1:00	D
    +# Rule	AW	1975	only	-	Mar	Sun>=1	3:00	0	W
    +# Rule	AW	1983	only	-	Oct	lastSun	2:00	1:00	D
    +# Rule	AW	1984	only	-	Mar	Sun>=1	3:00	0	W
    +
    +# From Bradley White (1991-03-04):
    +# A recent excerpt from an Australian newspaper...
    +# Western Australia...do[es] not have daylight saving.
    +
    +# From John D. Newman via Bradley White (1991-11-02):
    +# Western Australia is still on "winter time". Some DH in Sydney
    +# rang me at home a few days ago at 6.00am. (He had just arrived at
    +# work at 9.00am.)
    +# W.A. is switching to Summer Time on Nov 17th just to confuse
    +# everybody again.
    +
    +# From Arthur David Olson (1992-03-08):
    +# The 1992 ending date used in the rules is a best guess;
    +# it matches what was used in the past.
    +
    +# 
    +# The Australian Bureau of Meteorology FAQ
    +#  (1999-09-27) writes that Giles Meteorological Station uses
    +# South Australian time even though it's located in Western Australia.
    +
    +# Queensland
    +# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
    +# #   The state of QUEENSLAND.. [ Courtesy Qld. Dept Premier Econ&Trade Devel ]
    +# #						[ Dec 1990 ]
    +# ...
    +# Zone	Australia/Queensland	10:00	AQ	%sST
    +# ...
    +# Rule	AQ	1971	only	-	Oct	lastSun	2:00	1:00	D
    +# Rule	AQ	1972	only	-	Feb	lastSun	3:00	0	E
    +# Rule	AQ	1989	max	-	Oct	lastSun	2:00	1:00	D
    +# Rule	AQ	1990	max	-	Mar	Sun>=1	3:00	0	E
    +
    +# From Bradley White (1989-12-24):
    +# "Australia/Queensland" now observes daylight time (i.e. from
    +# October 1989).
    +
    +# From Bradley White (1991-03-04):
    +# A recent excerpt from an Australian newspaper...
    +# ...Queensland...[has] agreed to end daylight saving
    +# at 3am tomorrow (March 3)...
    +
    +# From John Mackin (1991-03-06):
    +# I can certainly confirm for my part that Daylight Saving in NSW did in fact
    +# end on Sunday, 3 March.  I don't know at what hour, though.  (It surprised
    +# me.)
    +
    +# From Bradley White (1992-03-08):
    +# ...there was recently a referendum in Queensland which resulted
    +# in the experimental daylight saving system being abandoned. So, ...
    +# ...
    +# Rule	QLD	1989	1991	-	Oct	lastSun	2:00	1:00	D
    +# Rule	QLD	1990	1992	-	Mar	Sun>=1	3:00	0	S
    +# ...
    +
    +# From Arthur David Olson (1992-03-08):
    +# The chosen rules the union of the 1971/1972 change and the 1989-1992 changes.
    +
    +# From Christopher Hunt (2006-11-21), after an advance warning
    +# from Jesper Norgaard Welen (2006-11-01):
    +# WA are trialing DST for three years.
    +# 
    +
    +# From Rives McDow (2002-04-09):
    +# The most interesting region I have found consists of three towns on the
    +# southern coast....  South Australia observes daylight saving time; Western
    +# Australia does not.  The two states are one and a half hours apart.  The
    +# residents decided to forget about this nonsense of changing the clock so
    +# much and set the local time 20 hours and 45 minutes from the
    +# international date line, or right in the middle of the time of South
    +# Australia and Western Australia....
    +#
    +# From Paul Eggert (2002-04-09):
    +# This is confirmed by the section entitled
    +# "What's the deal with time zones???" in
    +# .
    +#
    +# From Alex Livingston (2006-12-07):
    +# ... it was just on four years ago that I drove along the Eyre Highway,
    +# which passes through eastern Western Australia close to the southern
    +# coast of the continent.
    +#
    +# I paid particular attention to the time kept there. There can be no
    +# dispute that UTC+08:45 was considered "the time" from the border
    +# village just inside the border with South Australia to as far west
    +# as just east of Caiguna. There can also be no dispute that Eucla is
    +# the largest population centre in this zone....
    +#
    +# Now that Western Australia is observing daylight saving, the
    +# question arose whether this part of the state would follow suit. I
    +# just called the border village and confirmed that indeed they have,
    +# meaning that they are now observing UTC+09:45.
    +#
    +# (2006-12-09):
    +# I personally doubt that either experimentation with daylight saving
    +# in WA or its introduction in SA had anything to do with the genesis
    +# of this time zone.  My hunch is that it's been around since well
    +# before 1975.  I remember seeing it noted on road maps decades ago.
    +
    +# From Paul Eggert (2006-12-15):
    +# For lack of better info, assume the tradition dates back to the
    +# introduction of standard time in 1895.
    +
    +
    +# southeast Australia
    +#
    +# From Paul Eggert (2007-07-23):
    +# Starting autumn 2008 Victoria, NSW, South Australia, Tasmania and the ACT
    +# end DST the first Sunday in April and start DST the first Sunday in October.
    +# http://www.theage.com.au/news/national/daylight-savings-to-span-six-months/2007/06/27/1182623966703.html
    +
    +
    +# South Australia
    +
    +# From Bradley White (1991-03-04):
    +# A recent excerpt from an Australian newspaper...
    +# ...South Australia...[has] agreed to end daylight saving
    +# at 3am tomorrow (March 3)...
    +
    +# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
    +# #   The state of SOUTH AUSTRALIA....[ Courtesy of S.A. Dept of Labour ]
    +# #						[ Nov 1990 ]
    +# ...
    +# Zone	Australia/South		9:30	AS	%sST
    +# ...
    +# Rule	 AS	1971	max	-	Oct	lastSun	2:00	1:00	D
    +# Rule	 AS	1972	1985	-	Mar	Sun>=1	3:00	0	C
    +# Rule	 AS	1986	1990	-	Mar	Sun>=15	3:00	0	C
    +# Rule	 AS	1991	max	-	Mar	Sun>=1	3:00	0	C
    +
    +# From Bradley White (1992-03-11):
    +# Recent correspondence with a friend in Adelaide
    +# contained the following exchange:  "Due to the Adelaide Festival,
    +# South Australia delays setting back our clocks for a few weeks."
    +
    +# From Robert Elz (1992-03-13):
    +# I heard that apparently (or at least, it appears that)
    +# South Aus will have an extra 3 weeks daylight saving every even
    +# numbered year (from 1990).  That's when the Adelaide Festival
    +# is on...
    +
    +# From Robert Elz (1992-03-16, 00:57:07 +1000):
    +# DST didn't end in Adelaide today (yesterday)....
    +# But whether it's "4th Sunday" or "2nd last Sunday" I have no idea whatever...
    +# (it's just as likely to be "the Sunday we pick for this year"...).
    +
    +# From Bradley White (1994-04-11):
    +# If Sun, 15 March, 1992 was at +1030 as kre asserts, but yet Sun, 20 March,
    +# 1994 was at +0930 as John Connolly's customer seems to assert, then I can
    +# only conclude that the actual rule is more complicated....
    +
    +# From John Warburton (1994-10-07):
    +# The new Daylight Savings dates for South Australia ...
    +# was gazetted in the Government Hansard on Sep 26 1994....
    +# start on last Sunday in October and end in last sunday in March.
    +
    +# From Paul Eggert (2007-07-23):
    +# See "southeast Australia" above for 2008 and later.
    +
    +# Tasmania
    +
    +# The rules for 1967 through 1991 were reported by George Shepherd
    +# via Simon Woodhead via Robert Elz (1991-03-06):
    +# #  The state of TASMANIA.. [Courtesy Tasmanian Dept of Premier + Cabinet ]
    +# #					[ Nov 1990 ]
    +
    +# From Bill Hart via Guy Harris (1991-10-10):
    +# Oh yes, the new daylight savings rules are uniquely tasmanian, we have
    +# 6 weeks a year now when we are out of sync with the rest of Australia
    +# (but nothing new about that).
    +
    +# From Alex Livingston (1999-10-04):
    +# I heard on the ABC (Australian Broadcasting Corporation) radio news on the
    +# (long) weekend that Tasmania, which usually goes its own way in this regard,
    +# has decided to join with most of NSW, the ACT, and most of Victoria
    +# (Australia) and start daylight saving on the last Sunday in August in 2000
    +# instead of the first Sunday in October.
    +
    +# Sim Alam (2000-07-03) reported a legal citation for the 2000/2001 rules:
    +# http://www.thelaw.tas.gov.au/fragview/42++1968+GS3A@EN+2000070300
    +
    +# From Paul Eggert (2007-07-23):
    +# See "southeast Australia" above for 2008 and later.
    +
    +# Victoria
    +
    +# The rules for 1971 through 1991 were reported by George Shepherd
    +# via Simon Woodhead via Robert Elz (1991-03-06):
    +# #   The state of VICTORIA.. [ Courtesy of Vic. Dept of Premier + Cabinet ]
    +# #						[ Nov 1990 ]
    +
    +# From Scott Harrington (2001-08-29):
    +# On KQED's "City Arts and Lectures" program last night I heard an
    +# interesting story about daylight savings time.  Dr. John Heilbron was
    +# discussing his book "The Sun in the Church: Cathedrals as Solar
    +# Observatories"[1], and in particular the Shrine of Remembrance[2] located
    +# in Melbourne, Australia.
    +#
    +# Apparently the shrine's main purpose is a beam of sunlight which
    +# illuminates a special spot on the floor at the 11th hour of the 11th day
    +# of the 11th month (Remembrance Day) every year in memory of Australia's
    +# fallen WWI soldiers.  And if you go there on Nov. 11, at 11am local time,
    +# you will indeed see the sunbeam illuminate the special spot at the
    +# expected time.
    +#
    +# However, that is only because of some special mirror contraption that had
    +# to be employed, since due to daylight savings time, the true solar time of
    +# the remembrance moment occurs one hour later (or earlier?).  Perhaps
    +# someone with more information on this jury-rig can tell us more.
    +#
    +# [1] http://www.hup.harvard.edu/catalog/HEISUN.html
    +# [2] http://www.shrine.org.au
    +
    +# From Paul Eggert (2007-07-23):
    +# See "southeast Australia" above for 2008 and later.
    +
    +# New South Wales
    +
    +# From Arthur David Olson:
    +# New South Wales and subjurisdictions have their own ideas of a fun time.
    +# Based on law library research by John Mackin,
    +# who notes:
    +#	In Australia, time is not legislated federally, but rather by the
    +#	individual states.  Thus, while such terms as ``Eastern Standard Time''
    +#	[I mean, of course, Australian EST, not any other kind] are in common
    +#	use, _they have NO REAL MEANING_, as they are not defined in the
    +#	legislation.  This is very important to understand.
    +#	I have researched New South Wales time only...
    +
    +# From Eric Ulevik (1999-05-26):
    +# DST will start in NSW on the last Sunday of August, rather than the usual
    +# October in 2000.  [See: Matthew Moore,
    +# 
    +# Two months more daylight saving
    +# 
    +# Sydney Morning Herald (1999-05-26).]
    +
    +# From Paul Eggert (1999-09-27):
    +# See the following official NSW source:
    +# 
    +# Daylight Saving in New South Wales.
    +# 
    +#
    +# Narrabri Shire (NSW) council has announced it will ignore the extension of
    +# daylight saving next year.  See:
    +# 
    +# Narrabri Council to ignore daylight saving
    +#  (1999-07-22).  For now, we'll wait to see if this really happens.
    +#
    +# Victoria will following NSW.  See:
    +# 
    +# Vic to extend daylight saving
    +#  (1999-07-28).
    +#
    +# However, South Australia rejected the DST request.  See:
    +# 
    +# South Australia rejects Olympics daylight savings request
    +#  (1999-07-19).
    +#
    +# Queensland also will not observe DST for the Olympics.  See:
    +# 
    +# Qld says no to daylight savings for Olympics
    +#  (1999-06-01), which quotes Queensland Premier Peter Beattie as saying
    +# ``Look you've got to remember in my family when this came up last time
    +# I voted for it, my wife voted against it and she said to me it's all very
    +# well for you, you don't have to worry about getting the children out of
    +# bed, getting them to school, getting them to sleep at night.
    +# I've been through all this argument domestically...my wife rules.''
    +#
    +# Broken Hill will stick with South Australian time in 2000.  See:
    +# 
    +# Broken Hill to be behind the times
    +#  (1999-07-21).
    +
    +# IATA SSIM (1998-09) says that the spring 2000 change for Australian
    +# Capital Territory, New South Wales except Lord Howe Island and Broken
    +# Hill, and Victoria will be August 27, presumably due to the Sydney Olympics.
    +
    +# From Eric Ulevik, referring to Sydney's Sun Herald (2000-08-13), page 29:
    +# The Queensland Premier Peter Beattie is encouraging northern NSW
    +# towns to use Queensland time.
    +
    +# From Paul Eggert (2007-07-23):
    +# See "southeast Australia" above for 2008 and later.
    +
    +# Yancowinna
    +
    +# From John Mackin (1989-01-04):
    +# `Broken Hill' means the County of Yancowinna.
    +
    +# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
    +# # YANCOWINNA..  [ Confirmation courtesy of Broken Hill Postmaster ]
    +# #					[ Dec 1990 ]
    +# ...
    +# # Yancowinna uses Central Standard Time, despite [its] location on the
    +# # New South Wales side of the S.A. border. Most business and social dealings
    +# # are with CST zones, therefore CST is legislated by local government
    +# # although the switch to Summer Time occurs in line with N.S.W. There have
    +# # been years when this did not apply, but the historical data is not
    +# # presently available.
    +# Zone	Australia/Yancowinna	9:30	 AY	%sST
    +# ...
    +# Rule	 AY	1971	1985	-	Oct	lastSun	2:00	1:00	D
    +# Rule	 AY	1972	only	-	Feb	lastSun	3:00	0	C
    +# [followed by other Rules]
    +
    +# Lord Howe Island
    +
    +# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
    +# LHI...		[ Courtesy of Pauline Van Winsen ]
    +#					[ Dec 1990 ]
    +# Lord Howe Island is located off the New South Wales coast, and is half an
    +# hour ahead of NSW time.
    +
    +# From James Lonergan, Secretary, Lord Howe Island Board (2000-01-27):
    +# Lord Howe Island summer time in 2000/2001 will commence on the same
    +# date as the rest of NSW (i.e. 2000-08-27).  For your information the
    +# Lord Howe Island Board (controlling authority for the Island) is
    +# seeking the community's views on various options for summer time
    +# arrangements on the Island, e.g. advance clocks by 1 full hour
    +# instead of only 30 minutes.  [Dependent] on the wishes of residents
    +# the Board may approach the NSW government to change the existing
    +# arrangements.  The starting date for summer time on the Island will
    +# however always coincide with the rest of NSW.
    +
    +# From James Lonergan, Secretary, Lord Howe Island Board (2000-10-25):
    +# Lord Howe Island advances clocks by 30 minutes during DST in NSW and retards
    +# clocks by 30 minutes when DST finishes. Since DST was most recently
    +# introduced in NSW, the "changeover" time on the Island has been 02:00 as
    +# shown on clocks on LHI. I guess this means that for 30 minutes at the start
    +# of DST, LHI is actually 1 hour ahead of the rest of NSW.
    +
    +# From Paul Eggert (2006-03-22):
    +# For Lord Howe dates we use Shanks & Pottenger through 1989, and
    +# Lonergan thereafter.  For times we use Lonergan.
    +
    +# From Paul Eggert (2007-07-23):
    +# See "southeast Australia" above for 2008 and later.
    +
    +# From Steffen Thorsen (2009-04-28):
    +# According to the official press release, South Australia's extended daylight
    +# saving period will continue with the same rules as used during the 2008-2009
    +# summer (southern hemisphere).
    +#
    +# From
    +# 
    +# http://www.safework.sa.gov.au/uploaded_files/DaylightDatesSet.pdf
    +# 
    +# The extended daylight saving period that South Australia has been trialling
    +# for over the last year is now set to be ongoing.
    +# Daylight saving will continue to start on the first Sunday in October each
    +# year and finish on the first Sunday in April the following year.
    +# Industrial Relations Minister, Paul Caica, says this provides South Australia
    +# with a consistent half hour time difference with NSW, Victoria, Tasmania and
    +# the ACT for all 52 weeks of the year...
    +#
    +# We have a wrap-up here:
    +# 
    +# http://www.timeanddate.com/news/time/south-australia-extends-dst.html
    +# 
    +###############################################################################
    +
    +# New Zealand
    +
    +# From Mark Davies (1990-10-03):
    +# the 1989/90 year was a trial of an extended "daylight saving" period.
    +# This trial was deemed successful and the extended period adopted for
    +# subsequent years (with the addition of a further week at the start).
    +# source -- phone call to Ministry of Internal Affairs Head Office.
    +
    +# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
    +# # The Country of New Zealand   (Australia's east island -) Gee they hate that!
    +# #				   or is Australia the west island of N.Z.
    +# #	[ courtesy of Geoff Tribble.. Auckland N.Z. ]
    +# #				[ Nov 1990 ]
    +# ...
    +# Rule	NZ      1974    1988	-	Oct	lastSun	2:00	1:00	D
    +# Rule	NZ	1989	max	-	Oct	Sun>=1	2:00	1:00	D
    +# Rule	NZ      1975    1989	-	Mar	Sun>=1	3:00	0	S
    +# Rule	NZ	1990	max	-	Mar	lastSun	3:00	0	S
    +# ...
    +# Zone	NZ			12:00	NZ		NZ%sT	# New Zealand
    +# Zone	NZ-CHAT			12:45	-		NZ-CHAT # Chatham Island
    +
    +# From Arthur David Olson (1992-03-08):
    +# The chosen rules use the Davies October 8 values for the start of DST in 1989
    +# rather than the October 1 value.
    +
    +# From Paul Eggert (1995-12-19);
    +# Shank & Pottenger report 2:00 for all autumn changes in Australia and NZ.
    +# Robert Uzgalis writes that the New Zealand Daylight
    +# Savings Time Order in Council dated 1990-06-18 specifies 2:00 standard
    +# time on both the first Sunday in October and the third Sunday in March.
    +# As with Australia, we'll assume the tradition is 2:00s, not 2:00.
    +#
    +# From Paul Eggert (2006-03-22):
    +# The Department of Internal Affairs (DIA) maintains a brief history,
    +# as does Carol Squires; see tz-link.htm for the full references.
    +# Use these sources in preference to Shanks & Pottenger.
    +#
    +# For Chatham, IATA SSIM (1991/1999) gives the NZ rules but with
    +# transitions at 2:45 local standard time; this confirms that Chatham
    +# is always exactly 45 minutes ahead of Auckland.
    +
    +# From Colin Sharples (2007-04-30):
    +# DST will now start on the last Sunday in September, and end on the
    +# first Sunday in April.  The changes take effect this year, meaning
    +# that DST will begin on 2007-09-30 2008-04-06.
    +# http://www.dia.govt.nz/diawebsite.nsf/wpg_URL/Services-Daylight-Saving-Daylight-saving-to-be-extended
    +
    +###############################################################################
    +
    +
    +# Fiji
    +
    +# Howse writes (p 153) that in 1879 the British governor of Fiji
    +# enacted an ordinance standardizing the islands on Antipodean Time
    +# instead of the American system (which was one day behind).
    +
    +# From Rives McDow (1998-10-08):
    +# Fiji will introduce DST effective 0200 local time, 1998-11-01
    +# until 0300 local time 1999-02-28.  Each year the DST period will
    +# be from the first Sunday in November until the last Sunday in February.
    +
    +# From Paul Eggert (2000-01-08):
    +# IATA SSIM (1999-09) says DST ends 0100 local time.  Go with McDow.
    +
    +# From the BBC World Service (1998-10-31 11:32 UTC):
    +# The Fijiian government says the main reasons for the time change is to
    +# improve productivity and reduce road accidents.  But correspondents say it
    +# also hopes the move will boost Fiji's ability to compete with other pacific
    +# islands in the effort to attract tourists to witness the dawning of the new
    +# millenium.
    +
    +# http://www.fiji.gov.fj/press/2000_09/2000_09_13-05.shtml (2000-09-13)
    +# reports that Fiji has discontinued DST.
    +
    +# Johnston
    +
    +# Johnston data is from usno1995.
    +
    +
    +# Kiribati
    +
    +# From Paul Eggert (1996-01-22):
    +# Today's _Wall Street Journal_ (page 1) reports that Kiribati
    +# ``declared it the same day [throughout] the country as of Jan. 1, 1995''
    +# as part of the competition to be first into the 21st century.
    +
    +
    +# Kwajalein
    +
    +# In comp.risks 14.87 (26 August 1993), Peter Neumann writes:
    +# I wonder what happened in Kwajalein, where there was NO Friday,
    +# 1993-08-20.  Thursday night at midnight Kwajalein switched sides with
    +# respect to the International Date Line, to rejoin its fellow islands,
    +# going from 11:59 p.m. Thursday to 12:00 m. Saturday in a blink.
    +
    +
    +# N Mariana Is, Guam
    +
    +# Howse writes (p 153) ``The Spaniards, on the other hand, reached the
    +# Philippines and the Ladrones from America,'' and implies that the Ladrones
    +# (now called the Marianas) kept American date for quite some time.
    +# For now, we assume the Ladrones switched at the same time as the Philippines;
    +# see Asia/Manila.
    +
    +# US Public Law 106-564 (2000-12-23) made UTC+10 the official standard time,
    +# under the name "Chamorro Standard Time".  There is no official abbreviation,
    +# but Congressman Robert A. Underwood, author of the bill that became law,
    +# wrote in a press release (2000-12-27) that he will seek the use of "ChST".
    +
    +
    +# Micronesia
    +
    +# Alan Eugene Davis writes (1996-03-16),
    +# ``I am certain, having lived there for the past decade, that "Truk"
    +# (now properly known as Chuuk) ... is in the time zone GMT+10.''
    +#
    +# Shanks & Pottenger write that Truk switched from UTC+10 to UTC+11
    +# on 1978-10-01; ignore this for now.
    +
    +# From Paul Eggert (1999-10-29):
    +# The Federated States of Micronesia Visitors Board writes in
    +# 
    +# The Federated States of Micronesia - Visitor Information
    +#  (1999-01-26)
    +# that Truk and Yap are UTC+10, and Ponape and Kosrae are UTC+11.
    +# We don't know when Kosrae switched from UTC+12; assume January 1 for now.
    +
    +
    +# Midway
    +
    +# From Charles T O'Connor, KMTH DJ (1956),
    +# quoted in the KTMH section of the Radio Heritage Collection
    +#  (2002-12-31):
    +# For the past two months we've been on what is known as Daylight
    +# Saving Time.  This time has put us on air at 5am in the morning,
    +# your time down there in New Zealand.  Starting September 2, 1956
    +# we'll again go back to Standard Time.  This'll mean that we'll go to
    +# air at 6am your time.
    +#
    +# From Paul Eggert (2003-03-23):
    +# We don't know the date of that quote, but we'll guess they
    +# started DST on June 3.  Possibly DST was observed other years
    +# in Midway, but we have no record of it.
    +
    +
    +# Pitcairn
    +
    +# From Rives McDow (1999-11-08):
    +# A Proclamation was signed by the Governor of Pitcairn on the 27th March 1998
    +# with regard to Pitcairn Standard Time.  The Proclamation is as follows.
    +#
    +#	The local time for general purposes in the Islands shall be
    +#	Co-ordinated Universal time minus 8 hours and shall be known
    +#	as Pitcairn Standard Time.
    +#
    +# ... I have also seen Pitcairn listed as UTC minus 9 hours in several
    +# references, and can only assume that this was an error in interpretation
    +# somehow in light of this proclamation.
    +
    +# From Rives McDow (1999-11-09):
    +# The Proclamation regarding Pitcairn time came into effect on 27 April 1998
    +# ... at midnight.
    +
    +# From Howie Phelps (1999-11-10), who talked to a Pitcairner via shortwave:
    +# Betty Christian told me yesterday that their local time is the same as
    +# Pacific Standard Time. They used to be 1/2 hour different from us here in
    +# Sacramento but it was changed a couple of years ago.
    +
    +
    +# Samoa
    +
    +# Howse writes (p 153, citing p 10 of the 1883-11-18 New York Herald)
    +# that in 1879 the King of Samoa decided to change
    +# ``the date in his kingdom from the Antipodean to the American system,
    +# ordaining -- by a masterpiece of diplomatic flattery -- that
    +# the Fourth of July should be celebrated twice in that year.''
    +
    +
    +# Tonga
    +
    +# From Paul Eggert (1996-01-22):
    +# Today's _Wall Street Journal_ (p 1) reports that ``Tonga has been plotting
    +# to sneak ahead of [New Zealanders] by introducing daylight-saving time.''
    +# Since Kiribati has moved the Date Line it's not clear what Tonga will do.
    +
    +# Don Mundell writes in the 1997-02-20 Tonga Chronicle
    +# 
    +# How Tonga became `The Land where Time Begins'
    +# :
    +
    +# Until 1941 Tonga maintained a standard time 50 minutes ahead of NZST
    +# 12 hours and 20 minutes ahead of GMT.  When New Zealand adjusted its
    +# standard time in 1940s, Tonga had the choice of subtracting from its
    +# local time to come on the same standard time as New Zealand or of
    +# advancing its time to maintain the differential of 13 degrees
    +# (approximately 50 minutes ahead of New Zealand time).
    +#
    +# Because His Majesty King Taufa'ahau Tupou IV, then Crown Prince
    +# Tungi, preferred to ensure Tonga's title as the land where time
    +# begins, the Legislative Assembly approved the latter change.
    +#
    +# But some of the older, more conservative members from the outer
    +# islands objected. "If at midnight on Dec. 31, we move ahead 40
    +# minutes, as your Royal Highness wishes, what becomes of the 40
    +# minutes we have lost?"
    +#
    +# The Crown Prince, presented an unanswerable argument: "Remember that
    +# on the World Day of Prayer, you would be the first people on Earth
    +# to say your prayers in the morning."
    +
    +# From Paul Eggert (2006-03-22):
    +# Shanks & Pottenger say the transition was on 1968-10-01; go with Mundell.
    +
    +# From Eric Ulevik (1999-05-03):
    +# Tonga's director of tourism, who is also secretary of the National Millenium
    +# Committee, has a plan to get Tonga back in front.
    +# He has proposed a one-off move to tropical daylight saving for Tonga from
    +# October to March, which has won approval in principle from the Tongan
    +# Government.
    +
    +# From Steffen Thorsen (1999-09-09):
    +# * Tonga will introduce DST in November
    +#
    +# I was given this link by John Letts:
    +# 
    +# http://news.bbc.co.uk/hi/english/world/asia-pacific/newsid_424000/424764.stm
    +# 
    +#
    +# I have not been able to find exact dates for the transition in November
    +# yet. By reading this article it seems like Fiji will be 14 hours ahead
    +# of UTC as well, but as far as I know Fiji will only be 13 hours ahead
    +# (12 + 1 hour DST).
    +
    +# From Arthur David Olson (1999-09-20):
    +# According to 
    +# http://www.tongaonline.com/news/sept1799.html
    +# :
    +# "Daylight Savings Time will take effect on Oct. 2 through April 15, 2000
    +# and annually thereafter from the first Saturday in October through the
    +# third Saturday of April.  Under the system approved by Privy Council on
    +# Sept. 10, clocks must be turned ahead one hour on the opening day and
    +# set back an hour on the closing date."
    +# Alas, no indication of the time of day.
    +
    +# From Rives McDow (1999-10-06):
    +# Tonga started its Daylight Saving on Saturday morning October 2nd at 0200am.
    +# Daylight Saving ends on April 16 at 0300am which is Sunday morning.
    +
    +# From Steffen Thorsen (2000-10-31):
    +# Back in March I found a notice on the website http://www.tongaonline.com
    +# that Tonga changed back to standard time one month early, on March 19
    +# instead of the original reported date April 16. Unfortunately, the article
    +# is no longer available on the site, and I did not make a copy of the
    +# text, and I have forgotten to report it here.
    +# (Original URL was: http://www.tongaonline.com/news/march162000.htm )
    +
    +# From Rives McDow (2000-12-01):
    +# Tonga is observing DST as of 2000-11-04 and will stop on 2001-01-27.
    +
    +# From Sione Moala-Mafi (2001-09-20) via Rives McDow:
    +# At 2:00am on the first Sunday of November, the standard time in the Kingdom
    +# shall be moved forward by one hour to 3:00am.  At 2:00am on the last Sunday
    +# of January the standard time in the Kingdom shall be moved backward by one
    +# hour to 1:00am.
    +
    +# From Pulu 'Anau (2002-11-05):
    +# The law was for 3 years, supposedly to get renewed.  It wasn't.
    +
    +
    +# Wake
    +
    +# From Vernice Anderson, Personal Secretary to Philip Jessup,
    +# US Ambassador At Large (oral history interview, 1971-02-02):
    +#
    +# Saturday, the 14th [of October, 1950] -- ...  The time was all the
    +# more confusing at that point, because we had crossed the
    +# International Date Line, thus getting two Sundays.  Furthermore, we
    +# discovered that Wake Island had two hours of daylight saving time
    +# making calculation of time in Washington difficult if not almost
    +# impossible.
    +#
    +# http://www.trumanlibrary.org/wake/meeting.htm
    +
    +# From Paul Eggert (2003-03-23):
    +# We have no other report of DST in Wake Island, so omit this info for now.
    +
    +###############################################################################
    +
    +# The International Date Line
    +
    +# From Gwillim Law (2000-01-03):
    +#
    +# The International Date Line is not defined by any international standard,
    +# convention, or treaty.  Mapmakers are free to draw it as they please.
    +# Reputable mapmakers will simply ensure that every point of land appears on
    +# the correct side of the IDL, according to the date legally observed there.
    +#
    +# When Kiribati adopted a uniform date in 1995, thereby moving the Phoenix and
    +# Line Islands to the west side of the IDL (or, if you prefer, moving the IDL
    +# to the east side of the Phoenix and Line Islands), I suppose that most
    +# mapmakers redrew the IDL following the boundary of Kiribati.  Even that line
    +# has a rather arbitrary nature.  The straight-line boundaries between Pacific
    +# island nations that are shown on many maps are based on an international
    +# convention, but are not legally binding national borders.... The date is
    +# governed by the IDL; therefore, even on the high seas, there may be some
    +# places as late as fourteen hours later than UTC.  And, since the IDL is not
    +# an international standard, there are some places on the high seas where the
    +# correct date is ambiguous.
    +
    +# From Wikipedia  (2005-08-31):
    +# Before 1920, all ships kept local apparent time on the high seas by setting
    +# their clocks at night or at the morning sight so that, given the ship's
    +# speed and direction, it would be 12 o'clock when the Sun crossed the ship's
    +# meridian (12 o'clock = local apparent noon).  During 1917, at the
    +# Anglo-French Conference on Time-keeping at Sea, it was recommended that all
    +# ships, both military and civilian, should adopt hourly standard time zones
    +# on the high seas.  Whenever a ship was within the territorial waters of any
    +# nation it would use that nation's standard time.  The captain was permitted
    +# to change his ship's clocks at a time of his choice following his ship's
    +# entry into another zone time--he often chose midnight.  These zones were
    +# adopted by all major fleets between 1920 and 1925 but not by many
    +# independent merchant ships until World War II.
    +
    +# From Paul Eggert, using references suggested by Oscar van Vlijmen
    +# (2005-03-20):
    +#
    +# The American Practical Navigator (2002)
    +# 
    +# talks only about the 180-degree meridian with respect to ships in
    +# international waters; it ignores the international date line.
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/backward b/jdk/test/sun/util/calendar/zi/tzdata/backward
    new file mode 100644
    index 00000000000..4ccea7c7dbe
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/backward
    @@ -0,0 +1,140 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# This file provides links between current names for time zones
    +# and their old names.  Many names changed in late 1993.
    +
    +Link	Africa/Asmara		Africa/Asmera
    +Link	Africa/Bamako		Africa/Timbuktu
    +Link	America/Argentina/Catamarca	America/Argentina/ComodRivadavia
    +Link	America/Adak		America/Atka
    +Link	America/Argentina/Buenos_Aires	America/Buenos_Aires
    +Link	America/Argentina/Catamarca	America/Catamarca
    +Link	America/Atikokan	America/Coral_Harbour
    +Link	America/Argentina/Cordoba	America/Cordoba
    +Link	America/Tijuana		America/Ensenada
    +Link	America/Indiana/Indianapolis	America/Fort_Wayne
    +Link	America/Indiana/Indianapolis	America/Indianapolis
    +Link	America/Argentina/Jujuy	America/Jujuy
    +Link	America/Indiana/Knox	America/Knox_IN
    +Link	America/Kentucky/Louisville	America/Louisville
    +Link	America/Argentina/Mendoza	America/Mendoza
    +Link	America/Rio_Branco	America/Porto_Acre
    +Link	America/Argentina/Cordoba	America/Rosario
    +Link	America/St_Thomas	America/Virgin
    +Link	Asia/Ashgabat		Asia/Ashkhabad
    +Link	Asia/Chongqing		Asia/Chungking
    +Link	Asia/Dhaka		Asia/Dacca
    +Link	Asia/Kathmandu		Asia/Katmandu
    +Link	Asia/Kolkata		Asia/Calcutta
    +Link	Asia/Macau		Asia/Macao
    +Link	Asia/Jerusalem		Asia/Tel_Aviv
    +Link	Asia/Ho_Chi_Minh	Asia/Saigon
    +Link	Asia/Thimphu		Asia/Thimbu
    +Link	Asia/Makassar		Asia/Ujung_Pandang
    +Link	Asia/Ulaanbaatar	Asia/Ulan_Bator
    +Link	Atlantic/Faroe		Atlantic/Faeroe
    +Link	Europe/Oslo		Atlantic/Jan_Mayen
    +Link	Australia/Sydney	Australia/ACT
    +Link	Australia/Sydney	Australia/Canberra
    +Link	Australia/Lord_Howe	Australia/LHI
    +Link	Australia/Sydney	Australia/NSW
    +Link	Australia/Darwin	Australia/North
    +Link	Australia/Brisbane	Australia/Queensland
    +Link	Australia/Adelaide	Australia/South
    +Link	Australia/Hobart	Australia/Tasmania
    +Link	Australia/Melbourne	Australia/Victoria
    +Link	Australia/Perth		Australia/West
    +Link	Australia/Broken_Hill	Australia/Yancowinna
    +Link	America/Rio_Branco	Brazil/Acre
    +Link	America/Noronha		Brazil/DeNoronha
    +Link	America/Sao_Paulo	Brazil/East
    +Link	America/Manaus		Brazil/West
    +Link	America/Halifax		Canada/Atlantic
    +Link	America/Winnipeg	Canada/Central
    +Link	America/Regina		Canada/East-Saskatchewan
    +Link	America/Toronto		Canada/Eastern
    +Link	America/Edmonton	Canada/Mountain
    +Link	America/St_Johns	Canada/Newfoundland
    +Link	America/Vancouver	Canada/Pacific
    +Link	America/Regina		Canada/Saskatchewan
    +Link	America/Whitehorse	Canada/Yukon
    +Link	America/Santiago	Chile/Continental
    +Link	Pacific/Easter		Chile/EasterIsland
    +Link	America/Havana		Cuba
    +Link	Africa/Cairo		Egypt
    +Link	Europe/Dublin		Eire
    +Link	Europe/London		Europe/Belfast
    +Link	Europe/Chisinau		Europe/Tiraspol
    +Link	Europe/London		GB
    +Link	Europe/London		GB-Eire
    +Link	Etc/GMT			GMT+0
    +Link	Etc/GMT			GMT-0
    +Link	Etc/GMT			GMT0
    +Link	Etc/GMT			Greenwich
    +Link	Asia/Hong_Kong		Hongkong
    +Link	Atlantic/Reykjavik	Iceland
    +Link	Asia/Tehran		Iran
    +Link	Asia/Jerusalem		Israel
    +Link	America/Jamaica		Jamaica
    +Link	Asia/Tokyo		Japan
    +Link	Pacific/Kwajalein	Kwajalein
    +Link	Africa/Tripoli		Libya
    +Link	America/Tijuana		Mexico/BajaNorte
    +Link	America/Mazatlan	Mexico/BajaSur
    +Link	America/Mexico_City	Mexico/General
    +Link	Pacific/Auckland	NZ
    +Link	Pacific/Chatham		NZ-CHAT
    +Link	America/Denver		Navajo
    +Link	Asia/Shanghai		PRC
    +Link	Pacific/Pago_Pago	Pacific/Samoa
    +Link	Pacific/Chuuk		Pacific/Yap
    +Link	Pacific/Chuuk		Pacific/Truk
    +Link	Pacific/Pohnpei		Pacific/Ponape
    +Link	Europe/Warsaw		Poland
    +Link	Europe/Lisbon		Portugal
    +Link	Asia/Taipei		ROC
    +Link	Asia/Seoul		ROK
    +Link	Asia/Singapore		Singapore
    +Link	Europe/Istanbul		Turkey
    +Link	Etc/UCT			UCT
    +Link	America/Anchorage	US/Alaska
    +Link	America/Adak		US/Aleutian
    +Link	America/Phoenix		US/Arizona
    +Link	America/Chicago		US/Central
    +Link	America/Indiana/Indianapolis	US/East-Indiana
    +Link	America/New_York	US/Eastern
    +Link	Pacific/Honolulu	US/Hawaii
    +Link	America/Indiana/Knox	US/Indiana-Starke
    +Link	America/Detroit		US/Michigan
    +Link	America/Denver		US/Mountain
    +Link	America/Los_Angeles	US/Pacific
    +Link	Pacific/Pago_Pago	US/Samoa
    +Link	Etc/UTC			UTC
    +Link	Etc/UTC			Universal
    +Link	Europe/Moscow		W-SU
    +Link	Etc/UTC			Zulu
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/etcetera b/jdk/test/sun/util/calendar/zi/tzdata/etcetera
    new file mode 100644
    index 00000000000..609b305493c
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/etcetera
    @@ -0,0 +1,104 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# These entries are mostly present for historical reasons, so that
    +# people in areas not otherwise covered by the tz files could "zic -l"
    +# to a time zone that was right for their area.  These days, the
    +# tz files cover almost all the inhabited world, and the only practical
    +# need now for the entries that are not on UTC are for ships at sea
    +# that cannot use POSIX TZ settings.
    +
    +Zone	Etc/GMT		0	-	GMT
    +Zone	Etc/UTC		0	-	UTC
    +Zone	Etc/UCT		0	-	UCT
    +
    +# The following link uses older naming conventions,
    +# but it belongs here, not in the file `backward',
    +# as functions like gmtime load the "GMT" file to handle leap seconds properly.
    +# We want this to work even on installations that omit the other older names.
    +Link	Etc/GMT				GMT
    +
    +Link	Etc/UTC				Etc/Universal
    +Link	Etc/UTC				Etc/Zulu
    +
    +Link	Etc/GMT				Etc/Greenwich
    +Link	Etc/GMT				Etc/GMT-0
    +Link	Etc/GMT				Etc/GMT+0
    +Link	Etc/GMT				Etc/GMT0
    +
    +# We use POSIX-style signs in the Zone names and the output abbreviations,
    +# even though this is the opposite of what many people expect.
    +# POSIX has positive signs west of Greenwich, but many people expect
    +# positive signs east of Greenwich.  For example, TZ='Etc/GMT+4' uses
    +# the abbreviation "GMT+4" and corresponds to 4 hours behind UTC
    +# (i.e. west of Greenwich) even though many people would expect it to
    +# mean 4 hours ahead of UTC (i.e. east of Greenwich).
    +#
    +# In the draft 5 of POSIX 1003.1-200x, the angle bracket notation allows for
    +# TZ='+4'; if you want time zone abbreviations conforming to
    +# ISO 8601 you can use TZ='<-0400>+4'.  Thus the commonly-expected
    +# offset is kept within the angle bracket (and is used for display)
    +# while the POSIX sign is kept outside the angle bracket (and is used
    +# for calculation).
    +#
    +# Do not use a TZ setting like TZ='GMT+4', which is four hours behind
    +# GMT but uses the completely misleading abbreviation "GMT".
    +
    +# Earlier incarnations of this package were not POSIX-compliant,
    +# and had lines such as
    +#		Zone	GMT-12		-12	-	GMT-1200
    +# We did not want things to change quietly if someone accustomed to the old
    +# way does a
    +#		zic -l GMT-12
    +# so we moved the names into the Etc subdirectory.
    +
    +Zone	Etc/GMT-14	14	-	GMT-14	# 14 hours ahead of GMT
    +Zone	Etc/GMT-13	13	-	GMT-13
    +Zone	Etc/GMT-12	12	-	GMT-12
    +Zone	Etc/GMT-11	11	-	GMT-11
    +Zone	Etc/GMT-10	10	-	GMT-10
    +Zone	Etc/GMT-9	9	-	GMT-9
    +Zone	Etc/GMT-8	8	-	GMT-8
    +Zone	Etc/GMT-7	7	-	GMT-7
    +Zone	Etc/GMT-6	6	-	GMT-6
    +Zone	Etc/GMT-5	5	-	GMT-5
    +Zone	Etc/GMT-4	4	-	GMT-4
    +Zone	Etc/GMT-3	3	-	GMT-3
    +Zone	Etc/GMT-2	2	-	GMT-2
    +Zone	Etc/GMT-1	1	-	GMT-1
    +Zone	Etc/GMT+1	-1	-	GMT+1
    +Zone	Etc/GMT+2	-2	-	GMT+2
    +Zone	Etc/GMT+3	-3	-	GMT+3
    +Zone	Etc/GMT+4	-4	-	GMT+4
    +Zone	Etc/GMT+5	-5	-	GMT+5
    +Zone	Etc/GMT+6	-6	-	GMT+6
    +Zone	Etc/GMT+7	-7	-	GMT+7
    +Zone	Etc/GMT+8	-8	-	GMT+8
    +Zone	Etc/GMT+9	-9	-	GMT+9
    +Zone	Etc/GMT+10	-10	-	GMT+10
    +Zone	Etc/GMT+11	-11	-	GMT+11
    +Zone	Etc/GMT+12	-12	-	GMT+12
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/europe b/jdk/test/sun/util/calendar/zi/tzdata/europe
    new file mode 100644
    index 00000000000..9a0d0b9db94
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/europe
    @@ -0,0 +1,2879 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# This data is by no means authoritative; if you think you know better,
    +# go ahead and edit the file (and please send any changes to
    +# tz@elsie.nci.nih.gov for general use in the future).
    +
    +# From Paul Eggert (2006-03-22):
    +# A good source for time zone historical data outside the U.S. is
    +# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
    +# San Diego: ACS Publications, Inc. (2003).
    +#
    +# Gwillim Law writes that a good source
    +# for recent time zone data is the International Air Transport
    +# Association's Standard Schedules Information Manual (IATA SSIM),
    +# published semiannually.  Law sent in several helpful summaries
    +# of the IATA's data after 1990.
    +#
    +# Except where otherwise noted, Shanks & Pottenger is the source for
    +# entries through 1991, and IATA SSIM is the source for entries afterwards.
    +#
    +# Other sources occasionally used include:
    +#
    +#	Edward W. Whitman, World Time Differences,
    +#	Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
    +#	which I found in the UCLA library.
    +#
    +#	
    +#	William Willett, The Waste of Daylight, 19th edition
    +#	 (1914-03)
    +#
    +#	Brazil's Departamento Servico da Hora (DSH),
    +#	
    +#	History of Summer Time
    +#	 (1998-09-21, in Portuguese)
    +
    +#
    +# I invented the abbreviations marked `*' in the following table;
    +# the rest are from earlier versions of this file, or from other sources.
    +# Corrections are welcome!
    +#                   std dst  2dst
    +#                   LMT           Local Mean Time
    +#       -4:00       AST ADT       Atlantic
    +#       -3:00       WGT WGST      Western Greenland*
    +#       -1:00       EGT EGST      Eastern Greenland*
    +#        0:00       GMT BST  BDST Greenwich, British Summer
    +#        0:00       GMT IST       Greenwich, Irish Summer
    +#        0:00       WET WEST WEMT Western Europe
    +#        0:19:32.13 AMT NST       Amsterdam, Netherlands Summer (1835-1937)*
    +#        0:20       NET NEST      Netherlands (1937-1940)*
    +#        1:00       CET CEST CEMT Central Europe
    +#        1:00:14    SET           Swedish (1879-1899)*
    +#        2:00       EET EEST      Eastern Europe
    +#        3:00       MSK MSD       Moscow
    +#
    +# A reliable and entertaining source about time zones, especially in Britain,
    +# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
    +
    +# From Peter Ilieve (1994-12-04),
    +# The original six [EU members]: Belgium, France, (West) Germany, Italy,
    +# Luxembourg, the Netherlands.
    +# Plus, from 1 Jan 73: Denmark, Ireland, United Kingdom.
    +# Plus, from 1 Jan 81: Greece.
    +# Plus, from 1 Jan 86: Spain, Portugal.
    +# Plus, from 1 Jan 95: Austria, Finland, Sweden. (Norway negotiated terms for
    +# entry but in a referendum on 28 Nov 94 the people voted No by 52.2% to 47.8%
    +# on a turnout of 88.6%. This was almost the same result as Norway's previous
    +# referendum in 1972, they are the only country to have said No twice.
    +# Referendums in the other three countries voted Yes.)
    +# ...
    +# Estonia ... uses EU dates but not at 01:00 GMT, they use midnight GMT.
    +# I don't think they know yet what they will do from 1996 onwards.
    +# ...
    +# There shouldn't be any [current members who are not using EU rules].
    +# A Directive has the force of law, member states are obliged to enact
    +# national law to implement it. The only contentious issue was the
    +# different end date for the UK and Ireland, and this was always allowed
    +# in the Directive.
    +
    +
    +###############################################################################
    +
    +# Britain (United Kingdom) and Ireland (Eire)
    +
    +# From Peter Ilieve (1994-07-06):
    +#
    +# On 17 Jan 1994 the Independent, a UK quality newspaper, had a piece about
    +# historical vistas along the Thames in west London. There was a photo
    +# and a sketch map showing some of the sightlines involved. One paragraph
    +# of the text said:
    +#
    +# `An old stone obelisk marking a forgotten terrestrial meridian stands
    +# beside the river at Kew. In the 18th century, before time and longitude
    +# was standardised by the Royal Observatory in Greenwich, scholars observed
    +# this stone and the movement of stars from Kew Observatory nearby. They
    +# made their calculations and set the time for the Horse Guards and Parliament,
    +# but now the stone is obscured by scrubwood and can only be seen by walking
    +# along the towpath within a few yards of it.'
    +#
    +# I have a one inch to one mile map of London and my estimate of the stone's
    +# position is 51 deg. 28' 30" N, 0 deg. 18' 45" W. The longitude should
    +# be within about +-2". The Ordnance Survey grid reference is TQ172761.
    +#
    +# [This yields GMTOFF = -0:01:15 for London LMT in the 18th century.]
    +
    +# From Paul Eggert (1993-11-18):
    +#
    +# Howse writes that Britain was the first country to use standard time.
    +# The railways cared most about the inconsistencies of local mean time,
    +# and it was they who forced a uniform time on the country.
    +# The original idea was credited to Dr. William Hyde Wollaston (1766-1828)
    +# and was popularized by Abraham Follett Osler (1808-1903).
    +# The first railway to adopt London time was the Great Western Railway
    +# in November 1840; other railways followed suit, and by 1847 most
    +# (though not all) railways used London time.  On 1847-09-22 the
    +# Railway Clearing House, an industry standards body, recommended that GMT be
    +# adopted at all stations as soon as the General Post Office permitted it.
    +# The transition occurred on 12-01 for the L&NW, the Caledonian,
    +# and presumably other railways; the January 1848 Bradshaw's lists many
    +# railways as using GMT.  By 1855 the vast majority of public
    +# clocks in Britain were set to GMT (though some, like the great clock
    +# on Tom Tower at Christ Church, Oxford, were fitted with two minute hands,
    +# one for local time and one for GMT).  The last major holdout was the legal
    +# system, which stubbornly stuck to local time for many years, leading
    +# to oddities like polls opening at 08:13 and closing at 16:13.
    +# The legal system finally switched to GMT when the Statutes (Definition
    +# of Time) Act took effect; it received the Royal Assent on 1880-08-02.
    +#
    +# In the tables below, we condense this complicated story into a single
    +# transition date for London, namely 1847-12-01.  We don't know as much
    +# about Dublin, so we use 1880-08-02, the legal transition time.
    +
    +# From Paul Eggert (2003-09-27):
    +# Summer Time was first seriously proposed by William Willett (1857-1915),
    +# a London builder and member of the Royal Astronomical Society
    +# who circulated a pamphlet ``The Waste of Daylight'' (1907)
    +# that proposed advancing clocks 20 minutes on each of four Sundays in April,
    +# and retarding them by the same amount on four Sundays in September.
    +# A bill was drafted in 1909 and introduced in Parliament several times,
    +# but it met with ridicule and opposition, especially from farming interests.
    +# Later editions of the pamphlet proposed one-hour summer time, and
    +# it was eventually adopted as a wartime measure in 1916.
    +# See: Summer Time Arrives Early, The Times (2000-05-18).
    +# A monument to Willett was unveiled on 1927-05-21, in an open space in
    +# a 45-acre wood near Chislehurst, Kent that was purchased by popular
    +# subscription and open to the public.  On the south face of the monolith,
    +# designed by G. W. Miller, is the...William Willett Memorial Sundial,
    +# which is permanently set to Summer Time.
    +
    +# From Winston Churchill (1934-04-28):
    +# It is one of the paradoxes of history that we should owe the boon of
    +# summer time, which gives every year to the people of this country
    +# between 160 and 170 hours more daylight leisure, to a war which
    +# plunged Europe into darkness for four years, and shook the
    +# foundations of civilization throughout the world.
    +#	-- 
    +#	"A Silent Toast to William Willett", Pictorial Weekly
    +#	
    +
    +# From Paul Eggert (1996-09-03):
    +# The OED Supplement says that the English originally said ``Daylight Saving''
    +# when they were debating the adoption of DST in 1908; but by 1916 this
    +# term appears only in quotes taken from DST's opponents, whereas the
    +# proponents (who eventually won the argument) are quoted as using ``Summer''.
    +
    +# From Arthur David Olson (1989-01-19):
    +#
    +# A source at the British Information Office in New York avers that it's
    +# known as "British" Summer Time in all parts of the United Kingdom.
    +
    +# Date: 4 Jan 89 08:57:25 GMT (Wed)
    +# From: Jonathan Leffler
    +# [British Summer Time] is fixed annually by Act of Parliament.
    +# If you can predict what Parliament will do, you should be in
    +# politics making a fortune, not computing.
    +
    +# From Chris Carrier (1996-06-14):
    +# I remember reading in various wartime issues of the London Times the
    +# acronym BDST for British Double Summer Time.  Look for the published
    +# time of sunrise and sunset in The Times, when BDST was in effect, and
    +# if you find a zone reference it will say, "All times B.D.S.T."
    +
    +# From Joseph S. Myers (1999-09-02):
    +# ... some military cables (WO 219/4100 - this is a copy from the
    +# main SHAEF archives held in the US National Archives, SHAEF/5252/8/516)
    +# agree that the usage is BDST (this appears in a message dated 17 Feb 1945).
    +
    +# From Joseph S. Myers (2000-10-03):
    +# On 18th April 1941, Sir Stephen Tallents of the BBC wrote to Sir
    +# Alexander Maxwell of the Home Office asking whether there was any
    +# official designation; the reply of the 21st was that there wasn't
    +# but he couldn't think of anything better than the "Double British
    +# Summer Time" that the BBC had been using informally.
    +# http://student.cusu.cam.ac.uk/~jsm28/british-time/bbc-19410418.png
    +# http://student.cusu.cam.ac.uk/~jsm28/british-time/ho-19410421.png
    +
    +# From Sir Alexander Maxwell in the above-mentioned letter (1941-04-21):
    +# [N]o official designation has as far as I know been adopted for the time
    +# which is to be introduced in May....
    +# I cannot think of anything better than "Double British Summer Time"
    +# which could not be said to run counter to any official description.
    +
    +# From Paul Eggert (2000-10-02):
    +# Howse writes (p 157) `DBST' too, but `BDST' seems to have been common
    +# and follows the more usual convention of putting the location name first,
    +# so we use `BDST'.
    +
    +# Peter Ilieve (1998-04-19) described at length
    +# the history of summer time legislation in the United Kingdom.
    +# Since 1998 Joseph S. Myers has been updating
    +# and extending this list, which can be found in
    +# http://student.cusu.cam.ac.uk/~jsm28/british-time/
    +# 
    +# History of legal time in Britain
    +# 
    +# Rob Crowther (2012-01-04) reports that that URL no longer
    +# exists, and the article can now be found at:
    +# 
    +# http://www.polyomino.org.uk/british-time/
    +# 
    +
    +# From Joseph S. Myers (1998-01-06):
    +#
    +# The legal time in the UK outside of summer time is definitely GMT, not UTC;
    +# see Lord Tanlaw's speech
    +# 
    +# (Lords Hansard 11 June 1997 columns 964 to 976)
    +# .
    +
    +# From Paul Eggert (2006-03-22):
    +#
    +# For lack of other data, follow Shanks & Pottenger for Eire in 1940-1948.
    +#
    +# Given Ilieve and Myers's data, the following claims by Shanks & Pottenger
    +# are incorrect:
    +#     * Wales did not switch from GMT to daylight saving time until
    +#	1921 Apr 3, when they began to conform with the rest of Great Britain.
    +# Actually, Wales was identical after 1880.
    +#     * Eire had two transitions on 1916 Oct 1.
    +# It actually just had one transition.
    +#     * Northern Ireland used single daylight saving time throughout WW II.
    +# Actually, it conformed to Britain.
    +#     * GB-Eire changed standard time to 1 hour ahead of GMT on 1968-02-18.
    +# Actually, that date saw the usual switch to summer time.
    +# Standard time was not changed until 1968-10-27 (the clocks didn't change).
    +#
    +# Here is another incorrect claim by Shanks & Pottenger:
    +#     * Jersey, Guernsey, and the Isle of Man did not switch from GMT
    +#	to daylight saving time until 1921 Apr 3, when they began to
    +#	conform with Great Britain.
    +# S.R.&O. 1916, No. 382 and HO 45/10811/312364 (quoted above) say otherwise.
    +#
    +# The following claim by Shanks & Pottenger is possible though doubtful;
    +# we'll ignore it for now.
    +#     * Dublin's 1971-10-31 switch was at 02:00, even though London's was 03:00.
    +#
    +#
    +# Whitman says Dublin Mean Time was -0:25:21, which is more precise than
    +# Shanks & Pottenger.
    +# Perhaps this was Dunsink Observatory Time, as Dunsink Observatory
    +# (8 km NW of Dublin's center) seemingly was to Dublin as Greenwich was
    +# to London.  For example:
    +#
    +#   "Timeball on the ballast office is down.  Dunsink time."
    +#   -- James Joyce, Ulysses
    +
    +# From Joseph S. Myers (2005-01-26):
    +# Irish laws are available online at www.irishstatutebook.ie.  These include
    +# various relating to legal time, for example:
    +#
    +# ZZA13Y1923.html ZZA12Y1924.html ZZA8Y1925.html ZZSIV20PG1267.html
    +#
    +# ZZSI71Y1947.html ZZSI128Y1948.html ZZSI23Y1949.html ZZSI41Y1950.html
    +# ZZSI27Y1951.html ZZSI73Y1952.html
    +#
    +# ZZSI11Y1961.html ZZSI232Y1961.html ZZSI182Y1962.html
    +# ZZSI167Y1963.html ZZSI257Y1964.html ZZSI198Y1967.html
    +# ZZA23Y1968.html ZZA17Y1971.html
    +#
    +# ZZSI67Y1981.html ZZSI212Y1982.html ZZSI45Y1986.html
    +# ZZSI264Y1988.html ZZSI52Y1990.html ZZSI371Y1992.html
    +# ZZSI395Y1994.html ZZSI484Y1997.html ZZSI506Y2001.html
    +#
    +# [These are all relative to the root, e.g., the first is
    +# .]
    +#
    +# (These are those I found, but there could be more.  In any case these
    +# should allow various updates to the comments in the europe file to cover
    +# the laws applicable in Ireland.)
    +#
    +# (Note that the time in the Republic of Ireland since 1968 has been defined
    +# in terms of standard time being GMT+1 with a period of winter time when it
    +# is GMT, rather than standard time being GMT with a period of summer time
    +# being GMT+1.)
    +
    +# From Paul Eggert (1999-03-28):
    +# Clive Feather (, 1997-03-31)
    +# reports that Folkestone (Cheriton) Shuttle Terminal uses Concession Time
    +# (CT), equivalent to French civil time.
    +# Julian Hill (, 1998-09-30) reports that
    +# trains between Dollands Moor (the freight facility next door)
    +# and Frethun run in CT.
    +# My admittedly uninformed guess is that the terminal has two authorities,
    +# the French concession operators and the British civil authorities,
    +# and that the time depends on who you're talking to.
    +# If, say, the British police were called to the station for some reason,
    +# I would expect the official police report to use GMT/BST and not CET/CEST.
    +# This is a borderline case, but for now let's stick to GMT/BST.
    +
    +# From an anonymous contributor (1996-06-02):
    +# The law governing time in Ireland is under Statutory Instrument SI 395/94,
    +# which gives force to European Union 7th Council Directive # 94/21/EC.
    +# Under this directive, the Minister for Justice in Ireland makes appropriate
    +# regulations. I spoke this morning with the Secretary of the Department of
    +# Justice (tel +353 1 678 9711) who confirmed to me that the correct name is
    +# "Irish Summer Time", abbreviated to "IST".
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +# Summer Time Act, 1916
    +Rule	GB-Eire	1916	only	-	May	21	2:00s	1:00	BST
    +Rule	GB-Eire	1916	only	-	Oct	 1	2:00s	0	GMT
    +# S.R.&O. 1917, No. 358
    +Rule	GB-Eire	1917	only	-	Apr	 8	2:00s	1:00	BST
    +Rule	GB-Eire	1917	only	-	Sep	17	2:00s	0	GMT
    +# S.R.&O. 1918, No. 274
    +Rule	GB-Eire	1918	only	-	Mar	24	2:00s	1:00	BST
    +Rule	GB-Eire	1918	only	-	Sep	30	2:00s	0	GMT
    +# S.R.&O. 1919, No. 297
    +Rule	GB-Eire	1919	only	-	Mar	30	2:00s	1:00	BST
    +Rule	GB-Eire	1919	only	-	Sep	29	2:00s	0	GMT
    +# S.R.&O. 1920, No. 458
    +Rule	GB-Eire	1920	only	-	Mar	28	2:00s	1:00	BST
    +# S.R.&O. 1920, No. 1844
    +Rule	GB-Eire	1920	only	-	Oct	25	2:00s	0	GMT
    +# S.R.&O. 1921, No. 363
    +Rule	GB-Eire	1921	only	-	Apr	 3	2:00s	1:00	BST
    +Rule	GB-Eire	1921	only	-	Oct	 3	2:00s	0	GMT
    +# S.R.&O. 1922, No. 264
    +Rule	GB-Eire	1922	only	-	Mar	26	2:00s	1:00	BST
    +Rule	GB-Eire	1922	only	-	Oct	 8	2:00s	0	GMT
    +# The Summer Time Act, 1922
    +Rule	GB-Eire	1923	only	-	Apr	Sun>=16	2:00s	1:00	BST
    +Rule	GB-Eire	1923	1924	-	Sep	Sun>=16	2:00s	0	GMT
    +Rule	GB-Eire	1924	only	-	Apr	Sun>=9	2:00s	1:00	BST
    +Rule	GB-Eire	1925	1926	-	Apr	Sun>=16	2:00s	1:00	BST
    +# The Summer Time Act, 1925
    +Rule	GB-Eire	1925	1938	-	Oct	Sun>=2	2:00s	0	GMT
    +Rule	GB-Eire	1927	only	-	Apr	Sun>=9	2:00s	1:00	BST
    +Rule	GB-Eire	1928	1929	-	Apr	Sun>=16	2:00s	1:00	BST
    +Rule	GB-Eire	1930	only	-	Apr	Sun>=9	2:00s	1:00	BST
    +Rule	GB-Eire	1931	1932	-	Apr	Sun>=16	2:00s	1:00	BST
    +Rule	GB-Eire	1933	only	-	Apr	Sun>=9	2:00s	1:00	BST
    +Rule	GB-Eire	1934	only	-	Apr	Sun>=16	2:00s	1:00	BST
    +Rule	GB-Eire	1935	only	-	Apr	Sun>=9	2:00s	1:00	BST
    +Rule	GB-Eire	1936	1937	-	Apr	Sun>=16	2:00s	1:00	BST
    +Rule	GB-Eire	1938	only	-	Apr	Sun>=9	2:00s	1:00	BST
    +Rule	GB-Eire	1939	only	-	Apr	Sun>=16	2:00s	1:00	BST
    +# S.R.&O. 1939, No. 1379
    +Rule	GB-Eire	1939	only	-	Nov	Sun>=16	2:00s	0	GMT
    +# S.R.&O. 1940, No. 172 and No. 1883
    +Rule	GB-Eire	1940	only	-	Feb	Sun>=23	2:00s	1:00	BST
    +# S.R.&O. 1941, No. 476
    +Rule	GB-Eire	1941	only	-	May	Sun>=2	1:00s	2:00	BDST
    +Rule	GB-Eire	1941	1943	-	Aug	Sun>=9	1:00s	1:00	BST
    +# S.R.&O. 1942, No. 506
    +Rule	GB-Eire	1942	1944	-	Apr	Sun>=2	1:00s	2:00	BDST
    +# S.R.&O. 1944, No. 932
    +Rule	GB-Eire	1944	only	-	Sep	Sun>=16	1:00s	1:00	BST
    +# S.R.&O. 1945, No. 312
    +Rule	GB-Eire	1945	only	-	Apr	Mon>=2	1:00s	2:00	BDST
    +Rule	GB-Eire	1945	only	-	Jul	Sun>=9	1:00s	1:00	BST
    +# S.R.&O. 1945, No. 1208
    +Rule	GB-Eire	1945	1946	-	Oct	Sun>=2	2:00s	0	GMT
    +Rule	GB-Eire	1946	only	-	Apr	Sun>=9	2:00s	1:00	BST
    +# The Summer Time Act, 1947
    +Rule	GB-Eire	1947	only	-	Mar	16	2:00s	1:00	BST
    +Rule	GB-Eire	1947	only	-	Apr	13	1:00s	2:00	BDST
    +Rule	GB-Eire	1947	only	-	Aug	10	1:00s	1:00	BST
    +Rule	GB-Eire	1947	only	-	Nov	 2	2:00s	0	GMT
    +# Summer Time Order, 1948 (S.I. 1948/495)
    +Rule	GB-Eire	1948	only	-	Mar	14	2:00s	1:00	BST
    +Rule	GB-Eire	1948	only	-	Oct	31	2:00s	0	GMT
    +# Summer Time Order, 1949 (S.I. 1949/373)
    +Rule	GB-Eire	1949	only	-	Apr	 3	2:00s	1:00	BST
    +Rule	GB-Eire	1949	only	-	Oct	30	2:00s	0	GMT
    +# Summer Time Order, 1950 (S.I. 1950/518)
    +# Summer Time Order, 1951 (S.I. 1951/430)
    +# Summer Time Order, 1952 (S.I. 1952/451)
    +Rule	GB-Eire	1950	1952	-	Apr	Sun>=14	2:00s	1:00	BST
    +Rule	GB-Eire	1950	1952	-	Oct	Sun>=21	2:00s	0	GMT
    +# revert to the rules of the Summer Time Act, 1925
    +Rule	GB-Eire	1953	only	-	Apr	Sun>=16	2:00s	1:00	BST
    +Rule	GB-Eire	1953	1960	-	Oct	Sun>=2	2:00s	0	GMT
    +Rule	GB-Eire	1954	only	-	Apr	Sun>=9	2:00s	1:00	BST
    +Rule	GB-Eire	1955	1956	-	Apr	Sun>=16	2:00s	1:00	BST
    +Rule	GB-Eire	1957	only	-	Apr	Sun>=9	2:00s	1:00	BST
    +Rule	GB-Eire	1958	1959	-	Apr	Sun>=16	2:00s	1:00	BST
    +Rule	GB-Eire	1960	only	-	Apr	Sun>=9	2:00s	1:00	BST
    +# Summer Time Order, 1961 (S.I. 1961/71)
    +# Summer Time (1962) Order, 1961 (S.I. 1961/2465)
    +# Summer Time Order, 1963 (S.I. 1963/81)
    +Rule	GB-Eire	1961	1963	-	Mar	lastSun	2:00s	1:00	BST
    +Rule	GB-Eire	1961	1968	-	Oct	Sun>=23	2:00s	0	GMT
    +# Summer Time (1964) Order, 1963 (S.I. 1963/2101)
    +# Summer Time Order, 1964 (S.I. 1964/1201)
    +# Summer Time Order, 1967 (S.I. 1967/1148)
    +Rule	GB-Eire	1964	1967	-	Mar	Sun>=19	2:00s	1:00	BST
    +# Summer Time Order, 1968 (S.I. 1968/117)
    +Rule	GB-Eire	1968	only	-	Feb	18	2:00s	1:00	BST
    +# The British Standard Time Act, 1968
    +#	(no summer time)
    +# The Summer Time Act, 1972
    +Rule	GB-Eire	1972	1980	-	Mar	Sun>=16	2:00s	1:00	BST
    +Rule	GB-Eire	1972	1980	-	Oct	Sun>=23	2:00s	0	GMT
    +# Summer Time Order, 1980 (S.I. 1980/1089)
    +# Summer Time Order, 1982 (S.I. 1982/1673)
    +# Summer Time Order, 1986 (S.I. 1986/223)
    +# Summer Time Order, 1988 (S.I. 1988/931)
    +Rule	GB-Eire	1981	1995	-	Mar	lastSun	1:00u	1:00	BST
    +Rule	GB-Eire 1981	1989	-	Oct	Sun>=23	1:00u	0	GMT
    +# Summer Time Order, 1989 (S.I. 1989/985)
    +# Summer Time Order, 1992 (S.I. 1992/1729)
    +# Summer Time Order 1994 (S.I. 1994/2798)
    +Rule	GB-Eire 1990	1995	-	Oct	Sun>=22	1:00u	0	GMT
    +# Summer Time Order 1997 (S.I. 1997/2982)
    +# See EU for rules starting in 1996.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/London	-0:01:15 -	LMT	1847 Dec  1 0:00s
    +			 0:00	GB-Eire	%s	1968 Oct 27
    +			 1:00	-	BST	1971 Oct 31 2:00u
    +			 0:00	GB-Eire	%s	1996
    +			 0:00	EU	GMT/BST
    +Link	Europe/London	Europe/Jersey
    +Link	Europe/London	Europe/Guernsey
    +Link	Europe/London	Europe/Isle_of_Man
    +Zone	Europe/Dublin	-0:25:00 -	LMT	1880 Aug  2
    +			-0:25:21 -	DMT	1916 May 21 2:00
    +			-0:25:21 1:00	IST	1916 Oct  1 2:00s
    +			 0:00	GB-Eire	%s	1921 Dec  6 # independence
    +			 0:00	GB-Eire	GMT/IST	1940 Feb 25 2:00
    +			 0:00	1:00	IST	1946 Oct  6 2:00
    +			 0:00	-	GMT	1947 Mar 16 2:00
    +			 0:00	1:00	IST	1947 Nov  2 2:00
    +			 0:00	-	GMT	1948 Apr 18 2:00
    +			 0:00	GB-Eire	GMT/IST	1968 Oct 27
    +			 1:00	-	IST	1971 Oct 31 2:00u
    +			 0:00	GB-Eire	GMT/IST	1996
    +			 0:00	EU	GMT/IST
    +
    +###############################################################################
    +
    +# Europe
    +
    +# EU rules are for the European Union, previously known as the EC, EEC,
    +# Common Market, etc.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	EU	1977	1980	-	Apr	Sun>=1	 1:00u	1:00	S
    +Rule	EU	1977	only	-	Sep	lastSun	 1:00u	0	-
    +Rule	EU	1978	only	-	Oct	 1	 1:00u	0	-
    +Rule	EU	1979	1995	-	Sep	lastSun	 1:00u	0	-
    +Rule	EU	1981	max	-	Mar	lastSun	 1:00u	1:00	S
    +Rule	EU	1996	max	-	Oct	lastSun	 1:00u	0	-
    +# The most recent directive covers the years starting in 2002.  See:
    +# 
    +# Directive 2000/84/EC of the European Parliament and of the Council
    +# of 19 January 2001 on summer-time arrangements.
    +# 
    +
    +# W-Eur differs from EU only in that W-Eur uses standard time.
    +Rule	W-Eur	1977	1980	-	Apr	Sun>=1	 1:00s	1:00	S
    +Rule	W-Eur	1977	only	-	Sep	lastSun	 1:00s	0	-
    +Rule	W-Eur	1978	only	-	Oct	 1	 1:00s	0	-
    +Rule	W-Eur	1979	1995	-	Sep	lastSun	 1:00s	0	-
    +Rule	W-Eur	1981	max	-	Mar	lastSun	 1:00s	1:00	S
    +Rule	W-Eur	1996	max	-	Oct	lastSun	 1:00s	0	-
    +
    +# Older C-Eur rules are for convenience in the tables.
    +# From 1977 on, C-Eur differs from EU only in that C-Eur uses standard time.
    +Rule	C-Eur	1916	only	-	Apr	30	23:00	1:00	S
    +Rule	C-Eur	1916	only	-	Oct	 1	 1:00	0	-
    +Rule	C-Eur	1917	1918	-	Apr	Mon>=15	 2:00s	1:00	S
    +Rule	C-Eur	1917	1918	-	Sep	Mon>=15	 2:00s	0	-
    +Rule	C-Eur	1940	only	-	Apr	 1	 2:00s	1:00	S
    +Rule	C-Eur	1942	only	-	Nov	 2	 2:00s	0	-
    +Rule	C-Eur	1943	only	-	Mar	29	 2:00s	1:00	S
    +Rule	C-Eur	1943	only	-	Oct	 4	 2:00s	0	-
    +Rule	C-Eur	1944	1945	-	Apr	Mon>=1	 2:00s	1:00	S
    +# Whitman gives 1944 Oct 7; go with Shanks & Pottenger.
    +Rule	C-Eur	1944	only	-	Oct	 2	 2:00s	0	-
    +# From Jesper Norgaard Welen (2008-07-13):
    +#
    +# I found what is probably a typo of 2:00 which should perhaps be 2:00s
    +# in the C-Eur rule from tz database version 2008d (this part was
    +# corrected in version 2008d). The circumstancial evidence is simply the
    +# tz database itself, as seen below:
    +#
    +# Zone Europe/Paris 0:09:21 - LMT 1891 Mar 15  0:01
    +#    0:00 France WE%sT 1945 Sep 16  3:00
    +#
    +# Zone Europe/Monaco 0:29:32 - LMT 1891 Mar 15
    +#    0:00 France WE%sT 1945 Sep 16 3:00
    +#
    +# Zone Europe/Belgrade 1:22:00 - LMT 1884
    +#    1:00 1:00 CEST 1945 Sep 16  2:00s
    +#
    +# Rule France 1945 only - Sep 16  3:00 0 -
    +# Rule Belgium 1945 only - Sep 16  2:00s 0 -
    +# Rule Neth 1945 only - Sep 16 2:00s 0 -
    +#
    +# The rule line to be changed is:
    +#
    +# Rule C-Eur 1945 only - Sep 16  2:00 0 -
    +#
    +# It seems that Paris, Monaco, Rule France, Rule Belgium all agree on
    +# 2:00 standard time, e.g. 3:00 local time.  However there are no
    +# countries that use C-Eur rules in September 1945, so the only items
    +# affected are apparently these ficticious zones that translates acronyms
    +# CET and MET:
    +#
    +# Zone CET  1:00 C-Eur CE%sT
    +# Zone MET  1:00 C-Eur ME%sT
    +#
    +# It this is right then the corrected version would look like:
    +#
    +# Rule C-Eur 1945 only - Sep 16  2:00s 0 -
    +#
    +# A small step for mankind though 8-)
    +Rule	C-Eur	1945	only	-	Sep	16	 2:00s	0	-
    +Rule	C-Eur	1977	1980	-	Apr	Sun>=1	 2:00s	1:00	S
    +Rule	C-Eur	1977	only	-	Sep	lastSun	 2:00s	0	-
    +Rule	C-Eur	1978	only	-	Oct	 1	 2:00s	0	-
    +Rule	C-Eur	1979	1995	-	Sep	lastSun	 2:00s	0	-
    +Rule	C-Eur	1981	max	-	Mar	lastSun	 2:00s	1:00	S
    +Rule	C-Eur	1996	max	-	Oct	lastSun	 2:00s	0	-
    +
    +# E-Eur differs from EU only in that E-Eur switches at midnight local time.
    +Rule	E-Eur	1977	1980	-	Apr	Sun>=1	 0:00	1:00	S
    +Rule	E-Eur	1977	only	-	Sep	lastSun	 0:00	0	-
    +Rule	E-Eur	1978	only	-	Oct	 1	 0:00	0	-
    +Rule	E-Eur	1979	1995	-	Sep	lastSun	 0:00	0	-
    +Rule	E-Eur	1981	max	-	Mar	lastSun	 0:00	1:00	S
    +Rule	E-Eur	1996	max	-	Oct	lastSun	 0:00	0	-
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Russia	1917	only	-	Jul	 1	23:00	1:00	MST	# Moscow Summer Time
    +Rule	Russia	1917	only	-	Dec	28	 0:00	0	MMT	# Moscow Mean Time
    +Rule	Russia	1918	only	-	May	31	22:00	2:00	MDST	# Moscow Double Summer Time
    +Rule	Russia	1918	only	-	Sep	16	 1:00	1:00	MST
    +Rule	Russia	1919	only	-	May	31	23:00	2:00	MDST
    +Rule	Russia	1919	only	-	Jul	 1	 2:00	1:00	S
    +Rule	Russia	1919	only	-	Aug	16	 0:00	0	-
    +Rule	Russia	1921	only	-	Feb	14	23:00	1:00	S
    +Rule	Russia	1921	only	-	Mar	20	23:00	2:00	M # Midsummer
    +Rule	Russia	1921	only	-	Sep	 1	 0:00	1:00	S
    +Rule	Russia	1921	only	-	Oct	 1	 0:00	0	-
    +# Act No.925 of the Council of Ministers of the USSR (1980-10-24):
    +Rule	Russia	1981	1984	-	Apr	 1	 0:00	1:00	S
    +Rule	Russia	1981	1983	-	Oct	 1	 0:00	0	-
    +# Act No.967 of the Council of Ministers of the USSR (1984-09-13), repeated in
    +# Act No.227 of the Council of Ministers of the USSR (1989-03-14):
    +Rule	Russia	1984	1991	-	Sep	lastSun	 2:00s	0	-
    +Rule	Russia	1985	1991	-	Mar	lastSun	 2:00s	1:00	S
    +#
    +Rule	Russia	1992	only	-	Mar	lastSat	 23:00	1:00	S
    +Rule	Russia	1992	only	-	Sep	lastSat	 23:00	0	-
    +Rule	Russia	1993	2010	-	Mar	lastSun	 2:00s	1:00	S
    +Rule	Russia	1993	1995	-	Sep	lastSun	 2:00s	0	-
    +Rule	Russia	1996	2010	-	Oct	lastSun	 2:00s	0	-
    +
    +# From Alexander Krivenyshev (2011-06-14):
    +# According to Kremlin press service, Russian President Dmitry Medvedev
    +# signed a federal law "On calculation of time" on June 9, 2011.
    +# According to the law Russia is abolishing daylight saving time.
    +#
    +# Medvedev signed a law "On the Calculation of Time" (in russian):
    +# 
    +# http://bmockbe.ru/events/?ID=7583
    +# 
    +#
    +# Medvedev signed a law on the calculation of the time (in russian):
    +# 
    +# http://www.regnum.ru/news/polit/1413906.html
    +# 
    +
    +# From Arthur David Olson (2011-06-15):
    +# Take "abolishing daylight saving time" to mean that time is now considered
    +# to be standard.
    +
    +# These are for backward compatibility with older versions.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	WET		0:00	EU	WE%sT
    +Zone	CET		1:00	C-Eur	CE%sT
    +Zone	MET		1:00	C-Eur	ME%sT
    +Zone	EET		2:00	EU	EE%sT
    +
    +# Previous editions of this database used abbreviations like MET DST
    +# for Central European Summer Time, but this didn't agree with common usage.
    +
    +# From Markus Kuhn (1996-07-12):
    +# The official German names ... are
    +#
    +#	Mitteleuropaeische Zeit (MEZ)         = UTC+01:00
    +#	Mitteleuropaeische Sommerzeit (MESZ)  = UTC+02:00
    +#
    +# as defined in the German Time Act (Gesetz ueber die Zeitbestimmung (ZeitG),
    +# 1978-07-25, Bundesgesetzblatt, Jahrgang 1978, Teil I, S. 1110-1111)....
    +# I wrote ... to the German Federal Physical-Technical Institution
    +#
    +#	Physikalisch-Technische Bundesanstalt (PTB)
    +#	Laboratorium 4.41 "Zeiteinheit"
    +#	Postfach 3345
    +#	D-38023 Braunschweig
    +#	phone: +49 531 592-0
    +#
    +# ... I received today an answer letter from Dr. Peter Hetzel, head of the PTB
    +# department for time and frequency transmission.  He explained that the
    +# PTB translates MEZ and MESZ into English as
    +#
    +#	Central European Time (CET)         = UTC+01:00
    +#	Central European Summer Time (CEST) = UTC+02:00
    +
    +
    +# Albania
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Albania	1940	only	-	Jun	16	0:00	1:00	S
    +Rule	Albania	1942	only	-	Nov	 2	3:00	0	-
    +Rule	Albania	1943	only	-	Mar	29	2:00	1:00	S
    +Rule	Albania	1943	only	-	Apr	10	3:00	0	-
    +Rule	Albania	1974	only	-	May	 4	0:00	1:00	S
    +Rule	Albania	1974	only	-	Oct	 2	0:00	0	-
    +Rule	Albania	1975	only	-	May	 1	0:00	1:00	S
    +Rule	Albania	1975	only	-	Oct	 2	0:00	0	-
    +Rule	Albania	1976	only	-	May	 2	0:00	1:00	S
    +Rule	Albania	1976	only	-	Oct	 3	0:00	0	-
    +Rule	Albania	1977	only	-	May	 8	0:00	1:00	S
    +Rule	Albania	1977	only	-	Oct	 2	0:00	0	-
    +Rule	Albania	1978	only	-	May	 6	0:00	1:00	S
    +Rule	Albania	1978	only	-	Oct	 1	0:00	0	-
    +Rule	Albania	1979	only	-	May	 5	0:00	1:00	S
    +Rule	Albania	1979	only	-	Sep	30	0:00	0	-
    +Rule	Albania	1980	only	-	May	 3	0:00	1:00	S
    +Rule	Albania	1980	only	-	Oct	 4	0:00	0	-
    +Rule	Albania	1981	only	-	Apr	26	0:00	1:00	S
    +Rule	Albania	1981	only	-	Sep	27	0:00	0	-
    +Rule	Albania	1982	only	-	May	 2	0:00	1:00	S
    +Rule	Albania	1982	only	-	Oct	 3	0:00	0	-
    +Rule	Albania	1983	only	-	Apr	18	0:00	1:00	S
    +Rule	Albania	1983	only	-	Oct	 1	0:00	0	-
    +Rule	Albania	1984	only	-	Apr	 1	0:00	1:00	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Tirane	1:19:20 -	LMT	1914
    +			1:00	-	CET	1940 Jun 16
    +			1:00	Albania	CE%sT	1984 Jul
    +			1:00	EU	CE%sT
    +
    +# Andorra
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Andorra	0:06:04 -	LMT	1901
    +			0:00	-	WET	1946 Sep 30
    +			1:00	-	CET	1985 Mar 31 2:00
    +			1:00	EU	CE%sT
    +
    +# Austria
    +
    +# From Paul Eggert (2006-03-22): Shanks & Pottenger give 1918-06-16 and
    +# 1945-11-18, but the Austrian Federal Office of Metrology and
    +# Surveying (BEV) gives 1918-09-16 and for Vienna gives the "alleged"
    +# date of 1945-04-12 with no time.  For the 1980-04-06 transition
    +# Shanks & Pottenger give 02:00, the BEV 00:00.  Go with the BEV,
    +# and guess 02:00 for 1945-04-12.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Austria	1920	only	-	Apr	 5	2:00s	1:00	S
    +Rule	Austria	1920	only	-	Sep	13	2:00s	0	-
    +Rule	Austria	1946	only	-	Apr	14	2:00s	1:00	S
    +Rule	Austria	1946	1948	-	Oct	Sun>=1	2:00s	0	-
    +Rule	Austria	1947	only	-	Apr	 6	2:00s	1:00	S
    +Rule	Austria	1948	only	-	Apr	18	2:00s	1:00	S
    +Rule	Austria	1980	only	-	Apr	 6	0:00	1:00	S
    +Rule	Austria	1980	only	-	Sep	28	0:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Vienna	1:05:20 -	LMT	1893 Apr
    +			1:00	C-Eur	CE%sT	1920
    +			1:00	Austria	CE%sT	1940 Apr  1 2:00s
    +			1:00	C-Eur	CE%sT	1945 Apr  2 2:00s
    +			1:00	1:00	CEST	1945 Apr 12 2:00s
    +			1:00	-	CET	1946
    +			1:00	Austria	CE%sT	1981
    +			1:00	EU	CE%sT
    +
    +# Belarus
    +# From Yauhen Kharuzhy (2011-09-16):
    +# By latest Belarus government act Europe/Minsk timezone was changed to
    +# GMT+3 without DST (was GMT+2 with DST).
    +#
    +# Sources (Russian language):
    +# 1.
    +# 
    +# http://www.belta.by/ru/all_news/society/V-Belarusi-otmenjaetsja-perexod-na-sezonnoe-vremja_i_572952.html
    +# 
    +# 2.
    +# 
    +# http://naviny.by/rubrics/society/2011/09/16/ic_articles_116_175144/
    +# 
    +# 3.
    +# 
    +# http://news.tut.by/society/250578.html
    +# 
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Minsk	1:50:16 -	LMT	1880
    +			1:50	-	MMT	1924 May 2 # Minsk Mean Time
    +			2:00	-	EET	1930 Jun 21
    +			3:00	-	MSK	1941 Jun 28
    +			1:00	C-Eur	CE%sT	1944 Jul  3
    +			3:00	Russia	MSK/MSD	1990
    +			3:00	-	MSK	1991 Mar 31 2:00s
    +			2:00	1:00	EEST	1991 Sep 29 2:00s
    +			2:00	-	EET	1992 Mar 29 0:00s
    +			2:00	1:00	EEST	1992 Sep 27 0:00s
    +			2:00	Russia	EE%sT	2011 Mar 27 2:00s
    +			3:00	-	FET # Further-eastern European Time
    +
    +# Belgium
    +#
    +# From Paul Eggert (1997-07-02):
    +# Entries from 1918 through 1991 are taken from:
    +#	Annuaire de L'Observatoire Royal de Belgique,
    +#	Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe annee, 1991
    +#	(Imprimerie HAYEZ, s.p.r.l., Rue Fin, 4, 1080 BRUXELLES, MCMXC),
    +#	pp 8-9.
    +# LMT before 1892 was 0:17:30, according to the official journal of Belgium:
    +#	Moniteur Belge, Samedi 30 Avril 1892, N.121.
    +# Thanks to Pascal Delmoitie for these references.
    +# The 1918 rules are listed for completeness; they apply to unoccupied Belgium.
    +# Assume Brussels switched to WET in 1918 when the armistice took effect.
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Belgium	1918	only	-	Mar	 9	 0:00s	1:00	S
    +Rule	Belgium	1918	1919	-	Oct	Sat>=1	23:00s	0	-
    +Rule	Belgium	1919	only	-	Mar	 1	23:00s	1:00	S
    +Rule	Belgium	1920	only	-	Feb	14	23:00s	1:00	S
    +Rule	Belgium	1920	only	-	Oct	23	23:00s	0	-
    +Rule	Belgium	1921	only	-	Mar	14	23:00s	1:00	S
    +Rule	Belgium	1921	only	-	Oct	25	23:00s	0	-
    +Rule	Belgium	1922	only	-	Mar	25	23:00s	1:00	S
    +Rule	Belgium	1922	1927	-	Oct	Sat>=1	23:00s	0	-
    +Rule	Belgium	1923	only	-	Apr	21	23:00s	1:00	S
    +Rule	Belgium	1924	only	-	Mar	29	23:00s	1:00	S
    +Rule	Belgium	1925	only	-	Apr	 4	23:00s	1:00	S
    +# DSH writes that a royal decree of 1926-02-22 specified the Sun following 3rd
    +# Sat in Apr (except if it's Easter, in which case it's one Sunday earlier),
    +# to Sun following 1st Sat in Oct, and that a royal decree of 1928-09-15
    +# changed the transition times to 02:00 GMT.
    +Rule	Belgium	1926	only	-	Apr	17	23:00s	1:00	S
    +Rule	Belgium	1927	only	-	Apr	 9	23:00s	1:00	S
    +Rule	Belgium	1928	only	-	Apr	14	23:00s	1:00	S
    +Rule	Belgium	1928	1938	-	Oct	Sun>=2	 2:00s	0	-
    +Rule	Belgium	1929	only	-	Apr	21	 2:00s	1:00	S
    +Rule	Belgium	1930	only	-	Apr	13	 2:00s	1:00	S
    +Rule	Belgium	1931	only	-	Apr	19	 2:00s	1:00	S
    +Rule	Belgium	1932	only	-	Apr	 3	 2:00s	1:00	S
    +Rule	Belgium	1933	only	-	Mar	26	 2:00s	1:00	S
    +Rule	Belgium	1934	only	-	Apr	 8	 2:00s	1:00	S
    +Rule	Belgium	1935	only	-	Mar	31	 2:00s	1:00	S
    +Rule	Belgium	1936	only	-	Apr	19	 2:00s	1:00	S
    +Rule	Belgium	1937	only	-	Apr	 4	 2:00s	1:00	S
    +Rule	Belgium	1938	only	-	Mar	27	 2:00s	1:00	S
    +Rule	Belgium	1939	only	-	Apr	16	 2:00s	1:00	S
    +Rule	Belgium	1939	only	-	Nov	19	 2:00s	0	-
    +Rule	Belgium	1940	only	-	Feb	25	 2:00s	1:00	S
    +Rule	Belgium	1944	only	-	Sep	17	 2:00s	0	-
    +Rule	Belgium	1945	only	-	Apr	 2	 2:00s	1:00	S
    +Rule	Belgium	1945	only	-	Sep	16	 2:00s	0	-
    +Rule	Belgium	1946	only	-	May	19	 2:00s	1:00	S
    +Rule	Belgium	1946	only	-	Oct	 7	 2:00s	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Brussels	0:17:30 -	LMT	1880
    +			0:17:30	-	BMT	1892 May  1 12:00 # Brussels MT
    +			0:00	-	WET	1914 Nov  8
    +			1:00	-	CET	1916 May  1  0:00
    +			1:00	C-Eur	CE%sT	1918 Nov 11 11:00u
    +			0:00	Belgium	WE%sT	1940 May 20  2:00s
    +			1:00	C-Eur	CE%sT	1944 Sep  3
    +			1:00	Belgium	CE%sT	1977
    +			1:00	EU	CE%sT
    +
    +# Bosnia and Herzegovina
    +# see Serbia
    +
    +# Bulgaria
    +#
    +# From Plamen Simenov via Steffen Thorsen (1999-09-09):
    +# A document of Government of Bulgaria (No.94/1997) says:
    +# EET --> EETDST is in 03:00 Local time in last Sunday of March ...
    +# EETDST --> EET is in 04:00 Local time in last Sunday of October
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Bulg	1979	only	-	Mar	31	23:00	1:00	S
    +Rule	Bulg	1979	only	-	Oct	 1	 1:00	0	-
    +Rule	Bulg	1980	1982	-	Apr	Sat>=1	23:00	1:00	S
    +Rule	Bulg	1980	only	-	Sep	29	 1:00	0	-
    +Rule	Bulg	1981	only	-	Sep	27	 2:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Sofia	1:33:16 -	LMT	1880
    +			1:56:56	-	IMT	1894 Nov 30 # Istanbul MT?
    +			2:00	-	EET	1942 Nov  2  3:00
    +			1:00	C-Eur	CE%sT	1945
    +			1:00	-	CET	1945 Apr 2 3:00
    +			2:00	-	EET	1979 Mar 31 23:00
    +			2:00	Bulg	EE%sT	1982 Sep 26  2:00
    +			2:00	C-Eur	EE%sT	1991
    +			2:00	E-Eur	EE%sT	1997
    +			2:00	EU	EE%sT
    +
    +# Croatia
    +# see Serbia
    +
    +# Cyprus
    +# Please see the `asia' file for Asia/Nicosia.
    +
    +# Czech Republic
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Czech	1945	only	-	Apr	 8	2:00s	1:00	S
    +Rule	Czech	1945	only	-	Nov	18	2:00s	0	-
    +Rule	Czech	1946	only	-	May	 6	2:00s	1:00	S
    +Rule	Czech	1946	1949	-	Oct	Sun>=1	2:00s	0	-
    +Rule	Czech	1947	only	-	Apr	20	2:00s	1:00	S
    +Rule	Czech	1948	only	-	Apr	18	2:00s	1:00	S
    +Rule	Czech	1949	only	-	Apr	 9	2:00s	1:00	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Prague	0:57:44 -	LMT	1850
    +			0:57:44	-	PMT	1891 Oct     # Prague Mean Time
    +			1:00	C-Eur	CE%sT	1944 Sep 17 2:00s
    +			1:00	Czech	CE%sT	1979
    +			1:00	EU	CE%sT
    +
    +# Denmark, Faroe Islands, and Greenland
    +
    +# From Jesper Norgaard Welen (2005-04-26):
    +# http://www.hum.aau.dk/~poe/tid/tine/DanskTid.htm says that the law
    +# [introducing standard time] was in effect from 1894-01-01....
    +# The page http://www.retsinfo.dk/_GETDOCI_/ACCN/A18930008330-REGL
    +# confirms this, and states that the law was put forth 1893-03-29.
    +#
    +# The EU treaty with effect from 1973:
    +# http://www.retsinfo.dk/_GETDOCI_/ACCN/A19722110030-REGL
    +#
    +# This provoked a new law from 1974 to make possible summer time changes
    +# in subsequenet decrees with the law
    +# http://www.retsinfo.dk/_GETDOCI_/ACCN/A19740022330-REGL
    +#
    +# It seems however that no decree was set forward until 1980.  I have
    +# not found any decree, but in another related law, the effecting DST
    +# changes are stated explicitly to be from 1980-04-06 at 02:00 to
    +# 1980-09-28 at 02:00.  If this is true, this differs slightly from
    +# the EU rule in that DST runs to 02:00, not 03:00.  We don't know
    +# when Denmark began using the EU rule correctly, but we have only
    +# confirmation of the 1980-time, so I presume it was correct in 1981:
    +# The law is about the management of the extra hour, concerning
    +# working hours reported and effect on obligatory-rest rules (which
    +# was suspended on that night):
    +# http://www.retsinfo.dk/_GETDOCI_/ACCN/C19801120554-REGL
    +
    +# From Jesper Norgaard Welen (2005-06-11):
    +# The Herning Folkeblad (1980-09-26) reported that the night between
    +# Saturday and Sunday the clock is set back from three to two.
    +
    +# From Paul Eggert (2005-06-11):
    +# Hence the "02:00" of the 1980 law refers to standard time, not
    +# wall-clock time, and so the EU rules were in effect in 1980.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Denmark	1916	only	-	May	14	23:00	1:00	S
    +Rule	Denmark	1916	only	-	Sep	30	23:00	0	-
    +Rule	Denmark	1940	only	-	May	15	 0:00	1:00	S
    +Rule	Denmark	1945	only	-	Apr	 2	 2:00s	1:00	S
    +Rule	Denmark	1945	only	-	Aug	15	 2:00s	0	-
    +Rule	Denmark	1946	only	-	May	 1	 2:00s	1:00	S
    +Rule	Denmark	1946	only	-	Sep	 1	 2:00s	0	-
    +Rule	Denmark	1947	only	-	May	 4	 2:00s	1:00	S
    +Rule	Denmark	1947	only	-	Aug	10	 2:00s	0	-
    +Rule	Denmark	1948	only	-	May	 9	 2:00s	1:00	S
    +Rule	Denmark	1948	only	-	Aug	 8	 2:00s	0	-
    +#
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Europe/Copenhagen	 0:50:20 -	LMT	1890
    +			 0:50:20 -	CMT	1894 Jan  1 # Copenhagen MT
    +			 1:00	Denmark	CE%sT	1942 Nov  2 2:00s
    +			 1:00	C-Eur	CE%sT	1945 Apr  2 2:00
    +			 1:00	Denmark	CE%sT	1980
    +			 1:00	EU	CE%sT
    +Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
    +			 0:00	-	WET	1981
    +			 0:00	EU	WE%sT
    +#
    +# From Paul Eggert (2004-10-31):
    +# During World War II, Germany maintained secret manned weather stations in
    +# East Greenland and Franz Josef Land, but we don't know their time zones.
    +# My source for this is Wilhelm Dege's book mentioned under Svalbard.
    +#
    +# From Paul Eggert (2006-03-22):
    +# Greenland joined the EU as part of Denmark, obtained home rule on 1979-05-01,
    +# and left the EU on 1985-02-01.  It therefore should have been using EU
    +# rules at least through 1984.  Shanks & Pottenger say Scoresbysund and Godthab
    +# used C-Eur rules after 1980, but IATA SSIM (1991/1996) says they use EU
    +# rules since at least 1991.  Assume EU rules since 1980.
    +
    +# From Gwillin Law (2001-06-06), citing
    +#  (2001-03-15),
    +# and with translations corrected by Steffen Thorsen:
    +#
    +# Greenland has four local times, and the relation to UTC
    +# is according to the following time line:
    +#
    +# The military zone near Thule	UTC-4
    +# Standard Greenland time	UTC-3
    +# Scoresbysund			UTC-1
    +# Danmarkshavn			UTC
    +#
    +# In the military area near Thule and in Danmarkshavn DST will not be
    +# introduced.
    +
    +# From Rives McDow (2001-11-01):
    +#
    +# I correspond regularly with the Dansk Polarcenter, and wrote them at
    +# the time to clarify the situation in Thule.  Unfortunately, I have
    +# not heard back from them regarding my recent letter.  [But I have
    +# info from earlier correspondence.]
    +#
    +# According to the center, a very small local time zone around Thule
    +# Air Base keeps the time according to UTC-4, implementing daylight
    +# savings using North America rules, changing the time at 02:00 local time....
    +#
    +# The east coast of Greenland north of the community of Scoresbysund
    +# uses UTC in the same way as in Iceland, year round, with no dst.
    +# There are just a few stations on this coast, including the
    +# Danmarkshavn ICAO weather station mentioned in your September 29th
    +# email.  The other stations are two sledge patrol stations in
    +# Mestersvig and Daneborg, the air force base at Station Nord, and the
    +# DPC research station at Zackenberg.
    +#
    +# Scoresbysund and two small villages nearby keep time UTC-1 and use
    +# the same daylight savings time period as in West Greenland (Godthab).
    +#
    +# The rest of Greenland, including Godthab (this area, although it
    +# includes central Greenland, is known as west Greenland), keeps time
    +# UTC-3, with daylight savings methods according to European rules.
    +#
    +# It is common procedure to use UTC 0 in the wilderness of East and
    +# North Greenland, because it is mainly Icelandic aircraft operators
    +# maintaining traffic in these areas.  However, the official status of
    +# this area is that it sticks with Godthab time.  This area might be
    +# considered a dual time zone in some respects because of this.
    +
    +# From Rives McDow (2001-11-19):
    +# I heard back from someone stationed at Thule; the time change took place
    +# there at 2:00 AM.
    +
    +# From Paul Eggert (2006-03-22):
    +# From 1997 on the CIA map shows Danmarkshavn on GMT;
    +# the 1995 map as like Godthab.
    +# For lack of better info, assume they were like Godthab before 1996.
    +# startkart.no says Thule does not observe DST, but this is clearly an error,
    +# so go with Shanks & Pottenger for Thule transitions until this year.
    +# For 2007 on assume Thule will stay in sync with US DST rules.
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Thule	1991	1992	-	Mar	lastSun	2:00	1:00	D
    +Rule	Thule	1991	1992	-	Sep	lastSun	2:00	0	S
    +Rule	Thule	1993	2006	-	Apr	Sun>=1	2:00	1:00	D
    +Rule	Thule	1993	2006	-	Oct	lastSun	2:00	0	S
    +Rule	Thule	2007	max	-	Mar	Sun>=8	2:00	1:00	D
    +Rule	Thule	2007	max	-	Nov	Sun>=1	2:00	0	S
    +#
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Danmarkshavn -1:14:40 -	LMT	1916 Jul 28
    +			-3:00	-	WGT	1980 Apr  6 2:00
    +			-3:00	EU	WG%sT	1996
    +			0:00	-	GMT
    +Zone America/Scoresbysund -1:27:52 -	LMT	1916 Jul 28 # Ittoqqortoormiit
    +			-2:00	-	CGT	1980 Apr  6 2:00
    +			-2:00	C-Eur	CG%sT	1981 Mar 29
    +			-1:00	EU	EG%sT
    +Zone America/Godthab	-3:26:56 -	LMT	1916 Jul 28 # Nuuk
    +			-3:00	-	WGT	1980 Apr  6 2:00
    +			-3:00	EU	WG%sT
    +Zone America/Thule	-4:35:08 -	LMT	1916 Jul 28 # Pituffik air base
    +			-4:00	Thule	A%sT
    +
    +# Estonia
    +# From Peter Ilieve (1994-10-15):
    +# A relative in Tallinn confirms the accuracy of the data for 1989 onwards
    +# [through 1994] and gives the legal authority for it,
    +# a regulation of the Government of Estonia, No. 111 of 1989....
    +#
    +# From Peter Ilieve (1996-10-28):
    +# [IATA SSIM (1992/1996) claims that the Baltic republics switch at 01:00s,
    +# but a relative confirms that Estonia still switches at 02:00s, writing:]
    +# ``I do not [know] exactly but there are some little different
    +# (confusing) rules for International Air and Railway Transport Schedules
    +# conversion in Sunday connected with end of summer time in Estonia....
    +# A discussion is running about the summer time efficiency and effect on
    +# human physiology.  It seems that Estonia maybe will not change to
    +# summer time next spring.''
    +
    +# From Peter Ilieve (1998-11-04), heavily edited:
    +# 
    +# The 1998-09-22 Estonian time law
    +# 
    +# refers to the Eighth Directive and cites the association agreement between
    +# the EU and Estonia, ratified by the Estonian law (RT II 1995, 22--27, 120).
    +#
    +# I also asked [my relative] whether they use any standard abbreviation
    +# for their standard and summer times. He says no, they use "suveaeg"
    +# (summer time) and "talveaeg" (winter time).
    +
    +# From The Baltic Times (1999-09-09)
    +# via Steffen Thorsen:
    +# This year will mark the last time Estonia shifts to summer time,
    +# a council of the ruling coalition announced Sept. 6....
    +# But what this could mean for Estonia's chances of joining the European
    +# Union are still unclear.  In 1994, the EU declared summer time compulsory
    +# for all member states until 2001.  Brussels has yet to decide what to do
    +# after that.
    +
    +# From Mart Oruaas (2000-01-29):
    +# Regulation no. 301 (1999-10-12) obsoletes previous regulation
    +# no. 206 (1998-09-22) and thus sticks Estonia to +02:00 GMT for all
    +# the year round.  The regulation is effective 1999-11-01.
    +
    +# From Toomas Soome (2002-02-21):
    +# The Estonian government has changed once again timezone politics.
    +# Now we are using again EU rules.
    +#
    +# From Urmet Jaanes (2002-03-28):
    +# The legislative reference is Government decree No. 84 on 2002-02-21.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Tallinn	1:39:00	-	LMT	1880
    +			1:39:00	-	TMT	1918 Feb # Tallinn Mean Time
    +			1:00	C-Eur	CE%sT	1919 Jul
    +			1:39:00	-	TMT	1921 May
    +			2:00	-	EET	1940 Aug  6
    +			3:00	-	MSK	1941 Sep 15
    +			1:00	C-Eur	CE%sT	1944 Sep 22
    +			3:00	Russia	MSK/MSD	1989 Mar 26 2:00s
    +			2:00	1:00	EEST	1989 Sep 24 2:00s
    +			2:00	C-Eur	EE%sT	1998 Sep 22
    +			2:00	EU	EE%sT	1999 Nov  1
    +			2:00	-	EET	2002 Feb 21
    +			2:00	EU	EE%sT
    +
    +# Finland
    +
    +# From Hannu Strang (1994-09-25 06:03:37 UTC):
    +# Well, here in Helsinki we're just changing from summer time to regular one,
    +# and it's supposed to change at 4am...
    +
    +# From Janne Snabb (2010-0715):
    +#
    +# I noticed that the Finland data is not accurate for years 1981 and 1982.
    +# During these two first trial years the DST adjustment was made one hour
    +# earlier than in forthcoming years. Starting 1983 the adjustment was made
    +# according to the central European standards.
    +#
    +# This is documented in Heikki Oja: Aikakirja 2007, published by The Almanac
    +# Office of University of Helsinki, ISBN 952-10-3221-9, available online (in
    +# Finnish) at
    +#
    +# 
    +# http://almanakka.helsinki.fi/aikakirja/Aikakirja2007kokonaan.pdf
    +# 
    +#
    +# Page 105 (56 in PDF version) has a handy table of all past daylight savings
    +# transitions. It is easy enough to interpret without Finnish skills.
    +#
    +# This is also confirmed by Finnish Broadcasting Company's archive at:
    +#
    +# 
    +# http://www.yle.fi/elavaarkisto/?s=s&g=1&ag=5&t=&a=3401
    +# 
    +#
    +# The news clip from 1981 says that "the time between 2 and 3 o'clock does not
    +# exist tonight."
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Finland	1942	only	-	Apr	3	0:00	1:00	S
    +Rule	Finland	1942	only	-	Oct	3	0:00	0	-
    +Rule	Finland	1981	1982	-	Mar	lastSun	2:00	1:00	S
    +Rule	Finland	1981	1982	-	Sep	lastSun	3:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Helsinki	1:39:52 -	LMT	1878 May 31
    +			1:39:52	-	HMT	1921 May    # Helsinki Mean Time
    +			2:00	Finland	EE%sT	1983
    +			2:00	EU	EE%sT
    +
    +# Aaland Is
    +Link	Europe/Helsinki	Europe/Mariehamn
    +
    +
    +# France
    +
    +# From Ciro Discepolo (2000-12-20):
    +#
    +# Henri Le Corre, Regimes Horaires pour le monde entier, Editions
    +# Traditionnelles - Paris 2 books, 1993
    +#
    +# Gabriel, Traite de l'heure dans le monde, Guy Tredaniel editeur,
    +# Paris, 1991
    +#
    +# Francoise Gauquelin, Problemes de l'heure resolus en astrologie,
    +# Guy tredaniel, Paris 1987
    +
    +
    +#
    +# Shank & Pottenger seem to use `24:00' ambiguously; resolve it with Whitman.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	France	1916	only	-	Jun	14	23:00s	1:00	S
    +Rule	France	1916	1919	-	Oct	Sun>=1	23:00s	0	-
    +Rule	France	1917	only	-	Mar	24	23:00s	1:00	S
    +Rule	France	1918	only	-	Mar	 9	23:00s	1:00	S
    +Rule	France	1919	only	-	Mar	 1	23:00s	1:00	S
    +Rule	France	1920	only	-	Feb	14	23:00s	1:00	S
    +Rule	France	1920	only	-	Oct	23	23:00s	0	-
    +Rule	France	1921	only	-	Mar	14	23:00s	1:00	S
    +Rule	France	1921	only	-	Oct	25	23:00s	0	-
    +Rule	France	1922	only	-	Mar	25	23:00s	1:00	S
    +# DSH writes that a law of 1923-05-24 specified 3rd Sat in Apr at 23:00 to 1st
    +# Sat in Oct at 24:00; and that in 1930, because of Easter, the transitions
    +# were Apr 12 and Oct 5.  Go with Shanks & Pottenger.
    +Rule	France	1922	1938	-	Oct	Sat>=1	23:00s	0	-
    +Rule	France	1923	only	-	May	26	23:00s	1:00	S
    +Rule	France	1924	only	-	Mar	29	23:00s	1:00	S
    +Rule	France	1925	only	-	Apr	 4	23:00s	1:00	S
    +Rule	France	1926	only	-	Apr	17	23:00s	1:00	S
    +Rule	France	1927	only	-	Apr	 9	23:00s	1:00	S
    +Rule	France	1928	only	-	Apr	14	23:00s	1:00	S
    +Rule	France	1929	only	-	Apr	20	23:00s	1:00	S
    +Rule	France	1930	only	-	Apr	12	23:00s	1:00	S
    +Rule	France	1931	only	-	Apr	18	23:00s	1:00	S
    +Rule	France	1932	only	-	Apr	 2	23:00s	1:00	S
    +Rule	France	1933	only	-	Mar	25	23:00s	1:00	S
    +Rule	France	1934	only	-	Apr	 7	23:00s	1:00	S
    +Rule	France	1935	only	-	Mar	30	23:00s	1:00	S
    +Rule	France	1936	only	-	Apr	18	23:00s	1:00	S
    +Rule	France	1937	only	-	Apr	 3	23:00s	1:00	S
    +Rule	France	1938	only	-	Mar	26	23:00s	1:00	S
    +Rule	France	1939	only	-	Apr	15	23:00s	1:00	S
    +Rule	France	1939	only	-	Nov	18	23:00s	0	-
    +Rule	France	1940	only	-	Feb	25	 2:00	1:00	S
    +# The French rules for 1941-1944 were not used in Paris, but Shanks & Pottenger
    +# write that they were used in Monaco and in many French locations.
    +# Le Corre writes that the upper limit of the free zone was Arneguy, Orthez,
    +# Mont-de-Marsan, Bazas, Langon, Lamotte-Montravel, Marouil, La
    +# Rochefoucault, Champagne-Mouton, La Roche-Posay, La Haye-Descartes,
    +# Loches, Montrichard, Vierzon, Bourges, Moulins, Digoin,
    +# Paray-le-Monial, Montceau-les-Mines, Chalons-sur-Saone, Arbois,
    +# Dole, Morez, St-Claude, and Collonges (Haute-Savoie).
    +Rule	France	1941	only	-	May	 5	 0:00	2:00	M # Midsummer
    +# Shanks & Pottenger say this transition occurred at Oct 6 1:00,
    +# but go with Denis Excoffier (1997-12-12),
    +# who quotes the Ephemerides Astronomiques for 1998 from Bureau des Longitudes
    +# as saying 5/10/41 22hUT.
    +Rule	France	1941	only	-	Oct	 6	 0:00	1:00	S
    +Rule	France	1942	only	-	Mar	 9	 0:00	2:00	M
    +Rule	France	1942	only	-	Nov	 2	 3:00	1:00	S
    +Rule	France	1943	only	-	Mar	29	 2:00	2:00	M
    +Rule	France	1943	only	-	Oct	 4	 3:00	1:00	S
    +Rule	France	1944	only	-	Apr	 3	 2:00	2:00	M
    +Rule	France	1944	only	-	Oct	 8	 1:00	1:00	S
    +Rule	France	1945	only	-	Apr	 2	 2:00	2:00	M
    +Rule	France	1945	only	-	Sep	16	 3:00	0	-
    +# Shanks & Pottenger give Mar 28 2:00 and Sep 26 3:00;
    +# go with Excoffier's 28/3/76 0hUT and 25/9/76 23hUT.
    +Rule	France	1976	only	-	Mar	28	 1:00	1:00	S
    +Rule	France	1976	only	-	Sep	26	 1:00	0	-
    +# Shanks & Pottenger give 0:09:20 for Paris Mean Time, and Whitman 0:09:05,
    +# but Howse quotes the actual French legislation as saying 0:09:21.
    +# Go with Howse.  Howse writes that the time in France was officially based
    +# on PMT-0:09:21 until 1978-08-09, when the time base finally switched to UTC.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Paris	0:09:21 -	LMT	1891 Mar 15  0:01
    +			0:09:21	-	PMT	1911 Mar 11  0:01  # Paris MT
    +# Shanks & Pottenger give 1940 Jun 14 0:00; go with Excoffier and Le Corre.
    +			0:00	France	WE%sT	1940 Jun 14 23:00
    +# Le Corre says Paris stuck with occupied-France time after the liberation;
    +# go with Shanks & Pottenger.
    +			1:00	C-Eur	CE%sT	1944 Aug 25
    +			0:00	France	WE%sT	1945 Sep 16  3:00
    +			1:00	France	CE%sT	1977
    +			1:00	EU	CE%sT
    +
    +# Germany
    +
    +# From Markus Kuhn (1998-09-29):
    +# The German time zone web site by the Physikalisch-Technische
    +# Bundesanstalt contains DST information back to 1916.
    +# [See tz-link.htm for the URL.]
    +
    +# From Joerg Schilling (2002-10-23):
    +# In 1945, Berlin was switched to Moscow Summer time (GMT+4) by
    +# 
    +# General [Nikolai] Bersarin.
    +
    +# From Paul Eggert (2003-03-08):
    +# 
    +# http://www.parlament-berlin.de/pds-fraktion.nsf/727459127c8b66ee8525662300459099/defc77cb784f180ac1256c2b0030274b/$FILE/bersarint.pdf
    +# 
    +# says that Bersarin issued an order to use Moscow time on May 20.
    +# However, Moscow did not observe daylight saving in 1945, so
    +# this was equivalent to CEMT (GMT+3), not GMT+4.
    +
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Germany	1946	only	-	Apr	14	2:00s	1:00	S
    +Rule	Germany	1946	only	-	Oct	 7	2:00s	0	-
    +Rule	Germany	1947	1949	-	Oct	Sun>=1	2:00s	0	-
    +# http://www.ptb.de/de/org/4/44/441/salt.htm says the following transition
    +# occurred at 3:00 MEZ, not the 2:00 MEZ given in Shanks & Pottenger.
    +# Go with the PTB.
    +Rule	Germany	1947	only	-	Apr	 6	3:00s	1:00	S
    +Rule	Germany	1947	only	-	May	11	2:00s	2:00	M
    +Rule	Germany	1947	only	-	Jun	29	3:00	1:00	S
    +Rule	Germany	1948	only	-	Apr	18	2:00s	1:00	S
    +Rule	Germany	1949	only	-	Apr	10	2:00s	1:00	S
    +
    +Rule SovietZone	1945	only	-	May	24	2:00	2:00	M # Midsummer
    +Rule SovietZone	1945	only	-	Sep	24	3:00	1:00	S
    +Rule SovietZone	1945	only	-	Nov	18	2:00s	0	-
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Berlin	0:53:28 -	LMT	1893 Apr
    +			1:00	C-Eur	CE%sT	1945 May 24 2:00
    +			1:00 SovietZone	CE%sT	1946
    +			1:00	Germany	CE%sT	1980
    +			1:00	EU	CE%sT
    +
    +# Georgia
    +# Please see the "asia" file for Asia/Tbilisi.
    +# Herodotus (Histories, IV.45) says Georgia north of the Phasis (now Rioni)
    +# is in Europe.  Our reference location Tbilisi is in the Asian part.
    +
    +# Gibraltar
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Europe/Gibraltar	-0:21:24 -	LMT	1880 Aug  2 0:00s
    +			0:00	GB-Eire	%s	1957 Apr 14 2:00
    +			1:00	-	CET	1982
    +			1:00	EU	CE%sT
    +
    +# Greece
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +# Whitman gives 1932 Jul 5 - Nov 1; go with Shanks & Pottenger.
    +Rule	Greece	1932	only	-	Jul	 7	0:00	1:00	S
    +Rule	Greece	1932	only	-	Sep	 1	0:00	0	-
    +# Whitman gives 1941 Apr 25 - ?; go with Shanks & Pottenger.
    +Rule	Greece	1941	only	-	Apr	 7	0:00	1:00	S
    +# Whitman gives 1942 Feb 2 - ?; go with Shanks & Pottenger.
    +Rule	Greece	1942	only	-	Nov	 2	3:00	0	-
    +Rule	Greece	1943	only	-	Mar	30	0:00	1:00	S
    +Rule	Greece	1943	only	-	Oct	 4	0:00	0	-
    +# Whitman gives 1944 Oct 3 - Oct 31; go with Shanks & Pottenger.
    +Rule	Greece	1952	only	-	Jul	 1	0:00	1:00	S
    +Rule	Greece	1952	only	-	Nov	 2	0:00	0	-
    +Rule	Greece	1975	only	-	Apr	12	0:00s	1:00	S
    +Rule	Greece	1975	only	-	Nov	26	0:00s	0	-
    +Rule	Greece	1976	only	-	Apr	11	2:00s	1:00	S
    +Rule	Greece	1976	only	-	Oct	10	2:00s	0	-
    +Rule	Greece	1977	1978	-	Apr	Sun>=1	2:00s	1:00	S
    +Rule	Greece	1977	only	-	Sep	26	2:00s	0	-
    +Rule	Greece	1978	only	-	Sep	24	4:00	0	-
    +Rule	Greece	1979	only	-	Apr	 1	9:00	1:00	S
    +Rule	Greece	1979	only	-	Sep	29	2:00	0	-
    +Rule	Greece	1980	only	-	Apr	 1	0:00	1:00	S
    +Rule	Greece	1980	only	-	Sep	28	0:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Athens	1:34:52 -	LMT	1895 Sep 14
    +			1:34:52	-	AMT	1916 Jul 28 0:01     # Athens MT
    +			2:00	Greece	EE%sT	1941 Apr 30
    +			1:00	Greece	CE%sT	1944 Apr  4
    +			2:00	Greece	EE%sT	1981
    +			# Shanks & Pottenger say it switched to C-Eur in 1981;
    +			# go with EU instead, since Greece joined it on Jan 1.
    +			2:00	EU	EE%sT
    +
    +# Hungary
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Hungary	1918	only	-	Apr	 1	 3:00	1:00	S
    +Rule	Hungary	1918	only	-	Sep	29	 3:00	0	-
    +Rule	Hungary	1919	only	-	Apr	15	 3:00	1:00	S
    +Rule	Hungary	1919	only	-	Sep	15	 3:00	0	-
    +Rule	Hungary	1920	only	-	Apr	 5	 3:00	1:00	S
    +Rule	Hungary	1920	only	-	Sep	30	 3:00	0	-
    +Rule	Hungary	1945	only	-	May	 1	23:00	1:00	S
    +Rule	Hungary	1945	only	-	Nov	 3	 0:00	0	-
    +Rule	Hungary	1946	only	-	Mar	31	 2:00s	1:00	S
    +Rule	Hungary	1946	1949	-	Oct	Sun>=1	 2:00s	0	-
    +Rule	Hungary	1947	1949	-	Apr	Sun>=4	 2:00s	1:00	S
    +Rule	Hungary	1950	only	-	Apr	17	 2:00s	1:00	S
    +Rule	Hungary	1950	only	-	Oct	23	 2:00s	0	-
    +Rule	Hungary	1954	1955	-	May	23	 0:00	1:00	S
    +Rule	Hungary	1954	1955	-	Oct	 3	 0:00	0	-
    +Rule	Hungary	1956	only	-	Jun	Sun>=1	 0:00	1:00	S
    +Rule	Hungary	1956	only	-	Sep	lastSun	 0:00	0	-
    +Rule	Hungary	1957	only	-	Jun	Sun>=1	 1:00	1:00	S
    +Rule	Hungary	1957	only	-	Sep	lastSun	 3:00	0	-
    +Rule	Hungary	1980	only	-	Apr	 6	 1:00	1:00	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Budapest	1:16:20 -	LMT	1890 Oct
    +			1:00	C-Eur	CE%sT	1918
    +			1:00	Hungary	CE%sT	1941 Apr  6  2:00
    +			1:00	C-Eur	CE%sT	1945
    +			1:00	Hungary	CE%sT	1980 Sep 28  2:00s
    +			1:00	EU	CE%sT
    +
    +# Iceland
    +#
    +# From Adam David (1993-11-06):
    +# The name of the timezone in Iceland for system / mail / news purposes is GMT.
    +#
    +# (1993-12-05):
    +# This material is paraphrased from the 1988 edition of the University of
    +# Iceland Almanak.
    +#
    +# From January 1st, 1908 the whole of Iceland was standardised at 1 hour
    +# behind GMT. Previously, local mean solar time was used in different parts
    +# of Iceland, the almanak had been based on Reykjavik mean solar time which
    +# was 1 hour and 28 minutes behind GMT.
    +#
    +# "first day of winter" referred to [below] means the first day of the 26 weeks
    +# of winter, according to the old icelandic calendar that dates back to the
    +# time the norsemen first settled Iceland.  The first day of winter is always
    +# Saturday, but is not dependent on the Julian or Gregorian calendars.
    +#
    +# (1993-12-10):
    +# I have a reference from the Oxford Icelandic-English dictionary for the
    +# beginning of winter, which ties it to the ecclesiastical calendar (and thus
    +# to the julian/gregorian calendar) over the period in question.
    +#	the winter begins on the Saturday next before St. Luke's day
    +#	(old style), or on St. Luke's day, if a Saturday.
    +# St. Luke's day ought to be traceable from ecclesiastical sources. "old style"
    +# might be a reference to the Julian calendar as opposed to Gregorian, or it
    +# might mean something else (???).
    +#
    +# From Paul Eggert (2006-03-22):
    +# The Iceland Almanak, Shanks & Pottenger, and Whitman disagree on many points.
    +# We go with the Almanak, except for one claim from Shanks & Pottenger, namely
    +# that Reykavik was 21W57 from 1837 to 1908, local mean time before that.
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Iceland	1917	1918	-	Feb	19	23:00	1:00	S
    +Rule	Iceland	1917	only	-	Oct	21	 1:00	0	-
    +Rule	Iceland	1918	only	-	Nov	16	 1:00	0	-
    +Rule	Iceland	1939	only	-	Apr	29	23:00	1:00	S
    +Rule	Iceland	1939	only	-	Nov	29	 2:00	0	-
    +Rule	Iceland	1940	only	-	Feb	25	 2:00	1:00	S
    +Rule	Iceland	1940	only	-	Nov	 3	 2:00	0	-
    +Rule	Iceland	1941	only	-	Mar	 2	 1:00s	1:00	S
    +Rule	Iceland	1941	only	-	Nov	 2	 1:00s	0	-
    +Rule	Iceland	1942	only	-	Mar	 8	 1:00s	1:00	S
    +Rule	Iceland	1942	only	-	Oct	25	 1:00s	0	-
    +# 1943-1946 - first Sunday in March until first Sunday in winter
    +Rule	Iceland	1943	1946	-	Mar	Sun>=1	 1:00s	1:00	S
    +Rule	Iceland	1943	1948	-	Oct	Sun>=22	 1:00s	0	-
    +# 1947-1967 - first Sunday in April until first Sunday in winter
    +Rule	Iceland	1947	1967	-	Apr	Sun>=1	 1:00s	1:00	S
    +# 1949 Oct transition delayed by 1 week
    +Rule	Iceland	1949	only	-	Oct	30	 1:00s	0	-
    +Rule	Iceland	1950	1966	-	Oct	Sun>=22	 1:00s	0	-
    +Rule	Iceland	1967	only	-	Oct	29	 1:00s	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Atlantic/Reykjavik	-1:27:24 -	LMT	1837
    +			-1:27:48 -	RMT	1908 # Reykjavik Mean Time?
    +			-1:00	Iceland	IS%sT	1968 Apr 7 1:00s
    +			 0:00	-	GMT
    +
    +# Italy
    +#
    +# From Paul Eggert (2001-03-06):
    +# Sicily and Sardinia each had their own time zones from 1866 to 1893,
    +# called Palermo Time (+00:53:28) and Cagliari Time (+00:36:32).
    +# During World War II, German-controlled Italy used German time.
    +# But these events all occurred before the 1970 cutoff,
    +# so record only the time in Rome.
    +#
    +# From Paul Eggert (2006-03-22):
    +# For Italian DST we have three sources: Shanks & Pottenger, Whitman, and
    +# F. Pollastri
    +# 
    +# Day-light Saving Time in Italy (2006-02-03)
    +# 
    +# (`FP' below), taken from an Italian National Electrotechnical Institute
    +# publication. When the three sources disagree, guess who's right, as follows:
    +#
    +# year	FP	Shanks&P. (S)	Whitman (W)	Go with:
    +# 1916	06-03	06-03 24:00	06-03 00:00	FP & W
    +#	09-30	09-30 24:00	09-30 01:00	FP; guess 24:00s
    +# 1917	04-01	03-31 24:00	03-31 00:00	FP & S
    +#	09-30	09-29 24:00	09-30 01:00	FP & W
    +# 1918	03-09	03-09 24:00	03-09 00:00	FP & S
    +#	10-06	10-05 24:00	10-06 01:00	FP & W
    +# 1919	03-01	03-01 24:00	03-01 00:00	FP & S
    +#	10-04	10-04 24:00	10-04 01:00	FP; guess 24:00s
    +# 1920	03-20	03-20 24:00	03-20 00:00	FP & S
    +#	09-18	09-18 24:00	10-01 01:00	FP; guess 24:00s
    +# 1944	04-02	04-03 02:00			S (see C-Eur)
    +#	09-16	10-02 03:00			FP; guess 24:00s
    +# 1945	09-14	09-16 24:00			FP; guess 24:00s
    +# 1970	05-21	05-31 00:00			S
    +#	09-20	09-27 00:00			S
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Italy	1916	only	-	Jun	 3	0:00s	1:00	S
    +Rule	Italy	1916	only	-	Oct	 1	0:00s	0	-
    +Rule	Italy	1917	only	-	Apr	 1	0:00s	1:00	S
    +Rule	Italy	1917	only	-	Sep	30	0:00s	0	-
    +Rule	Italy	1918	only	-	Mar	10	0:00s	1:00	S
    +Rule	Italy	1918	1919	-	Oct	Sun>=1	0:00s	0	-
    +Rule	Italy	1919	only	-	Mar	 2	0:00s	1:00	S
    +Rule	Italy	1920	only	-	Mar	21	0:00s	1:00	S
    +Rule	Italy	1920	only	-	Sep	19	0:00s	0	-
    +Rule	Italy	1940	only	-	Jun	15	0:00s	1:00	S
    +Rule	Italy	1944	only	-	Sep	17	0:00s	0	-
    +Rule	Italy	1945	only	-	Apr	 2	2:00	1:00	S
    +Rule	Italy	1945	only	-	Sep	15	0:00s	0	-
    +Rule	Italy	1946	only	-	Mar	17	2:00s	1:00	S
    +Rule	Italy	1946	only	-	Oct	 6	2:00s	0	-
    +Rule	Italy	1947	only	-	Mar	16	0:00s	1:00	S
    +Rule	Italy	1947	only	-	Oct	 5	0:00s	0	-
    +Rule	Italy	1948	only	-	Feb	29	2:00s	1:00	S
    +Rule	Italy	1948	only	-	Oct	 3	2:00s	0	-
    +Rule	Italy	1966	1968	-	May	Sun>=22	0:00	1:00	S
    +Rule	Italy	1966	1969	-	Sep	Sun>=22	0:00	0	-
    +Rule	Italy	1969	only	-	Jun	 1	0:00	1:00	S
    +Rule	Italy	1970	only	-	May	31	0:00	1:00	S
    +Rule	Italy	1970	only	-	Sep	lastSun	0:00	0	-
    +Rule	Italy	1971	1972	-	May	Sun>=22	0:00	1:00	S
    +Rule	Italy	1971	only	-	Sep	lastSun	1:00	0	-
    +Rule	Italy	1972	only	-	Oct	 1	0:00	0	-
    +Rule	Italy	1973	only	-	Jun	 3	0:00	1:00	S
    +Rule	Italy	1973	1974	-	Sep	lastSun	0:00	0	-
    +Rule	Italy	1974	only	-	May	26	0:00	1:00	S
    +Rule	Italy	1975	only	-	Jun	 1	0:00s	1:00	S
    +Rule	Italy	1975	1977	-	Sep	lastSun	0:00s	0	-
    +Rule	Italy	1976	only	-	May	30	0:00s	1:00	S
    +Rule	Italy	1977	1979	-	May	Sun>=22	0:00s	1:00	S
    +Rule	Italy	1978	only	-	Oct	 1	0:00s	0	-
    +Rule	Italy	1979	only	-	Sep	30	0:00s	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Rome	0:49:56 -	LMT	1866 Sep 22
    +			0:49:56	-	RMT	1893 Nov  1 0:00s # Rome Mean
    +			1:00	Italy	CE%sT	1942 Nov  2 2:00s
    +			1:00	C-Eur	CE%sT	1944 Jul
    +			1:00	Italy	CE%sT	1980
    +			1:00	EU	CE%sT
    +
    +Link	Europe/Rome	Europe/Vatican
    +Link	Europe/Rome	Europe/San_Marino
    +
    +# Latvia
    +
    +# From Liene Kanepe (1998-09-17):
    +
    +# I asked about this matter Scientific Secretary of the Institute of Astronomy
    +# of The University of Latvia Dr. paed Mr. Ilgonis Vilks. I also searched the
    +# correct data in juridical acts and I found some juridical documents about
    +# changes in the counting of time in Latvia from 1981....
    +#
    +# Act No.35 of the Council of Ministers of Latvian SSR of 1981-01-22 ...
    +# according to the Act No.925 of the Council of Ministers of USSR of 1980-10-24
    +# ...: all year round the time of 2nd time zone + 1 hour, in addition turning
    +# the hands of the clock 1 hour forward on 1 April at 00:00 (GMT 31 March 21:00)
    +# and 1 hour backward on the 1 October at 00:00 (GMT 30 September 20:00).
    +#
    +# Act No.592 of the Council of Ministers of Latvian SSR of 1984-09-24 ...
    +# according to the Act No.967 of the Council of Ministers of USSR of 1984-09-13
    +# ...: all year round the time of 2nd time zone + 1 hour, in addition turning
    +# the hands of the clock 1 hour forward on the last Sunday of March at 02:00
    +# (GMT 23:00 on the previous day) and 1 hour backward on the last Sunday of
    +# September at 03:00 (GMT 23:00 on the previous day).
    +#
    +# Act No.81 of the Council of Ministers of Latvian SSR of 1989-03-22 ...
    +# according to the Act No.227 of the Council of Ministers of USSR of 1989-03-14
    +# ...: since the last Sunday of March 1989 in Lithuanian SSR, Latvian SSR,
    +# Estonian SSR and Kaliningrad region of Russian Federation all year round the
    +# time of 2nd time zone (Moscow time minus one hour). On the territory of Latvia
    +# transition to summer time is performed on the last Sunday of March at 02:00
    +# (GMT 00:00), turning the hands of the clock 1 hour forward.  The end of
    +# daylight saving time is performed on the last Sunday of September at 03:00
    +# (GMT 00:00), turning the hands of the clock 1 hour backward. Exception is
    +# 1989-03-26, when we must not turn the hands of the clock....
    +#
    +# The Regulations of the Cabinet of Ministers of the Republic of Latvia of
    +# 1997-01-21 on transition to Summer time ... established the same order of
    +# daylight savings time settings as in the States of the European Union.
    +
    +# From Andrei Ivanov (2000-03-06):
    +# This year Latvia will not switch to Daylight Savings Time (as specified in
    +# 
    +# The Regulations of the Cabinet of Ministers of the Rep. of Latvia of
    +# 29-Feb-2000 (#79), in Latvian for subscribers only).
    +
    +# 
    +# From RFE/RL Newsline (2001-01-03), noted after a heads-up by Rives McDow:
    +# 
    +# The Latvian government on 2 January decided that the country will
    +# institute daylight-saving time this spring, LETA reported.
    +# Last February the three Baltic states decided not to turn back their
    +# clocks one hour in the spring....
    +# Minister of Economy Aigars Kalvitis noted that Latvia had too few
    +# daylight hours and thus decided to comply with a draft European
    +# Commission directive that provides for instituting daylight-saving
    +# time in EU countries between 2002 and 2006. The Latvian government
    +# urged Lithuania and Estonia to adopt a similar time policy, but it
    +# appears that they will not do so....
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Latvia	1989	1996	-	Mar	lastSun	 2:00s	1:00	S
    +Rule	Latvia	1989	1996	-	Sep	lastSun	 2:00s	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Riga	1:36:24	-	LMT	1880
    +			1:36:24	-	RMT	1918 Apr 15 2:00 #Riga Mean Time
    +			1:36:24	1:00	LST	1918 Sep 16 3:00 #Latvian Summer
    +			1:36:24	-	RMT	1919 Apr  1 2:00
    +			1:36:24	1:00	LST	1919 May 22 3:00
    +			1:36:24	-	RMT	1926 May 11
    +			2:00	-	EET	1940 Aug  5
    +			3:00	-	MSK	1941 Jul
    +			1:00	C-Eur	CE%sT	1944 Oct 13
    +			3:00	Russia	MSK/MSD	1989 Mar lastSun 2:00s
    +			2:00	1:00	EEST	1989 Sep lastSun 2:00s
    +			2:00	Latvia	EE%sT	1997 Jan 21
    +			2:00	EU	EE%sT	2000 Feb 29
    +			2:00	-	EET	2001 Jan  2
    +			2:00	EU	EE%sT
    +
    +# Liechtenstein
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Vaduz	0:38:04 -	LMT	1894 Jun
    +			1:00	-	CET	1981
    +			1:00	EU	CE%sT
    +
    +# Lithuania
    +
    +# From Paul Eggert (1996-11-22):
    +# IATA SSIM (1992/1996) says Lithuania uses W-Eur rules, but since it is
    +# known to be wrong about Estonia and Latvia, assume it's wrong here too.
    +
    +# From Marius Gedminas (1998-08-07):
    +# I would like to inform that in this year Lithuanian time zone
    +# (Europe/Vilnius) was changed.
    +
    +# From ELTA No. 972 (2582) (1999-09-29),
    +# via Steffen Thorsen:
    +# Lithuania has shifted back to the second time zone (GMT plus two hours)
    +# to be valid here starting from October 31,
    +# as decided by the national government on Wednesday....
    +# The Lithuanian government also announced plans to consider a
    +# motion to give up shifting to summer time in spring, as it was
    +# already done by Estonia.
    +
    +# From the 
    +# Fact File, Lithuanian State Department of Tourism
    +#  (2000-03-27): Local time is GMT+2 hours ..., no daylight saving.
    +
    +# From a user via Klaus Marten (2003-02-07):
    +# As a candidate for membership of the European Union, Lithuania will
    +# observe Summer Time in 2003, changing its clocks at the times laid
    +# down in EU Directive 2000/84 of 19.I.01 (i.e. at the same times as its
    +# neighbour Latvia). The text of the Lithuanian government Order of
    +# 7.XI.02 to this effect can be found at
    +# http://www.lrvk.lt/nut/11/n1749.htm
    +
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Vilnius	1:41:16	-	LMT	1880
    +			1:24:00	-	WMT	1917	    # Warsaw Mean Time
    +			1:35:36	-	KMT	1919 Oct 10 # Kaunas Mean Time
    +			1:00	-	CET	1920 Jul 12
    +			2:00	-	EET	1920 Oct  9
    +			1:00	-	CET	1940 Aug  3
    +			3:00	-	MSK	1941 Jun 24
    +			1:00	C-Eur	CE%sT	1944 Aug
    +			3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
    +			2:00	1:00	EEST	1991 Sep 29 2:00s
    +			2:00	C-Eur	EE%sT	1998
    +			2:00	-	EET	1998 Mar 29 1:00u
    +			1:00	EU	CE%sT	1999 Oct 31 1:00u
    +			2:00	-	EET	2003 Jan  1
    +			2:00	EU	EE%sT
    +
    +# Luxembourg
    +# Whitman disagrees with most of these dates in minor ways;
    +# go with Shanks & Pottenger.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Lux	1916	only	-	May	14	23:00	1:00	S
    +Rule	Lux	1916	only	-	Oct	 1	 1:00	0	-
    +Rule	Lux	1917	only	-	Apr	28	23:00	1:00	S
    +Rule	Lux	1917	only	-	Sep	17	 1:00	0	-
    +Rule	Lux	1918	only	-	Apr	Mon>=15	 2:00s	1:00	S
    +Rule	Lux	1918	only	-	Sep	Mon>=15	 2:00s	0	-
    +Rule	Lux	1919	only	-	Mar	 1	23:00	1:00	S
    +Rule	Lux	1919	only	-	Oct	 5	 3:00	0	-
    +Rule	Lux	1920	only	-	Feb	14	23:00	1:00	S
    +Rule	Lux	1920	only	-	Oct	24	 2:00	0	-
    +Rule	Lux	1921	only	-	Mar	14	23:00	1:00	S
    +Rule	Lux	1921	only	-	Oct	26	 2:00	0	-
    +Rule	Lux	1922	only	-	Mar	25	23:00	1:00	S
    +Rule	Lux	1922	only	-	Oct	Sun>=2	 1:00	0	-
    +Rule	Lux	1923	only	-	Apr	21	23:00	1:00	S
    +Rule	Lux	1923	only	-	Oct	Sun>=2	 2:00	0	-
    +Rule	Lux	1924	only	-	Mar	29	23:00	1:00	S
    +Rule	Lux	1924	1928	-	Oct	Sun>=2	 1:00	0	-
    +Rule	Lux	1925	only	-	Apr	 5	23:00	1:00	S
    +Rule	Lux	1926	only	-	Apr	17	23:00	1:00	S
    +Rule	Lux	1927	only	-	Apr	 9	23:00	1:00	S
    +Rule	Lux	1928	only	-	Apr	14	23:00	1:00	S
    +Rule	Lux	1929	only	-	Apr	20	23:00	1:00	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Europe/Luxembourg	0:24:36 -	LMT	1904 Jun
    +			1:00	Lux	CE%sT	1918 Nov 25
    +			0:00	Lux	WE%sT	1929 Oct  6 2:00s
    +			0:00	Belgium	WE%sT	1940 May 14 3:00
    +			1:00	C-Eur	WE%sT	1944 Sep 18 3:00
    +			1:00	Belgium	CE%sT	1977
    +			1:00	EU	CE%sT
    +
    +# Macedonia
    +# see Serbia
    +
    +# Malta
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Malta	1973	only	-	Mar	31	0:00s	1:00	S
    +Rule	Malta	1973	only	-	Sep	29	0:00s	0	-
    +Rule	Malta	1974	only	-	Apr	21	0:00s	1:00	S
    +Rule	Malta	1974	only	-	Sep	16	0:00s	0	-
    +Rule	Malta	1975	1979	-	Apr	Sun>=15	2:00	1:00	S
    +Rule	Malta	1975	1980	-	Sep	Sun>=15	2:00	0	-
    +Rule	Malta	1980	only	-	Mar	31	2:00	1:00	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
    +			1:00	Italy	CE%sT	1942 Nov  2 2:00s
    +			1:00	C-Eur	CE%sT	1945 Apr  2 2:00s
    +			1:00	Italy	CE%sT	1973 Mar 31
    +			1:00	Malta	CE%sT	1981
    +			1:00	EU	CE%sT
    +
    +# Moldova
    +
    +# From Paul Eggert (2006-03-22):
    +# A previous version of this database followed Shanks & Pottenger, who write
    +# that Tiraspol switched to Moscow time on 1992-01-19 at 02:00.
    +# However, this is most likely an error, as Moldova declared independence
    +# on 1991-08-27 (the 1992-01-19 date is that of a Russian decree).
    +# In early 1992 there was large-scale interethnic violence in the area
    +# and it's possible that some Russophones continued to observe Moscow time.
    +# But [two people] separately reported via
    +# Jesper Norgaard that as of 2001-01-24 Tiraspol was like Chisinau.
    +# The Tiraspol entry has therefore been removed for now.
    +#
    +# From Alexander Krivenyshev (2011-10-17):
    +# Pridnestrovian Moldavian Republic (PMR, also known as
    +# "Pridnestrovie") has abolished seasonal clock change (no transition
    +# to the Winter Time).
    +#
    +# News (in Russian):
    +# 
    +# http://www.kyivpost.ua/russia/news/pridnestrove-otkazalos-ot-perehoda-na-zimnee-vremya-30954.html
    +# 
    +#
    +# 
    +# http://www.allmoldova.com/moldova-news/1249064116.html
    +# 
    +#
    +# The substance of this change (reinstatement of the Tiraspol entry)
    +# is from a patch from Petr Machata (2011-10-17)
    +#
    +# From Tim Parenti (2011-10-19)
    +# In addition, being situated at +4651+2938 would give Tiraspol
    +# a pre-1880 LMT offset of 1:58:32.
    +#
    +# (which agrees with the earlier entry that had been removed)
    +#
    +# From Alexander Krivenyshev (2011-10-26)
    +# NO need to divide Moldova into two timezones at this point.
    +# As of today, Transnistria (Pridnestrovie)- Tiraspol reversed its own
    +# decision to abolish DST this winter.
    +# Following Moldova and neighboring Ukraine- Transnistria (Pridnestrovie)-
    +# Tiraspol will go back to winter time on October 30, 2011.
    +# News from Moldova (in russian):
    +# 
    +# http://ru.publika.md/link_317061.html
    +# 
    +
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Chisinau	1:55:20 -	LMT	1880
    +			1:55	-	CMT	1918 Feb 15 # Chisinau MT
    +			1:44:24	-	BMT	1931 Jul 24 # Bucharest MT
    +			2:00	Romania	EE%sT	1940 Aug 15
    +			2:00	1:00	EEST	1941 Jul 17
    +			1:00	C-Eur	CE%sT	1944 Aug 24
    +			3:00	Russia	MSK/MSD	1990
    +			3:00	-	MSK	1990 May 6
    +			2:00	-	EET	1991
    +			2:00	Russia	EE%sT	1992
    +			2:00	E-Eur	EE%sT	1997
    +# See Romania commentary for the guessed 1997 transition to EU rules.
    +			2:00	EU	EE%sT
    +
    +# Monaco
    +# Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
    +# more precise 0:09:21.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Monaco	0:29:32 -	LMT	1891 Mar 15
    +			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
    +			0:00	France	WE%sT	1945 Sep 16 3:00
    +			1:00	France	CE%sT	1977
    +			1:00	EU	CE%sT
    +
    +# Montenegro
    +# see Serbia
    +
    +# Netherlands
    +
    +# Howse writes that the Netherlands' railways used GMT between 1892 and 1940,
    +# but for other purposes the Netherlands used Amsterdam mean time.
    +
    +# However, Robert H. van Gent writes (2001-04-01):
    +# Howse's statement is only correct up to 1909. From 1909-05-01 (00:00:00
    +# Amsterdam mean time) onwards, the whole of the Netherlands (including
    +# the Dutch railways) was required by law to observe Amsterdam mean time
    +# (19 minutes 32.13 seconds ahead of GMT). This had already been the
    +# common practice (except for the railways) for many decades but it was
    +# not until 1909 when the Dutch government finally defined this by law.
    +# On 1937-07-01 this was changed to 20 minutes (exactly) ahead of GMT and
    +# was generally known as Dutch Time ("Nederlandse Tijd").
    +#
    +# (2001-04-08):
    +# 1892-05-01 was the date when the Dutch railways were by law required to
    +# observe GMT while the remainder of the Netherlands adhered to the common
    +# practice of following Amsterdam mean time.
    +#
    +# (2001-04-09):
    +# In 1835 the authorities of the province of North Holland requested the
    +# municipal authorities of the towns and cities in the province to observe
    +# Amsterdam mean time but I do not know in how many cases this request was
    +# actually followed.
    +#
    +# From 1852 onwards the Dutch telegraph offices were by law required to
    +# observe Amsterdam mean time. As the time signals from the observatory of
    +# Leiden were also distributed by the telegraph system, I assume that most
    +# places linked up with the telegraph (and railway) system automatically
    +# adopted Amsterdam mean time.
    +#
    +# Although the early Dutch railway companies initially observed a variety
    +# of times, most of them had adopted Amsterdam mean time by 1858 but it
    +# was not until 1866 when they were all required by law to observe
    +# Amsterdam mean time.
    +
    +# The data before 1945 are taken from
    +# .
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Neth	1916	only	-	May	 1	0:00	1:00	NST	# Netherlands Summer Time
    +Rule	Neth	1916	only	-	Oct	 1	0:00	0	AMT	# Amsterdam Mean Time
    +Rule	Neth	1917	only	-	Apr	16	2:00s	1:00	NST
    +Rule	Neth	1917	only	-	Sep	17	2:00s	0	AMT
    +Rule	Neth	1918	1921	-	Apr	Mon>=1	2:00s	1:00	NST
    +Rule	Neth	1918	1921	-	Sep	lastMon	2:00s	0	AMT
    +Rule	Neth	1922	only	-	Mar	lastSun	2:00s	1:00	NST
    +Rule	Neth	1922	1936	-	Oct	Sun>=2	2:00s	0	AMT
    +Rule	Neth	1923	only	-	Jun	Fri>=1	2:00s	1:00	NST
    +Rule	Neth	1924	only	-	Mar	lastSun	2:00s	1:00	NST
    +Rule	Neth	1925	only	-	Jun	Fri>=1	2:00s	1:00	NST
    +# From 1926 through 1939 DST began 05-15, except that it was delayed by a week
    +# in years when 05-15 fell in the Pentecost weekend.
    +Rule	Neth	1926	1931	-	May	15	2:00s	1:00	NST
    +Rule	Neth	1932	only	-	May	22	2:00s	1:00	NST
    +Rule	Neth	1933	1936	-	May	15	2:00s	1:00	NST
    +Rule	Neth	1937	only	-	May	22	2:00s	1:00	NST
    +Rule	Neth	1937	only	-	Jul	 1	0:00	1:00	S
    +Rule	Neth	1937	1939	-	Oct	Sun>=2	2:00s	0	-
    +Rule	Neth	1938	1939	-	May	15	2:00s	1:00	S
    +Rule	Neth	1945	only	-	Apr	 2	2:00s	1:00	S
    +Rule	Neth	1945	only	-	Sep	16	2:00s	0	-
    +#
    +# Amsterdam Mean Time was +00:19:32.13 exactly, but the .13 is omitted
    +# below because the current format requires GMTOFF to be an integer.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Europe/Amsterdam	0:19:32 -	LMT	1835
    +			0:19:32	Neth	%s	1937 Jul  1
    +			0:20	Neth	NE%sT	1940 May 16 0:00 # Dutch Time
    +			1:00	C-Eur	CE%sT	1945 Apr  2 2:00
    +			1:00	Neth	CE%sT	1977
    +			1:00	EU	CE%sT
    +
    +# Norway
    +# http://met.no/met/met_lex/q_u/sommertid.html (2004-01) agrees with Shanks &
    +# Pottenger.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Norway	1916	only	-	May	22	1:00	1:00	S
    +Rule	Norway	1916	only	-	Sep	30	0:00	0	-
    +Rule	Norway	1945	only	-	Apr	 2	2:00s	1:00	S
    +Rule	Norway	1945	only	-	Oct	 1	2:00s	0	-
    +Rule	Norway	1959	1964	-	Mar	Sun>=15	2:00s	1:00	S
    +Rule	Norway	1959	1965	-	Sep	Sun>=15	2:00s	0	-
    +Rule	Norway	1965	only	-	Apr	25	2:00s	1:00	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Oslo	0:43:00 -	LMT	1895 Jan  1
    +			1:00	Norway	CE%sT	1940 Aug 10 23:00
    +			1:00	C-Eur	CE%sT	1945 Apr  2  2:00
    +			1:00	Norway	CE%sT	1980
    +			1:00	EU	CE%sT
    +
    +# Svalbard & Jan Mayen
    +
    +# From Steffen Thorsen (2001-05-01):
    +# Although I could not find it explicitly, it seems that Jan Mayen and
    +# Svalbard have been using the same time as Norway at least since the
    +# time they were declared as parts of Norway.  Svalbard was declared
    +# as a part of Norway by law of 1925-07-17 no 11, section 4 and Jan
    +# Mayen by law of 1930-02-27 no 2, section 2. (From
    +# http://www.lovdata.no/all/nl-19250717-011.html and
    +# http://www.lovdata.no/all/nl-19300227-002.html).  The law/regulation
    +# for normal/standard time in Norway is from 1894-06-29 no 1 (came
    +# into operation on 1895-01-01) and Svalbard/Jan Mayen seem to be a
    +# part of this law since 1925/1930. (From
    +# http://www.lovdata.no/all/nl-18940629-001.html ) I have not been
    +# able to find if Jan Mayen used a different time zone (e.g. -0100)
    +# before 1930. Jan Mayen has only been "inhabitated" since 1921 by
    +# Norwegian meteorologists and maybe used the same time as Norway ever
    +# since 1921.  Svalbard (Arctic/Longyearbyen) has been inhabited since
    +# before 1895, and therefore probably changed the local time somewhere
    +# between 1895 and 1925 (inclusive).
    +
    +# From Paul Eggert (2001-05-01):
    +#
    +# Actually, Jan Mayen was never occupied by Germany during World War II,
    +# so it must have diverged from Oslo time during the war, as Oslo was
    +# keeping Berlin time.
    +#
    +#  says that the meteorologists
    +# burned down their station in 1940 and left the island, but returned in
    +# 1941 with a small Norwegian garrison and continued operations despite
    +# frequent air ttacks from Germans.  In 1943 the Americans established a
    +# radiolocating station on the island, called "Atlantic City".  Possibly
    +# the UTC offset changed during the war, but I think it unlikely that
    +# Jan Mayen used German daylight-saving rules.
    +#
    +# Svalbard is more complicated, as it was raided in August 1941 by an
    +# Allied party that evacuated the civilian population to England (says
    +# ).  The Svalbard FAQ
    +#  says that the Germans were
    +# expelled on 1942-05-14.  However, small parties of Germans did return,
    +# and according to Wilhelm Dege's book "War North of 80" (1954)
    +# 
    +# the German armed forces at the Svalbard weather station code-named
    +# Haudegen did not surrender to the Allies until September 1945.
    +#
    +# All these events predate our cutoff date of 1970.  Unless we can
    +# come up with more definitive info about the timekeeping during the
    +# war years it's probably best just do...the following for now:
    +Link	Europe/Oslo	Arctic/Longyearbyen
    +
    +# Poland
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Poland	1918	1919	-	Sep	16	2:00s	0	-
    +Rule	Poland	1919	only	-	Apr	15	2:00s	1:00	S
    +Rule	Poland	1944	only	-	Apr	 3	2:00s	1:00	S
    +# Whitman gives 1944 Nov 30; go with Shanks & Pottenger.
    +Rule	Poland	1944	only	-	Oct	 4	2:00	0	-
    +# For 1944-1948 Whitman gives the previous day; go with Shanks & Pottenger.
    +Rule	Poland	1945	only	-	Apr	29	0:00	1:00	S
    +Rule	Poland	1945	only	-	Nov	 1	0:00	0	-
    +# For 1946 on the source is Kazimierz Borkowski,
    +# Torun Center for Astronomy, Dept. of Radio Astronomy, Nicolaus Copernicus U.,
    +# 
    +# Thanks to Przemyslaw Augustyniak (2005-05-28) for this reference.
    +# He also gives these further references:
    +# Mon Pol nr 13, poz 162 (1995) 
    +# Druk nr 2180 (2003) 
    +Rule	Poland	1946	only	-	Apr	14	0:00s	1:00	S
    +Rule	Poland	1946	only	-	Oct	 7	2:00s	0	-
    +Rule	Poland	1947	only	-	May	 4	2:00s	1:00	S
    +Rule	Poland	1947	1949	-	Oct	Sun>=1	2:00s	0	-
    +Rule	Poland	1948	only	-	Apr	18	2:00s	1:00	S
    +Rule	Poland	1949	only	-	Apr	10	2:00s	1:00	S
    +Rule	Poland	1957	only	-	Jun	 2	1:00s	1:00	S
    +Rule	Poland	1957	1958	-	Sep	lastSun	1:00s	0	-
    +Rule	Poland	1958	only	-	Mar	30	1:00s	1:00	S
    +Rule	Poland	1959	only	-	May	31	1:00s	1:00	S
    +Rule	Poland	1959	1961	-	Oct	Sun>=1	1:00s	0	-
    +Rule	Poland	1960	only	-	Apr	 3	1:00s	1:00	S
    +Rule	Poland	1961	1964	-	May	lastSun	1:00s	1:00	S
    +Rule	Poland	1962	1964	-	Sep	lastSun	1:00s	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Warsaw	1:24:00 -	LMT	1880
    +			1:24:00	-	WMT	1915 Aug  5   # Warsaw Mean Time
    +			1:00	C-Eur	CE%sT	1918 Sep 16 3:00
    +			2:00	Poland	EE%sT	1922 Jun
    +			1:00	Poland	CE%sT	1940 Jun 23 2:00
    +			1:00	C-Eur	CE%sT	1944 Oct
    +			1:00	Poland	CE%sT	1977
    +			1:00	W-Eur	CE%sT	1988
    +			1:00	EU	CE%sT
    +
    +# Portugal
    +#
    +# From Rui Pedro Salgueiro (1992-11-12):
    +# Portugal has recently (September, 27) changed timezone
    +# (from WET to MET or CET) to harmonize with EEC.
    +#
    +# Martin Bruckmann (1996-02-29) reports via Peter Ilieve
    +# that Portugal is reverting to 0:00 by not moving its clocks this spring.
    +# The new Prime Minister was fed up with getting up in the dark in the winter.
    +#
    +# From Paul Eggert (1996-11-12):
    +# IATA SSIM (1991-09) reports several 1991-09 and 1992-09 transitions
    +# at 02:00u, not 01:00u.  Assume that these are typos.
    +# IATA SSIM (1991/1992) reports that the Azores were at -1:00.
    +# IATA SSIM (1993-02) says +0:00; later issues (through 1996-09) say -1:00.
    +# Guess that the Azores changed to EU rules in 1992 (since that's when Portugal
    +# harmonized with the EU), and that they stayed +0:00 that winter.
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +# DSH writes that despite Decree 1,469 (1915), the change to the clocks was not
    +# done every year, depending on what Spain did, because of railroad schedules.
    +# Go with Shanks & Pottenger.
    +Rule	Port	1916	only	-	Jun	17	23:00	1:00	S
    +# Whitman gives 1916 Oct 31; go with Shanks & Pottenger.
    +Rule	Port	1916	only	-	Nov	 1	 1:00	0	-
    +Rule	Port	1917	only	-	Feb	28	23:00s	1:00	S
    +Rule	Port	1917	1921	-	Oct	14	23:00s	0	-
    +Rule	Port	1918	only	-	Mar	 1	23:00s	1:00	S
    +Rule	Port	1919	only	-	Feb	28	23:00s	1:00	S
    +Rule	Port	1920	only	-	Feb	29	23:00s	1:00	S
    +Rule	Port	1921	only	-	Feb	28	23:00s	1:00	S
    +Rule	Port	1924	only	-	Apr	16	23:00s	1:00	S
    +Rule	Port	1924	only	-	Oct	14	23:00s	0	-
    +Rule	Port	1926	only	-	Apr	17	23:00s	1:00	S
    +Rule	Port	1926	1929	-	Oct	Sat>=1	23:00s	0	-
    +Rule	Port	1927	only	-	Apr	 9	23:00s	1:00	S
    +Rule	Port	1928	only	-	Apr	14	23:00s	1:00	S
    +Rule	Port	1929	only	-	Apr	20	23:00s	1:00	S
    +Rule	Port	1931	only	-	Apr	18	23:00s	1:00	S
    +# Whitman gives 1931 Oct 8; go with Shanks & Pottenger.
    +Rule	Port	1931	1932	-	Oct	Sat>=1	23:00s	0	-
    +Rule	Port	1932	only	-	Apr	 2	23:00s	1:00	S
    +Rule	Port	1934	only	-	Apr	 7	23:00s	1:00	S
    +# Whitman gives 1934 Oct 5; go with Shanks & Pottenger.
    +Rule	Port	1934	1938	-	Oct	Sat>=1	23:00s	0	-
    +# Shanks & Pottenger give 1935 Apr 30; go with Whitman.
    +Rule	Port	1935	only	-	Mar	30	23:00s	1:00	S
    +Rule	Port	1936	only	-	Apr	18	23:00s	1:00	S
    +# Whitman gives 1937 Apr 2; go with Shanks & Pottenger.
    +Rule	Port	1937	only	-	Apr	 3	23:00s	1:00	S
    +Rule	Port	1938	only	-	Mar	26	23:00s	1:00	S
    +Rule	Port	1939	only	-	Apr	15	23:00s	1:00	S
    +# Whitman gives 1939 Oct 7; go with Shanks & Pottenger.
    +Rule	Port	1939	only	-	Nov	18	23:00s	0	-
    +Rule	Port	1940	only	-	Feb	24	23:00s	1:00	S
    +# Shanks & Pottenger give 1940 Oct 7; go with Whitman.
    +Rule	Port	1940	1941	-	Oct	 5	23:00s	0	-
    +Rule	Port	1941	only	-	Apr	 5	23:00s	1:00	S
    +Rule	Port	1942	1945	-	Mar	Sat>=8	23:00s	1:00	S
    +Rule	Port	1942	only	-	Apr	25	22:00s	2:00	M # Midsummer
    +Rule	Port	1942	only	-	Aug	15	22:00s	1:00	S
    +Rule	Port	1942	1945	-	Oct	Sat>=24	23:00s	0	-
    +Rule	Port	1943	only	-	Apr	17	22:00s	2:00	M
    +Rule	Port	1943	1945	-	Aug	Sat>=25	22:00s	1:00	S
    +Rule	Port	1944	1945	-	Apr	Sat>=21	22:00s	2:00	M
    +Rule	Port	1946	only	-	Apr	Sat>=1	23:00s	1:00	S
    +Rule	Port	1946	only	-	Oct	Sat>=1	23:00s	0	-
    +Rule	Port	1947	1949	-	Apr	Sun>=1	 2:00s	1:00	S
    +Rule	Port	1947	1949	-	Oct	Sun>=1	 2:00s	0	-
    +# Shanks & Pottenger say DST was observed in 1950; go with Whitman.
    +# Whitman gives Oct lastSun for 1952 on; go with Shanks & Pottenger.
    +Rule	Port	1951	1965	-	Apr	Sun>=1	 2:00s	1:00	S
    +Rule	Port	1951	1965	-	Oct	Sun>=1	 2:00s	0	-
    +Rule	Port	1977	only	-	Mar	27	 0:00s	1:00	S
    +Rule	Port	1977	only	-	Sep	25	 0:00s	0	-
    +Rule	Port	1978	1979	-	Apr	Sun>=1	 0:00s	1:00	S
    +Rule	Port	1978	only	-	Oct	 1	 0:00s	0	-
    +Rule	Port	1979	1982	-	Sep	lastSun	 1:00s	0	-
    +Rule	Port	1980	only	-	Mar	lastSun	 0:00s	1:00	S
    +Rule	Port	1981	1982	-	Mar	lastSun	 1:00s	1:00	S
    +Rule	Port	1983	only	-	Mar	lastSun	 2:00s	1:00	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +# Shanks & Pottenger say the transition from LMT to WET occurred 1911-05-24;
    +# Willett says 1912-01-01.  Go with Willett.
    +Zone	Europe/Lisbon	-0:36:32 -	LMT	1884
    +			-0:36:32 -	LMT	1912 Jan  1  # Lisbon Mean Time
    +			 0:00	Port	WE%sT	1966 Apr  3 2:00
    +			 1:00	-	CET	1976 Sep 26 1:00
    +			 0:00	Port	WE%sT	1983 Sep 25 1:00s
    +			 0:00	W-Eur	WE%sT	1992 Sep 27 1:00s
    +			 1:00	EU	CE%sT	1996 Mar 31 1:00u
    +			 0:00	EU	WE%sT
    +Zone Atlantic/Azores	-1:42:40 -	LMT	1884		# Ponta Delgada
    +			-1:54:32 -	HMT	1911 May 24  # Horta Mean Time
    +			-2:00	Port	AZO%sT	1966 Apr  3 2:00 # Azores Time
    +			-1:00	Port	AZO%sT	1983 Sep 25 1:00s
    +			-1:00	W-Eur	AZO%sT	1992 Sep 27 1:00s
    +			 0:00	EU	WE%sT	1993 Mar 28 1:00u
    +			-1:00	EU	AZO%sT
    +Zone Atlantic/Madeira	-1:07:36 -	LMT	1884		# Funchal
    +			-1:07:36 -	FMT	1911 May 24  # Funchal Mean Time
    +			-1:00	Port	MAD%sT	1966 Apr  3 2:00 # Madeira Time
    +			 0:00	Port	WE%sT	1983 Sep 25 1:00s
    +			 0:00	EU	WE%sT
    +
    +# Romania
    +#
    +# From Paul Eggert (1999-10-07):
    +# 
    +# Nine O'clock (1998-10-23) reports that the switch occurred at
    +# 04:00 local time in fall 1998.  For lack of better info,
    +# assume that Romania and Moldova switched to EU rules in 1997,
    +# the same year as Bulgaria.
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Romania	1932	only	-	May	21	 0:00s	1:00	S
    +Rule	Romania	1932	1939	-	Oct	Sun>=1	 0:00s	0	-
    +Rule	Romania	1933	1939	-	Apr	Sun>=2	 0:00s	1:00	S
    +Rule	Romania	1979	only	-	May	27	 0:00	1:00	S
    +Rule	Romania	1979	only	-	Sep	lastSun	 0:00	0	-
    +Rule	Romania	1980	only	-	Apr	 5	23:00	1:00	S
    +Rule	Romania	1980	only	-	Sep	lastSun	 1:00	0	-
    +Rule	Romania	1991	1993	-	Mar	lastSun	 0:00s	1:00	S
    +Rule	Romania	1991	1993	-	Sep	lastSun	 0:00s	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
    +			1:44:24	-	BMT	1931 Jul 24	# Bucharest MT
    +			2:00	Romania	EE%sT	1981 Mar 29 2:00s
    +			2:00	C-Eur	EE%sT	1991
    +			2:00	Romania	EE%sT	1994
    +			2:00	E-Eur	EE%sT	1997
    +			2:00	EU	EE%sT
    +
    +# Russia
    +
    +# From Paul Eggert (2006-03-22):
    +# Except for Moscow after 1919-07-01, I invented the time zone abbreviations.
    +# Moscow time zone abbreviations after 1919-07-01, and Moscow rules after 1991,
    +# are from Andrey A. Chernov.  The rest is from Shanks & Pottenger,
    +# except we follow Chernov's report that 1992 DST transitions were Sat
    +# 23:00, not Sun 02:00s.
    +#
    +# From Stanislaw A. Kuzikowski (1994-06-29):
    +# But now it is some months since Novosibirsk is 3 hours ahead of Moscow!
    +# I do not know why they have decided to make this change;
    +# as far as I remember it was done exactly during winter->summer switching
    +# so we (Novosibirsk) simply did not switch.
    +#
    +# From Andrey A. Chernov (1996-10-04):
    +# `MSK' and `MSD' were born and used initially on Moscow computers with
    +# UNIX-like OSes by several developer groups (e.g. Demos group, Kiae group)....
    +# The next step was the UUCP network, the Relcom predecessor
    +# (used mainly for mail), and MSK/MSD was actively used there.
    +#
    +# From Chris Carrier (1996-10-30):
    +# According to a friend of mine who rode the Trans-Siberian Railroad from
    +# Moscow to Irkutsk in 1995, public air and rail transport in Russia ...
    +# still follows Moscow time, no matter where in Russia it is located.
    +#
    +# For Grozny, Chechnya, we have the following story from
    +# John Daniszewski, "Scavengers in the Rubble", Los Angeles Times (2001-02-07):
    +# News--often false--is spread by word of mouth.  A rumor that it was
    +# time to move the clocks back put this whole city out of sync with
    +# the rest of Russia for two weeks--even soldiers stationed here began
    +# enforcing curfew at the wrong time.
    +#
    +# From Gwillim Law (2001-06-05):
    +# There's considerable evidence that Sakhalin Island used to be in
    +# UTC+11, and has changed to UTC+10, in this decade.  I start with the
    +# SSIM, which listed Yuzhno-Sakhalinsk in zone RU10 along with Magadan
    +# until February 1997, and then in RU9 with Khabarovsk and Vladivostok
    +# since September 1997....  Although the Kuril Islands are
    +# administratively part of Sakhalin oblast', they appear to have
    +# remained on UTC+11 along with Magadan.
    +#
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +#
    +# Kaliningradskaya oblast'.
    +Zone Europe/Kaliningrad	 1:22:00 -	LMT	1893 Apr
    +			 1:00	C-Eur	CE%sT	1945
    +			 2:00	Poland	CE%sT	1946
    +			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
    +			 2:00	Russia	EE%sT	2011 Mar 27 2:00s
    +			 3:00	-	FET # Further-eastern European Time
    +#
    +# From Oscar van Vlijmen (2001-08-25): [This region consists of]
    +# Respublika Adygeya, Arkhangel'skaya oblast',
    +# Belgorodskaya oblast', Bryanskaya oblast', Vladimirskaya oblast',
    +# Vologodskaya oblast', Voronezhskaya oblast',
    +# Respublika Dagestan, Ivanovskaya oblast', Respublika Ingushetiya,
    +# Kabarbino-Balkarskaya Respublika, Respublika Kalmykiya,
    +# Kalyzhskaya oblast', Respublika Karachaevo-Cherkessiya,
    +# Respublika Kareliya, Respublika Komi,
    +# Kostromskaya oblast', Krasnodarskij kraj, Kurskaya oblast',
    +# Leningradskaya oblast', Lipetskaya oblast', Respublika Marij El,
    +# Respublika Mordoviya, Moskva, Moskovskaya oblast',
    +# Murmanskaya oblast', Nenetskij avtonomnyj okrug,
    +# Nizhegorodskaya oblast', Novgorodskaya oblast', Orlovskaya oblast',
    +# Penzenskaya oblast', Pskovskaya oblast', Rostovskaya oblast',
    +# Ryazanskaya oblast', Sankt-Peterburg,
    +# Respublika Severnaya Osetiya, Smolenskaya oblast',
    +# Stavropol'skij kraj, Tambovskaya oblast', Respublika Tatarstan,
    +# Tverskaya oblast', Tyl'skaya oblast', Ul'yanovskaya oblast',
    +# Chechenskaya Respublika, Chuvashskaya oblast',
    +# Yaroslavskaya oblast'
    +Zone Europe/Moscow	 2:30:20 -	LMT	1880
    +			 2:30	-	MMT	1916 Jul  3 # Moscow Mean Time
    +			 2:30:48 Russia	%s	1919 Jul  1 2:00
    +			 3:00	Russia	MSK/MSD	1922 Oct
    +			 2:00	-	EET	1930 Jun 21
    +			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
    +			 2:00	Russia	EE%sT	1992 Jan 19 2:00s
    +			 3:00	Russia	MSK/MSD	2011 Mar 27 2:00s
    +			 4:00	-	MSK
    +#
    +# Astrakhanskaya oblast', Kirovskaya oblast', Saratovskaya oblast',
    +# Volgogradskaya oblast'.  Shanks & Pottenger say Kirov is still at +0400
    +# but Wikipedia (2006-05-09) says +0300.  Perhaps it switched after the
    +# others?  But we have no data.
    +Zone Europe/Volgograd	 2:57:40 -	LMT	1920 Jan  3
    +			 3:00	-	TSAT	1925 Apr  6 # Tsaritsyn Time
    +			 3:00	-	STAT	1930 Jun 21 # Stalingrad Time
    +			 4:00	-	STAT	1961 Nov 11
    +			 4:00	Russia	VOL%sT	1989 Mar 26 2:00s # Volgograd T
    +			 3:00	Russia	VOL%sT	1991 Mar 31 2:00s
    +			 4:00	-	VOLT	1992 Mar 29 2:00s
    +			 3:00	Russia	VOL%sT	2011 Mar 27 2:00s
    +			 4:00	-	VOLT
    +#
    +# From Oscar van Vlijmen (2001-08-25): [This region consists of]
    +# Samarskaya oblast', Udmyrtskaya respublika
    +Zone Europe/Samara	 3:20:36 -	LMT	1919 Jul  1 2:00
    +			 3:00	-	SAMT	1930 Jun 21
    +			 4:00	-	SAMT	1935 Jan 27
    +			 4:00	Russia	KUY%sT	1989 Mar 26 2:00s # Kuybyshev
    +			 3:00	Russia	KUY%sT	1991 Mar 31 2:00s
    +			 2:00	Russia	KUY%sT	1991 Sep 29 2:00s
    +			 3:00	-	KUYT	1991 Oct 20 3:00
    +			 4:00	Russia	SAM%sT	2010 Mar 28 2:00s # Samara Time
    +			 3:00	Russia	SAM%sT	2011 Mar 27 2:00s
    +			 4:00	-	SAMT
    +
    +#
    +# From Oscar van Vlijmen (2001-08-25): [This region consists of]
    +# Respublika Bashkortostan, Komi-Permyatskij avtonomnyj okrug,
    +# Kurganskaya oblast', Orenburgskaya oblast', Permskaya oblast',
    +# Sverdlovskaya oblast', Tyumenskaya oblast',
    +# Khanty-Manskijskij avtonomnyj okrug, Chelyabinskaya oblast',
    +# Yamalo-Nenetskij avtonomnyj okrug.
    +Zone Asia/Yekaterinburg	 4:02:24 -	LMT	1919 Jul 15 4:00
    +			 4:00	-	SVET	1930 Jun 21 # Sverdlovsk Time
    +			 5:00	Russia	SVE%sT	1991 Mar 31 2:00s
    +			 4:00	Russia	SVE%sT	1992 Jan 19 2:00s
    +			 5:00	Russia	YEK%sT	2011 Mar 27 2:00s
    +			 6:00	-	YEKT	# Yekaterinburg Time
    +#
    +# From Oscar van Vlijmen (2001-08-25): [This region consists of]
    +# Respublika Altaj, Altajskij kraj, Omskaya oblast'.
    +Zone Asia/Omsk		 4:53:36 -	LMT	1919 Nov 14
    +			 5:00	-	OMST	1930 Jun 21 # Omsk TIme
    +			 6:00	Russia	OMS%sT	1991 Mar 31 2:00s
    +			 5:00	Russia	OMS%sT	1992 Jan 19 2:00s
    +			 6:00	Russia	OMS%sT	2011 Mar 27 2:00s
    +			 7:00	-	OMST
    +#
    +# From Paul Eggert (2006-08-19): I'm guessing about Tomsk here; it's
    +# not clear when it switched from +7 to +6.
    +# Novosibirskaya oblast', Tomskaya oblast'.
    +Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14 6:00
    +			 6:00	-	NOVT	1930 Jun 21 # Novosibirsk Time
    +			 7:00	Russia	NOV%sT	1991 Mar 31 2:00s
    +			 6:00	Russia	NOV%sT	1992 Jan 19 2:00s
    +			 7:00	Russia	NOV%sT	1993 May 23 # say Shanks & P.
    +			 6:00	Russia	NOV%sT	2011 Mar 27 2:00s
    +			 7:00	-	NOVT
    +
    +# From Alexander Krivenyshev (2009-10-13):
    +# Kemerovo oblast' (Kemerovo region) in Russia will change current time zone on
    +# March 28, 2010:
    +# from current Russia Zone 6 - Krasnoyarsk Time Zone (KRA) UTC +0700
    +# to Russia Zone 5 - Novosibirsk Time Zone (NOV) UTC +0600
    +#
    +# This is according to Government of Russia decree # 740, on September
    +# 14, 2009 "Application in the territory of the Kemerovo region the Fifth
    +# time zone." ("Russia Zone 5" or old "USSR Zone 5" is GMT +0600)
    +#
    +# Russian Government web site (Russian language)
    +# 
    +# http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archive/2009/09/14/991633.htm
    +# 
    +# or Russian-English translation by WorldTimeZone.com with reference
    +# map to local region and new Russia Time Zone map after March 28, 2010
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_russia03.html
    +# 
    +#
    +# Thus, when Russia will switch to DST on the night of March 28, 2010
    +# Kemerovo region (Kemerovo oblast') will not change the clock.
    +#
    +# As a result, Kemerovo oblast' will be in the same time zone as
    +# Novosibirsk, Omsk, Tomsk, Barnaul and Altai Republic.
    +
    +Zone Asia/Novokuznetsk	 5:48:48 -	NMT	1920 Jan  6
    +			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
    +			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
    +			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
    +			 7:00	Russia	KRA%sT	2010 Mar 28 2:00s
    +			 6:00	Russia	NOV%sT	2011 Mar 27 2:00s
    +			 7:00	-	NOVT # Novosibirsk/Novokuznetsk Time
    +
    +#
    +# From Oscar van Vlijmen (2001-08-25): [This region consists of]
    +# Krasnoyarskij kraj,
    +# Tajmyrskij (Dolgano-Nenetskij) avtonomnyj okrug,
    +# Respublika Tuva, Respublika Khakasiya, Evenkijskij avtonomnyj okrug.
    +Zone Asia/Krasnoyarsk	 6:11:20 -	LMT	1920 Jan  6
    +			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
    +			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
    +			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
    +			 7:00	Russia	KRA%sT	2011 Mar 27 2:00s
    +			 8:00	-	KRAT
    +#
    +# From Oscar van Vlijmen (2001-08-25): [This region consists of]
    +# Respublika Buryatiya, Irkutskaya oblast',
    +# Ust'-Ordynskij Buryatskij avtonomnyj okrug.
    +Zone Asia/Irkutsk	 6:57:20 -	LMT	1880
    +			 6:57:20 -	IMT	1920 Jan 25 # Irkutsk Mean Time
    +			 7:00	-	IRKT	1930 Jun 21 # Irkutsk Time
    +			 8:00	Russia	IRK%sT	1991 Mar 31 2:00s
    +			 7:00	Russia	IRK%sT	1992 Jan 19 2:00s
    +			 8:00	Russia	IRK%sT	2011 Mar 27 2:00s
    +			 9:00	-	IRKT
    +#
    +# From Oscar van Vlijmen (2003-10-18): [This region consists of]
    +# Aginskij Buryatskij avtonomnyj okrug, Amurskaya oblast',
    +# [parts of] Respublika Sakha (Yakutiya), Chitinskaya oblast'.
    +
    +# From Oscar van Vlijmen (2009-11-29):
    +# ...some regions of [Russia] were merged with others since 2005...
    +# Some names were changed, no big deal, except for one instance: a new name.
    +# YAK/YAKST: UTC+9 Zabajkal'skij kraj.
    +
    +# From Oscar van Vlijmen (2009-11-29):
    +# The Sakha districts are: Aldanskij, Amginskij, Anabarskij,
    +# Verkhnevilyujskij, Vilyujskij, Gornyj,
    +# Zhiganskij, Kobyajskij, Lenskij, Megino-Kangalasskij, Mirninskij,
    +# Namskij, Nyurbinskij, Olenyokskij, Olyokminskij,
    +# Suntarskij, Tattinskij, Ust'-Aldanskij, Khangalasskij,
    +# Churapchinskij, Eveno-Bytantajskij Natsional'nij.
    +
    +Zone Asia/Yakutsk	 8:38:40 -	LMT	1919 Dec 15
    +			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
    +			 9:00	Russia	YAK%sT	1991 Mar 31 2:00s
    +			 8:00	Russia	YAK%sT	1992 Jan 19 2:00s
    +			 9:00	Russia	YAK%sT	2011 Mar 27 2:00s
    +			 10:00	-	YAKT
    +#
    +# From Oscar van Vlijmen (2003-10-18): [This region consists of]
    +# Evrejskaya avtonomnaya oblast', Khabarovskij kraj, Primorskij kraj,
    +# [parts of] Respublika Sakha (Yakutiya).
    +
    +# From Oscar van Vlijmen (2009-11-29):
    +# The Sakha districts are: Bulunskij, Verkhoyanskij, Tomponskij, Ust'-Majskij,
    +# Ust'-Yanskij.
    +Zone Asia/Vladivostok	 8:47:44 -	LMT	1922 Nov 15
    +			 9:00	-	VLAT	1930 Jun 21 # Vladivostok Time
    +			10:00	Russia	VLA%sT	1991 Mar 31 2:00s
    +			 9:00	Russia	VLA%sST	1992 Jan 19 2:00s
    +			10:00	Russia	VLA%sT	2011 Mar 27 2:00s
    +			11:00	-	VLAT
    +#
    +# Sakhalinskaya oblast'.
    +# The Zone name should be Yuzhno-Sakhalinsk, but that's too long.
    +Zone Asia/Sakhalin	 9:30:48 -	LMT	1905 Aug 23
    +			 9:00	-	CJT	1938
    +			 9:00	-	JST	1945 Aug 25
    +			11:00	Russia	SAK%sT	1991 Mar 31 2:00s # Sakhalin T.
    +			10:00	Russia	SAK%sT	1992 Jan 19 2:00s
    +			11:00	Russia	SAK%sT	1997 Mar lastSun 2:00s
    +			10:00	Russia	SAK%sT	2011 Mar 27 2:00s
    +			11:00	-	SAKT
    +#
    +# From Oscar van Vlijmen (2003-10-18): [This region consists of]
    +# Magadanskaya oblast', Respublika Sakha (Yakutiya).
    +# Probably also: Kuril Islands.
    +
    +# From Oscar van Vlijmen (2009-11-29):
    +# The Sakha districts are: Abyjskij, Allaikhovskij, Verkhhhnekolymskij, Momskij,
    +# Nizhnekolymskij, Ojmyakonskij, Srednekolymskij.
    +Zone Asia/Magadan	10:03:12 -	LMT	1924 May  2
    +			10:00	-	MAGT	1930 Jun 21 # Magadan Time
    +			11:00	Russia	MAG%sT	1991 Mar 31 2:00s
    +			10:00	Russia	MAG%sT	1992 Jan 19 2:00s
    +			11:00	Russia	MAG%sT	2011 Mar 27 2:00s
    +			12:00	-	MAGT
    +#
    +# From Oscar van Vlijmen (2001-08-25): [This region consists of]
    +# Kamchatskaya oblast', Koryakskij avtonomnyj okrug.
    +#
    +# The Zone name should be Asia/Petropavlovsk-Kamchatski, but that's too long.
    +Zone Asia/Kamchatka	10:34:36 -	LMT	1922 Nov 10
    +			11:00	-	PETT	1930 Jun 21 # P-K Time
    +			12:00	Russia	PET%sT	1991 Mar 31 2:00s
    +			11:00	Russia	PET%sT	1992 Jan 19 2:00s
    +			12:00	Russia	PET%sT	2010 Mar 28 2:00s
    +			11:00	Russia	PET%sT	2011 Mar 27 2:00s
    +			12:00	-	PETT
    +#
    +# Chukotskij avtonomnyj okrug
    +Zone Asia/Anadyr	11:49:56 -	LMT	1924 May  2
    +			12:00	-	ANAT	1930 Jun 21 # Anadyr Time
    +			13:00	Russia	ANA%sT	1982 Apr  1 0:00s
    +			12:00	Russia	ANA%sT	1991 Mar 31 2:00s
    +			11:00	Russia	ANA%sT	1992 Jan 19 2:00s
    +			12:00	Russia	ANA%sT	2010 Mar 28 2:00s
    +			11:00	Russia	ANA%sT	2011 Mar 27 2:00s
    +			12:00	-	ANAT
    +
    +# Serbia
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Belgrade	1:22:00	-	LMT	1884
    +			1:00	-	CET	1941 Apr 18 23:00
    +			1:00	C-Eur	CE%sT	1945
    +			1:00	-	CET	1945 May 8 2:00s
    +			1:00	1:00	CEST	1945 Sep 16  2:00s
    +# Metod Kozelj reports that the legal date of
    +# transition to EU rules was 1982-11-27, for all of Yugoslavia at the time.
    +# Shanks & Pottenger don't give as much detail, so go with Kozelj.
    +			1:00	-	CET	1982 Nov 27
    +			1:00	EU	CE%sT
    +Link Europe/Belgrade Europe/Ljubljana	# Slovenia
    +Link Europe/Belgrade Europe/Podgorica	# Montenegro
    +Link Europe/Belgrade Europe/Sarajevo	# Bosnia and Herzegovina
    +Link Europe/Belgrade Europe/Skopje	# Macedonia
    +Link Europe/Belgrade Europe/Zagreb	# Croatia
    +
    +# Slovakia
    +Link Europe/Prague Europe/Bratislava
    +
    +# Slovenia
    +# see Serbia
    +
    +# Spain
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +# For 1917-1919 Whitman gives Apr Sat>=1 - Oct Sat>=1;
    +# go with Shanks & Pottenger.
    +Rule	Spain	1917	only	-	May	 5	23:00s	1:00	S
    +Rule	Spain	1917	1919	-	Oct	 6	23:00s	0	-
    +Rule	Spain	1918	only	-	Apr	15	23:00s	1:00	S
    +Rule	Spain	1919	only	-	Apr	 5	23:00s	1:00	S
    +# Whitman gives 1921 Feb 28 - Oct 14; go with Shanks & Pottenger.
    +Rule	Spain	1924	only	-	Apr	16	23:00s	1:00	S
    +# Whitman gives 1924 Oct 14; go with Shanks & Pottenger.
    +Rule	Spain	1924	only	-	Oct	 4	23:00s	0	-
    +Rule	Spain	1926	only	-	Apr	17	23:00s	1:00	S
    +# Whitman says no DST in 1929; go with Shanks & Pottenger.
    +Rule	Spain	1926	1929	-	Oct	Sat>=1	23:00s	0	-
    +Rule	Spain	1927	only	-	Apr	 9	23:00s	1:00	S
    +Rule	Spain	1928	only	-	Apr	14	23:00s	1:00	S
    +Rule	Spain	1929	only	-	Apr	20	23:00s	1:00	S
    +# Whitman gives 1937 Jun 16, 1938 Apr 16, 1940 Apr 13;
    +# go with Shanks & Pottenger.
    +Rule	Spain	1937	only	-	May	22	23:00s	1:00	S
    +Rule	Spain	1937	1939	-	Oct	Sat>=1	23:00s	0	-
    +Rule	Spain	1938	only	-	Mar	22	23:00s	1:00	S
    +Rule	Spain	1939	only	-	Apr	15	23:00s	1:00	S
    +Rule	Spain	1940	only	-	Mar	16	23:00s	1:00	S
    +# Whitman says no DST 1942-1945; go with Shanks & Pottenger.
    +Rule	Spain	1942	only	-	May	 2	22:00s	2:00	M # Midsummer
    +Rule	Spain	1942	only	-	Sep	 1	22:00s	1:00	S
    +Rule	Spain	1943	1946	-	Apr	Sat>=13	22:00s	2:00	M
    +Rule	Spain	1943	only	-	Oct	 3	22:00s	1:00	S
    +Rule	Spain	1944	only	-	Oct	10	22:00s	1:00	S
    +Rule	Spain	1945	only	-	Sep	30	 1:00	1:00	S
    +Rule	Spain	1946	only	-	Sep	30	 0:00	0	-
    +Rule	Spain	1949	only	-	Apr	30	23:00	1:00	S
    +Rule	Spain	1949	only	-	Sep	30	 1:00	0	-
    +Rule	Spain	1974	1975	-	Apr	Sat>=13	23:00	1:00	S
    +Rule	Spain	1974	1975	-	Oct	Sun>=1	 1:00	0	-
    +Rule	Spain	1976	only	-	Mar	27	23:00	1:00	S
    +Rule	Spain	1976	1977	-	Sep	lastSun	 1:00	0	-
    +Rule	Spain	1977	1978	-	Apr	 2	23:00	1:00	S
    +Rule	Spain	1978	only	-	Oct	 1	 1:00	0	-
    +# The following rules are copied from Morocco from 1967 through 1978.
    +Rule SpainAfrica 1967	only	-	Jun	 3	12:00	1:00	S
    +Rule SpainAfrica 1967	only	-	Oct	 1	 0:00	0	-
    +Rule SpainAfrica 1974	only	-	Jun	24	 0:00	1:00	S
    +Rule SpainAfrica 1974	only	-	Sep	 1	 0:00	0	-
    +Rule SpainAfrica 1976	1977	-	May	 1	 0:00	1:00	S
    +Rule SpainAfrica 1976	only	-	Aug	 1	 0:00	0	-
    +Rule SpainAfrica 1977	only	-	Sep	28	 0:00	0	-
    +Rule SpainAfrica 1978	only	-	Jun	 1	 0:00	1:00	S
    +Rule SpainAfrica 1978	only	-	Aug	 4	 0:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Madrid	-0:14:44 -	LMT	1901 Jan  1  0:00s
    +			 0:00	Spain	WE%sT	1946 Sep 30
    +			 1:00	Spain	CE%sT	1979
    +			 1:00	EU	CE%sT
    +Zone	Africa/Ceuta	-0:21:16 -	LMT	1901
    +			 0:00	-	WET	1918 May  6 23:00
    +			 0:00	1:00	WEST	1918 Oct  7 23:00
    +			 0:00	-	WET	1924
    +			 0:00	Spain	WE%sT	1929
    +			 0:00 SpainAfrica WE%sT 1984 Mar 16
    +			 1:00	-	CET	1986
    +			 1:00	EU	CE%sT
    +Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
    +			-1:00	-	CANT	1946 Sep 30 1:00 # Canaries Time
    +			 0:00	-	WET	1980 Apr  6 0:00s
    +			 0:00	1:00	WEST	1980 Sep 28 0:00s
    +			 0:00	EU	WE%sT
    +# IATA SSIM (1996-09) says the Canaries switch at 2:00u, not 1:00u.
    +# Ignore this for now, as the Canaries are part of the EU.
    +
    +# Sweden
    +
    +# From Ivan Nilsson (2001-04-13), superseding Shanks & Pottenger:
    +#
    +# The law "Svensk forfattningssamling 1878, no 14" about standard time in 1879:
    +# From the beginning of 1879 (that is 01-01 00:00) the time for all
    +# places in the country is "the mean solar time for the meridian at
    +# three degrees, or twelve minutes of time, to the west of the
    +# meridian of the Observatory of Stockholm".  The law is dated 1878-05-31.
    +#
    +# The observatory at that time had the meridian 18 degrees 03' 30"
    +# eastern longitude = 01:12:14 in time.  Less 12 minutes gives the
    +# national standard time as 01:00:14 ahead of GMT....
    +#
    +# About the beginning of CET in Sweden. The lawtext ("Svensk
    +# forfattningssamling 1899, no 44") states, that "from the beginning
    +# of 1900... ... the same as the mean solar time for the meridian at
    +# the distance of one hour of time from the meridian of the English
    +# observatory at Greenwich, or at 12 minutes 14 seconds to the west
    +# from the meridian of the Observatory of Stockholm". The law is dated
    +# 1899-06-16.  In short: At 1900-01-01 00:00:00 the new standard time
    +# in Sweden is 01:00:00 ahead of GMT.
    +#
    +# 1916: The lawtext ("Svensk forfattningssamling 1916, no 124") states
    +# that "1916-05-15 is considered to begin one hour earlier". It is
    +# pretty obvious that at 05-14 23:00 the clocks are set to 05-15 00:00....
    +# Further the law says, that "1916-09-30 is considered to end one hour later".
    +#
    +# The laws regulating [DST] are available on the site of the Swedish
    +# Parliament beginning with 1985 - the laws regulating 1980/1984 are
    +# not available on the site (to my knowledge they are only available
    +# in Swedish):  (type
    +# "sommartid" without the quotes in the field "Fritext" and then click
    +# the Sok-button).
    +#
    +# (2001-05-13):
    +#
    +# I have now found a newspaper stating that at 1916-10-01 01:00
    +# summertime the church-clocks etc were set back one hour to show
    +# 1916-10-01 00:00 standard time.  The article also reports that some
    +# people thought the switch to standard time would take place already
    +# at 1916-10-01 00:00 summer time, but they had to wait for another
    +# hour before the event took place.
    +#
    +# Source: The newspaper "Dagens Nyheter", 1916-10-01, page 7 upper left.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
    +			1:00:14	-	SET	1900 Jan  1	# Swedish Time
    +			1:00	-	CET	1916 May 14 23:00
    +			1:00	1:00	CEST	1916 Oct  1 01:00
    +			1:00	-	CET	1980
    +			1:00	EU	CE%sT
    +
    +# Switzerland
    +# From Howse:
    +# By the end of the 18th century clocks and watches became commonplace
    +# and their performance improved enormously.  Communities began to keep
    +# mean time in preference to apparent time -- Geneva from 1780 ....
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +# From Whitman (who writes ``Midnight?''):
    +# Rule	Swiss	1940	only	-	Nov	 2	0:00	1:00	S
    +# Rule	Swiss	1940	only	-	Dec	31	0:00	0	-
    +# From Shanks & Pottenger:
    +# Rule	Swiss	1941	1942	-	May	Sun>=1	2:00	1:00	S
    +# Rule	Swiss	1941	1942	-	Oct	Sun>=1	0:00	0	-
    +
    +# From Alois Treindl (2008-12-17):
    +# I have researched the DST usage in Switzerland during the 1940ies.
    +#
    +# As I wrote in an earlier message, I suspected the current tzdata values
    +# to be wrong. This is now verified.
    +#
    +# I have found copies of the original ruling by the Swiss Federal
    +# government, in 'Eidgen[o]ssische Gesetzessammlung 1941 and 1942' (Swiss
    +# federal law collection)...
    +#
    +# DST began on Monday 5 May 1941, 1:00 am by shifting the clocks to 2:00 am
    +# DST ended on Monday 6 Oct 1941, 2:00 am by shifting the clocks to 1:00 am.
    +#
    +# DST began on Monday, 4 May 1942 at 01:00 am
    +# DST ended on Monday, 5 Oct 1942 at 02:00 am
    +#
    +# There was no DST in 1940, I have checked the law collection carefully.
    +# It is also indicated by the fact that the 1942 entry in the law
    +# collection points back to 1941 as a reference, but no reference to any
    +# other years are made.
    +#
    +# Newspaper articles I have read in the archives on 6 May 1941 reported
    +# about the introduction of DST (Sommerzeit in German) during the previous
    +# night as an absolute novelty, because this was the first time that such
    +# a thing had happened in Switzerland.
    +#
    +# I have also checked 1916, because one book source (Gabriel, Traite de
    +# l'heure dans le monde) claims that Switzerland had DST in 1916. This is
    +# false, no official document could be found. Probably Gabriel got misled
    +# by references to Germany, which introduced DST in 1916 for the first time.
    +#
    +# The tzdata rules for Switzerland must be changed to:
    +# Rule  Swiss   1941    1942    -       May     Mon>=1  1:00    1:00    S
    +# Rule  Swiss   1941    1942    -       Oct     Mon>=1  2:00    0       -
    +#
    +# The 1940 rules must be deleted.
    +#
    +# One further detail for Switzerland, which is probably out of scope for
    +# most users of tzdata:
    +# The zone file
    +# Zone    Europe/Zurich   0:34:08 -       LMT     1848 Sep 12
    +#                          0:29:44 -       BMT     1894 Jun #Bern Mean Time
    +#                          1:00    Swiss   CE%sT   1981
    +#                          1:00    EU      CE%sT
    +# describes all of Switzerland correctly, with the exception of
    +# the Cantone Geneve (Geneva, Genf). Between 1848 and 1894 Geneve did not
    +# follow Bern Mean Time but kept its own local mean time.
    +# To represent this, an extra zone would be needed.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Swiss	1941	1942	-	May	Mon>=1	1:00	1:00	S
    +Rule	Swiss	1941	1942	-	Oct	Mon>=1	2:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Zurich	0:34:08 -	LMT	1848 Sep 12
    +			0:29:44	-	BMT	1894 Jun # Bern Mean Time
    +			1:00	Swiss	CE%sT	1981
    +			1:00	EU	CE%sT
    +
    +# Turkey
    +
    +# From Amar Devegowda (2007-01-03):
    +# The time zone rules for Istanbul, Turkey have not been changed for years now.
    +# ... The latest rules are available at -
    +# http://www.timeanddate.com/worldclock/timezone.html?n=107
    +# From Steffen Thorsen (2007-01-03):
    +# I have been able to find press records back to 1996 which all say that
    +# DST started 01:00 local time and end at 02:00 local time.  I am not sure
    +# what happened before that.  One example for each year from 1996 to 2001:
    +# http://newspot.byegm.gov.tr/arsiv/1996/21/N4.htm
    +# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING97/03/97X03X25.TXT
    +# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING98/03/98X03X02.HTM
    +# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING99/10/99X10X26.HTM#%2016
    +# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2000/03/00X03X06.HTM#%2021
    +# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2001/03/23x03x01.HTM#%2027
    +# From Paul Eggert (2007-01-03):
    +# Prefer the above source to Shanks & Pottenger for time stamps after 1990.
    +
    +# From Steffen Thorsen (2007-03-09):
    +# Starting 2007 though, it seems that they are adopting EU's 1:00 UTC
    +# start/end time, according to the following page (2007-03-07):
    +# http://www.ntvmsnbc.com/news/402029.asp
    +# The official document is located here - it is in Turkish...:
    +# http://rega.basbakanlik.gov.tr/eskiler/2007/03/20070307-7.htm
    +# I was able to locate the following seemingly official document
    +# (on a non-government server though) describing dates between 2002 and 2006:
    +# http://www.alomaliye.com/bkk_2002_3769.htm
    +
    +# From Gökdeniz Karadağ (2011-03-10):
    +#
    +# According to the articles linked below, Turkey will change into summer
    +# time zone (GMT+3) on March 28, 2011 at 3:00 a.m. instead of March 27.
    +# This change is due to a nationwide exam on 27th.
    +#
    +# 
    +# http://www.worldbulletin.net/?aType=haber&ArticleID=70872
    +# 
    +# Turkish:
    +# 
    +# http://www.hurriyet.com.tr/ekonomi/17230464.asp?gid=373
    +# 
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Turkey	1916	only	-	May	 1	0:00	1:00	S
    +Rule	Turkey	1916	only	-	Oct	 1	0:00	0	-
    +Rule	Turkey	1920	only	-	Mar	28	0:00	1:00	S
    +Rule	Turkey	1920	only	-	Oct	25	0:00	0	-
    +Rule	Turkey	1921	only	-	Apr	 3	0:00	1:00	S
    +Rule	Turkey	1921	only	-	Oct	 3	0:00	0	-
    +Rule	Turkey	1922	only	-	Mar	26	0:00	1:00	S
    +Rule	Turkey	1922	only	-	Oct	 8	0:00	0	-
    +# Whitman gives 1923 Apr 28 - Sep 16 and no DST in 1924-1925;
    +# go with Shanks & Pottenger.
    +Rule	Turkey	1924	only	-	May	13	0:00	1:00	S
    +Rule	Turkey	1924	1925	-	Oct	 1	0:00	0	-
    +Rule	Turkey	1925	only	-	May	 1	0:00	1:00	S
    +Rule	Turkey	1940	only	-	Jun	30	0:00	1:00	S
    +Rule	Turkey	1940	only	-	Oct	 5	0:00	0	-
    +Rule	Turkey	1940	only	-	Dec	 1	0:00	1:00	S
    +Rule	Turkey	1941	only	-	Sep	21	0:00	0	-
    +Rule	Turkey	1942	only	-	Apr	 1	0:00	1:00	S
    +# Whitman omits the next two transition and gives 1945 Oct 1;
    +# go with Shanks & Pottenger.
    +Rule	Turkey	1942	only	-	Nov	 1	0:00	0	-
    +Rule	Turkey	1945	only	-	Apr	 2	0:00	1:00	S
    +Rule	Turkey	1945	only	-	Oct	 8	0:00	0	-
    +Rule	Turkey	1946	only	-	Jun	 1	0:00	1:00	S
    +Rule	Turkey	1946	only	-	Oct	 1	0:00	0	-
    +Rule	Turkey	1947	1948	-	Apr	Sun>=16	0:00	1:00	S
    +Rule	Turkey	1947	1950	-	Oct	Sun>=2	0:00	0	-
    +Rule	Turkey	1949	only	-	Apr	10	0:00	1:00	S
    +Rule	Turkey	1950	only	-	Apr	19	0:00	1:00	S
    +Rule	Turkey	1951	only	-	Apr	22	0:00	1:00	S
    +Rule	Turkey	1951	only	-	Oct	 8	0:00	0	-
    +Rule	Turkey	1962	only	-	Jul	15	0:00	1:00	S
    +Rule	Turkey	1962	only	-	Oct	 8	0:00	0	-
    +Rule	Turkey	1964	only	-	May	15	0:00	1:00	S
    +Rule	Turkey	1964	only	-	Oct	 1	0:00	0	-
    +Rule	Turkey	1970	1972	-	May	Sun>=2	0:00	1:00	S
    +Rule	Turkey	1970	1972	-	Oct	Sun>=2	0:00	0	-
    +Rule	Turkey	1973	only	-	Jun	 3	1:00	1:00	S
    +Rule	Turkey	1973	only	-	Nov	 4	3:00	0	-
    +Rule	Turkey	1974	only	-	Mar	31	2:00	1:00	S
    +Rule	Turkey	1974	only	-	Nov	 3	5:00	0	-
    +Rule	Turkey	1975	only	-	Mar	30	0:00	1:00	S
    +Rule	Turkey	1975	1976	-	Oct	lastSun	0:00	0	-
    +Rule	Turkey	1976	only	-	Jun	 1	0:00	1:00	S
    +Rule	Turkey	1977	1978	-	Apr	Sun>=1	0:00	1:00	S
    +Rule	Turkey	1977	only	-	Oct	16	0:00	0	-
    +Rule	Turkey	1979	1980	-	Apr	Sun>=1	3:00	1:00	S
    +Rule	Turkey	1979	1982	-	Oct	Mon>=11	0:00	0	-
    +Rule	Turkey	1981	1982	-	Mar	lastSun	3:00	1:00	S
    +Rule	Turkey	1983	only	-	Jul	31	0:00	1:00	S
    +Rule	Turkey	1983	only	-	Oct	 2	0:00	0	-
    +Rule	Turkey	1985	only	-	Apr	20	0:00	1:00	S
    +Rule	Turkey	1985	only	-	Sep	28	0:00	0	-
    +Rule	Turkey	1986	1990	-	Mar	lastSun	2:00s	1:00	S
    +Rule	Turkey	1986	1990	-	Sep	lastSun	2:00s	0	-
    +Rule	Turkey	1991	2006	-	Mar	lastSun	1:00s	1:00	S
    +Rule	Turkey	1991	1995	-	Sep	lastSun	1:00s	0	-
    +Rule	Turkey	1996	2006	-	Oct	lastSun	1:00s	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	Europe/Istanbul	1:55:52 -	LMT	1880
    +			1:56:56	-	IMT	1910 Oct # Istanbul Mean Time?
    +			2:00	Turkey	EE%sT	1978 Oct 15
    +			3:00	Turkey	TR%sT	1985 Apr 20 # Turkey Time
    +			2:00	Turkey	EE%sT	2007
    +			2:00	EU	EE%sT	2011 Mar 27 1:00u
    +			2:00	-	EET	2011 Mar 28 1:00u
    +			2:00	EU	EE%sT
    +Link	Europe/Istanbul	Asia/Istanbul	# Istanbul is in both continents.
    +
    +# Ukraine
    +#
    +# From Igor Karpov, who works for the Ukranian Ministry of Justice,
    +# via Garrett Wollman (2003-01-27):
    +# BTW, I've found the official document on this matter. It's goverment
    +# regulations number 509, May 13, 1996. In my poor translation it says:
    +# "Time in Ukraine is set to second timezone (Kiev time). Each last Sunday
    +# of March at 3am the time is changing to 4am and each last Sunday of
    +# October the time at 4am is changing to 3am"
    +
    +# From Alexander Krivenyshev (2011-09-20):
    +# On September 20, 2011 the deputies of the Verkhovna Rada agreed to
    +# abolish the transfer clock to winter time.
    +#
    +# Bill number 8330 of MP from the Party of Regions Oleg Nadoshi got
    +# approval from 266 deputies.
    +#
    +# Ukraine abolishes transter back to the winter time (in Russian)
    +# 
    +# http://news.mail.ru/politics/6861560/
    +# 
    +#
    +# The Ukrainians will no longer change the clock (in Russian)
    +# 
    +# http://www.segodnya.ua/news/14290482.html
    +# 
    +#
    +# Deputies cancelled the winter time (in Russian)
    +# 
    +# http://www.pravda.com.ua/rus/news/2011/09/20/6600616/
    +# 
    +#
    +# From Philip Pizzey (2011-10-18):
    +# Today my Ukrainian colleagues have informed me that the
    +# Ukrainian parliament have decided that they will go to winter
    +# time this year after all.
    +#
    +# From Udo Schwedt (2011-10-18):
    +# As far as I understand, the recent change to the Ukranian time zone
    +# (Europe/Kiev) to introduce permanent daylight saving time (similar
    +# to Russia) was reverted today:
    +#
    +# 
    +# http://portal.rada.gov.ua/rada/control/en/publish/article/info_left?art_id=287324&cat_id=105995
    +# 
    +#
    +# Also reported by Alexander Bokovoy (2011-10-18) who also noted:
    +# The law documents themselves are at
    +#
    +# 
    +# http://w1.c1.rada.gov.ua/pls/zweb_n/webproc4_1?id=&pf3511=41484
    +# 
    +
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +# Most of Ukraine since 1970 has been like Kiev.
    +# "Kyiv" is the transliteration of the Ukrainian name, but
    +# "Kiev" is more common in English.
    +Zone Europe/Kiev	2:02:04 -	LMT	1880
    +			2:02:04	-	KMT	1924 May  2 # Kiev Mean Time
    +			2:00	-	EET	1930 Jun 21
    +			3:00	-	MSK	1941 Sep 20
    +			1:00	C-Eur	CE%sT	1943 Nov  6
    +			3:00	Russia	MSK/MSD	1990
    +			3:00	-	MSK	1990 Jul  1 2:00
    +			2:00	-	EET	1992
    +			2:00	E-Eur	EE%sT	1995
    +			2:00	EU	EE%sT
    +# Ruthenia used CET 1990/1991.
    +# "Uzhhorod" is the transliteration of the Ukrainian name, but
    +# "Uzhgorod" is more common in English.
    +Zone Europe/Uzhgorod	1:29:12 -	LMT	1890 Oct
    +			1:00	-	CET	1940
    +			1:00	C-Eur	CE%sT	1944 Oct
    +			1:00	1:00	CEST	1944 Oct 26
    +			1:00	-	CET	1945 Jun 29
    +			3:00	Russia	MSK/MSD	1990
    +			3:00	-	MSK	1990 Jul  1 2:00
    +			1:00	-	CET	1991 Mar 31 3:00
    +			2:00	-	EET	1992
    +			2:00	E-Eur	EE%sT	1995
    +			2:00	EU	EE%sT
    +# Zaporozh'ye and eastern Lugansk oblasts observed DST 1990/1991.
    +# "Zaporizhia" is the transliteration of the Ukrainian name, but
    +# "Zaporozh'ye" is more common in English.  Use the common English
    +# spelling, except omit the apostrophe as it is not allowed in
    +# portable Posix file names.
    +Zone Europe/Zaporozhye	2:20:40 -	LMT	1880
    +			2:20	-	CUT	1924 May  2 # Central Ukraine T
    +			2:00	-	EET	1930 Jun 21
    +			3:00	-	MSK	1941 Aug 25
    +			1:00	C-Eur	CE%sT	1943 Oct 25
    +			3:00	Russia	MSK/MSD	1991 Mar 31 2:00
    +			2:00	E-Eur	EE%sT	1995
    +			2:00	EU	EE%sT
    +# Central Crimea used Moscow time 1994/1997.
    +Zone Europe/Simferopol	2:16:24 -	LMT	1880
    +			2:16	-	SMT	1924 May  2 # Simferopol Mean T
    +			2:00	-	EET	1930 Jun 21
    +			3:00	-	MSK	1941 Nov
    +			1:00	C-Eur	CE%sT	1944 Apr 13
    +			3:00	Russia	MSK/MSD	1990
    +			3:00	-	MSK	1990 Jul  1 2:00
    +			2:00	-	EET	1992
    +# From Paul Eggert (2006-03-22):
    +# The _Economist_ (1994-05-28, p 45) reports that central Crimea switched
    +# from Kiev to Moscow time sometime after the January 1994 elections.
    +# Shanks (1999) says ``date of change uncertain'', but implies that it happened
    +# sometime between the 1994 DST switches.  Shanks & Pottenger simply say
    +# 1994-09-25 03:00, but that can't be right.  For now, guess it
    +# changed in May.
    +			2:00	E-Eur	EE%sT	1994 May
    +# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
    +			3:00	E-Eur	MSK/MSD	1996 Mar 31 3:00s
    +			3:00	1:00	MSD	1996 Oct 27 3:00s
    +# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
    +# Assume it happened in March by not changing the clocks.
    +			3:00	Russia	MSK/MSD	1997
    +			3:00	-	MSK	1997 Mar lastSun 1:00u
    +			2:00	EU	EE%sT
    +
    +###############################################################################
    +
    +# One source shows that Bulgaria, Cyprus, Finland, and Greece observe DST from
    +# the last Sunday in March to the last Sunday in September in 1986.
    +# The source shows Romania changing a day later than everybody else.
    +#
    +# According to Bernard Sieloff's source, Poland is in the MET time zone but
    +# uses the WE DST rules.  The Western USSR uses EET+1 and ME DST rules.
    +# Bernard Sieloff's source claims Romania switches on the same day, but at
    +# 00:00 standard time (i.e., 01:00 DST).  It also claims that Turkey
    +# switches on the same day, but switches on at 01:00 standard time
    +# and off at 00:00 standard time (i.e., 01:00 DST)
    +
    +# ...
    +# Date: Wed, 28 Jan 87 16:56:27 -0100
    +# From: Tom Hofmann
    +# ...
    +#
    +# ...the European time rules are...standardized since 1981, when
    +# most European coun[tr]ies started DST.  Before that year, only
    +# a few countries (UK, France, Italy) had DST, each according
    +# to own national rules.  In 1981, however, DST started on
    +# 'Apr firstSun', and not on 'Mar lastSun' as in the following
    +# years...
    +# But also since 1981 there are some more national exceptions
    +# than listed in 'europe': Switzerland, for example, joined DST
    +# one year later, Denmark ended DST on 'Oct 1' instead of 'Sep
    +# lastSun' in 1981---I don't know how they handle now.
    +#
    +# Finally, DST ist always from 'Apr 1' to 'Oct 1' in the
    +# Soviet Union (as far as I know).
    +#
    +# Tom Hofmann, Scientific Computer Center, CIBA-GEIGY AG,
    +# 4002 Basle, Switzerland
    +# ...
    +
    +# ...
    +# Date: Wed, 4 Feb 87 22:35:22 +0100
    +# From: Dik T. Winter
    +# ...
    +#
    +# The information from Tom Hofmann is (as far as I know) not entirely correct.
    +# After a request from chongo at amdahl I tried to retrieve all information
    +# about DST in Europe.  I was able to find all from about 1969.
    +#
    +# ...standardization on DST in Europe started in about 1977 with switches on
    +# first Sunday in April and last Sunday in September...
    +# In 1981 UK joined Europe insofar that
    +# the starting day for both shifted to last Sunday in March.  And from 1982
    +# the whole of Europe used DST, with switch dates April 1 and October 1 in
    +# the Sov[i]et Union.  In 1985 the SU reverted to standard Europe[a]n switch
    +# dates...
    +#
    +# It should also be remembered that time-zones are not constants; e.g.
    +# Portugal switched in 1976 from MET (or CET) to WET with DST...
    +# Note also that though there were rules for switch dates not
    +# all countries abided to these dates, and many individual deviations
    +# occurred, though not since 1982 I believe.  Another note: it is always
    +# assumed that DST is 1 hour ahead of normal time, this need not be the
    +# case; at least in the Netherlands there have been times when DST was 2 hours
    +# in advance of normal time.
    +#
    +# ...
    +# dik t. winter, cwi, amsterdam, nederland
    +# ...
    +
    +# From Bob Devine (1988-01-28):
    +# ...
    +# Greece: Last Sunday in April to last Sunday in September (iffy on dates).
    +# Since 1978.  Change at midnight.
    +# ...
    +# Monaco: has same DST as France.
    +# ...
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/factory b/jdk/test/sun/util/calendar/zi/tzdata/factory
    new file mode 100644
    index 00000000000..53ca3aa5d31
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/factory
    @@ -0,0 +1,33 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# For companies who don't want to put time zone specification in
    +# their installation procedures.  When users run date, they'll get the message.
    +# Also useful for the "comp.sources" version.
    +
    +# Zone	NAME	GMTOFF	RULES	FORMAT
    +Zone	Factory	0	- "Local time zone must be set--see zic manual page"
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/gmt b/jdk/test/sun/util/calendar/zi/tzdata/gmt
    new file mode 100644
    index 00000000000..0be31797d7f
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/gmt
    @@ -0,0 +1,27 @@
    +#
    +# Copyright (c) 2000, 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.
    +#
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	GMT		0:00	-	GMT
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/iso3166.tab b/jdk/test/sun/util/calendar/zi/tzdata/iso3166.tab
    new file mode 100644
    index 00000000000..fee3f33911a
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/iso3166.tab
    @@ -0,0 +1,299 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +# ISO 3166 alpha-2 country codes
    +#
    +# From Paul Eggert (2006-09-27):
    +#
    +# This file contains a table with the following columns:
    +# 1.  ISO 3166-1 alpha-2 country code, current as of
    +#     ISO 3166-1 Newsletter VI-1 (2007-09-21).  See:
    +#     
    +#     ISO 3166 Maintenance agency (ISO 3166/MA)
    +#     .
    +# 2.  The usual English name for the country,
    +#     chosen so that alphabetic sorting of subsets produces helpful lists.
    +#     This is not the same as the English name in the ISO 3166 tables.
    +#
    +# Columns are separated by a single tab.
    +# The table is sorted by country code.
    +#
    +# Lines beginning with `#' are comments.
    +#
    +# From Arthur David Olson (2011-08-17):
    +# Resynchronized today with the ISO 3166 site (adding SS for South Sudan).
    +#
    +#country-
    +#code	country name
    +AD	Andorra
    +AE	United Arab Emirates
    +AF	Afghanistan
    +AG	Antigua & Barbuda
    +AI	Anguilla
    +AL	Albania
    +AM	Armenia
    +AO	Angola
    +AQ	Antarctica
    +AR	Argentina
    +AS	Samoa (American)
    +AT	Austria
    +AU	Australia
    +AW	Aruba
    +AX	Aaland Islands
    +AZ	Azerbaijan
    +BA	Bosnia & Herzegovina
    +BB	Barbados
    +BD	Bangladesh
    +BE	Belgium
    +BF	Burkina Faso
    +BG	Bulgaria
    +BH	Bahrain
    +BI	Burundi
    +BJ	Benin
    +BL	St Barthelemy
    +BM	Bermuda
    +BN	Brunei
    +BO	Bolivia
    +BQ	Bonaire Sint Eustatius & Saba
    +BR	Brazil
    +BS	Bahamas
    +BT	Bhutan
    +BV	Bouvet Island
    +BW	Botswana
    +BY	Belarus
    +BZ	Belize
    +CA	Canada
    +CC	Cocos (Keeling) Islands
    +CD	Congo (Dem. Rep.)
    +CF	Central African Rep.
    +CG	Congo (Rep.)
    +CH	Switzerland
    +CI	Cote d'Ivoire
    +CK	Cook Islands
    +CL	Chile
    +CM	Cameroon
    +CN	China
    +CO	Colombia
    +CR	Costa Rica
    +CU	Cuba
    +CV	Cape Verde
    +CW	Curacao
    +CX	Christmas Island
    +CY	Cyprus
    +CZ	Czech Republic
    +DE	Germany
    +DJ	Djibouti
    +DK	Denmark
    +DM	Dominica
    +DO	Dominican Republic
    +DZ	Algeria
    +EC	Ecuador
    +EE	Estonia
    +EG	Egypt
    +EH	Western Sahara
    +ER	Eritrea
    +ES	Spain
    +ET	Ethiopia
    +FI	Finland
    +FJ	Fiji
    +FK	Falkland Islands
    +FM	Micronesia
    +FO	Faroe Islands
    +FR	France
    +GA	Gabon
    +GB	Britain (UK)
    +GD	Grenada
    +GE	Georgia
    +GF	French Guiana
    +GG	Guernsey
    +GH	Ghana
    +GI	Gibraltar
    +GL	Greenland
    +GM	Gambia
    +GN	Guinea
    +GP	Guadeloupe
    +GQ	Equatorial Guinea
    +GR	Greece
    +GS	South Georgia & the South Sandwich Islands
    +GT	Guatemala
    +GU	Guam
    +GW	Guinea-Bissau
    +GY	Guyana
    +HK	Hong Kong
    +HM	Heard Island & McDonald Islands
    +HN	Honduras
    +HR	Croatia
    +HT	Haiti
    +HU	Hungary
    +ID	Indonesia
    +IE	Ireland
    +IL	Israel
    +IM	Isle of Man
    +IN	India
    +IO	British Indian Ocean Territory
    +IQ	Iraq
    +IR	Iran
    +IS	Iceland
    +IT	Italy
    +JE	Jersey
    +JM	Jamaica
    +JO	Jordan
    +JP	Japan
    +KE	Kenya
    +KG	Kyrgyzstan
    +KH	Cambodia
    +KI	Kiribati
    +KM	Comoros
    +KN	St Kitts & Nevis
    +KP	Korea (North)
    +KR	Korea (South)
    +KW	Kuwait
    +KY	Cayman Islands
    +KZ	Kazakhstan
    +LA	Laos
    +LB	Lebanon
    +LC	St Lucia
    +LI	Liechtenstein
    +LK	Sri Lanka
    +LR	Liberia
    +LS	Lesotho
    +LT	Lithuania
    +LU	Luxembourg
    +LV	Latvia
    +LY	Libya
    +MA	Morocco
    +MC	Monaco
    +MD	Moldova
    +ME	Montenegro
    +MF	St Martin (French part)
    +MG	Madagascar
    +MH	Marshall Islands
    +MK	Macedonia
    +ML	Mali
    +MM	Myanmar (Burma)
    +MN	Mongolia
    +MO	Macau
    +MP	Northern Mariana Islands
    +MQ	Martinique
    +MR	Mauritania
    +MS	Montserrat
    +MT	Malta
    +MU	Mauritius
    +MV	Maldives
    +MW	Malawi
    +MX	Mexico
    +MY	Malaysia
    +MZ	Mozambique
    +NA	Namibia
    +NC	New Caledonia
    +NE	Niger
    +NF	Norfolk Island
    +NG	Nigeria
    +NI	Nicaragua
    +NL	Netherlands
    +NO	Norway
    +NP	Nepal
    +NR	Nauru
    +NU	Niue
    +NZ	New Zealand
    +OM	Oman
    +PA	Panama
    +PE	Peru
    +PF	French Polynesia
    +PG	Papua New Guinea
    +PH	Philippines
    +PK	Pakistan
    +PL	Poland
    +PM	St Pierre & Miquelon
    +PN	Pitcairn
    +PR	Puerto Rico
    +PS	Palestine
    +PT	Portugal
    +PW	Palau
    +PY	Paraguay
    +QA	Qatar
    +RE	Reunion
    +RO	Romania
    +RS	Serbia
    +RU	Russia
    +RW	Rwanda
    +SA	Saudi Arabia
    +SB	Solomon Islands
    +SC	Seychelles
    +SD	Sudan
    +SE	Sweden
    +SG	Singapore
    +SH	St Helena
    +SI	Slovenia
    +SJ	Svalbard & Jan Mayen
    +SK	Slovakia
    +SL	Sierra Leone
    +SM	San Marino
    +SN	Senegal
    +SO	Somalia
    +SR	Suriname
    +SS	South Sudan
    +ST	Sao Tome & Principe
    +SV	El Salvador
    +SX	Sint Maarten
    +SY	Syria
    +SZ	Swaziland
    +TC	Turks & Caicos Is
    +TD	Chad
    +TF	French Southern & Antarctic Lands
    +TG	Togo
    +TH	Thailand
    +TJ	Tajikistan
    +TK	Tokelau
    +TL	East Timor
    +TM	Turkmenistan
    +TN	Tunisia
    +TO	Tonga
    +TR	Turkey
    +TT	Trinidad & Tobago
    +TV	Tuvalu
    +TW	Taiwan
    +TZ	Tanzania
    +UA	Ukraine
    +UG	Uganda
    +UM	US minor outlying islands
    +US	United States
    +UY	Uruguay
    +UZ	Uzbekistan
    +VA	Vatican City
    +VC	St Vincent
    +VE	Venezuela
    +VG	Virgin Islands (UK)
    +VI	Virgin Islands (US)
    +VN	Vietnam
    +VU	Vanuatu
    +WF	Wallis & Futuna
    +WS	Samoa (western)
    +YE	Yemen
    +YT	Mayotte
    +ZA	South Africa
    +ZM	Zambia
    +ZW	Zimbabwe
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/jdk11_backward b/jdk/test/sun/util/calendar/zi/tzdata/jdk11_backward
    new file mode 100644
    index 00000000000..5404ceaae4c
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/jdk11_backward
    @@ -0,0 +1,51 @@
    +#
    +# Copyright (c) 2000, 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.
    +#
    +# JDK 1.1.x compatible time zone IDs
    +#
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	SystemV	min	1973	-	Apr	lastSun	2:00	1:00	D
    +Rule	SystemV	min	1973	-	Oct	lastSun	2:00	0	S
    +Rule	SystemV	1974	only	-	Jan	6	2:00	1:00	D
    +Rule	SystemV	1974	only	-	Nov	lastSun	2:00	0	S
    +Rule	SystemV	1975	only	-	Feb	23	2:00	1:00	D
    +Rule	SystemV	1975	only	-	Oct	lastSun	2:00	0	S
    +Rule	SystemV	1976	max	-	Apr	lastSun	2:00	1:00	D
    +Rule	SystemV	1976	max	-	Oct	lastSun	2:00	0	S
    +
    +# Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
    +Zone	SystemV/AST4ADT	-4:00	SystemV		A%sT
    +Zone	SystemV/EST5EDT	-5:00	SystemV		E%sT
    +Zone	SystemV/CST6CDT	-6:00	SystemV		C%sT
    +Zone	SystemV/MST7MDT	-7:00	SystemV		M%sT
    +Zone	SystemV/PST8PDT	-8:00	SystemV		P%sT
    +Zone	SystemV/YST9YDT	-9:00	SystemV		Y%sT
    +Zone	SystemV/AST4	-4:00	-		AST
    +Zone	SystemV/EST5	-5:00	-		EST
    +Zone	SystemV/CST6	-6:00	-		CST
    +Zone	SystemV/MST7	-7:00	-		MST
    +Zone	SystemV/PST8	-8:00	-		PST
    +Zone	SystemV/YST9	-9:00	-		YST
    +Zone	SystemV/HST10	-10:00	-		HST
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/leapseconds b/jdk/test/sun/util/calendar/zi/tzdata/leapseconds
    new file mode 100644
    index 00000000000..ab6720ded58
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/leapseconds
    @@ -0,0 +1,123 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# Allowance for leapseconds added to each timezone file.
    +
    +# The International Earth Rotation Service periodically uses leap seconds
    +# to keep UTC to within 0.9 s of UT1
    +# (which measures the true angular orientation of the earth in space); see
    +# Terry J Quinn, The BIPM and the accurate measure of time,
    +# Proc IEEE 79, 7 (July 1991), 894-905.
    +# There were no leap seconds before 1972, because the official mechanism
    +# accounting for the discrepancy between atomic time and the earth's rotation
    +# did not exist until the early 1970s.
    +
    +# The correction (+ or -) is made at the given time, so lines
    +# will typically look like:
    +#	Leap	YEAR	MON	DAY	23:59:60	+	R/S
    +# or
    +#	Leap	YEAR	MON	DAY	23:59:59	-	R/S
    +
    +# If the leapsecond is Rolling (R) the given time is local time
    +# If the leapsecond is Stationary (S) the given time is UTC
    +
    +# Leap	YEAR	MONTH	DAY	HH:MM:SS	CORR	R/S
    +Leap	1972	Jun	30	23:59:60	+	S
    +Leap	1972	Dec	31	23:59:60	+	S
    +Leap	1973	Dec	31	23:59:60	+	S
    +Leap	1974	Dec	31	23:59:60	+	S
    +Leap	1975	Dec	31	23:59:60	+	S
    +Leap	1976	Dec	31	23:59:60	+	S
    +Leap	1977	Dec	31	23:59:60	+	S
    +Leap	1978	Dec	31	23:59:60	+	S
    +Leap	1979	Dec	31	23:59:60	+	S
    +Leap	1981	Jun	30	23:59:60	+	S
    +Leap	1982	Jun	30	23:59:60	+	S
    +Leap	1983	Jun	30	23:59:60	+	S
    +Leap	1985	Jun	30	23:59:60	+	S
    +Leap	1987	Dec	31	23:59:60	+	S
    +Leap	1989	Dec	31	23:59:60	+	S
    +Leap	1990	Dec	31	23:59:60	+	S
    +Leap	1992	Jun	30	23:59:60	+	S
    +Leap	1993	Jun	30	23:59:60	+	S
    +Leap	1994	Jun	30	23:59:60	+	S
    +Leap	1995	Dec	31	23:59:60	+	S
    +Leap	1997	Jun	30	23:59:60	+	S
    +Leap	1998	Dec	31	23:59:60	+	S
    +Leap	2005	Dec	31	23:59:60	+	S
    +Leap	2008	Dec	31	23:59:60	+	S
    +Leap	2012	Jun	30	23:59:60	+	S
    +
    +# INTERNATIONAL EARTH ROTATION AND REFERENCE SYSTEMS SERVICE (IERS)
    +#
    +# SERVICE INTERNATIONAL DE LA ROTATION TERRESTRE ET DES SYSTEMES DE REFERENCE
    +#
    +#
    +# SERVICE DE LA ROTATION TERRESTRE
    +# OBSERVATOIRE DE PARIS
    +# 61, Av. de l'Observatoire 75014 PARIS (France)
    +# Tel.      : 33 (0) 1 40 51 22 26
    +# FAX       : 33 (0) 1 40 51 22 91
    +# e-mail    : (E-Mail Removed)
    +# http://hpiers.obspm.fr/eop-pc
    +#
    +# Paris, 5 January 2012
    +#
    +#
    +# Bulletin C 43
    +#
    +# To authorities responsible
    +# for the measurement and
    +# distribution of time
    +#
    +#
    +# UTC TIME STEP
    +# on the 1st of July 2012
    +#
    +#
    +# A positive leap second will be introduced at the end of June 2012.
    +# The sequence of dates of the UTC second markers will be:
    +#
    +#                          2012 June 30,     23h 59m 59s
    +#                          2012 June 30,     23h 59m 60s
    +#                          2012 July  1,      0h  0m  0s
    +#
    +# The difference between UTC and the International Atomic Time TAI is:
    +#
    +# from 2009 January 1, 0h UTC, to 2012 July 1  0h UTC  : UTC-TAI = - 34s
    +# from 2012 July 1,    0h UTC, until further notice    : UTC-TAI = - 35s
    +#
    +# Leap seconds can be introduced in UTC at the end of the months of December
    +# or June, depending on the evolution of UT1-TAI. Bulletin C is mailed every
    +# six months, either to announce a time step in UTC or to confirm that there
    +# will be no time step at the next possible date.
    +#
    +#
    +# Daniel GAMBIS
    +# Head
    +# Earth Orientation Center of IERS
    +# Observatoire de Paris, France
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/northamerica b/jdk/test/sun/util/calendar/zi/tzdata/northamerica
    new file mode 100644
    index 00000000000..c3033267404
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/northamerica
    @@ -0,0 +1,3258 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# also includes Central America and the Caribbean
    +
    +# This data is by no means authoritative; if you think you know better,
    +# go ahead and edit the file (and please send any changes to
    +# tz@elsie.nci.nih.gov for general use in the future).
    +
    +# From Paul Eggert (1999-03-22):
    +# A reliable and entertaining source about time zones is
    +# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
    +
    +###############################################################################
    +
    +# United States
    +
    +# From Paul Eggert (1999-03-31):
    +# Howse writes (pp 121-125) that time zones were invented by
    +# Professor Charles Ferdinand Dowd (1825-1904),
    +# Principal of Temple Grove Ladies' Seminary (Saratoga Springs, NY).
    +# His pamphlet ``A System of National Time for Railroads'' (1870)
    +# was the result of his proposals at the Convention of Railroad Trunk Lines
    +# in New York City (1869-10).  His 1870 proposal was based on Washington, DC,
    +# but in 1872-05 he moved the proposed origin to Greenwich.
    +# His proposal was adopted by the railroads on 1883-11-18 at 12:00,
    +# and the most of the country soon followed suit.
    +
    +# From Paul Eggert (2005-04-16):
    +# That 1883 transition occurred at 12:00 new time, not at 12:00 old time.
    +# See p 46 of David Prerau, Seize the daylight, Thunder's Mouth Press (2005).
    +
    +# From Paul Eggert (2006-03-22):
    +# A good source for time zone historical data in the US is
    +# Thomas G. Shanks, The American Atlas (5th edition),
    +# San Diego: ACS Publications, Inc. (1991).
    +# Make sure you have the errata sheet; the book is somewhat useless without it.
    +# It is the source for most of the pre-1991 US entries below.
    +
    +# From Paul Eggert (2001-03-06):
    +# Daylight Saving Time was first suggested as a joke by Benjamin Franklin
    +# in his whimsical essay ``An Economical Project for Diminishing the Cost
    +# of Light'' published in the Journal de Paris (1784-04-26).
    +# Not everyone is happy with the results:
    +#
    +#	I don't really care how time is reckoned so long as there is some
    +#	agreement about it, but I object to being told that I am saving
    +#	daylight when my reason tells me that I am doing nothing of the kind.
    +#	I even object to the implication that I am wasting something
    +#	valuable if I stay in bed after the sun has risen.  As an admirer
    +#	of moonlight I resent the bossy insistence of those who want to
    +#	reduce my time for enjoying it.  At the back of the Daylight Saving
    +#	scheme I detect the bony, blue-fingered hand of Puritanism, eager
    +#	to push people into bed earlier, and get them up earlier, to make
    +#	them healthy, wealthy and wise in spite of themselves.
    +#
    +#	-- Robertson Davies, The diary of Samuel Marchbanks,
    +#	   Clarke, Irwin (1947), XIX, Sunday
    +#
    +# For more about the first ten years of DST in the United States, see
    +# Robert Garland's 
    +# Ten years of daylight saving from the Pittsburgh standpoint
    +# (Carnegie Library of Pittsburgh, 1927).
    +#
    +# Shanks says that DST was called "War Time" in the US in 1918 and 1919.
    +# However, DST was imposed by the Standard Time Act of 1918, which
    +# was the first nationwide legal time standard, and apparently
    +# time was just called "Standard Time" or "Daylight Saving Time".
    +
    +# From Arthur David Olson:
    +# US Daylight Saving Time ended on the last Sunday of *October* in 1974.
    +# See, for example, the front page of the Saturday, 1974-10-26
    +# and Sunday, 1974-10-27 editions of the Washington Post.
    +
    +# From Arthur David Olson:
    +# Before the Uniform Time Act of 1966 took effect in 1967, observance of
    +# Daylight Saving Time in the US was by local option, except during wartime.
    +
    +# From Arthur David Olson (2000-09-25):
    +# Last night I heard part of a rebroadcast of a 1945 Arch Oboler radio drama.
    +# In the introduction, Oboler spoke of "Eastern Peace Time."
    +# An AltaVista search turned up
    +# :
    +# "When the time is announced over the radio now, it is 'Eastern Peace
    +# Time' instead of the old familiar 'Eastern War Time.'  Peace is wonderful."
    +#  (August 1945) by way of confirmation.
    +
    +# From Joseph Gallant citing
    +# George H. Douglas, _The Early Days of Radio Broadcasting_ (1987):
    +# At 7 P.M. (Eastern War Time) [on 1945-08-14], the networks were set
    +# to switch to London for Attlee's address, but the American people
    +# never got to hear his speech live. According to one press account,
    +# CBS' Bob Trout was first to announce the word of Japan's surrender,
    +# but a few seconds later, NBC, ABC and Mutual also flashed the word
    +# of surrender, all of whom interrupting the bells of Big Ben in
    +# London which were to precede Mr. Attlee's speech.
    +
    +# From Paul Eggert (2003-02-09): It was Robert St John, not Bob Trout.  From
    +# Myrna Oliver's obituary of St John on page B16 of today's Los Angeles Times:
    +#
    +# ... a war-weary U.S. clung to radios, awaiting word of Japan's surrender.
    +# Any announcement from Asia would reach St. John's New York newsroom on a
    +# wire service teletype machine, which had prescribed signals for major news.
    +# Associated Press, for example, would ring five bells before spewing out
    +# typed copy of an important story, and 10 bells for news "of transcendental
    +# importance."
    +#
    +# On Aug. 14, stalling while talking steadily into the NBC networks' open
    +# microphone, St. John heard five bells and waited only to hear a sixth bell,
    +# before announcing confidently: "Ladies and gentlemen, World War II is over.
    +# The Japanese have agreed to our surrender terms."
    +#
    +# He had scored a 20-second scoop on other broadcasters.
    +
    +# From Arthur David Olson (2005-08-22):
    +# Paul has been careful to use the "US" rules only in those locations
    +# that are part of the United States; this reflects the real scope of
    +# U.S. government action.  So even though the "US" rules have changed
    +# in the latest release, other countries won't be affected.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	US	1918	1919	-	Mar	lastSun	2:00	1:00	D
    +Rule	US	1918	1919	-	Oct	lastSun	2:00	0	S
    +Rule	US	1942	only	-	Feb	9	2:00	1:00	W # War
    +Rule	US	1945	only	-	Aug	14	23:00u	1:00	P # Peace
    +Rule	US	1945	only	-	Sep	30	2:00	0	S
    +Rule	US	1967	2006	-	Oct	lastSun	2:00	0	S
    +Rule	US	1967	1973	-	Apr	lastSun	2:00	1:00	D
    +Rule	US	1974	only	-	Jan	6	2:00	1:00	D
    +Rule	US	1975	only	-	Feb	23	2:00	1:00	D
    +Rule	US	1976	1986	-	Apr	lastSun	2:00	1:00	D
    +Rule	US	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
    +Rule	US	2007	max	-	Mar	Sun>=8	2:00	1:00	D
    +Rule	US	2007	max	-	Nov	Sun>=1	2:00	0	S
    +
    +# From Arthur David Olson, 2005-12-19
    +# We generate the files specified below to guard against old files with
    +# obsolete information being left in the time zone binary directory.
    +# We limit the list to names that have appeared in previous versions of
    +# this time zone package.
    +# We do these as separate Zones rather than as Links to avoid problems if
    +# a particular place changes whether it observes DST.
    +# We put these specifications here in the northamerica file both to
    +# increase the chances that they'll actually get compiled and to
    +# avoid the need to duplicate the US rules in another file.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	EST		 -5:00	-	EST
    +Zone	MST		 -7:00	-	MST
    +Zone	HST		-10:00	-	HST
    +Zone	EST5EDT		 -5:00	US	E%sT
    +Zone	CST6CDT		 -6:00	US	C%sT
    +Zone	MST7MDT		 -7:00	US	M%sT
    +Zone	PST8PDT		 -8:00	US	P%sT
    +
    +# From Bob Devine (1988-01-28):
    +# ...Alaska (and Hawaii) had the timezone names changed in 1967.
    +#    old			 new
    +#    Pacific Standard Time(PST)  -same-
    +#    Yukon Standard Time(YST)    -same-
    +#    Central Alaska S.T. (CAT)   Alaska-Hawaii St[an]dard Time (AHST)
    +#    Nome Standard Time (NT)     Bering Standard Time (BST)
    +#
    +# ...Alaska's timezone lines were redrawn in 1983 to give only 2 tz.
    +#    The YST zone now covers nearly all of the state, AHST just part
    +#    of the Aleutian islands.   No DST.
    +
    +# From Paul Eggert (1995-12-19):
    +# The tables below use `NST', not `NT', for Nome Standard Time.
    +# I invented `CAWT' for Central Alaska War Time.
    +
    +# From U. S. Naval Observatory (1989-01-19):
    +# USA  EASTERN       5 H  BEHIND UTC    NEW YORK, WASHINGTON
    +# USA  EASTERN       4 H  BEHIND UTC    APR 3 - OCT 30
    +# USA  CENTRAL       6 H  BEHIND UTC    CHICAGO, HOUSTON
    +# USA  CENTRAL       5 H  BEHIND UTC    APR 3 - OCT 30
    +# USA  MOUNTAIN      7 H  BEHIND UTC    DENVER
    +# USA  MOUNTAIN      6 H  BEHIND UTC    APR 3 - OCT 30
    +# USA  PACIFIC       8 H  BEHIND UTC    L.A., SAN FRANCISCO
    +# USA  PACIFIC       7 H  BEHIND UTC    APR 3 - OCT 30
    +# USA  ALASKA STD    9 H  BEHIND UTC    MOST OF ALASKA     (AKST)
    +# USA  ALASKA STD    8 H  BEHIND UTC    APR 3 - OCT 30 (AKDT)
    +# USA  ALEUTIAN     10 H  BEHIND UTC    ISLANDS WEST OF 170W
    +# USA  - " -         9 H  BEHIND UTC    APR 3 - OCT 30
    +# USA  HAWAII       10 H  BEHIND UTC
    +# USA  BERING       11 H  BEHIND UTC    SAMOA, MIDWAY
    +
    +# From Arthur David Olson (1989-01-21):
    +# The above dates are for 1988.
    +# Note the "AKST" and "AKDT" abbreviations, the claim that there's
    +# no DST in Samoa, and the claim that there is DST in Alaska and the
    +# Aleutians.
    +
    +# From Arthur David Olson (1988-02-13):
    +# Legal standard time zone names, from United States Code (1982 Edition and
    +# Supplement III), Title 15, Chapter 6, Section 260 and forward.  First, names
    +# up to 1967-04-01 (when most provisions of the Uniform Time Act of 1966
    +# took effect), as explained in sections 263 and 261:
    +#	(none)
    +#	United States standard eastern time
    +#	United States standard mountain time
    +#	United States standard central time
    +#	United States standard Pacific time
    +#	(none)
    +#	United States standard Alaska time
    +#	(none)
    +# Next, names from 1967-04-01 until 1983-11-30 (the date for
    +# public law 98-181):
    +#	Atlantic standard time
    +#	eastern standard time
    +#	central standard time
    +#	mountain standard time
    +#	Pacific standard time
    +#	Yukon standard time
    +#	Alaska-Hawaii standard time
    +#	Bering standard time
    +# And after 1983-11-30:
    +#	Atlantic standard time
    +#	eastern standard time
    +#	central standard time
    +#	mountain standard time
    +#	Pacific standard time
    +#	Alaska standard time
    +#	Hawaii-Aleutian standard time
    +#	Samoa standard time
    +# The law doesn't give abbreviations.
    +#
    +# From Paul Eggert (2000-01-08), following a heads-up from Rives McDow:
    +# Public law 106-564 (2000-12-23) introduced the abbreviation
    +# "Chamorro Standard Time" for time in Guam and the Northern Marianas.
    +# See the file "australasia".
    +
    +# From Arthur David Olson, 2005-08-09
    +# The following was signed into law on 2005-08-08.
    +#
    +# H.R. 6, Energy Policy Act of 2005, SEC. 110. DAYLIGHT SAVINGS.
    +#   (a) Amendment- Section 3(a) of the Uniform Time Act of 1966 (15
    +#   U.S.C. 260a(a)) is amended--
    +#     (1) by striking `first Sunday of April' and inserting `second
    +#     Sunday of March'; and
    +#     (2) by striking `last Sunday of October' and inserting `first
    +#     Sunday of November'.
    +#   (b) Effective Date- Subsection (a) shall take effect 1 year after the
    +#   date of enactment of this Act or March 1, 2007, whichever is later.
    +#   (c) Report to Congress- Not later than 9 months after the effective
    +#   date stated in subsection (b), the Secretary shall report to Congress
    +#   on the impact of this section on energy consumption in the United
    +#   States.
    +#   (d) Right to Revert- Congress retains the right to revert the
    +#   Daylight Saving Time back to the 2005 time schedules once the
    +#   Department study is complete.
    +
    +# US eastern time, represented by New York
    +
    +# Connecticut, Delaware, District of Columbia, most of Florida,
    +# Georgia, southeast Indiana (Dearborn and Ohio counties), eastern Kentucky
    +# (except America/Kentucky/Louisville below), Maine, Maryland, Massachusetts,
    +# New Hampshire, New Jersey, New York, North Carolina, Ohio,
    +# Pennsylvania, Rhode Island, South Carolina, eastern Tennessee,
    +# Vermont, Virginia, West Virginia
    +
    +# From Dave Cantor (2004-11-02):
    +# Early this summer I had the occasion to visit the Mount Washington
    +# Observatory weather station atop (of course!) Mount Washington [, NH]....
    +# One of the staff members said that the station was on Eastern Standard Time
    +# and didn't change their clocks for Daylight Saving ... so that their
    +# reports will always have times which are 5 hours behind UTC.
    +
    +# From Paul Eggert (2005-08-26):
    +# According to today's Huntsville Times
    +# 
    +# a few towns on Alabama's "eastern border with Georgia, such as Phenix City
    +# in Russell County, Lanett in Chambers County and some towns in Lee County,
    +# set their watches and clocks on Eastern time."  It quotes H.H. "Bubba"
    +# Roberts, city administrator in Phenix City. as saying "We are in the Central
    +# time zone, but we do go by the Eastern time zone because so many people work
    +# in Columbus."
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
    +Rule	NYC	1920	only	-	Mar	lastSun	2:00	1:00	D
    +Rule	NYC	1920	only	-	Oct	lastSun	2:00	0	S
    +Rule	NYC	1921	1966	-	Apr	lastSun	2:00	1:00	D
    +Rule	NYC	1921	1954	-	Sep	lastSun	2:00	0	S
    +Rule	NYC	1955	1966	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/New_York	-4:56:02 -	LMT	1883 Nov 18 12:03:58
    +			-5:00	US	E%sT	1920
    +			-5:00	NYC	E%sT	1942
    +			-5:00	US	E%sT	1946
    +			-5:00	NYC	E%sT	1967
    +			-5:00	US	E%sT
    +
    +# US central time, represented by Chicago
    +
    +# Alabama, Arkansas, Florida panhandle (Bay, Calhoun, Escambia,
    +# Gulf, Holmes, Jackson, Okaloosa, Santa Rosa, Walton, and
    +# Washington counties), Illinois, western Indiana
    +# (Gibson, Jasper, Lake, LaPorte, Newton, Porter, Posey, Spencer,
    +# Vanderburgh, and Warrick counties), Iowa, most of Kansas, western
    +# Kentucky, Louisiana, Minnesota, Mississippi, Missouri, eastern
    +# Nebraska, eastern North Dakota, Oklahoma, eastern South Dakota,
    +# western Tennessee, most of Texas, Wisconsin
    +
    +# From Larry M. Smith (2006-04-26) re Wisconsin:
    +# http://www.legis.state.wi.us/statutes/Stat0175.pdf ...
    +# is currently enforced at the 01:00 time of change.  Because the local
    +# "bar time" in the state corresponds to 02:00, a number of citations
    +# are issued for the "sale of class 'B' alcohol after prohibited
    +# hours" within the deviated hour of this change every year....
    +#
    +# From Douglas R. Bomberg (2007-03-12):
    +# Wisconsin has enacted (nearly eleventh-hour) legislation to get WI
    +# Statue 175 closer in synch with the US Congress' intent....
    +# http://www.legis.state.wi.us/2007/data/acts/07Act3.pdf
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
    +Rule	Chicago	1920	only	-	Jun	13	2:00	1:00	D
    +Rule	Chicago	1920	1921	-	Oct	lastSun	2:00	0	S
    +Rule	Chicago	1921	only	-	Mar	lastSun	2:00	1:00	D
    +Rule	Chicago	1922	1966	-	Apr	lastSun	2:00	1:00	D
    +Rule	Chicago	1922	1954	-	Sep	lastSun	2:00	0	S
    +Rule	Chicago	1955	1966	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Chicago	-5:50:36 -	LMT	1883 Nov 18 12:09:24
    +			-6:00	US	C%sT	1920
    +			-6:00	Chicago	C%sT	1936 Mar  1 2:00
    +			-5:00	-	EST	1936 Nov 15 2:00
    +			-6:00	Chicago	C%sT	1942
    +			-6:00	US	C%sT	1946
    +			-6:00	Chicago	C%sT	1967
    +			-6:00	US	C%sT
    +# Oliver County, ND switched from mountain to central time on 1992-10-25.
    +Zone America/North_Dakota/Center -6:45:12 - LMT	1883 Nov 18 12:14:48
    +			-7:00	US	M%sT	1992 Oct 25 02:00
    +			-6:00	US	C%sT
    +# Morton County, ND, switched from mountain to central time on
    +# 2003-10-26, except for the area around Mandan which was already central time.
    +# See .
    +# Officially this switch also included part of Sioux County, and
    +# Jones, Mellette, and Todd Counties in South Dakota;
    +# but in practice these other counties were already observing central time.
    +# See .
    +Zone America/North_Dakota/New_Salem -6:45:39 - LMT 1883 Nov 18 12:14:21
    +			-7:00	US	M%sT	2003 Oct 26 02:00
    +			-6:00	US	C%sT
    +
    +# From Josh Findley (2011-01-21):
    +# ...it appears that Mercer County, North Dakota, changed from the
    +# mountain time zone to the central time zone at the last transition from
    +# daylight-saving to standard time (on Nov. 7, 2010):
    +# 
    +# http://www.gpo.gov/fdsys/pkg/FR-2010-09-29/html/2010-24376.htm
    +# 
    +# 
    +# http://www.bismarcktribune.com/news/local/article_1eb1b588-c758-11df-b472-001cc4c03286.html
    +# 
    +
    +# From Andy Lipscomb (2011-01-24):
    +# ...according to the Census Bureau, the largest city is Beulah (although
    +# it's commonly referred to as Beulah-Hazen, with Hazen being the next
    +# largest city in Mercer County).  Google Maps places Beulah's city hall
    +# at 4715'51" north, 10146'40" west, which yields an offset of 6h47'07".
    +
    +Zone America/North_Dakota/Beulah -6:47:07 - LMT 1883 Nov 18 12:12:53
    +			-7:00	US	M%sT	2010 Nov  7 2:00
    +			-6:00	US	C%sT
    +
    +# US mountain time, represented by Denver
    +#
    +# Colorado, far western Kansas, Montana, western
    +# Nebraska, Nevada border (Jackpot, Owyhee, and Mountain City),
    +# New Mexico, southwestern North Dakota,
    +# western South Dakota, far western Texas (El Paso County, Hudspeth County,
    +# and Pine Springs and Nickel Creek in Culberson County), Utah, Wyoming
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
    +Rule	Denver	1920	1921	-	Mar	lastSun	2:00	1:00	D
    +Rule	Denver	1920	only	-	Oct	lastSun	2:00	0	S
    +Rule	Denver	1921	only	-	May	22	2:00	0	S
    +Rule	Denver	1965	1966	-	Apr	lastSun	2:00	1:00	D
    +Rule	Denver	1965	1966	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Denver	-6:59:56 -	LMT	1883 Nov 18 12:00:04
    +			-7:00	US	M%sT	1920
    +			-7:00	Denver	M%sT	1942
    +			-7:00	US	M%sT	1946
    +			-7:00	Denver	M%sT	1967
    +			-7:00	US	M%sT
    +
    +# US Pacific time, represented by Los Angeles
    +#
    +# California, northern Idaho (Benewah, Bonner, Boundary, Clearwater,
    +# Idaho, Kootenai, Latah, Lewis, Nez Perce, and Shoshone counties,
    +# and the northern three-quarters of Idaho county),
    +# most of Nevada, most of Oregon, and Washington
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
    +Rule	CA	1948	only	-	Mar	14	2:00	1:00	D
    +Rule	CA	1949	only	-	Jan	 1	2:00	0	S
    +Rule	CA	1950	1966	-	Apr	lastSun	2:00	1:00	D
    +Rule	CA	1950	1961	-	Sep	lastSun	2:00	0	S
    +Rule	CA	1962	1966	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Los_Angeles -7:52:58 -	LMT	1883 Nov 18 12:07:02
    +			-8:00	US	P%sT	1946
    +			-8:00	CA	P%sT	1967
    +			-8:00	US	P%sT
    +
    +# Alaska
    +# AK%sT is the modern abbreviation for -9:00 per USNO.
    +#
    +# From Paul Eggert (2001-05-30):
    +# Howse writes that Alaska switched from the Julian to the Gregorian calendar,
    +# and from east-of-GMT to west-of-GMT days, when the US bought it from Russia.
    +# This was on 1867-10-18, a Friday; the previous day was 1867-10-06 Julian,
    +# also a Friday.  Include only the time zone part of this transition,
    +# ignoring the switch from Julian to Gregorian, since we can't represent
    +# the Julian calendar.
    +#
    +# As far as we know, none of the exact locations mentioned below were
    +# permanently inhabited in 1867 by anyone using either calendar.
    +# (Yakutat was colonized by the Russians in 1799, but the settlement
    +# was destroyed in 1805 by a Yakutat-kon war party.)  However, there
    +# were nearby inhabitants in some cases and for our purposes perhaps
    +# it's best to simply use the official transition.
    +#
    +
    +# From Steve Ferguson (2011-01-31):
    +# The author lives in Alaska and many of the references listed are only
    +# available to Alaskan residents.
    +#
    +# 
    +# http://www.alaskahistoricalsociety.org/index.cfm?section=discover%20alaska&page=Glimpses%20of%20the%20Past&viewpost=2&ContentId=98
    +# 
    +
    +# From Arthur David Olson (2011-02-01):
    +# Here's database-relevant material from the 2001 "Alaska History" article:
    +#
    +# On September 20 [1979]...DOT...officials decreed that on April 27,
    +# 1980, Juneau and other nearby communities would move to Yukon Time.
    +# Sitka, Petersburg, Wrangell, and Ketchikan, however, would remain on
    +# Pacific Time.
    +#
    +# ...on September 22, 1980, DOT Secretary Neil E. Goldschmidt rescinded the
    +# Department's September 1979 decision. Juneau and other communities in
    +# northern Southeast reverted to Pacific Time on October 26.
    +#
    +# On October 28 [1983]...the Metlakatla Indian Community Council voted
    +# unanimously to keep the reservation on Pacific Time.
    +#
    +# According to DOT official Joanne Petrie, Indian reservations are not
    +# bound to follow time zones imposed by neighboring jurisdictions.
    +#
    +# (The last is consistent with how the database now handles the Navajo
    +# Nation.)
    +
    +# From Arthur David Olson (2011-02-09):
    +# I just spoke by phone with a staff member at the Metlakatla Indian
    +# Community office (using contact information available at
    +# 
    +# http://www.commerce.state.ak.us/dca/commdb/CIS.cfm?Comm_Boro_name=Metlakatla
    +# ).
    +# It's shortly after 1:00 here on the east coast of the United States;
    +# the staffer said it was shortly after 10:00 there. When I asked whether
    +# that meant they were on Pacific time, they said no--they were on their
    +# own time. I asked about daylight saving; they said it wasn't used. I
    +# did not inquire about practices in the past.
    +
    +# From Arthur David Olson (2011-08-17):
    +# For lack of better information, assume that Metlakatla's
    +# abandonment of use of daylight saving resulted from the 1983 vote.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Juneau	 15:02:19 -	LMT	1867 Oct 18
    +			 -8:57:41 -	LMT	1900 Aug 20 12:00
    +			 -8:00	-	PST	1942
    +			 -8:00	US	P%sT	1946
    +			 -8:00	-	PST	1969
    +			 -8:00	US	P%sT	1980 Apr 27 2:00
    +			 -9:00	US	Y%sT	1980 Oct 26 2:00
    +			 -8:00	US	P%sT	1983 Oct 30 2:00
    +			 -9:00	US	Y%sT	1983 Nov 30
    +			 -9:00	US	AK%sT
    +Zone America/Sitka	 14:58:47 -	LMT	1867 Oct 18
    +			 -9:01:13 -	LMT	1900 Aug 20 12:00
    +			 -8:00	-	PST	1942
    +			 -8:00	US	P%sT	1946
    +			 -8:00	-	PST	1969
    +			 -8:00	US	P%sT	1983 Oct 30 2:00
    +			 -9:00	US	Y%sT	1983 Nov 30
    +			 -9:00	US	AK%sT
    +Zone America/Metlakatla	 15:13:42 -	LMT	1867 Oct 18
    +			 -8:46:18 -	LMT	1900 Aug 20 12:00
    +			 -8:00	-	PST	1942
    +			 -8:00	US	P%sT	1946
    +			 -8:00	-	PST	1969
    +			 -8:00	US	P%sT	1983 Oct 30 2:00
    +			 -8:00	-	MeST
    +Zone America/Yakutat	 14:41:05 -	LMT	1867 Oct 18
    +			 -9:18:55 -	LMT	1900 Aug 20 12:00
    +			 -9:00	-	YST	1942
    +			 -9:00	US	Y%sT	1946
    +			 -9:00	-	YST	1969
    +			 -9:00	US	Y%sT	1983 Nov 30
    +			 -9:00	US	AK%sT
    +Zone America/Anchorage	 14:00:24 -	LMT	1867 Oct 18
    +			 -9:59:36 -	LMT	1900 Aug 20 12:00
    +			-10:00	-	CAT	1942
    +			-10:00	US	CAT/CAWT 1945 Aug 14 23:00u
    +			-10:00	US	CAT/CAPT 1946 # Peace
    +			-10:00	-	CAT	1967 Apr
    +			-10:00	-	AHST	1969
    +			-10:00	US	AH%sT	1983 Oct 30 2:00
    +			 -9:00	US	Y%sT	1983 Nov 30
    +			 -9:00	US	AK%sT
    +Zone America/Nome	 12:58:21 -	LMT	1867 Oct 18
    +			-11:01:38 -	LMT	1900 Aug 20 12:00
    +			-11:00	-	NST	1942
    +			-11:00	US	N%sT	1946
    +			-11:00	-	NST	1967 Apr
    +			-11:00	-	BST	1969
    +			-11:00	US	B%sT	1983 Oct 30 2:00
    +			 -9:00	US	Y%sT	1983 Nov 30
    +			 -9:00	US	AK%sT
    +Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
    +			-11:46:38 -	LMT	1900 Aug 20 12:00
    +			-11:00	-	NST	1942
    +			-11:00	US	N%sT	1946
    +			-11:00	-	NST	1967 Apr
    +			-11:00	-	BST	1969
    +			-11:00	US	B%sT	1983 Oct 30 2:00
    +			-10:00	US	AH%sT	1983 Nov 30
    +			-10:00	US	HA%sT
    +# The following switches don't quite make our 1970 cutoff.
    +#
    +# Shanks writes that part of southwest Alaska (e.g. Aniak)
    +# switched from -11:00 to -10:00 on 1968-09-22 at 02:00,
    +# and another part (e.g. Akiak) made the same switch five weeks later.
    +#
    +# From David Flater (2004-11-09):
    +# In e-mail, 2004-11-02, Ray Hudson, historian/liaison to the Unalaska
    +# Historic Preservation Commission, provided this information, which
    +# suggests that Unalaska deviated from statutory time from early 1967
    +# possibly until 1983:
    +#
    +#  Minutes of the Unalaska City Council Meeting, January 10, 1967:
    +#  "Except for St. Paul and Akutan, Unalaska is the only important
    +#  location not on Alaska Standard Time.  The following resolution was
    +#  made by William Robinson and seconded by Henry Swanson:  Be it
    +#  resolved that the City of Unalaska hereby goes to Alaska Standard
    +#  Time as of midnight Friday, January 13, 1967 (1 A.M. Saturday,
    +#  January 14, Alaska Standard Time.)  This resolution was passed with
    +#  three votes for and one against."
    +
    +# Hawaii
    +
    +# From Arthur David Olson (2010-12-09):
    +# "Hawaiian Time" by Robert C. Schmitt and Doak C. Cox appears on pages 207-225
    +# of volume 26 of The Hawaiian Journal of History (1992). As of 2010-12-09,
    +# the article is available at
    +# 
    +# http://evols.library.manoa.hawaii.edu/bitstream/10524/239/2/JL26215.pdf
    +# 
    +# and indicates that standard time was adopted effective noon, January
    +# 13, 1896 (page 218), that in "1933, the Legislature decreed daylight
    +# saving for the period between the last Sunday of each April and the
    +# last Sunday of each September, but less than a month later repealed the
    +# act," (page 220), that year-round daylight saving time was in effect
    +# from 1942-02-09 to 1945-09-30 (page 221, with no time of day given for
    +# when clocks changed) and that clocks were changed by 30 minutes
    +# effective the second Sunday of June, 1947 (page 219, with no time of
    +# day given for when clocks changed). A footnote for the 1933 changes
    +# cites Session Laws of Hawaii 1933, "Act. 90 (approved 26 Apr. 1933)
    +# and Act 163 (approved 21 May 1933)."
    +
    +# From Arthur David Olson (2011-01-19):
    +# The following is from "Laws of the Territory of Hawaii Passed by the
    +# Seventeenth Legislature: Regular Session 1933," available (as of
    +# 2011-01-19) at American University's Pence Law Library. Page 85: "Act
    +# 90...At 2 o'clock ante meridian of the last Sunday in April of each
    +# year, the standard time of this Territory shall be advanced one
    +# hour...This Act shall take effect upon its approval. Approved this 26th
    +# day of April, A. D. 1933. LAWRENCE M JUDD, Governor of the Territory of
    +# Hawaii." Page 172:  "Act 163...Act 90 of the Session Laws of 1933 is
    +# hereby repealed...This Act shall take effect upon its approval, upon
    +# which date the standard time of this Territory shall be restored to
    +# that existing immediately prior to the taking effect of said Act 90.
    +# Approved this 21st day of May, A. D. 1933. LAWRENCE M. JUDD, Governor
    +# of the Territory of Hawaii."
    +#
    +# Note that 1933-05-21 was a Sunday.
    +# We're left to guess the time of day when Act 163 was approved; guess noon.
    +
    +Zone Pacific/Honolulu	-10:31:26 -	LMT	1896 Jan 13 12:00 #Schmitt&Cox
    +			-10:30	-	HST	1933 Apr 30 2:00 #Laws 1933
    +			-10:30	1:00	HDT	1933 May 21 12:00 #Laws 1933+12
    +			-10:30	-	HST	1942 Feb 09 2:00 #Schmitt&Cox+2
    +			-10:30	1:00	HDT	1945 Sep 30 2:00 #Schmitt&Cox+2
    +			-10:30	-	HST	1947 Jun  8 2:00 #Schmitt&Cox+2
    +			-10:00	-	HST
    +
    +# Now we turn to US areas that have diverged from the consensus since 1970.
    +
    +# Arizona mostly uses MST.
    +
    +# From Paul Eggert (2002-10-20):
    +#
    +# The information in the rest of this paragraph is derived from the
    +# 
    +# Daylight Saving Time web page (2002-01-23) maintained by the
    +# Arizona State Library, Archives and Public Records.
    +# Between 1944-01-01 and 1944-04-01 the State of Arizona used standard
    +# time, but by federal law railroads, airlines, bus lines, military
    +# personnel, and some engaged in interstate commerce continued to
    +# observe war (i.e., daylight saving) time.  The 1944-03-17 Phoenix
    +# Gazette says that was the date the law changed, and that 04-01 was
    +# the date the state's clocks would change.  In 1945 the State of
    +# Arizona used standard time all year, again with exceptions only as
    +# mandated by federal law.  Arizona observed DST in 1967, but Arizona
    +# Laws 1968, ch. 183 (effective 1968-03-21) repealed DST.
    +#
    +# Shanks says the 1944 experiment came to an end on 1944-03-17.
    +# Go with the Arizona State Library instead.
    +
    +Zone America/Phoenix	-7:28:18 -	LMT	1883 Nov 18 11:31:42
    +			-7:00	US	M%sT	1944 Jan  1 00:01
    +			-7:00	-	MST	1944 Apr  1 00:01
    +			-7:00	US	M%sT	1944 Oct  1 00:01
    +			-7:00	-	MST	1967
    +			-7:00	US	M%sT	1968 Mar 21
    +			-7:00	-	MST
    +# From Arthur David Olson (1988-02-13):
    +# A writer from the Inter Tribal Council of Arizona, Inc.,
    +# notes in private correspondence dated 1987-12-28 that "Presently, only the
    +# Navajo Nation participates in the Daylight Saving Time policy, due to its
    +# large size and location in three states."  (The "only" means that other
    +# tribal nations don't use DST.)
    +
    +Link America/Denver America/Shiprock
    +
    +# Southern Idaho (Ada, Adams, Bannock, Bear Lake, Bingham, Blaine,
    +# Boise, Bonneville, Butte, Camas, Canyon, Caribou, Cassia, Clark,
    +# Custer, Elmore, Franklin, Fremont, Gem, Gooding, Jefferson, Jerome,
    +# Lemhi, Lincoln, Madison, Minidoka, Oneida, Owyhee, Payette, Power,
    +# Teton, Twin Falls, Valley, Washington counties, and the southern
    +# quarter of Idaho county) and eastern Oregon (most of Malheur County)
    +# switched four weeks late in 1974.
    +#
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Boise	-7:44:49 -	LMT	1883 Nov 18 12:15:11
    +			-8:00	US	P%sT	1923 May 13 2:00
    +			-7:00	US	M%sT	1974
    +			-7:00	-	MST	1974 Feb  3 2:00
    +			-7:00	US	M%sT
    +
    +# Indiana
    +#
    +# For a map of Indiana's time zone regions, see:
    +# 
    +# What time is it in Indiana?
    +#  (2006-03-01)
    +#
    +# From Paul Eggert (2007-08-17):
    +# Since 1970, most of Indiana has been like America/Indiana/Indianapolis,
    +# with the following exceptions:
    +#
    +# - Gibson, Jasper, Lake, LaPorte, Newton, Porter, Posey, Spencer,
    +#   Vandenburgh, and Warrick counties have been like America/Chicago.
    +#
    +# - Dearborn and Ohio counties have been like America/New_York.
    +#
    +# - Clark, Floyd, and Harrison counties have been like
    +#   America/Kentucky/Louisville.
    +#
    +# - Crawford, Daviess, Dubois, Knox, Martin, Perry, Pike, Pulaski, Starke,
    +#   and Switzerland counties have their own time zone histories as noted below.
    +#
    +# Shanks partitioned Indiana into 345 regions, each with its own time history,
    +# and wrote ``Even newspaper reports present contradictory information.''
    +# Those Hoosiers!  Such a flighty and changeable people!
    +# Fortunately, most of the complexity occurred before our cutoff date of 1970.
    +#
    +# Other than Indianapolis, the Indiana place names are so nondescript
    +# that they would be ambiguous if we left them at the `America' level.
    +# So we reluctantly put them all in a subdirectory `America/Indiana'.
    +
    +# From Paul Eggert (2005-08-16):
    +# http://www.mccsc.edu/time.html says that Indiana will use DST starting 2006.
    +
    +# From Nathan Stratton Treadway (2006-03-30):
    +# http://www.dot.gov/affairs/dot0406.htm [3705 B]
    +# From Deborah Goldsmith (2006-01-18):
    +# http://dmses.dot.gov/docimages/pdf95/382329_web.pdf [2.9 MB]
    +# From Paul Eggert (2006-01-20):
    +# It says "DOT is relocating the time zone boundary in Indiana to move Starke,
    +# Pulaski, Knox, Daviess, Martin, Pike, Dubois, and Perry Counties from the
    +# Eastern Time Zone to the Central Time Zone.... The effective date of
    +# this rule is 2:OO a.m. EST Sunday, April 2, 2006, which is the
    +# changeover date from standard time to Daylight Saving Time."
    +# Strictly speaking, this means the affected counties will change their
    +# clocks twice that night, but this obviously is in error.  The intent
    +# is that 01:59:59 EST be followed by 02:00:00 CDT.
    +
    +# From Gwillim Law (2007-02-10):
    +# The Associated Press has been reporting that Pulaski County, Indiana is
    +# going to switch from Central to Eastern Time on March 11, 2007....
    +# http://www.indystar.com/apps/pbcs.dll/article?AID=/20070207/LOCAL190108/702070524/0/LOCAL
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
    +Rule Indianapolis 1941	only	-	Jun	22	2:00	1:00	D
    +Rule Indianapolis 1941	1954	-	Sep	lastSun	2:00	0	S
    +Rule Indianapolis 1946	1954	-	Apr	lastSun	2:00	1:00	D
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Indiana/Indianapolis -5:44:38 - LMT 1883 Nov 18 12:15:22
    +			-6:00	US	C%sT	1920
    +			-6:00 Indianapolis C%sT	1942
    +			-6:00	US	C%sT	1946
    +			-6:00 Indianapolis C%sT	1955 Apr 24 2:00
    +			-5:00	-	EST	1957 Sep 29 2:00
    +			-6:00	-	CST	1958 Apr 27 2:00
    +			-5:00	-	EST	1969
    +			-5:00	US	E%sT	1971
    +			-5:00	-	EST	2006
    +			-5:00	US	E%sT
    +#
    +# Eastern Crawford County, Indiana, left its clocks alone in 1974,
    +# as well as from 1976 through 2005.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
    +Rule	Marengo	1951	only	-	Apr	lastSun	2:00	1:00	D
    +Rule	Marengo	1951	only	-	Sep	lastSun	2:00	0	S
    +Rule	Marengo	1954	1960	-	Apr	lastSun	2:00	1:00	D
    +Rule	Marengo	1954	1960	-	Sep	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Indiana/Marengo -5:45:23 -	LMT	1883 Nov 18 12:14:37
    +			-6:00	US	C%sT	1951
    +			-6:00	Marengo	C%sT	1961 Apr 30 2:00
    +			-5:00	-	EST	1969
    +			-5:00	US	E%sT	1974 Jan  6 2:00
    +			-6:00	1:00	CDT	1974 Oct 27 2:00
    +			-5:00	US	E%sT	1976
    +			-5:00	-	EST	2006
    +			-5:00	US	E%sT
    +#
    +# Daviess, Dubois, Knox, and Martin Counties, Indiana,
    +# switched from eastern to central time in April 2006, then switched back
    +# in November 2007.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
    +Rule Vincennes	1946	only	-	Apr	lastSun	2:00	1:00	D
    +Rule Vincennes	1946	only	-	Sep	lastSun	2:00	0	S
    +Rule Vincennes	1953	1954	-	Apr	lastSun	2:00	1:00	D
    +Rule Vincennes	1953	1959	-	Sep	lastSun	2:00	0	S
    +Rule Vincennes	1955	only	-	May	 1	0:00	1:00	D
    +Rule Vincennes	1956	1963	-	Apr	lastSun	2:00	1:00	D
    +Rule Vincennes	1960	only	-	Oct	lastSun	2:00	0	S
    +Rule Vincennes	1961	only	-	Sep	lastSun	2:00	0	S
    +Rule Vincennes	1962	1963	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Indiana/Vincennes -5:50:07 - LMT	1883 Nov 18 12:09:53
    +			-6:00	US	C%sT	1946
    +			-6:00 Vincennes	C%sT	1964 Apr 26 2:00
    +			-5:00	-	EST	1969
    +			-5:00	US	E%sT	1971
    +			-5:00	-	EST	2006 Apr  2 2:00
    +			-6:00	US	C%sT	2007 Nov  4 2:00
    +			-5:00	US	E%sT
    +#
    +# Perry County, Indiana, switched from eastern to central time in April 2006.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
    +Rule Perry	1946	only	-	Apr	lastSun	2:00	1:00	D
    +Rule Perry	1946	only	-	Sep	lastSun	2:00	0	S
    +Rule Perry	1953	1954	-	Apr	lastSun	2:00	1:00	D
    +Rule Perry	1953	1959	-	Sep	lastSun	2:00	0	S
    +Rule Perry	1955	only	-	May	 1	0:00	1:00	D
    +Rule Perry	1956	1963	-	Apr	lastSun	2:00	1:00	D
    +Rule Perry	1960	only	-	Oct	lastSun	2:00	0	S
    +Rule Perry	1961	only	-	Sep	lastSun	2:00	0	S
    +Rule Perry	1962	1963	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Indiana/Tell_City -5:47:03 - LMT	1883 Nov 18 12:12:57
    +			-6:00	US	C%sT	1946
    +			-6:00 Perry	C%sT	1964 Apr 26 2:00
    +			-5:00	-	EST	1969
    +			-5:00	US	E%sT	1971
    +			-5:00	-	EST	2006 Apr  2 2:00
    +			-6:00	US	C%sT
    +#
    +# Pike County, Indiana moved from central to eastern time in 1977,
    +# then switched back in 2006, then switched back again in 2007.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
    +Rule	Pike	1955	only	-	May	 1	0:00	1:00	D
    +Rule	Pike	1955	1960	-	Sep	lastSun	2:00	0	S
    +Rule	Pike	1956	1964	-	Apr	lastSun	2:00	1:00	D
    +Rule	Pike	1961	1964	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Indiana/Petersburg -5:49:07 - LMT	1883 Nov 18 12:10:53
    +			-6:00	US	C%sT	1955
    +			-6:00	Pike	C%sT	1965 Apr 25 2:00
    +			-5:00	-	EST	1966 Oct 30 2:00
    +			-6:00	US	C%sT	1977 Oct 30 2:00
    +			-5:00	-	EST	2006 Apr  2 2:00
    +			-6:00	US	C%sT	2007 Nov  4 2:00
    +			-5:00	US	E%sT
    +#
    +# Starke County, Indiana moved from central to eastern time in 1991,
    +# then switched back in 2006.
    +# From Arthur David Olson (1991-10-28):
    +# An article on page A3 of the Sunday, 1991-10-27 Washington Post
    +# notes that Starke County switched from Central time to Eastern time as of
    +# 1991-10-27.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
    +Rule	Starke	1947	1961	-	Apr	lastSun	2:00	1:00	D
    +Rule	Starke	1947	1954	-	Sep	lastSun	2:00	0	S
    +Rule	Starke	1955	1956	-	Oct	lastSun	2:00	0	S
    +Rule	Starke	1957	1958	-	Sep	lastSun	2:00	0	S
    +Rule	Starke	1959	1961	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Indiana/Knox -5:46:30 -	LMT	1883 Nov 18 12:13:30
    +			-6:00	US	C%sT	1947
    +			-6:00	Starke	C%sT	1962 Apr 29 2:00
    +			-5:00	-	EST	1963 Oct 27 2:00
    +			-6:00	US	C%sT	1991 Oct 27 2:00
    +			-5:00	-	EST	2006 Apr  2 2:00
    +			-6:00	US	C%sT
    +#
    +# Pulaski County, Indiana, switched from eastern to central time in
    +# April 2006 and then switched back in March 2007.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
    +Rule	Pulaski	1946	1960	-	Apr	lastSun	2:00	1:00	D
    +Rule	Pulaski	1946	1954	-	Sep	lastSun	2:00	0	S
    +Rule	Pulaski	1955	1956	-	Oct	lastSun	2:00	0	S
    +Rule	Pulaski	1957	1960	-	Sep	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Indiana/Winamac -5:46:25 - LMT	1883 Nov 18 12:13:35
    +			-6:00	US	C%sT	1946
    +			-6:00	Pulaski	C%sT	1961 Apr 30 2:00
    +			-5:00	-	EST	1969
    +			-5:00	US	E%sT	1971
    +			-5:00	-	EST	2006 Apr  2 2:00
    +			-6:00	US	C%sT	2007 Mar 11 2:00
    +			-5:00	US	E%sT
    +#
    +# Switzerland County, Indiana, did not observe DST from 1973 through 2005.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Indiana/Vevay -5:40:16 -	LMT	1883 Nov 18 12:19:44
    +			-6:00	US	C%sT	1954 Apr 25 2:00
    +			-5:00	-	EST	1969
    +			-5:00	US	E%sT	1973
    +			-5:00	-	EST	2006
    +			-5:00	US	E%sT
    +
    +# Part of Kentucky left its clocks alone in 1974.
    +# This also includes Clark, Floyd, and Harrison counties in Indiana.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
    +Rule Louisville	1921	only	-	May	1	2:00	1:00	D
    +Rule Louisville	1921	only	-	Sep	1	2:00	0	S
    +Rule Louisville	1941	1961	-	Apr	lastSun	2:00	1:00	D
    +Rule Louisville	1941	only	-	Sep	lastSun	2:00	0	S
    +Rule Louisville	1946	only	-	Jun	2	2:00	0	S
    +Rule Louisville	1950	1955	-	Sep	lastSun	2:00	0	S
    +Rule Louisville	1956	1960	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Kentucky/Louisville -5:43:02 -	LMT	1883 Nov 18 12:16:58
    +			-6:00	US	C%sT	1921
    +			-6:00 Louisville C%sT	1942
    +			-6:00	US	C%sT	1946
    +			-6:00 Louisville C%sT	1961 Jul 23 2:00
    +			-5:00	-	EST	1968
    +			-5:00	US	E%sT	1974 Jan  6 2:00
    +			-6:00	1:00	CDT	1974 Oct 27 2:00
    +			-5:00	US	E%sT
    +#
    +# Wayne County, Kentucky
    +#
    +# From
    +# 
    +# Lake Cumberland LIFE
    +#  (1999-01-29) via WKYM-101.7:
    +# Clinton County has joined Wayne County in asking the DoT to change from
    +# the Central to the Eastern time zone....  The Wayne County government made
    +# the same request in December.  And while Russell County officials have not
    +# taken action, the majority of respondents to a poll conducted there in
    +# August indicated they would like to change to "fast time" also.
    +# The three Lake Cumberland counties are the farthest east of any U.S.
    +# location in the Central time zone.
    +#
    +# From Rich Wales (2000-08-29):
    +# After prolonged debate, and despite continuing deep differences of opinion,
    +# Wayne County (central Kentucky) is switching from Central (-0600) to Eastern
    +# (-0500) time.  They won't "fall back" this year.  See Sara Shipley,
    +# The difference an hour makes, Nando Times (2000-08-29 15:33 -0400).
    +#
    +# From Paul Eggert (2001-07-16):
    +# The final rule was published in the
    +# 
    +# Federal Register 65, 160 (2000-08-17), page 50154-50158.
    +# 
    +#
    +Zone America/Kentucky/Monticello -5:39:24 - LMT	1883 Nov 18 12:20:36
    +			-6:00	US	C%sT	1946
    +			-6:00	-	CST	1968
    +			-6:00	US	C%sT	2000 Oct 29  2:00
    +			-5:00	US	E%sT
    +
    +
    +# From Rives McDow (2000-08-30):
    +# Here ... are all the changes in the US since 1985.
    +# Kearny County, KS (put all of county on central;
    +#	previously split between MST and CST) ... 1990-10
    +# Starke County, IN (from CST to EST) ... 1991-10
    +# Oliver County, ND (from MST to CST) ... 1992-10
    +# West Wendover, NV (from PST TO MST) ... 1999-10
    +# Wayne County, KY (from CST to EST) ... 2000-10
    +#
    +# From Paul Eggert (2001-07-17):
    +# We don't know where the line used to be within Kearny County, KS,
    +# so omit that change for now.
    +# See America/Indiana/Knox for the Starke County, IN change.
    +# See America/North_Dakota/Center for the Oliver County, ND change.
    +# West Wendover, NV officially switched from Pacific to mountain time on
    +# 1999-10-31.  See the
    +# 
    +# Federal Register 64, 203 (1999-10-21), page 56705-56707.
    +# 
    +# However, the Federal Register says that West Wendover already operated
    +# on mountain time, and the rule merely made this official;
    +# hence a separate tz entry is not needed.
    +
    +# Michigan
    +#
    +# From Bob Devine (1988-01-28):
    +# Michigan didn't observe DST from 1968 to 1973.
    +#
    +# From Paul Eggert (1999-03-31):
    +# Shanks writes that Michigan started using standard time on 1885-09-18,
    +# but Howse writes (pp 124-125, referring to Popular Astronomy, 1901-01)
    +# that Detroit kept
    +#
    +#	local time until 1900 when the City Council decreed that clocks should
    +#	be put back twenty-eight minutes to Central Standard Time.  Half the
    +#	city obeyed, half refused.  After considerable debate, the decision
    +#	was rescinded and the city reverted to Sun time.  A derisive offer to
    +#	erect a sundial in front of the city hall was referred to the
    +#	Committee on Sewers.  Then, in 1905, Central time was adopted
    +#	by city vote.
    +#
    +# This story is too entertaining to be false, so go with Howse over Shanks.
    +#
    +# From Paul Eggert (2001-03-06):
    +# Garland (1927) writes ``Cleveland and Detroit advanced their clocks
    +# one hour in 1914.''  This change is not in Shanks.  We have no more
    +# info, so omit this for now.
    +#
    +# Most of Michigan observed DST from 1973 on, but was a bit late in 1975.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
    +Rule	Detroit	1948	only	-	Apr	lastSun	2:00	1:00	D
    +Rule	Detroit	1948	only	-	Sep	lastSun	2:00	0	S
    +Rule	Detroit	1967	only	-	Jun	14	2:00	1:00	D
    +Rule	Detroit	1967	only	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Detroit	-5:32:11 -	LMT	1905
    +			-6:00	-	CST	1915 May 15 2:00
    +			-5:00	-	EST	1942
    +			-5:00	US	E%sT	1946
    +			-5:00	Detroit	E%sT	1973
    +			-5:00	US	E%sT	1975
    +			-5:00	-	EST	1975 Apr 27 2:00
    +			-5:00	US	E%sT
    +#
    +# Dickinson, Gogebic, Iron, and Menominee Counties, Michigan,
    +# switched from EST to CST/CDT in 1973.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
    +Rule Menominee	1946	only	-	Apr	lastSun	2:00	1:00	D
    +Rule Menominee	1946	only	-	Sep	lastSun	2:00	0	S
    +Rule Menominee	1966	only	-	Apr	lastSun	2:00	1:00	D
    +Rule Menominee	1966	only	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
    +			-6:00	US	C%sT	1946
    +			-6:00 Menominee	C%sT	1969 Apr 27 2:00
    +			-5:00	-	EST	1973 Apr 29 2:00
    +			-6:00	US	C%sT
    +
    +# Navassa
    +# administered by the US Fish and Wildlife Service
    +# claimed by US under the provisions of the 1856 Guano Islands Act
    +# also claimed by Haiti
    +# occupied 1857/1900 by the Navassa Phosphate Co
    +# US lighthouse 1917/1996-09
    +# currently uninhabited
    +# see Mark Fineman, ``An Isle Rich in Guano and Discord'',
    +# _Los Angeles Times_ (1998-11-10), A1, A10; it cites
    +# Jimmy Skaggs, _The Great Guano Rush_ (1994).
    +
    +################################################################################
    +
    +
    +# From Paul Eggert (2006-03-22):
    +# A good source for time zone historical data outside the U.S. is
    +# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
    +# San Diego: ACS Publications, Inc. (2003).
    +#
    +# Gwillim Law writes that a good source
    +# for recent time zone data is the International Air Transport
    +# Association's Standard Schedules Information Manual (IATA SSIM),
    +# published semiannually.  Law sent in several helpful summaries
    +# of the IATA's data after 1990.
    +#
    +# Except where otherwise noted, Shanks & Pottenger is the source for
    +# entries through 1990, and IATA SSIM is the source for entries afterwards.
    +#
    +# Other sources occasionally used include:
    +#
    +#	Edward W. Whitman, World Time Differences,
    +#	Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
    +#	which I found in the UCLA library.
    +#
    +#	
    +#	William Willett, The Waste of Daylight, 19th edition
    +#	 (1914-03)
    +#
    +# See the `europe' file for Greenland.
    +
    +# Canada
    +
    +# From Alain LaBont (1994-11-14):
    +# I post here the time zone abbreviations standardized in Canada
    +# for both English and French in the CAN/CSA-Z234.4-89 standard....
    +#
    +#	UTC	Standard time	Daylight savings time
    +#	offset	French	English	French	English
    +#	-2:30	-	-	HAT	NDT
    +#	-3	-	-	HAA	ADT
    +#	-3:30	HNT	NST	-	-
    +#	-4	HNA	AST	HAE	EDT
    +#	-5	HNE	EST	HAC	CDT
    +#	-6	HNC	CST	HAR	MDT
    +#	-7	HNR	MST	HAP	PDT
    +#	-8	HNP	PST	HAY	YDT
    +#	-9	HNY	YST	-	-
    +#
    +#	HN: Heure Normale	ST: Standard Time
    +#	HA: Heure Avance	DT: Daylight saving Time
    +#
    +#	A: de l'Atlantique	Atlantic
    +#	C: du Centre		Central
    +#	E: de l'Est		Eastern
    +#	M:			Mountain
    +#	N:			Newfoundland
    +#	P: du Pacifique		Pacific
    +#	R: des Rocheuses
    +#	T: de Terre-Neuve
    +#	Y: du Yukon		Yukon
    +#
    +# From Paul Eggert (1994-11-22):
    +# Alas, this sort of thing must be handled by localization software.
    +
    +# Unless otherwise specified, the data for Canada are all from Shanks
    +# & Pottenger.
    +
    +# From Chris Walton (2006-04-01, 2006-04-25, 2006-06-26, 2007-01-31,
    +# 2007-03-01):
    +# The British Columbia government announced yesterday that it will
    +# adjust daylight savings next year to align with changes in the
    +# U.S. and the rest of Canada....
    +# http://www2.news.gov.bc.ca/news_releases_2005-2009/2006AG0014-000330.htm
    +# ...
    +# Nova Scotia
    +# Daylight saving time will be extended by four weeks starting in 2007....
    +# http://www.gov.ns.ca/just/regulations/rg2/2006/ma1206.pdf
    +#
    +# [For New Brunswick] the new legislation dictates that the time change is to
    +# be done at 02:00 instead of 00:01.
    +# http://www.gnb.ca/0062/acts/BBA-2006/Chap-19.pdf
    +# ...
    +# Manitoba has traditionally changed the clock every fall at 03:00.
    +# As of 2006, the transition is to take place one hour earlier at 02:00.
    +# http://web2.gov.mb.ca/laws/statutes/ccsm/o030e.php
    +# ...
    +# [Alberta, Ontario, Quebec] will follow US rules.
    +# http://www.qp.gov.ab.ca/documents/spring/CH03_06.CFM
    +# http://www.e-laws.gov.on.ca/DBLaws/Source/Regs/English/2006/R06111_e.htm
    +# http://www2.publicationsduquebec.gouv.qc.ca/dynamicSearch/telecharge.php?type=5&file=2006C39A.PDF
    +# ...
    +# P.E.I. will follow US rules....
    +# http://www.assembly.pe.ca/bills/pdf_chapter/62/3/chapter-41.pdf
    +# ...
    +# Province of Newfoundland and Labrador....
    +# http://www.hoa.gov.nl.ca/hoa/bills/Bill0634.htm
    +# ...
    +# Yukon
    +# http://www.gov.yk.ca/legislation/regs/oic2006_127.pdf
    +# ...
    +# N.W.T. will follow US rules.  Whoever maintains the government web site
    +# does not seem to believe in bookmarks.  To see the news release, click the
    +# following link and search for "Daylight Savings Time Change".  Press the
    +# "Daylight Savings Time Change" link; it will fire off a popup using
    +# JavaScript.
    +# http://www.exec.gov.nt.ca/currentnews/currentPR.asp?mode=archive
    +# ...
    +# Nunavut
    +# An amendment to the Interpretation Act was registered on February 19/2007....
    +# http://action.attavik.ca/home/justice-gn/attach/2007/gaz02part2.pdf
    +
    +# From Paul Eggert (2006-04-25):
    +# H. David Matthews and Mary Vincent's map
    +# 
    +# "It's about TIME", _Canadian Geographic_ (September-October 1998)
    +#  contains detailed boundaries for regions observing nonstandard
    +# time and daylight saving time arrangements in Canada circa 1998.
    +#
    +# INMS, the Institute for National Measurement Standards in Ottawa, has 
    +# information about standard and daylight saving time zones in Canada.
    +#  (updated periodically).
    +# Its unofficial information is often taken from Matthews and Vincent.
    +
    +# From Paul Eggert (2006-06-27):
    +# For now, assume all of DST-observing Canada will fall into line with the
    +# new US DST rules,
    +
    +# From Chris Walton (2011-12-01)
    +# In the first of Tammy Hardwick's articles
    +# 
    +# http://www.ilovecreston.com/?p=articles&t=spec&ar=260
    +# 
    +# she quotes the Friday November 1/1918 edition of the Creston Review.
    +# The quote includes these two statements:
    +# 'Sunday the CPR went back to the old system of time...'
    +# '... The daylight saving scheme was dropped all over Canada at the same time,'
    +# These statements refer to a transition from daylight time to standard time
    +# that occurred nationally on Sunday October 27/1918.  This transition was
    +# also documented in the Saturday October 26/1918 edition of the Toronto Star.
    +
    +# In light of that evidence, we alter the date from the earlier believed
    +# Oct 31, to Oct 27, 1918 (and Sunday is a more likely transition day
    +# than Thursday) in all Canadian rulesets.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Canada	1918	only	-	Apr	14	2:00	1:00	D
    +Rule	Canada	1918	only	-	Oct	27	2:00	0	S
    +Rule	Canada	1942	only	-	Feb	 9	2:00	1:00	W # War
    +Rule	Canada	1945	only	-	Aug	14	23:00u	1:00	P # Peace
    +Rule	Canada	1945	only	-	Sep	30	2:00	0	S
    +Rule	Canada	1974	1986	-	Apr	lastSun	2:00	1:00	D
    +Rule	Canada	1974	2006	-	Oct	lastSun	2:00	0	S
    +Rule	Canada	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
    +Rule	Canada	2007	max	-	Mar	Sun>=8	2:00	1:00	D
    +Rule	Canada	2007	max	-	Nov	Sun>=1	2:00	0	S
    +
    +
    +# Newfoundland and Labrador
    +
    +# From Paul Eggert (2000-10-02):
    +# Matthews and Vincent (1998) write that Labrador should use NST/NDT,
    +# but the only part of Labrador that follows the rules is the
    +# southeast corner, including Port Hope Simpson and Mary's Harbour,
    +# but excluding, say, Black Tickle.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	StJohns	1917	only	-	Apr	 8	2:00	1:00	D
    +Rule	StJohns	1917	only	-	Sep	17	2:00	0	S
    +# Whitman gives 1919 Apr 5 and 1920 Apr 5; go with Shanks & Pottenger.
    +Rule	StJohns	1919	only	-	May	 5	23:00	1:00	D
    +Rule	StJohns	1919	only	-	Aug	12	23:00	0	S
    +# For 1931-1935 Whitman gives Apr same date; go with Shanks & Pottenger.
    +Rule	StJohns	1920	1935	-	May	Sun>=1	23:00	1:00	D
    +Rule	StJohns	1920	1935	-	Oct	lastSun	23:00	0	S
    +# For 1936-1941 Whitman gives May Sun>=8 and Oct Sun>=1; go with Shanks &
    +# Pottenger.
    +Rule	StJohns	1936	1941	-	May	Mon>=9	0:00	1:00	D
    +Rule	StJohns	1936	1941	-	Oct	Mon>=2	0:00	0	S
    +# Whitman gives the following transitions:
    +# 1942 03-01/12-31, 1943 05-30/09-05, 1944 07-10/09-02, 1945 01-01/10-07
    +# but go with Shanks & Pottenger and assume they used Canadian rules.
    +# For 1946-9 Whitman gives May 5,4,9,1 - Oct 1,5,3,2, and for 1950 he gives
    +# Apr 30 - Sep 24; go with Shanks & Pottenger.
    +Rule	StJohns	1946	1950	-	May	Sun>=8	2:00	1:00	D
    +Rule	StJohns	1946	1950	-	Oct	Sun>=2	2:00	0	S
    +Rule	StJohns	1951	1986	-	Apr	lastSun	2:00	1:00	D
    +Rule	StJohns	1951	1959	-	Sep	lastSun	2:00	0	S
    +Rule	StJohns	1960	1986	-	Oct	lastSun	2:00	0	S
    +# From Paul Eggert (2000-10-02):
    +# INMS (2000-09-12) says that, since 1988 at least, Newfoundland switches
    +# at 00:01 local time.  For now, assume it started in 1987.
    +
    +# From Michael Pelley (2011-09-12):
    +# We received today, Monday, September 12, 2011, notification that the
    +# changes to the Newfoundland Standard Time Act have been proclaimed.
    +# The change in the Act stipulates that the change from Daylight Savings
    +# Time to Standard Time and from Standard Time to Daylight Savings Time
    +# now occurs at 2:00AM.
    +# ...
    +# 
    +# http://www.assembly.nl.ca/legislation/sr/annualstatutes/2011/1106.chp.htm
    +# 
    +# ...
    +# MICHAEL PELLEY  |  Manager of Enterprise Architecture - Solution Delivery
    +# Office of the Chief Information Officer
    +# Executive Council
    +# Government of Newfoundland & Labrador
    +
    +Rule	StJohns	1987	only	-	Apr	Sun>=1	0:01	1:00	D
    +Rule	StJohns	1987	2006	-	Oct	lastSun	0:01	0	S
    +Rule	StJohns	1988	only	-	Apr	Sun>=1	0:01	2:00	DD
    +Rule	StJohns	1989	2006	-	Apr	Sun>=1	0:01	1:00	D
    +Rule	StJohns	2007	2011	-	Mar	Sun>=8	0:01	1:00	D
    +Rule	StJohns	2007	2010	-	Nov	Sun>=1	0:01	0	S
    +#
    +# St John's has an apostrophe, but Posix file names can't have apostrophes.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/St_Johns	-3:30:52 -	LMT	1884
    +			-3:30:52 StJohns N%sT	1918
    +			-3:30:52 Canada	N%sT	1919
    +			-3:30:52 StJohns N%sT	1935 Mar 30
    +			-3:30	StJohns	N%sT	1942 May 11
    +			-3:30	Canada	N%sT	1946
    +			-3:30	StJohns	N%sT	2011 Nov
    +			-3:30	Canada	N%sT
    +
    +# most of east Labrador
    +
    +# The name `Happy Valley-Goose Bay' is too long; use `Goose Bay'.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Goose_Bay	-4:01:40 -	LMT	1884 # Happy Valley-Goose Bay
    +			-3:30:52 -	NST	1918
    +			-3:30:52 Canada N%sT	1919
    +			-3:30:52 -	NST	1935 Mar 30
    +			-3:30	-	NST	1936
    +			-3:30	StJohns	N%sT	1942 May 11
    +			-3:30	Canada	N%sT	1946
    +			-3:30	StJohns	N%sT	1966 Mar 15 2:00
    +			-4:00	StJohns	A%sT	2011 Nov
    +			-4:00	Canada	A%sT
    +
    +
    +# west Labrador, Nova Scotia, Prince Edward I
    +
    +# From Paul Eggert (2006-03-22):
    +# Shanks & Pottenger write that since 1970 most of this region has been like
    +# Halifax.  Many locales did not observe peacetime DST until 1972;
    +# Glace Bay, NS is the largest that we know of.
    +# Shanks & Pottenger also write that Liverpool, NS was the only town
    +# in Canada to observe DST in 1971 but not 1970; for now we'll assume
    +# this is a typo.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Halifax	1916	only	-	Apr	 1	0:00	1:00	D
    +Rule	Halifax	1916	only	-	Oct	 1	0:00	0	S
    +Rule	Halifax	1920	only	-	May	 9	0:00	1:00	D
    +Rule	Halifax	1920	only	-	Aug	29	0:00	0	S
    +Rule	Halifax	1921	only	-	May	 6	0:00	1:00	D
    +Rule	Halifax	1921	1922	-	Sep	 5	0:00	0	S
    +Rule	Halifax	1922	only	-	Apr	30	0:00	1:00	D
    +Rule	Halifax	1923	1925	-	May	Sun>=1	0:00	1:00	D
    +Rule	Halifax	1923	only	-	Sep	 4	0:00	0	S
    +Rule	Halifax	1924	only	-	Sep	15	0:00	0	S
    +Rule	Halifax	1925	only	-	Sep	28	0:00	0	S
    +Rule	Halifax	1926	only	-	May	16	0:00	1:00	D
    +Rule	Halifax	1926	only	-	Sep	13	0:00	0	S
    +Rule	Halifax	1927	only	-	May	 1	0:00	1:00	D
    +Rule	Halifax	1927	only	-	Sep	26	0:00	0	S
    +Rule	Halifax	1928	1931	-	May	Sun>=8	0:00	1:00	D
    +Rule	Halifax	1928	only	-	Sep	 9	0:00	0	S
    +Rule	Halifax	1929	only	-	Sep	 3	0:00	0	S
    +Rule	Halifax	1930	only	-	Sep	15	0:00	0	S
    +Rule	Halifax	1931	1932	-	Sep	Mon>=24	0:00	0	S
    +Rule	Halifax	1932	only	-	May	 1	0:00	1:00	D
    +Rule	Halifax	1933	only	-	Apr	30	0:00	1:00	D
    +Rule	Halifax	1933	only	-	Oct	 2	0:00	0	S
    +Rule	Halifax	1934	only	-	May	20	0:00	1:00	D
    +Rule	Halifax	1934	only	-	Sep	16	0:00	0	S
    +Rule	Halifax	1935	only	-	Jun	 2	0:00	1:00	D
    +Rule	Halifax	1935	only	-	Sep	30	0:00	0	S
    +Rule	Halifax	1936	only	-	Jun	 1	0:00	1:00	D
    +Rule	Halifax	1936	only	-	Sep	14	0:00	0	S
    +Rule	Halifax	1937	1938	-	May	Sun>=1	0:00	1:00	D
    +Rule	Halifax	1937	1941	-	Sep	Mon>=24	0:00	0	S
    +Rule	Halifax	1939	only	-	May	28	0:00	1:00	D
    +Rule	Halifax	1940	1941	-	May	Sun>=1	0:00	1:00	D
    +Rule	Halifax	1946	1949	-	Apr	lastSun	2:00	1:00	D
    +Rule	Halifax	1946	1949	-	Sep	lastSun	2:00	0	S
    +Rule	Halifax	1951	1954	-	Apr	lastSun	2:00	1:00	D
    +Rule	Halifax	1951	1954	-	Sep	lastSun	2:00	0	S
    +Rule	Halifax	1956	1959	-	Apr	lastSun	2:00	1:00	D
    +Rule	Halifax	1956	1959	-	Sep	lastSun	2:00	0	S
    +Rule	Halifax	1962	1973	-	Apr	lastSun	2:00	1:00	D
    +Rule	Halifax	1962	1973	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Halifax	-4:14:24 -	LMT	1902 Jun 15
    +			-4:00	Halifax	A%sT	1918
    +			-4:00	Canada	A%sT	1919
    +			-4:00	Halifax	A%sT	1942 Feb  9 2:00s
    +			-4:00	Canada	A%sT	1946
    +			-4:00	Halifax	A%sT	1974
    +			-4:00	Canada	A%sT
    +Zone America/Glace_Bay	-3:59:48 -	LMT	1902 Jun 15
    +			-4:00	Canada	A%sT	1953
    +			-4:00	Halifax	A%sT	1954
    +			-4:00	-	AST	1972
    +			-4:00	Halifax	A%sT	1974
    +			-4:00	Canada	A%sT
    +
    +# New Brunswick
    +
    +# From Paul Eggert (2007-01-31):
    +# The Time Definition Act 
    +# says they changed at 00:01 through 2006, and
    +#  makes it
    +# clear that this was the case since at least 1993.
    +# For now, assume it started in 1993.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Moncton	1933	1935	-	Jun	Sun>=8	1:00	1:00	D
    +Rule	Moncton	1933	1935	-	Sep	Sun>=8	1:00	0	S
    +Rule	Moncton	1936	1938	-	Jun	Sun>=1	1:00	1:00	D
    +Rule	Moncton	1936	1938	-	Sep	Sun>=1	1:00	0	S
    +Rule	Moncton	1939	only	-	May	27	1:00	1:00	D
    +Rule	Moncton	1939	1941	-	Sep	Sat>=21	1:00	0	S
    +Rule	Moncton	1940	only	-	May	19	1:00	1:00	D
    +Rule	Moncton	1941	only	-	May	 4	1:00	1:00	D
    +Rule	Moncton	1946	1972	-	Apr	lastSun	2:00	1:00	D
    +Rule	Moncton	1946	1956	-	Sep	lastSun	2:00	0	S
    +Rule	Moncton	1957	1972	-	Oct	lastSun	2:00	0	S
    +Rule	Moncton	1993	2006	-	Apr	Sun>=1	0:01	1:00	D
    +Rule	Moncton	1993	2006	-	Oct	lastSun	0:01	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Moncton	-4:19:08 -	LMT	1883 Dec  9
    +			-5:00	-	EST	1902 Jun 15
    +			-4:00	Canada	A%sT	1933
    +			-4:00	Moncton	A%sT	1942
    +			-4:00	Canada	A%sT	1946
    +			-4:00	Moncton	A%sT	1973
    +			-4:00	Canada	A%sT	1993
    +			-4:00	Moncton	A%sT	2007
    +			-4:00	Canada	A%sT
    +
    +# Quebec
    +
    +# From Paul Eggert (2006-07-09):
    +# Shanks & Pottenger write that since 1970 most of Quebec has been
    +# like Montreal.
    +
    +# From Paul Eggert (2006-06-27):
    +# Matthews and Vincent (1998) also write that Quebec east of the -63
    +# meridian is supposed to observe AST, but residents as far east as
    +# Natashquan use EST/EDT, and residents east of Natashquan use AST.
    +# In "Official time in Quebec" the Quebec department of justice writes in
    +# http://www.justice.gouv.qc.ca/english/publications/generale/temps-regl-1-a.htm
    +# that "The residents of the Municipality of the
    +# Cote-Nord-du-Golfe-Saint-Laurent and the municipalities of Saint-Augustin,
    +# Bonne-Esperance and Blanc-Sablon apply the Official Time Act as it is
    +# written and use Atlantic standard time all year round. The same applies to
    +# the residents of the Native facilities along the lower North Shore."
    +# 
    +# says this common practice was codified into law as of 2007.
    +# For lack of better info, guess this practice began around 1970, contra to
    +# Shanks & Pottenger who have this region observing AST/ADT.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Mont	1917	only	-	Mar	25	2:00	1:00	D
    +Rule	Mont	1917	only	-	Apr	24	0:00	0	S
    +Rule	Mont	1919	only	-	Mar	31	2:30	1:00	D
    +Rule	Mont	1919	only	-	Oct	25	2:30	0	S
    +Rule	Mont	1920	only	-	May	 2	2:30	1:00	D
    +Rule	Mont	1920	1922	-	Oct	Sun>=1	2:30	0	S
    +Rule	Mont	1921	only	-	May	 1	2:00	1:00	D
    +Rule	Mont	1922	only	-	Apr	30	2:00	1:00	D
    +Rule	Mont	1924	only	-	May	17	2:00	1:00	D
    +Rule	Mont	1924	1926	-	Sep	lastSun	2:30	0	S
    +Rule	Mont	1925	1926	-	May	Sun>=1	2:00	1:00	D
    +# The 1927-to-1937 rules can be expressed more simply as
    +# Rule	Mont	1927	1937	-	Apr	lastSat	24:00	1:00	D
    +# Rule	Mont	1927	1937	-	Sep	lastSat	24:00	0	S
    +# The rules below avoid use of 24:00
    +# (which pre-1998 versions of zic cannot handle).
    +Rule	Mont	1927	only	-	May	1	0:00	1:00	D
    +Rule	Mont	1927	1932	-	Sep	lastSun	0:00	0	S
    +Rule	Mont	1928	1931	-	Apr	lastSun	0:00	1:00	D
    +Rule	Mont	1932	only	-	May	1	0:00	1:00	D
    +Rule	Mont	1933	1940	-	Apr	lastSun	0:00	1:00	D
    +Rule	Mont	1933	only	-	Oct	1	0:00	0	S
    +Rule	Mont	1934	1939	-	Sep	lastSun	0:00	0	S
    +Rule	Mont	1946	1973	-	Apr	lastSun	2:00	1:00	D
    +Rule	Mont	1945	1948	-	Sep	lastSun	2:00	0	S
    +Rule	Mont	1949	1950	-	Oct	lastSun	2:00	0	S
    +Rule	Mont	1951	1956	-	Sep	lastSun	2:00	0	S
    +Rule	Mont	1957	1973	-	Oct	lastSun	2:00	0	S
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Blanc-Sablon -3:48:28 -	LMT	1884
    +			-4:00	Canada	A%sT	1970
    +			-4:00	-	AST
    +Zone America/Montreal	-4:54:16 -	LMT	1884
    +			-5:00	Mont	E%sT	1918
    +			-5:00	Canada	E%sT	1919
    +			-5:00	Mont	E%sT	1942 Feb  9 2:00s
    +			-5:00	Canada	E%sT	1946
    +			-5:00	Mont	E%sT	1974
    +			-5:00	Canada	E%sT
    +
    +
    +# Ontario
    +
    +# From Paul Eggert (2006-07-09):
    +# Shanks & Pottenger write that since 1970 most of Ontario has been like
    +# Toronto.
    +# Thunder Bay skipped DST in 1973.
    +# Many smaller locales did not observe peacetime DST until 1974;
    +# Nipigon (EST) and Rainy River (CST) are the largest that we know of.
    +# Far west Ontario is like Winnipeg; far east Quebec is like Halifax.
    +
    +# From Mark Brader (2003-07-26):
    +# [According to the Toronto Star] Orillia, Ontario, adopted DST
    +# effective Saturday, 1912-06-22, 22:00; the article mentions that
    +# Port Arthur (now part of Thunder Bay, Ontario) as well as Moose Jaw
    +# have already done so.  In Orillia DST was to run until Saturday,
    +# 1912-08-31 (no time mentioned), but it was met with considerable
    +# hostility from certain segments of the public, and was revoked after
    +# only two weeks -- I copied it as Saturday, 1912-07-07, 22:00, but
    +# presumably that should be -07-06.  (1912-06-19, -07-12; also letters
    +# earlier in June).
    +#
    +# Kenora, Ontario, was to abandon DST on 1914-06-01 (-05-21).
    +
    +# From Paul Eggert (1997-10-17):
    +# Mark Brader writes that an article in the 1997-10-14 Toronto Star
    +# says that Atikokan, Ontario currently does not observe DST,
    +# but will vote on 11-10 whether to use EST/EDT.
    +# He also writes that the
    +# 
    +# Ontario Time Act (1990, Chapter T.9)
    +# 
    +# says that Ontario east of 90W uses EST/EDT, and west of 90W uses CST/CDT.
    +# Officially Atikokan is therefore on CST/CDT, and most likely this report
    +# concerns a non-official time observed as a matter of local practice.
    +#
    +# From Paul Eggert (2000-10-02):
    +# Matthews and Vincent (1998) write that Atikokan, Pickle Lake, and
    +# New Osnaburgh observe CST all year, that Big Trout Lake observes
    +# CST/CDT, and that Upsala and Shebandowan observe EST/EDT, all in
    +# violation of the official Ontario rules.
    +#
    +# From Paul Eggert (2006-07-09):
    +# Chris Walton (2006-07-06) mentioned an article by Stephanie MacLellan in the
    +# 2005-07-21 Chronicle-Journal, which said:
    +#
    +#	The clocks in Atikokan stay set on standard time year-round.
    +#	This means they spend about half the time on central time and
    +#	the other half on eastern time.
    +#
    +#	For the most part, the system works, Mayor Dennis Brown said.
    +#
    +#	"The majority of businesses in Atikokan deal more with Eastern
    +#	Canada, but there are some that deal with Western Canada," he
    +#	said.  "I don't see any changes happening here."
    +#
    +# Walton also writes "Supposedly Pickle Lake and Mishkeegogamang
    +# [New Osnaburgh] follow the same practice."
    +
    +# From Garry McKinnon (2006-07-14) via Chris Walton:
    +# I chatted with a member of my board who has an outstanding memory
    +# and a long history in Atikokan (and in the telecom industry) and he
    +# can say for certain that Atikokan has been practicing the current
    +# time keeping since 1952, at least.
    +
    +# From Paul Eggert (2006-07-17):
    +# Shanks & Pottenger say that Atikokan has agreed with Rainy River
    +# ever since standard time was introduced, but the information from
    +# McKinnon sounds more authoritative.  For now, assume that Atikokan
    +# switched to EST immediately after WWII era daylight saving time
    +# ended.  This matches the old (less-populous) America/Coral_Harbour
    +# entry since our cutoff date of 1970, so we can move
    +# America/Coral_Harbour to the 'backward' file.
    +
    +# From Mark Brader (2010-03-06):
    +#
    +# Currently the database has:
    +#
    +# # Ontario
    +#
    +# # From Paul Eggert (2006-07-09):
    +# # Shanks & Pottenger write that since 1970 most of Ontario has been like
    +# # Toronto.
    +# # Thunder Bay skipped DST in 1973.
    +# # Many smaller locales did not observe peacetime DST until 1974;
    +# # Nipigon (EST) and Rainy River (CST) are the largest that we know of.
    +#
    +# In the (Toronto) Globe and Mail for Saturday, 1955-09-24, in the bottom
    +# right corner of page 1, it says that Toronto will return to standard
    +# time at 2 am Sunday morning (which agrees with the database), and that:
    +#
    +#     The one-hour setback will go into effect throughout most of Ontario,
    +#     except in areas like Windsor which remains on standard time all year.
    +#
    +# Windsor is, of course, a lot larger than Nipigon.
    +#
    +# I only came across this incidentally.  I don't know if Windsor began
    +# observing DST when Detroit did, or in 1974, or on some other date.
    +#
    +# By the way, the article continues by noting that:
    +#
    +#     Some cities in the United States have pushed the deadline back
    +#     three weeks and will change over from daylight saving in October.
    +
    +# From Arthur David Olson (2010-07-17):
    +#
    +# "Standard Time and Time Zones in Canada" appeared in
    +# The Journal of The Royal Astronomical Society of Canada,
    +# volume 26, number 2 (February 1932) and, as of 2010-07-17,
    +# was available at
    +# 
    +# http://adsabs.harvard.edu/full/1932JRASC..26...49S
    +# 
    +#
    +# It includes the text below (starting on page 57):
    +#
    +#   A list of the places in Canada using daylight saving time would
    +# require yearly revision. From information kindly furnished by
    +# the provincial governments and by the postmasters in many cities
    +# and towns, it is found that the following places used daylight sav-
    +# ing in 1930. The information for the province of Quebec is definite,
    +# for the other provinces only approximate:
    +#
    +# 	Province	Daylight saving time used
    +# Prince Edward Island	Not used.
    +# Nova Scotia		In Halifax only.
    +# New Brunswick		In St. John only.
    +# Quebec		In the following places:
    +# 			Montreal	Lachine
    +# 			Quebec		Mont-Royal
    +# 			Levis		Iberville
    +# 			St. Lambert	Cap de la Madeleine
    +# 			Verdun		Loretteville
    +# 			Westmount	Richmond
    +# 			Outremont	St. Jerome
    +# 			Longueuil	Greenfield Park
    +# 			Arvida		Waterloo
    +# 			Chambly-Canton	Beaulieu
    +# 			Melbourne	La Tuque
    +# 			St. Theophile	Buckingham
    +# Ontario		Used generally in the cities and towns along
    +# 			the southerly part of the province. Not
    +# 			used in the northwesterlhy part.
    +# Manitoba		Not used.
    +# Saskatchewan		In Regina only.
    +# Alberta		Not used.
    +# British Columbia	Not used.
    +#
    +#   With some exceptions, the use of daylight saving may be said to be limited
    +# to those cities and towns lying between Quebec city and Windsor, Ont.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Toronto	1919	only	-	Mar	30	23:30	1:00	D
    +Rule	Toronto	1919	only	-	Oct	26	0:00	0	S
    +Rule	Toronto	1920	only	-	May	 2	2:00	1:00	D
    +Rule	Toronto	1920	only	-	Sep	26	0:00	0	S
    +Rule	Toronto	1921	only	-	May	15	2:00	1:00	D
    +Rule	Toronto	1921	only	-	Sep	15	2:00	0	S
    +Rule	Toronto	1922	1923	-	May	Sun>=8	2:00	1:00	D
    +# Shanks & Pottenger say 1923-09-19; assume it's a typo and that "-16"
    +# was meant.
    +Rule	Toronto	1922	1926	-	Sep	Sun>=15	2:00	0	S
    +Rule	Toronto	1924	1927	-	May	Sun>=1	2:00	1:00	D
    +# The 1927-to-1939 rules can be expressed more simply as
    +# Rule	Toronto	1927	1937	-	Sep	Sun>=25	2:00	0	S
    +# Rule	Toronto	1928	1937	-	Apr	Sun>=25	2:00	1:00	D
    +# Rule	Toronto	1938	1940	-	Apr	lastSun	2:00	1:00	D
    +# Rule	Toronto	1938	1939	-	Sep	lastSun	2:00	0	S
    +# The rules below avoid use of Sun>=25
    +# (which pre-2004 versions of zic cannot handle).
    +Rule	Toronto	1927	1932	-	Sep	lastSun	2:00	0	S
    +Rule	Toronto	1928	1931	-	Apr	lastSun	2:00	1:00	D
    +Rule	Toronto	1932	only	-	May	1	2:00	1:00	D
    +Rule	Toronto	1933	1940	-	Apr	lastSun	2:00	1:00	D
    +Rule	Toronto	1933	only	-	Oct	1	2:00	0	S
    +Rule	Toronto	1934	1939	-	Sep	lastSun	2:00	0	S
    +Rule	Toronto	1945	1946	-	Sep	lastSun	2:00	0	S
    +Rule	Toronto	1946	only	-	Apr	lastSun	2:00	1:00	D
    +Rule	Toronto	1947	1949	-	Apr	lastSun	0:00	1:00	D
    +Rule	Toronto	1947	1948	-	Sep	lastSun	0:00	0	S
    +Rule	Toronto	1949	only	-	Nov	lastSun	0:00	0	S
    +Rule	Toronto	1950	1973	-	Apr	lastSun	2:00	1:00	D
    +Rule	Toronto	1950	only	-	Nov	lastSun	2:00	0	S
    +Rule	Toronto	1951	1956	-	Sep	lastSun	2:00	0	S
    +# Shanks & Pottenger say Toronto ended DST a week early in 1971,
    +# namely on 1971-10-24, but Mark Brader wrote (2003-05-31) that this
    +# is wrong, and that he had confirmed it by checking the 1971-10-30
    +# Toronto Star, which said that DST was ending 1971-10-31 as usual.
    +Rule	Toronto	1957	1973	-	Oct	lastSun	2:00	0	S
    +
    +# From Paul Eggert (2003-07-27):
    +# Willett (1914-03) writes (p. 17) "In the Cities of Fort William, and
    +# Port Arthur, Ontario, the principle of the Bill has been in
    +# operation for the past three years, and in the City of Moose Jaw,
    +# Saskatchewan, for one year."
    +
    +# From David Bryan via Tory Tronrud, Director/Curator,
    +# Thunder Bay Museum (2003-11-12):
    +# There is some suggestion, however, that, by-law or not, daylight
    +# savings time was being practiced in Fort William and Port Arthur
    +# before 1909.... [I]n 1910, the line between the Eastern and Central
    +# Time Zones was permanently moved about two hundred miles west to
    +# include the Thunder Bay area....  When Canada adopted daylight
    +# savings time in 1916, Fort William and Port Arthur, having done so
    +# already, did not change their clocks....  During the Second World
    +# War,... [t]he cities agreed to implement DST during the summer
    +# months for the remainder of the war years.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Toronto	-5:17:32 -	LMT	1895
    +			-5:00	Canada	E%sT	1919
    +			-5:00	Toronto	E%sT	1942 Feb  9 2:00s
    +			-5:00	Canada	E%sT	1946
    +			-5:00	Toronto	E%sT	1974
    +			-5:00	Canada	E%sT
    +Zone America/Thunder_Bay -5:57:00 -	LMT	1895
    +			-6:00	-	CST	1910
    +			-5:00	-	EST	1942
    +			-5:00	Canada	E%sT	1970
    +			-5:00	Mont	E%sT	1973
    +			-5:00	-	EST	1974
    +			-5:00	Canada	E%sT
    +Zone America/Nipigon	-5:53:04 -	LMT	1895
    +			-5:00	Canada	E%sT	1940 Sep 29
    +			-5:00	1:00	EDT	1942 Feb  9 2:00s
    +			-5:00	Canada	E%sT
    +Zone America/Rainy_River -6:18:16 -	LMT	1895
    +			-6:00	Canada	C%sT	1940 Sep 29
    +			-6:00	1:00	CDT	1942 Feb  9 2:00s
    +			-6:00	Canada	C%sT
    +Zone America/Atikokan	-6:06:28 -	LMT	1895
    +			-6:00	Canada	C%sT	1940 Sep 29
    +			-6:00	1:00	CDT	1942 Feb  9 2:00s
    +			-6:00	Canada	C%sT	1945 Sep 30 2:00
    +			-5:00	-	EST
    +
    +
    +# Manitoba
    +
    +# From Rob Douglas (2006-04-06):
    +# the old Manitoba Time Act - as amended by Bill 2, assented to
    +# March 27, 1987 ... said ...
    +# "between two o'clock Central Standard Time in the morning of
    +# the first Sunday of April of each year and two o'clock Central
    +# Standard Time in the morning of the last Sunday of October next
    +# following, one hour in advance of Central Standard Time."...
    +# I believe that the English legislation [of the old time act] had =
    +# been assented to (March 22, 1967)....
    +# Also, as far as I can tell, there was no order-in-council varying
    +# the time of Daylight Saving Time for 2005 and so the provisions of
    +# the 1987 version would apply - the changeover was at 2:00 Central
    +# Standard Time (i.e. not until 3:00 Central Daylight Time).
    +
    +# From Paul Eggert (2006-04-10):
    +# Shanks & Pottenger say Manitoba switched at 02:00 (not 02:00s)
    +# starting 1966.  Since 02:00s is clearly correct for 1967 on, assume
    +# it was also 02:00s in 1966.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Winn	1916	only	-	Apr	23	0:00	1:00	D
    +Rule	Winn	1916	only	-	Sep	17	0:00	0	S
    +Rule	Winn	1918	only	-	Apr	14	2:00	1:00	D
    +Rule	Winn	1918	only	-	Oct	27	2:00	0	S
    +Rule	Winn	1937	only	-	May	16	2:00	1:00	D
    +Rule	Winn	1937	only	-	Sep	26	2:00	0	S
    +Rule	Winn	1942	only	-	Feb	 9	2:00	1:00	W # War
    +Rule	Winn	1945	only	-	Aug	14	23:00u	1:00	P # Peace
    +Rule	Winn	1945	only	-	Sep	lastSun	2:00	0	S
    +Rule	Winn	1946	only	-	May	12	2:00	1:00	D
    +Rule	Winn	1946	only	-	Oct	13	2:00	0	S
    +Rule	Winn	1947	1949	-	Apr	lastSun	2:00	1:00	D
    +Rule	Winn	1947	1949	-	Sep	lastSun	2:00	0	S
    +Rule	Winn	1950	only	-	May	 1	2:00	1:00	D
    +Rule	Winn	1950	only	-	Sep	30	2:00	0	S
    +Rule	Winn	1951	1960	-	Apr	lastSun	2:00	1:00	D
    +Rule	Winn	1951	1958	-	Sep	lastSun	2:00	0	S
    +Rule	Winn	1959	only	-	Oct	lastSun	2:00	0	S
    +Rule	Winn	1960	only	-	Sep	lastSun	2:00	0	S
    +Rule	Winn	1963	only	-	Apr	lastSun	2:00	1:00	D
    +Rule	Winn	1963	only	-	Sep	22	2:00	0	S
    +Rule	Winn	1966	1986	-	Apr	lastSun	2:00s	1:00	D
    +Rule	Winn	1966	2005	-	Oct	lastSun	2:00s	0	S
    +Rule	Winn	1987	2005	-	Apr	Sun>=1	2:00s	1:00	D
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Winnipeg	-6:28:36 -	LMT	1887 Jul 16
    +			-6:00	Winn	C%sT	2006
    +			-6:00	Canada	C%sT
    +
    +
    +# Saskatchewan
    +
    +# From Mark Brader (2003-07-26):
    +# The first actual adoption of DST in Canada was at the municipal
    +# level.  As the [Toronto] Star put it (1912-06-07), "While people
    +# elsewhere have long been talking of legislation to save daylight,
    +# the city of Moose Jaw [Saskatchewan] has acted on its own hook."
    +# DST in Moose Jaw began on Saturday, 1912-06-01 (no time mentioned:
    +# presumably late evening, as below), and would run until "the end of
    +# the summer".  The discrepancy between municipal time and railroad
    +# time was noted.
    +
    +# From Paul Eggert (2003-07-27):
    +# Willett (1914-03) notes that DST "has been in operation ... in the
    +# City of Moose Jaw, Saskatchewan, for one year."
    +
    +# From Paul Eggert (2006-03-22):
    +# Shanks & Pottenger say that since 1970 this region has mostly been as Regina.
    +# Some western towns (e.g. Swift Current) switched from MST/MDT to CST in 1972.
    +# Other western towns (e.g. Lloydminster) are like Edmonton.
    +# Matthews and Vincent (1998) write that Denare Beach and Creighton
    +# are like Winnipeg, in violation of Saskatchewan law.
    +
    +# From W. Jones (1992-11-06):
    +# The. . .below is based on information I got from our law library, the
    +# provincial archives, and the provincial Community Services department.
    +# A precise history would require digging through newspaper archives, and
    +# since you didn't say what you wanted, I didn't bother.
    +#
    +# Saskatchewan is split by a time zone meridian (105W) and over the years
    +# the boundary became pretty ragged as communities near it reevaluated
    +# their affiliations in one direction or the other.  In 1965 a provincial
    +# referendum favoured legislating common time practices.
    +#
    +# On 15 April 1966 the Time Act (c. T-14, Revised Statutes of
    +# Saskatchewan 1978) was proclaimed, and established that the eastern
    +# part of Saskatchewan would use CST year round, that districts in
    +# northwest Saskatchewan would by default follow CST but could opt to
    +# follow Mountain Time rules (thus 1 hour difference in the winter and
    +# zero in the summer), and that districts in southwest Saskatchewan would
    +# by default follow MT but could opt to follow CST.
    +#
    +# It took a few years for the dust to settle (I know one story of a town
    +# on one time zone having its school in another, such that a mom had to
    +# serve her family lunch in two shifts), but presently it seems that only
    +# a few towns on the border with Alberta (e.g. Lloydminster) follow MT
    +# rules any more; all other districts appear to have used CST year round
    +# since sometime in the 1960s.
    +
    +# From Chris Walton (2006-06-26):
    +# The Saskatchewan time act which was last updated in 1996 is about 30 pages
    +# long and rather painful to read.
    +# http://www.qp.gov.sk.ca/documents/English/Statutes/Statutes/T14.pdf
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Regina	1918	only	-	Apr	14	2:00	1:00	D
    +Rule	Regina	1918	only	-	Oct	27	2:00	0	S
    +Rule	Regina	1930	1934	-	May	Sun>=1	0:00	1:00	D
    +Rule	Regina	1930	1934	-	Oct	Sun>=1	0:00	0	S
    +Rule	Regina	1937	1941	-	Apr	Sun>=8	0:00	1:00	D
    +Rule	Regina	1937	only	-	Oct	Sun>=8	0:00	0	S
    +Rule	Regina	1938	only	-	Oct	Sun>=1	0:00	0	S
    +Rule	Regina	1939	1941	-	Oct	Sun>=8	0:00	0	S
    +Rule	Regina	1942	only	-	Feb	 9	2:00	1:00	W # War
    +Rule	Regina	1945	only	-	Aug	14	23:00u	1:00	P # Peace
    +Rule	Regina	1945	only	-	Sep	lastSun	2:00	0	S
    +Rule	Regina	1946	only	-	Apr	Sun>=8	2:00	1:00	D
    +Rule	Regina	1946	only	-	Oct	Sun>=8	2:00	0	S
    +Rule	Regina	1947	1957	-	Apr	lastSun	2:00	1:00	D
    +Rule	Regina	1947	1957	-	Sep	lastSun	2:00	0	S
    +Rule	Regina	1959	only	-	Apr	lastSun	2:00	1:00	D
    +Rule	Regina	1959	only	-	Oct	lastSun	2:00	0	S
    +#
    +Rule	Swift	1957	only	-	Apr	lastSun	2:00	1:00	D
    +Rule	Swift	1957	only	-	Oct	lastSun	2:00	0	S
    +Rule	Swift	1959	1961	-	Apr	lastSun	2:00	1:00	D
    +Rule	Swift	1959	only	-	Oct	lastSun	2:00	0	S
    +Rule	Swift	1960	1961	-	Sep	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Regina	-6:58:36 -	LMT	1905 Sep
    +			-7:00	Regina	M%sT	1960 Apr lastSun 2:00
    +			-6:00	-	CST
    +Zone America/Swift_Current -7:11:20 -	LMT	1905 Sep
    +			-7:00	Canada	M%sT	1946 Apr lastSun 2:00
    +			-7:00	Regina	M%sT	1950
    +			-7:00	Swift	M%sT	1972 Apr lastSun 2:00
    +			-6:00	-	CST
    +
    +
    +# Alberta
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Edm	1918	1919	-	Apr	Sun>=8	2:00	1:00	D
    +Rule	Edm	1918	only	-	Oct	27	2:00	0	S
    +Rule	Edm	1919	only	-	May	27	2:00	0	S
    +Rule	Edm	1920	1923	-	Apr	lastSun	2:00	1:00	D
    +Rule	Edm	1920	only	-	Oct	lastSun	2:00	0	S
    +Rule	Edm	1921	1923	-	Sep	lastSun	2:00	0	S
    +Rule	Edm	1942	only	-	Feb	 9	2:00	1:00	W # War
    +Rule	Edm	1945	only	-	Aug	14	23:00u	1:00	P # Peace
    +Rule	Edm	1945	only	-	Sep	lastSun	2:00	0	S
    +Rule	Edm	1947	only	-	Apr	lastSun	2:00	1:00	D
    +Rule	Edm	1947	only	-	Sep	lastSun	2:00	0	S
    +Rule	Edm	1967	only	-	Apr	lastSun	2:00	1:00	D
    +Rule	Edm	1967	only	-	Oct	lastSun	2:00	0	S
    +Rule	Edm	1969	only	-	Apr	lastSun	2:00	1:00	D
    +Rule	Edm	1969	only	-	Oct	lastSun	2:00	0	S
    +Rule	Edm	1972	1986	-	Apr	lastSun	2:00	1:00	D
    +Rule	Edm	1972	2006	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Edmonton	-7:33:52 -	LMT	1906 Sep
    +			-7:00	Edm	M%sT	1987
    +			-7:00	Canada	M%sT
    +
    +
    +# British Columbia
    +
    +# From Paul Eggert (2006-03-22):
    +# Shanks & Pottenger write that since 1970 most of this region has
    +# been like Vancouver.
    +# Dawson Creek uses MST.  Much of east BC is like Edmonton.
    +# Matthews and Vincent (1998) write that Creston is like Dawson Creek.
    +
    +# It seems though that (re: Creston) is not entirely correct:
    +
    +# From Chris Walton (2011-12-01):
    +# There are two areas within the Canadian province of British Columbia
    +# that do not currently observe daylight saving:
    +# a) The Creston Valley (includes the town of Creston and surrounding area)
    +# b) The eastern half of the Peace River Regional District
    +# (includes the cities of Dawson Creek and Fort St. John)
    +
    +# Earlier this year I stumbled across a detailed article about the time
    +# keeping history of Creston; it was written by Tammy Hardwick who is the
    +# manager of the Creston & District Museum. The article was written in May 2009.
    +# 
    +# http://www.ilovecreston.com/?p=articles&t=spec&ar=260
    +# 
    +# According to the article, Creston has not changed its clocks since June 1918.
    +# i.e. Creston has been stuck on UTC-7 for 93 years.
    +# Dawson Creek, on the other hand, changed its clocks as recently as April 1972.
    +
    +# Unfortunately the exact date for the time change in June 1918 remains
    +# unknown and will be difficult to ascertain.  I e-mailed Tammy a few months
    +# ago to ask if Sunday June 2 was a reasonable guess.  She said it was just
    +# as plausible as any other date (in June).  She also said that after writing the
    +# article she had discovered another time change in 1916; this is the subject
    +# of another article which she wrote in October 2010.
    +# 
    +# http://www.creston.museum.bc.ca/index.php?module=comments&uop=view_comment&cm+id=56
    +# 
    +
    +# Here is a summary of the three clock change events in Creston's history:
    +# 1. 1884 or 1885: adoption of Mountain Standard Time (GMT-7)
    +# Exact date unknown
    +# 2. Oct 1916: switch to Pacific Standard Time (GMT-8)
    +# Exact date in October unknown;  Sunday October 1 is a reasonable guess.
    +# 3. June 1918: switch to Pacific Daylight Time (GMT-7)
    +# Exact date in June unknown; Sunday June 2 is a reasonable guess.
    +# note#1:
    +# On Oct 27/1918 when daylight saving ended in the rest of Canada,
    +# Creston did not change its clocks.
    +# note#2:
    +# During WWII when the Federal Government legislated a mandatory clock change,
    +# Creston did not oblige.
    +# note#3:
    +# There is no guarantee that Creston will remain on Mountain Standard Time
    +# (UTC-7) forever.
    +# The subject was debated at least once this year by the town Council.
    +# 
    +# http://www.bclocalnews.com/kootenay_rockies/crestonvalleyadvance/news/116760809.html
    +# 
    +
    +# During a period WWII, summer time (Daylight saying) was mandatory in Canada.
    +# In Creston, that was handled by shifting the area to PST (-8:00) then applying
    +# summer time to cause the offset to be -7:00, the same as it had been before
    +# the change.  It can be argued that the timezone abbreviation during this
    +# period should be PDT rather than MST, but that doesn't seem important enough
    +# (to anyone) to further complicate the rules.
    +
    +# The transition dates (and times) are guesses.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Vanc	1918	only	-	Apr	14	2:00	1:00	D
    +Rule	Vanc	1918	only	-	Oct	27	2:00	0	S
    +Rule	Vanc	1942	only	-	Feb	 9	2:00	1:00	W # War
    +Rule	Vanc	1945	only	-	Aug	14	23:00u	1:00	P # Peace
    +Rule	Vanc	1945	only	-	Sep	30	2:00	0	S
    +Rule	Vanc	1946	1986	-	Apr	lastSun	2:00	1:00	D
    +Rule	Vanc	1946	only	-	Oct	13	2:00	0	S
    +Rule	Vanc	1947	1961	-	Sep	lastSun	2:00	0	S
    +Rule	Vanc	1962	2006	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Vancouver	-8:12:28 -	LMT	1884
    +			-8:00	Vanc	P%sT	1987
    +			-8:00	Canada	P%sT
    +Zone America/Dawson_Creek -8:00:56 -	LMT	1884
    +			-8:00	Canada	P%sT	1947
    +			-8:00	Vanc	P%sT	1972 Aug 30 2:00
    +			-7:00	-	MST
    +Zone America/Creston	-7:46:04 -	LMT	1884
    +			-7:00	-	MST	1916 Oct 1
    +			-8:00	-	PST	1918 Jun 2
    +			-7:00	-	MST
    +
    +# Northwest Territories, Nunavut, Yukon
    +
    +# From Paul Eggert (2006-03-22):
    +# Dawson switched to PST in 1973.  Inuvik switched to MST in 1979.
    +# Mathew Englander (1996-10-07) gives the following refs:
    +#	* 1967. Paragraph 28(34)(g) of the Interpretation Act, S.C. 1967-68,
    +#	c. 7 defines Yukon standard time as UTC-9.  This is still valid;
    +#	see Interpretation Act, R.S.C. 1985, c. I-21, s. 35(1).
    +#	* C.O. 1973/214 switched Yukon to PST on 1973-10-28 00:00.
    +#	* O.I.C. 1980/02 established DST.
    +#	* O.I.C. 1987/056 changed DST to Apr firstSun 2:00 to Oct lastSun 2:00.
    +# Shanks & Pottenger say Yukon's 1973-10-28 switch was at 2:00; go
    +# with Englander.
    +# From Chris Walton (2006-06-26):
    +# Here is a link to the old daylight saving portion of the interpretation
    +# act which was last updated in 1987:
    +# http://www.gov.yk.ca/legislation/regs/oic1987_056.pdf
    +
    +# From Rives McDow (1999-09-04):
    +# Nunavut ... moved ... to incorporate the whole territory into one time zone.
    +# 
    +# Nunavut moves to single time zone Oct. 31
    +# 
    +#
    +# From Antoine Leca (1999-09-06):
    +# We then need to create a new timezone for the Kitikmeot region of Nunavut
    +# to differentiate it from the Yellowknife region.
    +
    +# From Paul Eggert (1999-09-20):
    +# 
    +# Basic Facts: The New Territory
    +#  (1999) reports that Pangnirtung operates on eastern time,
    +# and that Coral Harbour does not observe DST.  We don't know when
    +# Pangnirtung switched to eastern time; we'll guess 1995.
    +
    +# From Rives McDow (1999-11-08):
    +# On October 31, when the rest of Nunavut went to Central time,
    +# Pangnirtung wobbled.  Here is the result of their wobble:
    +#
    +# The following businesses and organizations in Pangnirtung use Central Time:
    +#
    +#	First Air, Power Corp, Nunavut Construction, Health Center, RCMP,
    +#	Eastern Arctic National Parks, A & D Specialist
    +#
    +# The following businesses and organizations in Pangnirtung use Eastern Time:
    +#
    +#	Hamlet office, All other businesses, Both schools, Airport operator
    +#
    +# This has made for an interesting situation there, which warranted the news.
    +# No one there that I spoke with seems concerned, or has plans to
    +# change the local methods of keeping time, as it evidently does not
    +# really interfere with any activities or make things difficult locally.
    +# They plan to celebrate New Year's turn-over twice, one hour apart,
    +# so it appears that the situation will last at least that long.
    +# The Nunavut Intergovernmental Affairs hopes that they will "come to
    +# their senses", but the locals evidently don't see any problem with
    +# the current state of affairs.
    +
    +# From Michaela Rodrigue, writing in the
    +# 
    +# Nunatsiaq News (1999-11-19):
    +# Clyde River, Pangnirtung and Sanikiluaq now operate with two time zones,
    +# central - or Nunavut time - for government offices, and eastern time
    +# for municipal offices and schools....  Igloolik [was similar but then]
    +# made the switch to central time on Saturday, Nov. 6.
    +
    +# From Paul Eggert (2000-10-02):
    +# Matthews and Vincent (1998) say the following, but we lack histories
    +# for these potential new Zones.
    +#
    +# The Canadian Forces station at Alert uses Eastern Time while the
    +# handful of residents at the Eureka weather station [in the Central
    +# zone] skip daylight savings.  Baffin Island, which is crossed by the
    +# Central, Eastern and Atlantic Time zones only uses Eastern Time.
    +# Gjoa Haven, Taloyoak and Pelly Bay all use Mountain instead of
    +# Central Time and Southampton Island [in the Central zone] is not
    +# required to use daylight savings.
    +
    +# From
    +# 
    +# Nunavut now has two time zones
    +#  (2000-11-10):
    +# The Nunavut government would allow its employees in Kugluktuk and
    +# Cambridge Bay to operate on central time year-round, putting them
    +# one hour behind the rest of Nunavut for six months during the winter.
    +# At the end of October the two communities had rebelled against
    +# Nunavut's unified time zone, refusing to shift to eastern time with
    +# the rest of the territory for the winter.  Cambridge Bay remained on
    +# central time, while Kugluktuk, even farther west, reverted to
    +# mountain time, which they had used before the advent of Nunavut's
    +# unified time zone in 1999.
    +#
    +# From Rives McDow (2001-01-20), quoting the Nunavut government:
    +# The preceding decision came into effect at midnight, Saturday Nov 4, 2000.
    +
    +# From Paul Eggert (2000-12-04):
    +# Let's just keep track of the official times for now.
    +
    +# From Rives McDow (2001-03-07):
    +# The premier of Nunavut has issued a ministerial statement advising
    +# that effective 2001-04-01, the territory of Nunavut will revert
    +# back to three time zones (mountain, central, and eastern).  Of the
    +# cities in Nunavut, Coral Harbor is the only one that I know of that
    +# has said it will not observe dst, staying on EST year round.  I'm
    +# checking for more info, and will get back to you if I come up with
    +# more.
    +# [Also see  (2001-03-09).]
    +
    +# From Gwillim Law (2005-05-21):
    +# According to maps at
    +# http://inms-ienm.nrc-cnrc.gc.ca/images/time_services/TZ01SWE.jpg
    +# http://inms-ienm.nrc-cnrc.gc.ca/images/time_services/TZ01SSE.jpg
    +# (both dated 2003), and
    +# http://www.canadiangeographic.ca/Magazine/SO98/geomap.asp
    +# (from a 1998 Canadian Geographic article), the de facto and de jure time
    +# for Southampton Island (at the north end of Hudson Bay) is UTC-5 all year
    +# round.  Using Google, it's easy to find other websites that confirm this.
    +# I wasn't able to find how far back this time regimen goes, but since it
    +# predates the creation of Nunavut, it probably goes back many years....
    +# The Inuktitut name of Coral Harbour is Sallit, but it's rarely used.
    +#
    +# From Paul Eggert (2005-07-26):
    +# For lack of better information, assume that Southampton Island observed
    +# daylight saving only during wartime.
    +
    +# From Chris Walton (2007-03-01):
    +# ... the community of Resolute (located on Cornwallis Island in
    +# Nunavut) moved from Central Time to Eastern Time last November.
    +# Basically the community did not change its clocks at the end of
    +# daylight saving....
    +# http://www.nnsl.com/frames/newspapers/2006-11/nov13_06none.html
    +
    +# From Chris Walton (2011-03-21):
    +# Back in 2007 I initiated the creation of a new "zone file" for Resolute
    +# Bay. Resolute Bay is a small community located about 900km north of
    +# the Arctic Circle. The zone file was required because Resolute Bay had
    +# decided to use UTC-5 instead of UTC-6 for the winter of 2006-2007.
    +#
    +# According to new information which I received last week, Resolute Bay
    +# went back to using UTC-6 in the winter of 2007-2008...
    +#
    +# On March 11/2007 most of Canada went onto daylight saving. On March
    +# 14/2007 I phoned the Resolute Bay hamlet office to do a "time check." I
    +# talked to somebody that was both knowledgeable and helpful. I was able
    +# to confirm that Resolute Bay was still operating on UTC-5. It was
    +# explained to me that Resolute Bay had been on the Eastern Time zone
    +# (EST) in the winter, and was now back on the Central Time zone (CDT).
    +# i.e. the time zone had changed twice in the last year but the clocks
    +# had not moved. The residents had to know which time zone they were in
    +# so they could follow the correct TV schedule...
    +#
    +# On Nov 02/2008 most of Canada went onto standard time. On Nov 03/2008 I
    +# phoned the Resolute Bay hamlet office...[D]ue to the challenging nature
    +# of the phone call, I decided to seek out an alternate source of
    +# information. I found an e-mail address for somebody by the name of
    +# Stephanie Adams whose job was listed as "Inns North Support Officer for
    +# Arctic Co-operatives." I was under the impression that Stephanie lived
    +# and worked in Resolute Bay...
    +#
    +# On March 14/2011 I phoned the hamlet office again. I was told that
    +# Resolute Bay had been using Central Standard Time over the winter of
    +# 2010-2011 and that the clocks had therefore been moved one hour ahead
    +# on March 13/2011. The person I talked to was aware that Resolute Bay
    +# had previously experimented with Eastern Standard Time but he could not
    +# tell me when the practice had stopped.
    +#
    +# On March 17/2011 I searched the Web to find an e-mail address of
    +# somebody that might be able to tell me exactly when Resolute Bay went
    +# off Eastern Standard Time. I stumbled on the name "Aziz Kheraj." Aziz
    +# used to be the mayor of Resolute Bay and he apparently owns half the
    +# businesses including "South Camp Inn." This website has some info on
    +# Aziz:
    +# 
    +# http://www.uphere.ca/node/493
    +# 
    +#
    +# I sent Aziz an e-mail asking when Resolute Bay had stopped using
    +# Eastern Standard Time.
    +#
    +# Aziz responded quickly with this: "hi, The time was not changed for the
    +# 1 year only, the following year, the community went back to the old way
    +# of "spring ahead-fall behind" currently we are zulu plus 5 hrs and in
    +# the winter Zulu plus 6 hrs"
    +#
    +# This of course conflicted with everything I had ascertained in November 2008.
    +#
    +# I sent Aziz a copy of my 2008 e-mail exchange with Stephanie. Aziz
    +# responded with this: "Hi, Stephanie lives in Winnipeg. I live here, You
    +# may want to check with the weather office in Resolute Bay or do a
    +# search on the weather through Env. Canada. web site"
    +#
    +# If I had realized the Stephanie did not live in Resolute Bay I would
    +# never have contacted her.  I now believe that all the information I
    +# obtained in November 2008 should be ignored...
    +# I apologize for reporting incorrect information in 2008.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	NT_YK	1918	only	-	Apr	14	2:00	1:00	D
    +Rule	NT_YK	1918	only	-	Oct	27	2:00	0	S
    +Rule	NT_YK	1919	only	-	May	25	2:00	1:00	D
    +Rule	NT_YK	1919	only	-	Nov	 1	0:00	0	S
    +Rule	NT_YK	1942	only	-	Feb	 9	2:00	1:00	W # War
    +Rule	NT_YK	1945	only	-	Aug	14	23:00u	1:00	P # Peace
    +Rule	NT_YK	1945	only	-	Sep	30	2:00	0	S
    +Rule	NT_YK	1965	only	-	Apr	lastSun	0:00	2:00	DD
    +Rule	NT_YK	1965	only	-	Oct	lastSun	2:00	0	S
    +Rule	NT_YK	1980	1986	-	Apr	lastSun	2:00	1:00	D
    +Rule	NT_YK	1980	2006	-	Oct	lastSun	2:00	0	S
    +Rule	NT_YK	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +# aka Panniqtuuq
    +Zone America/Pangnirtung 0	-	zzz	1921 # trading post est.
    +			-4:00	NT_YK	A%sT	1995 Apr Sun>=1 2:00
    +			-5:00	Canada	E%sT	1999 Oct 31 2:00
    +			-6:00	Canada	C%sT	2000 Oct 29 2:00
    +			-5:00	Canada	E%sT
    +# formerly Frobisher Bay
    +Zone America/Iqaluit	0	-	zzz	1942 Aug # Frobisher Bay est.
    +			-5:00	NT_YK	E%sT	1999 Oct 31 2:00
    +			-6:00	Canada	C%sT	2000 Oct 29 2:00
    +			-5:00	Canada	E%sT
    +# aka Qausuittuq
    +Zone America/Resolute	0	-	zzz	1947 Aug 31 # Resolute founded
    +			-6:00	NT_YK	C%sT	2000 Oct 29 2:00
    +			-5:00	-	EST	2001 Apr  1 3:00
    +			-6:00	Canada	C%sT	2006 Oct 29 2:00
    +			-5:00	-	EST	2007 Mar 11 3:00
    +			-6:00	Canada	C%sT
    +# aka Kangiqiniq
    +Zone America/Rankin_Inlet 0	-	zzz	1957 # Rankin Inlet founded
    +			-6:00	NT_YK	C%sT	2000 Oct 29 2:00
    +			-5:00	-	EST	2001 Apr  1 3:00
    +			-6:00	Canada	C%sT
    +# aka Iqaluktuuttiaq
    +Zone America/Cambridge_Bay 0	-	zzz	1920 # trading post est.?
    +			-7:00	NT_YK	M%sT	1999 Oct 31 2:00
    +			-6:00	Canada	C%sT	2000 Oct 29 2:00
    +			-5:00	-	EST	2000 Nov  5 0:00
    +			-6:00	-	CST	2001 Apr  1 3:00
    +			-7:00	Canada	M%sT
    +Zone America/Yellowknife 0	-	zzz	1935 # Yellowknife founded?
    +			-7:00	NT_YK	M%sT	1980
    +			-7:00	Canada	M%sT
    +Zone America/Inuvik	0	-	zzz	1953 # Inuvik founded
    +			-8:00	NT_YK	P%sT	1979 Apr lastSun 2:00
    +			-7:00	NT_YK	M%sT	1980
    +			-7:00	Canada	M%sT
    +Zone America/Whitehorse	-9:00:12 -	LMT	1900 Aug 20
    +			-9:00	NT_YK	Y%sT	1966 Jul 1 2:00
    +			-8:00	NT_YK	P%sT	1980
    +			-8:00	Canada	P%sT
    +Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
    +			-9:00	NT_YK	Y%sT	1973 Oct 28 0:00
    +			-8:00	NT_YK	P%sT	1980
    +			-8:00	Canada	P%sT
    +
    +
    +###############################################################################
    +
    +# Mexico
    +
    +# From Paul Eggert (2001-03-05):
    +# The Investigation and Analysis Service of the
    +# Mexican Library of Congress (MLoC) has published a
    +# 
    +# history of Mexican local time (in Spanish)
    +# .
    +#
    +# Here are the discrepancies between Shanks & Pottenger (S&P) and the MLoC.
    +# (In all cases we go with the MLoC.)
    +# S&P report that Baja was at -8:00 in 1922/1923.
    +# S&P say the 1930 transition in Baja was 1930-11-16.
    +# S&P report no DST during summer 1931.
    +# S&P report a transition at 1932-03-30 23:00, not 1932-04-01.
    +
    +# From Gwillim Law (2001-02-20):
    +# There are some other discrepancies between the Decrees page and the
    +# tz database.  I think they can best be explained by supposing that
    +# the researchers who prepared the Decrees page failed to find some of
    +# the relevant documents.
    +
    +# From Alan Perry (1996-02-15):
    +# A guy from our Mexico subsidiary finally found the Presidential Decree
    +# outlining the timezone changes in Mexico.
    +#
    +# ------------- Begin Forwarded Message -------------
    +#
    +# I finally got my hands on the Official Presidential Decree that sets up the
    +# rules for the DST changes. The rules are:
    +#
    +# 1. The country is divided in 3 timezones:
    +#    - Baja California Norte (the Mexico/BajaNorte TZ)
    +#    - Baja California Sur, Nayarit, Sinaloa and Sonora (the Mexico/BajaSur TZ)
    +#    - The rest of the country (the Mexico/General TZ)
    +#
    +# 2. From the first Sunday in April at 2:00 AM to the last Sunday in October
    +#    at 2:00 AM, the times in each zone are as follows:
    +#    BajaNorte: GMT+7
    +#    BajaSur:   GMT+6
    +#    General:   GMT+5
    +#
    +# 3. The rest of the year, the times are as follows:
    +#    BajaNorte: GMT+8
    +#    BajaSur:   GMT+7
    +#    General:   GMT+6
    +#
    +# The Decree was published in Mexico's Official Newspaper on January 4th.
    +#
    +# -------------- End Forwarded Message --------------
    +# From Paul Eggert (1996-06-12):
    +# For an English translation of the decree, see
    +# 
    +# ``Diario Oficial: Time Zone Changeover'' (1996-01-04).
    +# 
    +
    +# From Rives McDow (1998-10-08):
    +# The State of Quintana Roo has reverted back to central STD and DST times
    +# (i.e. UTC -0600 and -0500 as of 1998-08-02).
    +
    +# From Rives McDow (2000-01-10):
    +# Effective April 4, 1999 at 2:00 AM local time, Sonora changed to the time
    +# zone 5 hours from the International Date Line, and will not observe daylight
    +# savings time so as to stay on the same time zone as the southern part of
    +# Arizona year round.
    +
    +# From Jesper Norgaard, translating
    +#  (2001-01-17):
    +# In Oaxaca, the 55.000 teachers from the Section 22 of the National
    +# Syndicate of Education Workers, refuse to apply daylight saving each
    +# year, so that the more than 10,000 schools work at normal hour the
    +# whole year.
    +
    +# From Gwillim Law (2001-01-19):
    +#  ... says
    +# (translated):...
    +# January 17, 2000 - The Energy Secretary, Ernesto Martens, announced
    +# that Summer Time will be reduced from seven to five months, starting
    +# this year....
    +# 
    +# [translated], says "summer time will ... take effect on the first Sunday
    +# in May, and end on the last Sunday of September.
    +
    +# From Arthur David Olson (2001-01-25):
    +# The 2001-01-24 traditional Washington Post contained the page one
    +# story "Timely Issue Divides Mexicans."...
    +# http://www.washingtonpost.com/wp-dyn/articles/A37383-2001Jan23.html
    +# ... Mexico City Mayor Lopez Obrador "...is threatening to keep
    +# Mexico City and its 20 million residents on a different time than
    +# the rest of the country..." In particular, Lopez Obrador would abolish
    +# observation of Daylight Saving Time.
    +
    +# 
    +# Official statute published by the Energy Department
    +#  (2001-02-01) shows Baja and Chihauhua as still using US DST rules,
    +# and Sonora with no DST.  This was reported by Jesper Norgaard (2001-02-03).
    +
    +# From Paul Eggert (2001-03-03):
    +#
    +# 
    +# James F. Smith writes in today's LA Times
    +# 
    +# * Sonora will continue to observe standard time.
    +# * Last week Mexico City's mayor Andres Manuel Lopez Obrador decreed that
    +#   the Federal District will not adopt DST.
    +# * 4 of 16 district leaders announced they'll ignore the decree.
    +# * The decree does not affect federal-controlled facilities including
    +#   the airport, banks, hospitals, and schools.
    +#
    +# For now we'll assume that the Federal District will bow to federal rules.
    +
    +# From Jesper Norgaard (2001-04-01):
    +# I found some references to the Mexican application of daylight
    +# saving, which modifies what I had already sent you, stating earlier
    +# that a number of northern Mexican states would go on daylight
    +# saving. The modification reverts this to only cover Baja California
    +# (Norte), while all other states (except Sonora, who has no daylight
    +# saving all year) will follow the original decree of president
    +# Vicente Fox, starting daylight saving May 6, 2001 and ending
    +# September 30, 2001.
    +# References: "Diario de Monterrey" 
    +# Palabra  (2001-03-31)
    +
    +# From Reuters (2001-09-04):
    +# Mexico's Supreme Court on Tuesday declared that daylight savings was
    +# unconstitutional in Mexico City, creating the possibility the
    +# capital will be in a different time zone from the rest of the nation
    +# next year....  The Supreme Court's ruling takes effect at 2:00
    +# a.m. (0800 GMT) on Sept. 30, when Mexico is scheduled to revert to
    +# standard time. "This is so residents of the Federal District are not
    +# subject to unexpected time changes," a statement from the court said.
    +
    +# From Jesper Norgaard Welen (2002-03-12):
    +# ... consulting my local grocery store(!) and my coworkers, they all insisted
    +# that a new decision had been made to reinstate US style DST in Mexico....
    +# http://www.conae.gob.mx/ahorro/horaver2001_m1_2002.html (2002-02-20)
    +# confirms this.  Sonora as usual is the only state where DST is not applied.
    +
    +# From Steffen Thorsen (2009-12-28):
    +#
    +# Steffen Thorsen wrote:
    +# > Mexico's House of Representatives has approved a proposal for northern
    +# > Mexico's border cities to share the same daylight saving schedule as
    +# > the United States.
    +# Now this has passed both the Congress and the Senate, so starting from
    +# 2010, some border regions will be the same:
    +# 
    +# http://www.signonsandiego.com/news/2009/dec/28/clocks-will-match-both-sides-border/
    +# 
    +# 
    +# http://www.elmananarey.com/diario/noticia/nacional/noticias/empatan_horario_de_frontera_con_eu/621939
    +# 
    +# (Spanish)
    +#
    +# Could not find the new law text, but the proposed law text changes are here:
    +# 
    +# http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/20091210-V.pdf
    +# 
    +# (Gaceta Parlamentaria)
    +#
    +# There is also a list of the votes here:
    +# 
    +# http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/V2-101209.html
    +# 
    +#
    +# Our page:
    +# 
    +# http://www.timeanddate.com/news/time/north-mexico-dst-change.html
    +# 
    +
    +# From Arthur David Olson (2010-01-20):
    +# The page
    +# 
    +# http://dof.gob.mx/nota_detalle.php?codigo=5127480&fecha=06/01/2010
    +# 
    +# includes this text:
    +# En los municipios fronterizos de Tijuana y Mexicali en Baja California;
    +# Juárez y Ojinaga en Chihuahua; Acuña y Piedras Negras en Coahuila;
    +# Anáhuac en Nuevo León; y Nuevo Laredo, Reynosa y Matamoros en
    +# Tamaulipas, la aplicación de este horario estacional surtirá efecto
    +# desde las dos horas del segundo domingo de marzo y concluirá a las dos
    +# horas del primer domingo de noviembre.
    +# En los municipios fronterizos que se encuentren ubicados en la franja
    +# fronteriza norte en el territorio comprendido entre la línea
    +# internacional y la línea paralela ubicada a una distancia de veinte
    +# kilómetros, así como la Ciudad de Ensenada, Baja California, hacia el
    +# interior del país, la aplicación de este horario estacional surtirá
    +# efecto desde las dos horas del segundo domingo de marzo y concluirá a
    +# las dos horas del primer domingo de noviembre.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Mexico	1939	only	-	Feb	5	0:00	1:00	D
    +Rule	Mexico	1939	only	-	Jun	25	0:00	0	S
    +Rule	Mexico	1940	only	-	Dec	9	0:00	1:00	D
    +Rule	Mexico	1941	only	-	Apr	1	0:00	0	S
    +Rule	Mexico	1943	only	-	Dec	16	0:00	1:00	W # War
    +Rule	Mexico	1944	only	-	May	1	0:00	0	S
    +Rule	Mexico	1950	only	-	Feb	12	0:00	1:00	D
    +Rule	Mexico	1950	only	-	Jul	30	0:00	0	S
    +Rule	Mexico	1996	2000	-	Apr	Sun>=1	2:00	1:00	D
    +Rule	Mexico	1996	2000	-	Oct	lastSun	2:00	0	S
    +Rule	Mexico	2001	only	-	May	Sun>=1	2:00	1:00	D
    +Rule	Mexico	2001	only	-	Sep	lastSun	2:00	0	S
    +Rule	Mexico	2002	max	-	Apr	Sun>=1	2:00	1:00	D
    +Rule	Mexico	2002	max	-	Oct	lastSun	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +# Quintana Roo
    +Zone America/Cancun	-5:47:04 -	LMT	1922 Jan  1  0:12:56
    +			-6:00	-	CST	1981 Dec 23
    +			-5:00	Mexico	E%sT	1998 Aug  2  2:00
    +			-6:00	Mexico	C%sT
    +# Campeche, Yucatan
    +Zone America/Merida	-5:58:28 -	LMT	1922 Jan  1  0:01:32
    +			-6:00	-	CST	1981 Dec 23
    +			-5:00	-	EST	1982 Dec  2
    +			-6:00	Mexico	C%sT
    +# Coahuila, Durango, Nuevo Leon, Tamaulipas (near US border)
    +Zone America/Matamoros	-6:40:00 -	LMT	1921 Dec 31 23:20:00
    +			-6:00	-	CST	1988
    +			-6:00	US	C%sT	1989
    +			-6:00	Mexico	C%sT	2010
    +			-6:00	US	C%sT
    +# Coahuila, Durango, Nuevo Leon, Tamaulipas (away from US border)
    +Zone America/Monterrey	-6:41:16 -	LMT	1921 Dec 31 23:18:44
    +			-6:00	-	CST	1988
    +			-6:00	US	C%sT	1989
    +			-6:00	Mexico	C%sT
    +# Central Mexico
    +Zone America/Mexico_City -6:36:36 -	LMT	1922 Jan  1 0:23:24
    +			-7:00	-	MST	1927 Jun 10 23:00
    +			-6:00	-	CST	1930 Nov 15
    +			-7:00	-	MST	1931 May  1 23:00
    +			-6:00	-	CST	1931 Oct
    +			-7:00	-	MST	1932 Apr  1
    +			-6:00	Mexico	C%sT	2001 Sep 30 02:00
    +			-6:00	-	CST	2002 Feb 20
    +			-6:00	Mexico	C%sT
    +# Chihuahua (near US border)
    +Zone America/Ojinaga	-6:57:40 -	LMT	1922 Jan 1 0:02:20
    +			-7:00	-	MST	1927 Jun 10 23:00
    +			-6:00	-	CST	1930 Nov 15
    +			-7:00	-	MST	1931 May  1 23:00
    +			-6:00	-	CST	1931 Oct
    +			-7:00	-	MST	1932 Apr  1
    +			-6:00	-	CST	1996
    +			-6:00	Mexico	C%sT	1998
    +			-6:00	-	CST	1998 Apr Sun>=1 3:00
    +			-7:00	Mexico	M%sT	2010
    +			-7:00	US	M%sT
    +# Chihuahua (away from US border)
    +Zone America/Chihuahua	-7:04:20 -	LMT	1921 Dec 31 23:55:40
    +			-7:00	-	MST	1927 Jun 10 23:00
    +			-6:00	-	CST	1930 Nov 15
    +			-7:00	-	MST	1931 May  1 23:00
    +			-6:00	-	CST	1931 Oct
    +			-7:00	-	MST	1932 Apr  1
    +			-6:00	-	CST	1996
    +			-6:00	Mexico	C%sT	1998
    +			-6:00	-	CST	1998 Apr Sun>=1 3:00
    +			-7:00	Mexico	M%sT
    +# Sonora
    +Zone America/Hermosillo	-7:23:52 -	LMT	1921 Dec 31 23:36:08
    +			-7:00	-	MST	1927 Jun 10 23:00
    +			-6:00	-	CST	1930 Nov 15
    +			-7:00	-	MST	1931 May  1 23:00
    +			-6:00	-	CST	1931 Oct
    +			-7:00	-	MST	1932 Apr  1
    +			-6:00	-	CST	1942 Apr 24
    +			-7:00	-	MST	1949 Jan 14
    +			-8:00	-	PST	1970
    +			-7:00	Mexico	M%sT	1999
    +			-7:00	-	MST
    +
    +# From Alexander Krivenyshev (2010-04-21):
    +# According to news, Bahía de Banderas (Mexican state of Nayarit)
    +# changed time zone UTC-7 to new time zone UTC-6 on April 4, 2010 (to
    +# share the same time zone as nearby city Puerto Vallarta, Jalisco).
    +#
    +# (Spanish)
    +# Bahía de Banderas homologa su horario al del centro del
    +# país, a partir de este domingo
    +# 
    +# http://www.nayarit.gob.mx/notes.asp?id=20748
    +# 
    +#
    +# Bahía de Banderas homologa su horario con el del Centro del
    +# País
    +# 
    +# http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50"
    +# 
    +#
    +# (English)
    +# Puerto Vallarta and Bahía de Banderas: One Time Zone
    +# 
    +# http://virtualvallarta.com/puertovallarta/puertovallarta/localnews/2009-12-03-Puerto-Vallarta-and-Bahia-de-Banderas-One-Time-Zone.shtml
    +# 
    +#
    +# or
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_mexico08.html
    +# 
    +#
    +# "Mexico's Senate approved the amendments to the Mexican Schedule System that
    +# will allow Bahía de Banderas and Puerto Vallarta to share the same time
    +# zone ..."
    +# Baja California Sur, Nayarit, Sinaloa
    +
    +# From Arthur David Olson (2010-05-01):
    +# Use "Bahia_Banderas" to keep the name to fourteen characters.
    +
    +Zone America/Mazatlan	-7:05:40 -	LMT	1921 Dec 31 23:54:20
    +			-7:00	-	MST	1927 Jun 10 23:00
    +			-6:00	-	CST	1930 Nov 15
    +			-7:00	-	MST	1931 May  1 23:00
    +			-6:00	-	CST	1931 Oct
    +			-7:00	-	MST	1932 Apr  1
    +			-6:00	-	CST	1942 Apr 24
    +			-7:00	-	MST	1949 Jan 14
    +			-8:00	-	PST	1970
    +			-7:00	Mexico	M%sT
    +
    +Zone America/Bahia_Banderas	-7:01:00 -	LMT	1921 Dec 31 23:59:00
    +			-7:00	-	MST	1927 Jun 10 23:00
    +			-6:00	-	CST	1930 Nov 15
    +			-7:00	-	MST	1931 May  1 23:00
    +			-6:00	-	CST	1931 Oct
    +			-7:00	-	MST	1932 Apr  1
    +			-6:00	-	CST	1942 Apr 24
    +			-7:00	-	MST	1949 Jan 14
    +			-8:00	-	PST	1970
    +			-7:00	Mexico	M%sT	2010 Apr 4 2:00
    +			-6:00	Mexico	C%sT
    +
    +# Baja California (near US border)
    +Zone America/Tijuana	-7:48:04 -	LMT	1922 Jan  1  0:11:56
    +			-7:00	-	MST	1924
    +			-8:00	-	PST	1927 Jun 10 23:00
    +			-7:00	-	MST	1930 Nov 15
    +			-8:00	-	PST	1931 Apr  1
    +			-8:00	1:00	PDT	1931 Sep 30
    +			-8:00	-	PST	1942 Apr 24
    +			-8:00	1:00	PWT	1945 Aug 14 23:00u
    +			-8:00	1:00	PPT	1945 Nov 12 # Peace
    +			-8:00	-	PST	1948 Apr  5
    +			-8:00	1:00	PDT	1949 Jan 14
    +			-8:00	-	PST	1954
    +			-8:00	CA	P%sT	1961
    +			-8:00	-	PST	1976
    +			-8:00	US	P%sT	1996
    +			-8:00	Mexico	P%sT	2001
    +			-8:00	US	P%sT	2002 Feb 20
    +			-8:00	Mexico	P%sT	2010
    +			-8:00	US	P%sT
    +# Baja California (away from US border)
    +Zone America/Santa_Isabel	-7:39:28 -	LMT	1922 Jan  1  0:20:32
    +			-7:00	-	MST	1924
    +			-8:00	-	PST	1927 Jun 10 23:00
    +			-7:00	-	MST	1930 Nov 15
    +			-8:00	-	PST	1931 Apr  1
    +			-8:00	1:00	PDT	1931 Sep 30
    +			-8:00	-	PST	1942 Apr 24
    +			-8:00	1:00	PWT	1945 Aug 14 23:00u
    +			-8:00	1:00	PPT	1945 Nov 12 # Peace
    +			-8:00	-	PST	1948 Apr  5
    +			-8:00	1:00	PDT	1949 Jan 14
    +			-8:00	-	PST	1954
    +			-8:00	CA	P%sT	1961
    +			-8:00	-	PST	1976
    +			-8:00	US	P%sT	1996
    +			-8:00	Mexico	P%sT	2001
    +			-8:00	US	P%sT	2002 Feb 20
    +			-8:00	Mexico	P%sT
    +# From Paul Eggert (2006-03-22):
    +# Formerly there was an America/Ensenada zone, which differed from
    +# America/Tijuana only in that it did not observe DST from 1976
    +# through 1995.  This was as per Shanks (1999).  But Shanks & Pottenger say
    +# Ensenada did not observe DST from 1948 through 1975.  Guy Harris reports
    +# that the 1987 OAG says "Only Ensenada, Mexicale, San Felipe and
    +# Tijuana observe DST," which agrees with Shanks & Pottenger but implies that
    +# DST-observance was a town-by-town matter back then.  This concerns
    +# data after 1970 so most likely there should be at least one Zone
    +# other than America/Tijuana for Baja, but it's not clear yet what its
    +# name or contents should be.
    +#
    +# Revillagigedo Is
    +# no information
    +
    +###############################################################################
    +
    +# Anguilla
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Anguilla	-4:12:16 -	LMT	1912 Mar 2
    +			-4:00	-	AST
    +
    +# Antigua and Barbuda
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Antigua	-4:07:12 -	LMT	1912 Mar 2
    +			-5:00	-	EST	1951
    +			-4:00	-	AST
    +
    +# Bahamas
    +#
    +# From Sue Williams (2006-12-07):
    +# The Bahamas announced about a month ago that they plan to change their DST
    +# rules to sync with the U.S. starting in 2007....
    +# http://www.jonesbahamas.com/?c=45&a=10412
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Bahamas	1964	1975	-	Oct	lastSun	2:00	0	S
    +Rule	Bahamas	1964	1975	-	Apr	lastSun	2:00	1:00	D
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Nassau	-5:09:24 -	LMT	1912 Mar 2
    +			-5:00	Bahamas	E%sT	1976
    +			-5:00	US	E%sT
    +
    +# Barbados
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Barb	1977	only	-	Jun	12	2:00	1:00	D
    +Rule	Barb	1977	1978	-	Oct	Sun>=1	2:00	0	S
    +Rule	Barb	1978	1980	-	Apr	Sun>=15	2:00	1:00	D
    +Rule	Barb	1979	only	-	Sep	30	2:00	0	S
    +Rule	Barb	1980	only	-	Sep	25	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Barbados	-3:58:28 -	LMT	1924		# Bridgetown
    +			-3:58:28 -	BMT	1932	  # Bridgetown Mean Time
    +			-4:00	Barb	A%sT
    +
    +# Belize
    +# Whitman entirely disagrees with Shanks; go with Shanks & Pottenger.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Belize	1918	1942	-	Oct	Sun>=2	0:00	0:30	HD
    +Rule	Belize	1919	1943	-	Feb	Sun>=9	0:00	0	S
    +Rule	Belize	1973	only	-	Dec	 5	0:00	1:00	D
    +Rule	Belize	1974	only	-	Feb	 9	0:00	0	S
    +Rule	Belize	1982	only	-	Dec	18	0:00	1:00	D
    +Rule	Belize	1983	only	-	Feb	12	0:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Belize	-5:52:48 -	LMT	1912 Apr
    +			-6:00	Belize	C%sT
    +
    +# Bermuda
    +
    +# From Dan Jones, reporting in The Royal Gazette (2006-06-26):
    +
    +# Next year, however, clocks in the US will go forward on the second Sunday
    +# in March, until the first Sunday in November.  And, after the Time Zone
    +# (Seasonal Variation) Bill 2006 was passed in the House of Assembly on
    +# Friday, the same thing will happen in Bermuda.
    +# http://www.theroyalgazette.com/apps/pbcs.dll/article?AID=/20060529/NEWS/105290135
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Atlantic/Bermuda	-4:19:04 -	LMT	1930 Jan  1 2:00    # Hamilton
    +			-4:00	-	AST	1974 Apr 28 2:00
    +			-4:00	Bahamas	A%sT	1976
    +			-4:00	US	A%sT
    +
    +# Cayman Is
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Cayman	-5:25:32 -	LMT	1890		# Georgetown
    +			-5:07:12 -	KMT	1912 Feb    # Kingston Mean Time
    +			-5:00	-	EST
    +
    +# Costa Rica
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	CR	1979	1980	-	Feb	lastSun	0:00	1:00	D
    +Rule	CR	1979	1980	-	Jun	Sun>=1	0:00	0	S
    +Rule	CR	1991	1992	-	Jan	Sat>=15	0:00	1:00	D
    +# IATA SSIM (1991-09) says the following was at 1:00;
    +# go with Shanks & Pottenger.
    +Rule	CR	1991	only	-	Jul	 1	0:00	0	S
    +Rule	CR	1992	only	-	Mar	15	0:00	0	S
    +# There are too many San Joses elsewhere, so we'll use `Costa Rica'.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Costa_Rica	-5:36:20 -	LMT	1890		# San Jose
    +			-5:36:20 -	SJMT	1921 Jan 15 # San Jose Mean Time
    +			-6:00	CR	C%sT
    +# Coco
    +# no information; probably like America/Costa_Rica
    +
    +# Cuba
    +
    +# From Arthur David Olson (1999-03-29):
    +# The 1999-03-28 exhibition baseball game held in Havana, Cuba, between
    +# the Cuban National Team and the Baltimore Orioles was carried live on
    +# the Orioles Radio Network, including affiliate WTOP in Washington, DC.
    +# During the game, play-by-play announcer Jim Hunter noted that
    +# "We'll be losing two hours of sleep...Cuba switched to Daylight Saving
    +# Time today."  (The "two hour" remark referred to losing one hour of
    +# sleep on 1999-03-28--when the announcers were in Cuba as it switched
    +# to DST--and one more hour on 1999-04-04--when the announcers will have
    +# returned to Baltimore, which switches on that date.)
    +
    +# From Evert van der Veer via Steffen Thorsen (2004-10-28):
    +# Cuba is not going back to standard time this year.
    +# From Paul Eggert (2006-03-22):
    +# http://www.granma.cu/ingles/2004/septiembre/juev30/41medid-i.html
    +# says that it's due to a problem at the Antonio Guiteras
    +# thermoelectric plant, and says "This October there will be no return
    +# to normal hours (after daylight saving time)".
    +# For now, let's assume that it's a temporary measure.
    +
    +# From Carlos A. Carnero Delgado (2005-11-12):
    +# This year (just like in 2004-2005) there's no change in time zone
    +# adjustment in Cuba.  We will stay in daylight saving time:
    +# http://www.granma.cu/espanol/2005/noviembre/mier9/horario.html
    +
    +# From Jesper Norgaard Welen (2006-10-21):
    +# An article in GRANMA INTERNACIONAL claims that Cuba will end
    +# the 3 years of permanent DST next weekend, see
    +# http://www.granma.cu/ingles/2006/octubre/lun16/43horario.html
    +# "On Saturday night, October 28 going into Sunday, October 29, at 01:00,
    +# watches should be set back one hour -- going back to 00:00 hours -- returning
    +# to the normal schedule....
    +
    +# From Paul Eggert (2007-03-02):
    +# http://www.granma.cubaweb.cu/english/news/art89.html, dated yesterday,
    +# says Cuban clocks will advance at midnight on March 10.
    +# For lack of better information, assume Cuba will use US rules,
    +# except that it switches at midnight standard time as usual.
    +#
    +# From Steffen Thorsen (2007-10-25):
    +# Carlos Alberto Fonseca Arauz informed me that Cuba will end DST one week
    +# earlier - on the last Sunday of October, just like in 2006.
    +#
    +# He supplied these references:
    +#
    +# http://www.prensalatina.com.mx/article.asp?ID=%7B4CC32C1B-A9F7-42FB-8A07-8631AFC923AF%7D&language=ES
    +# http://actualidad.terra.es/sociedad/articulo/cuba_llama_ahorrar_energia_cambio_1957044.htm
    +#
    +# From Alex Kryvenishev (2007-10-25):
    +# Here is also article from Granma (Cuba):
    +#
    +# [Regira] el Horario Normal desde el [proximo] domingo 28 de octubre
    +# http://www.granma.cubaweb.cu/2007/10/24/nacional/artic07.html
    +#
    +# http://www.worldtimezone.com/dst_news/dst_news_cuba03.html
    +
    +# From Arthur David Olson (2008-03-09):
    +# I'm in Maryland which is now observing United States Eastern Daylight
    +# Time. At 9:44 local time I used RealPlayer to listen to
    +# 
    +# http://media.enet.cu/radioreloj
    +# , a Cuban information station, and heard
    +# the time announced as "ocho cuarenta y cuatro" ("eight forty-four"),
    +# indicating that Cuba is still on standard time.
    +
    +# From Steffen Thorsen (2008-03-12):
    +# It seems that Cuba will start DST on Sunday, 2007-03-16...
    +# It was announced yesterday, according to this source (in Spanish):
    +# 
    +# http://www.nnc.cubaweb.cu/marzo-2008/cien-1-11-3-08.htm
    +# 
    +#
    +# Some more background information is posted here:
    +# 
    +# http://www.timeanddate.com/news/time/cuba-starts-dst-march-16.html
    +# 
    +#
    +# The article also says that Cuba has been observing DST since 1963,
    +# while Shanks (and tzdata) has 1965 as the first date (except in the
    +# 1940's). Many other web pages in Cuba also claim that it has been
    +# observed since 1963, but with the exception of 1970 - an exception
    +# which is not present in tzdata/Shanks. So there is a chance we need to
    +# change some historic records as well.
    +#
    +# One example:
    +# 
    +# http://www.radiohc.cu/espanol/noticias/mar07/11mar/hor.htm
    +# 
    +
    +# From Jesper Norgaard Welen (2008-03-13):
    +# The Cuban time change has just been confirmed on the most authoritative
    +# web site, the Granma.  Please check out
    +# 
    +# http://www.granma.cubaweb.cu/2008/03/13/nacional/artic10.html
    +# 
    +#
    +# Basically as expected after Steffen Thorsens information, the change
    +# will take place midnight between Saturday and Sunday.
    +
    +# From Arthur David Olson (2008-03-12):
    +# Assume Sun>=15 (third Sunday) going forward.
    +
    +# From Alexander Krivenyshev (2009-03-04)
    +# According to the Radio Reloj - Cuba will start Daylight Saving Time on
    +# midnight between Saturday, March 07, 2009 and Sunday, March 08, 2009-
    +# not on midnight March 14 / March 15 as previously thought.
    +#
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_cuba05.html
    +# (in Spanish)
    +# 
    +
    +# From Arthur David Olson (2009-03-09)
    +# I listened over the Internet to
    +# 
    +# http://media.enet.cu/readioreloj
    +# 
    +# this morning; when it was 10:05 a. m. here in Bethesda, Maryland the
    +# the time was announced as "diez cinco"--the same time as here, indicating
    +# that has indeed switched to DST. Assume second Sunday from 2009 forward.
    +
    +# From Steffen Thorsen (2011-03-08):
    +# Granma announced that Cuba is going to start DST on 2011-03-20 00:00:00
    +# this year. Nothing about the end date known so far (if that has
    +# changed at all).
    +#
    +# Source:
    +# 
    +# http://granma.co.cu/2011/03/08/nacional/artic01.html
    +# 
    +#
    +# Our info:
    +# 
    +# http://www.timeanddate.com/news/time/cuba-starts-dst-2011.html
    +# 
    +#
    +# From Steffen Thorsen (2011-10-30)
    +# Cuba will end DST two weeks later this year. Instead of going back
    +# tonight, it has been delayed to 2011-11-13 at 01:00.
    +#
    +# One source (Spanish)
    +# 
    +# http://www.radioangulo.cu/noticias/cuba/17105-cuba-restablecera-el-horario-del-meridiano-de-greenwich.html
    +# 
    +#
    +# Our page:
    +# 
    +# http://www.timeanddate.com/news/time/cuba-time-changes-2011.html
    +# 
    +#
    +# From Steffen Thorsen (2012-03-01)
    +# According to Radio Reloj, Cuba will start DST on Midnight between March
    +# 31 and April 1.
    +#
    +# Radio Reloj has the following info (Spanish):
    +# 
    +# http://www.radioreloj.cu/index.php/noticias-radio-reloj/71-miscelaneas/7529-cuba-aplicara-el-horario-de-verano-desde-el-1-de-abril
    +# 
    +#
    +# Our info on it:
    +# 
    +# http://www.timeanddate.com/news/time/cuba-starts-dst-2012.html
    +# 
    +
    +# From Steffen Thorsen (2012-11-03):
    +# Radio Reloj and many other sources report that Cuba is changing back
    +# to standard time on 2012-11-04:
    +# http://www.radioreloj.cu/index.php/noticias-radio-reloj/36-nacionales/9961-regira-horario-normal-en-cuba-desde-el-domingo-cuatro-de-noviembre
    +# From Paul Eggert (2012-11-03):
    +# For now, assume the future rule is first Sunday in November.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Cuba	1928	only	-	Jun	10	0:00	1:00	D
    +Rule	Cuba	1928	only	-	Oct	10	0:00	0	S
    +Rule	Cuba	1940	1942	-	Jun	Sun>=1	0:00	1:00	D
    +Rule	Cuba	1940	1942	-	Sep	Sun>=1	0:00	0	S
    +Rule	Cuba	1945	1946	-	Jun	Sun>=1	0:00	1:00	D
    +Rule	Cuba	1945	1946	-	Sep	Sun>=1	0:00	0	S
    +Rule	Cuba	1965	only	-	Jun	1	0:00	1:00	D
    +Rule	Cuba	1965	only	-	Sep	30	0:00	0	S
    +Rule	Cuba	1966	only	-	May	29	0:00	1:00	D
    +Rule	Cuba	1966	only	-	Oct	2	0:00	0	S
    +Rule	Cuba	1967	only	-	Apr	8	0:00	1:00	D
    +Rule	Cuba	1967	1968	-	Sep	Sun>=8	0:00	0	S
    +Rule	Cuba	1968	only	-	Apr	14	0:00	1:00	D
    +Rule	Cuba	1969	1977	-	Apr	lastSun	0:00	1:00	D
    +Rule	Cuba	1969	1971	-	Oct	lastSun	0:00	0	S
    +Rule	Cuba	1972	1974	-	Oct	8	0:00	0	S
    +Rule	Cuba	1975	1977	-	Oct	lastSun	0:00	0	S
    +Rule	Cuba	1978	only	-	May	7	0:00	1:00	D
    +Rule	Cuba	1978	1990	-	Oct	Sun>=8	0:00	0	S
    +Rule	Cuba	1979	1980	-	Mar	Sun>=15	0:00	1:00	D
    +Rule	Cuba	1981	1985	-	May	Sun>=5	0:00	1:00	D
    +Rule	Cuba	1986	1989	-	Mar	Sun>=14	0:00	1:00	D
    +Rule	Cuba	1990	1997	-	Apr	Sun>=1	0:00	1:00	D
    +Rule	Cuba	1991	1995	-	Oct	Sun>=8	0:00s	0	S
    +Rule	Cuba	1996	only	-	Oct	 6	0:00s	0	S
    +Rule	Cuba	1997	only	-	Oct	12	0:00s	0	S
    +Rule	Cuba	1998	1999	-	Mar	lastSun	0:00s	1:00	D
    +Rule	Cuba	1998	2003	-	Oct	lastSun	0:00s	0	S
    +Rule	Cuba	2000	2004	-	Apr	Sun>=1	0:00s	1:00	D
    +Rule	Cuba	2006	2010	-	Oct	lastSun	0:00s	0	S
    +Rule	Cuba	2007	only	-	Mar	Sun>=8	0:00s	1:00	D
    +Rule	Cuba	2008	only	-	Mar	Sun>=15	0:00s	1:00	D
    +Rule	Cuba	2009	2010	-	Mar	Sun>=8	0:00s	1:00	D
    +Rule	Cuba	2011	only	-	Mar	Sun>=15	0:00s	1:00	D
    +Rule	Cuba	2011	only	-	Nov	13	0:00s	0	S
    +Rule	Cuba	2012	only	-	Apr	1	0:00s	1:00	D
    +Rule	Cuba	2012	max	-	Nov	Sun>=1	0:00s	0	S
    +Rule	Cuba	2013	max	-	Mar	Sun>=8	0:00s	1:00	D
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Havana	-5:29:28 -	LMT	1890
    +			-5:29:36 -	HMT	1925 Jul 19 12:00 # Havana MT
    +			-5:00	Cuba	C%sT
    +
    +# Dominica
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Dominica	-4:05:36 -	LMT	1911 Jul 1 0:01		# Roseau
    +			-4:00	-	AST
    +
    +# Dominican Republic
    +
    +# From Steffen Thorsen (2000-10-30):
    +# Enrique Morales reported to me that the Dominican Republic has changed the
    +# time zone to Eastern Standard Time as of Sunday 29 at 2 am....
    +# http://www.listin.com.do/antes/261000/republica/princi.html
    +
    +# From Paul Eggert (2000-12-04):
    +# That URL (2000-10-26, in Spanish) says they planned to use US-style DST.
    +
    +# From Rives McDow (2000-12-01):
    +# Dominican Republic changed its mind and presidential decree on Tuesday,
    +# November 28, 2000, with a new decree.  On Sunday, December 3 at 1:00 AM the
    +# Dominican Republic will be reverting to 8 hours from the International Date
    +# Line, and will not be using DST in the foreseeable future.  The reason they
    +# decided to use DST was to be in synch with Puerto Rico, who was also going
    +# to implement DST.  When Puerto Rico didn't implement DST, the president
    +# decided to revert.
    +
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	DR	1966	only	-	Oct	30	0:00	1:00	D
    +Rule	DR	1967	only	-	Feb	28	0:00	0	S
    +Rule	DR	1969	1973	-	Oct	lastSun	0:00	0:30	HD
    +Rule	DR	1970	only	-	Feb	21	0:00	0	S
    +Rule	DR	1971	only	-	Jan	20	0:00	0	S
    +Rule	DR	1972	1974	-	Jan	21	0:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Santo_Domingo -4:39:36 -	LMT	1890
    +			-4:40	-	SDMT	1933 Apr  1 12:00 # S. Dom. MT
    +			-5:00	DR	E%sT	1974 Oct 27
    +			-4:00	-	AST	2000 Oct 29 02:00
    +			-5:00	US	E%sT	2000 Dec  3 01:00
    +			-4:00	-	AST
    +
    +# El Salvador
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Salv	1987	1988	-	May	Sun>=1	0:00	1:00	D
    +Rule	Salv	1987	1988	-	Sep	lastSun	0:00	0	S
    +# There are too many San Salvadors elsewhere, so use America/El_Salvador
    +# instead of America/San_Salvador.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/El_Salvador -5:56:48 -	LMT	1921		# San Salvador
    +			-6:00	Salv	C%sT
    +
    +# Grenada
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Grenada	-4:07:00 -	LMT	1911 Jul	# St George's
    +			-4:00	-	AST
    +
    +# Guadeloupe
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Guadeloupe	-4:06:08 -	LMT	1911 Jun 8	# Pointe a Pitre
    +			-4:00	-	AST
    +# St Barthelemy
    +Link America/Guadeloupe	America/St_Barthelemy
    +# St Martin (French part)
    +Link America/Guadeloupe	America/Marigot
    +
    +# Guatemala
    +#
    +# From Gwillim Law (2006-04-22), after a heads-up from Oscar van Vlijmen:
    +# Diario Co Latino, at
    +# http://www.diariocolatino.com/internacionales/detalles.asp?NewsID=8079,
    +# says in an article dated 2006-04-19 that the Guatemalan government had
    +# decided on that date to advance official time by 60 minutes, to lessen the
    +# impact of the elevated cost of oil....  Daylight saving time will last from
    +# 2006-04-29 24:00 (Guatemalan standard time) to 2006-09-30 (time unspecified).
    +# From Paul Eggert (2006-06-22):
    +# The Ministry of Energy and Mines, press release CP-15/2006
    +# (2006-04-19), says DST ends at 24:00.  See
    +# .
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Guat	1973	only	-	Nov	25	0:00	1:00	D
    +Rule	Guat	1974	only	-	Feb	24	0:00	0	S
    +Rule	Guat	1983	only	-	May	21	0:00	1:00	D
    +Rule	Guat	1983	only	-	Sep	22	0:00	0	S
    +Rule	Guat	1991	only	-	Mar	23	0:00	1:00	D
    +Rule	Guat	1991	only	-	Sep	 7	0:00	0	S
    +Rule	Guat	2006	only	-	Apr	30	0:00	1:00	D
    +Rule	Guat	2006	only	-	Oct	 1	0:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Guatemala	-6:02:04 -	LMT	1918 Oct 5
    +			-6:00	Guat	C%sT
    +
    +# Haiti
    +# From Gwillim Law (2005-04-15):
    +# Risto O. Nykanen wrote me that Haiti is now on DST.
    +# I searched for confirmation, and I found a
    +#  press release
    +# on the Web page of the Haitian Consulate in Chicago (2005-03-31),
    +# .  Translated from French, it says:
    +#
    +#  "The Prime Minister's Communication Office notifies the public in general
    +#   and the press in particular that, following a decision of the Interior
    +#   Ministry and the Territorial Collectivities [I suppose that means the
    +#   provinces], Haiti will move to Eastern Daylight Time in the night from next
    +#   Saturday the 2nd to Sunday the 3rd.
    +#
    +#  "Consequently, the Prime Minister's Communication Office wishes to inform
    +#   the population that the country's clocks will be set forward one hour
    +#   starting at midnight.  This provision will hold until the last Saturday in
    +#   October 2005.
    +#
    +#  "Port-au-Prince, March 31, 2005"
    +#
    +# From Steffen Thorsen (2006-04-04):
    +# I have been informed by users that Haiti observes DST this year like
    +# last year, so the current "only" rule for 2005 might be changed to a
    +# "max" rule or to last until 2006. (Who knows if they will observe DST
    +# next year or if they will extend their DST like US/Canada next year).
    +#
    +# I have found this article about it (in French):
    +# http://www.haitipressnetwork.com/news.cfm?articleID=7612
    +#
    +# The reason seems to be an energy crisis.
    +
    +# From Stephen Colebourne (2007-02-22):
    +# Some IATA info: Haiti won't be having DST in 2007.
    +
    +# From Steffen Thorsen (2012-03-11):
    +# According to several news sources, Haiti will observe DST this year,
    +# apparently using the same start and end date as USA/Canada.
    +# So this means they have already changed their time.
    +#
    +# (Sources in French):
    +# 
    +# http://www.alterpresse.org/spip.php?article12510
    +# 
    +# 
    +# http://radiovision2000haiti.net/home/?p=13253
    +# 
    +#
    +# Our coverage:
    +# 
    +# http://www.timeanddate.com/news/time/haiti-dst-2012.html
    +# 
    +
    +# From Arthur David Olson (2012-03-11):
    +# The alterpresse.org source seems to show a US-style leap from 2:00 a.m. to
    +# 3:00 a.m. rather than the traditional Haitian jump at midnight.
    +# Assume a US-style fall back as well XXX.
    +# Do not yet assume that the change carries forward past 2012 XXX.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Haiti	1983	only	-	May	8	0:00	1:00	D
    +Rule	Haiti	1984	1987	-	Apr	lastSun	0:00	1:00	D
    +Rule	Haiti	1983	1987	-	Oct	lastSun	0:00	0	S
    +# Shanks & Pottenger say AT is 2:00, but IATA SSIM (1991/1997) says 1:00s.
    +# Go with IATA.
    +Rule	Haiti	1988	1997	-	Apr	Sun>=1	1:00s	1:00	D
    +Rule	Haiti	1988	1997	-	Oct	lastSun	1:00s	0	S
    +Rule	Haiti	2005	2006	-	Apr	Sun>=1	0:00	1:00	D
    +Rule	Haiti	2005	2006	-	Oct	lastSun	0:00	0	S
    +Rule	Haiti	2012	only	-	Mar	Sun>=8	2:00	1:00	D
    +Rule	Haiti	2012	only	-	Nov	Sun>=1	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Port-au-Prince -4:49:20 -	LMT	1890
    +			-4:49	-	PPMT	1917 Jan 24 12:00 # P-a-P MT
    +			-5:00	Haiti	E%sT
    +
    +# Honduras
    +# Shanks & Pottenger say 1921 Jan 1; go with Whitman's more precise Apr 1.
    +
    +# From Paul Eggert (2006-05-05):
    +# worldtimezone.com reports a 2006-05-02 Spanish-language AP article
    +# saying Honduras will start using DST midnight Saturday, effective 4
    +# months until September.  La Tribuna reported today
    +#  that Manuel Zelaya, the president
    +# of Honduras, refused to back down on this.
    +
    +# From Jesper Norgaard Welen (2006-08-08):
    +# It seems that Honduras has returned from DST to standard time this Monday at
    +# 00:00 hours (prolonging Sunday to 25 hours duration).
    +# http://www.worldtimezone.com/dst_news/dst_news_honduras04.html
    +
    +# From Paul Eggert (2006-08-08):
    +# Also see Diario El Heraldo, The country returns to standard time (2006-08-08)
    +# .
    +# It mentions executive decree 18-2006.
    +
    +# From Steffen Thorsen (2006-08-17):
    +# Honduras will observe DST from 2007 to 2009, exact dates are not
    +# published, I have located this authoritative source:
    +# http://www.presidencia.gob.hn/noticia.aspx?nId=47
    +
    +# From Steffen Thorsen (2007-03-30):
    +# http://www.laprensahn.com/pais_nota.php?id04962=7386
    +# So it seems that Honduras will not enter DST this year....
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Hond	1987	1988	-	May	Sun>=1	0:00	1:00	D
    +Rule	Hond	1987	1988	-	Sep	lastSun	0:00	0	S
    +Rule	Hond	2006	only	-	May	Sun>=1	0:00	1:00	D
    +Rule	Hond	2006	only	-	Aug	Mon>=1	0:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Tegucigalpa -5:48:52 -	LMT	1921 Apr
    +			-6:00	Hond	C%sT
    +#
    +# Great Swan I ceded by US to Honduras in 1972
    +
    +# Jamaica
    +
    +# From Bob Devine (1988-01-28):
    +# Follows US rules.
    +
    +# From U. S. Naval Observatory (1989-01-19):
    +# JAMAICA             5 H  BEHIND UTC
    +
    +# From Shanks & Pottenger:
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Jamaica	-5:07:12 -	LMT	1890		# Kingston
    +			-5:07:12 -	KMT	1912 Feb    # Kingston Mean Time
    +			-5:00	-	EST	1974 Apr 28 2:00
    +			-5:00	US	E%sT	1984
    +			-5:00	-	EST
    +
    +# Martinique
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Martinique	-4:04:20 -      LMT	1890		# Fort-de-France
    +			-4:04:20 -	FFMT	1911 May     # Fort-de-France MT
    +			-4:00	-	AST	1980 Apr  6
    +			-4:00	1:00	ADT	1980 Sep 28
    +			-4:00	-	AST
    +
    +# Montserrat
    +# From Paul Eggert (2006-03-22):
    +# In 1995 volcanic eruptions forced evacuation of Plymouth, the capital.
    +# world.gazetteer.com says Cork Hill is the most populous location now.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Montserrat	-4:08:52 -	LMT	1911 Jul 1 0:01   # Cork Hill
    +			-4:00	-	AST
    +
    +# Nicaragua
    +#
    +# This uses Shanks & Pottenger for times before 2005.
    +#
    +# From Steffen Thorsen (2005-04-12):
    +# I've got reports from 8 different people that Nicaragua just started
    +# DST on Sunday 2005-04-10, in order to save energy because of
    +# expensive petroleum.  The exact end date for DST is not yet
    +# announced, only "September" but some sites also say "mid-September".
    +# Some background information is available on the President's official site:
    +# http://www.presidencia.gob.ni/Presidencia/Files_index/Secretaria/Notas%20de%20Prensa/Presidente/2005/ABRIL/Gobierno-de-nicaragua-adelanta-hora-oficial-06abril.htm
    +# The Decree, no 23-2005 is available here:
    +# http://www.presidencia.gob.ni/buscador_gaceta/BD/DECRETOS/2005/Decreto%2023-2005%20Se%20adelanta%20en%20una%20hora%20en%20todo%20el%20territorio%20nacional%20apartir%20de%20las%2024horas%20del%2009%20de%20Abril.pdf
    +#
    +# From Paul Eggert (2005-05-01):
    +# The decree doesn't say anything about daylight saving, but for now let's
    +# assume that it is daylight saving....
    +#
    +# From Gwillim Law (2005-04-21):
    +# The Associated Press story on the time change, which can be found at
    +# http://www.lapalmainteractivo.com/guias/content/gen/ap/America_Latina/AMC_GEN_NICARAGUA_HORA.html
    +# and elsewhere, says (fifth paragraph, translated from Spanish):  "The last
    +# time that a change of clocks was applied to save energy was in the year 2000
    +# during the Arnoldo Aleman administration."...
    +# The northamerica file says that Nicaragua has been on UTC-6 continuously
    +# since December 1998.  I wasn't able to find any details of Nicaraguan time
    +# changes in 2000.  Perhaps a note could be added to the northamerica file, to
    +# the effect that we have indirect evidence that DST was observed in 2000.
    +#
    +# From Jesper Norgaard Welen (2005-11-02):
    +# Nicaragua left DST the 2005-10-02 at 00:00 (local time).
    +# http://www.presidencia.gob.ni/presidencia/files_index/secretaria/comunicados/2005/septiembre/26septiembre-cambio-hora.htm
    +# (2005-09-26)
    +#
    +# From Jesper Norgaard Welen (2006-05-05):
    +# http://www.elnuevodiario.com.ni/2006/05/01/nacionales/18410
    +# (my informal translation)
    +# By order of the president of the republic, Enrique Bolanos, Nicaragua
    +# advanced by sixty minutes their official time, yesterday at 2 in the
    +# morning, and will stay that way until 30.th. of september.
    +#
    +# From Jesper Norgaard Welen (2006-09-30):
    +# http://www.presidencia.gob.ni/buscador_gaceta/BD/DECRETOS/2006/D-063-2006P-PRN-Cambio-Hora.pdf
    +# My informal translation runs:
    +# The natural sun time is restored in all the national territory, in that the
    +# time is returned one hour at 01:00 am of October 1 of 2006.
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Nic	1979	1980	-	Mar	Sun>=16	0:00	1:00	D
    +Rule	Nic	1979	1980	-	Jun	Mon>=23	0:00	0	S
    +Rule	Nic	2005	only	-	Apr	10	0:00	1:00	D
    +Rule	Nic	2005	only	-	Oct	Sun>=1	0:00	0	S
    +Rule	Nic	2006	only	-	Apr	30	2:00	1:00	D
    +Rule	Nic	2006	only	-	Oct	Sun>=1	1:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Managua	-5:45:08 -	LMT	1890
    +			-5:45:12 -	MMT	1934 Jun 23 # Managua Mean Time?
    +			-6:00	-	CST	1973 May
    +			-5:00	-	EST	1975 Feb 16
    +			-6:00	Nic	C%sT	1992 Jan  1 4:00
    +			-5:00	-	EST	1992 Sep 24
    +			-6:00	-	CST	1993
    +			-5:00	-	EST	1997
    +			-6:00	Nic	C%sT
    +
    +# Panama
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Panama	-5:18:08 -	LMT	1890
    +			-5:19:36 -	CMT	1908 Apr 22   # Colon Mean Time
    +			-5:00	-	EST
    +
    +# Puerto Rico
    +# There are too many San Juans elsewhere, so we'll use `Puerto_Rico'.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Puerto_Rico -4:24:25 -	LMT	1899 Mar 28 12:00    # San Juan
    +			-4:00	-	AST	1942 May  3
    +			-4:00	US	A%sT	1946
    +			-4:00	-	AST
    +
    +# St Kitts-Nevis
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/St_Kitts	-4:10:52 -	LMT	1912 Mar 2	# Basseterre
    +			-4:00	-	AST
    +
    +# St Lucia
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/St_Lucia	-4:04:00 -	LMT	1890		# Castries
    +			-4:04:00 -	CMT	1912	    # Castries Mean Time
    +			-4:00	-	AST
    +
    +# St Pierre and Miquelon
    +# There are too many St Pierres elsewhere, so we'll use `Miquelon'.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15	# St Pierre
    +			-4:00	-	AST	1980 May
    +			-3:00	-	PMST	1987 # Pierre & Miquelon Time
    +			-3:00	Canada	PM%sT
    +
    +# St Vincent and the Grenadines
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/St_Vincent	-4:04:56 -	LMT	1890		# Kingstown
    +			-4:04:56 -	KMT	1912	   # Kingstown Mean Time
    +			-4:00	-	AST
    +
    +# Turks and Caicos
    +#
    +# From Chris Dunn in
    +# 
    +# (2007-03-15): In the Turks & Caicos Islands (America/Grand_Turk) the
    +# daylight saving dates for time changes have been adjusted to match
    +# the recent U.S. change of dates.
    +#
    +# From Brian Inglis (2007-04-28):
    +# http://www.turksandcaicos.tc/calendar/index.htm [2007-04-26]
    +# there is an entry for Nov 4 "Daylight Savings Time Ends 2007" and three
    +# rows before that there is an out of date entry for Oct:
    +# "Eastern Standard Times Begins 2007
    +# Clocks are set back one hour at 2:00 a.m. local Daylight Saving Time"
    +# indicating that the normal ET rules are followed.
    +#
    +# From Paul Eggert (2006-05-01):
    +# Shanks & Pottenger say they use US DST rules, but IATA SSIM (1991/1998)
    +# says they switch at midnight.  Go with Shanks & Pottenger.
    +#
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	TC	1979	1986	-	Apr	lastSun	2:00	1:00	D
    +Rule	TC	1979	2006	-	Oct	lastSun	2:00	0	S
    +Rule	TC	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
    +Rule	TC	2007	max	-	Mar	Sun>=8	2:00	1:00	D
    +Rule	TC	2007	max	-	Nov	Sun>=1	2:00	0	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Grand_Turk	-4:44:32 -	LMT	1890
    +			-5:07:12 -	KMT	1912 Feb    # Kingston Mean Time
    +			-5:00	TC	E%sT
    +
    +# British Virgin Is
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Tortola	-4:18:28 -	LMT	1911 Jul    # Road Town
    +			-4:00	-	AST
    +
    +# Virgin Is
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/St_Thomas	-4:19:44 -	LMT	1911 Jul    # Charlotte Amalie
    +			-4:00	-	AST
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/pacificnew b/jdk/test/sun/util/calendar/zi/tzdata/pacificnew
    new file mode 100644
    index 00000000000..7738a48087b
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/pacificnew
    @@ -0,0 +1,51 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# From Arthur David Olson (1989-04-05):
    +# On 1989-04-05, the U. S. House of Representatives passed (238-154) a bill
    +# establishing "Pacific Presidential Election Time"; it was not acted on
    +# by the Senate or signed into law by the President.
    +# You might want to change the "PE" (Presidential Election) below to
    +# "Q" (Quadrennial) to maintain three-character zone abbreviations.
    +# If you're really conservative, you might want to change it to "D".
    +# Avoid "L" (Leap Year), which won't be true in 2100.
    +
    +# If Presidential Election Time is ever established, replace "XXXX" below
    +# with the year the law takes effect and uncomment the "##" lines.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +## Rule	Twilite	XXXX	max	-	Apr	Sun>=1	2:00	1:00	D
    +## Rule	Twilite	XXXX	max	uspres	Oct	lastSun	2:00	1:00	PE
    +## Rule	Twilite	XXXX	max	uspres	Nov	Sun>=7	2:00	0	S
    +## Rule	Twilite	XXXX	max	nonpres	Oct	lastSun	2:00	0	S
    +
    +# Zone	NAME			GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
    +## Zone	America/Los_Angeles-PET	-8:00	US		P%sT	XXXX
    +##				-8:00	Twilite		P%sT
    +
    +# For now...
    +Link	America/Los_Angeles	US/Pacific-New	##
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/solar87 b/jdk/test/sun/util/calendar/zi/tzdata/solar87
    new file mode 100644
    index 00000000000..46b1d56025f
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/solar87
    @@ -0,0 +1,413 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# So much for footnotes about Saudi Arabia.
    +# Apparent noon times below are for Riyadh; your mileage will vary.
    +# Times were computed using formulas in the U.S. Naval Observatory's
    +# Almanac for Computers 1987; the formulas "will give EqT to an accuracy of
    +# [plus or minus two] seconds during the current year."
    +#
    +# Rounding to the nearest five seconds results in fewer than
    +# 256 different "time types"--a limit that's faced because time types are
    +# stored on disk as unsigned chars.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	sol87	1987	only	-	Jan	1	12:03:20s -0:03:20 -
    +Rule	sol87	1987	only	-	Jan	2	12:03:50s -0:03:50 -
    +Rule	sol87	1987	only	-	Jan	3	12:04:15s -0:04:15 -
    +Rule	sol87	1987	only	-	Jan	4	12:04:45s -0:04:45 -
    +Rule	sol87	1987	only	-	Jan	5	12:05:10s -0:05:10 -
    +Rule	sol87	1987	only	-	Jan	6	12:05:40s -0:05:40 -
    +Rule	sol87	1987	only	-	Jan	7	12:06:05s -0:06:05 -
    +Rule	sol87	1987	only	-	Jan	8	12:06:30s -0:06:30 -
    +Rule	sol87	1987	only	-	Jan	9	12:06:55s -0:06:55 -
    +Rule	sol87	1987	only	-	Jan	10	12:07:20s -0:07:20 -
    +Rule	sol87	1987	only	-	Jan	11	12:07:45s -0:07:45 -
    +Rule	sol87	1987	only	-	Jan	12	12:08:10s -0:08:10 -
    +Rule	sol87	1987	only	-	Jan	13	12:08:30s -0:08:30 -
    +Rule	sol87	1987	only	-	Jan	14	12:08:55s -0:08:55 -
    +Rule	sol87	1987	only	-	Jan	15	12:09:15s -0:09:15 -
    +Rule	sol87	1987	only	-	Jan	16	12:09:35s -0:09:35 -
    +Rule	sol87	1987	only	-	Jan	17	12:09:55s -0:09:55 -
    +Rule	sol87	1987	only	-	Jan	18	12:10:15s -0:10:15 -
    +Rule	sol87	1987	only	-	Jan	19	12:10:35s -0:10:35 -
    +Rule	sol87	1987	only	-	Jan	20	12:10:55s -0:10:55 -
    +Rule	sol87	1987	only	-	Jan	21	12:11:10s -0:11:10 -
    +Rule	sol87	1987	only	-	Jan	22	12:11:30s -0:11:30 -
    +Rule	sol87	1987	only	-	Jan	23	12:11:45s -0:11:45 -
    +Rule	sol87	1987	only	-	Jan	24	12:12:00s -0:12:00 -
    +Rule	sol87	1987	only	-	Jan	25	12:12:15s -0:12:15 -
    +Rule	sol87	1987	only	-	Jan	26	12:12:30s -0:12:30 -
    +Rule	sol87	1987	only	-	Jan	27	12:12:40s -0:12:40 -
    +Rule	sol87	1987	only	-	Jan	28	12:12:55s -0:12:55 -
    +Rule	sol87	1987	only	-	Jan	29	12:13:05s -0:13:05 -
    +Rule	sol87	1987	only	-	Jan	30	12:13:15s -0:13:15 -
    +Rule	sol87	1987	only	-	Jan	31	12:13:25s -0:13:25 -
    +Rule	sol87	1987	only	-	Feb	1	12:13:35s -0:13:35 -
    +Rule	sol87	1987	only	-	Feb	2	12:13:40s -0:13:40 -
    +Rule	sol87	1987	only	-	Feb	3	12:13:50s -0:13:50 -
    +Rule	sol87	1987	only	-	Feb	4	12:13:55s -0:13:55 -
    +Rule	sol87	1987	only	-	Feb	5	12:14:00s -0:14:00 -
    +Rule	sol87	1987	only	-	Feb	6	12:14:05s -0:14:05 -
    +Rule	sol87	1987	only	-	Feb	7	12:14:10s -0:14:10 -
    +Rule	sol87	1987	only	-	Feb	8	12:14:10s -0:14:10 -
    +Rule	sol87	1987	only	-	Feb	9	12:14:15s -0:14:15 -
    +Rule	sol87	1987	only	-	Feb	10	12:14:15s -0:14:15 -
    +Rule	sol87	1987	only	-	Feb	11	12:14:15s -0:14:15 -
    +Rule	sol87	1987	only	-	Feb	12	12:14:15s -0:14:15 -
    +Rule	sol87	1987	only	-	Feb	13	12:14:15s -0:14:15 -
    +Rule	sol87	1987	only	-	Feb	14	12:14:15s -0:14:15 -
    +Rule	sol87	1987	only	-	Feb	15	12:14:10s -0:14:10 -
    +Rule	sol87	1987	only	-	Feb	16	12:14:10s -0:14:10 -
    +Rule	sol87	1987	only	-	Feb	17	12:14:05s -0:14:05 -
    +Rule	sol87	1987	only	-	Feb	18	12:14:00s -0:14:00 -
    +Rule	sol87	1987	only	-	Feb	19	12:13:55s -0:13:55 -
    +Rule	sol87	1987	only	-	Feb	20	12:13:50s -0:13:50 -
    +Rule	sol87	1987	only	-	Feb	21	12:13:45s -0:13:45 -
    +Rule	sol87	1987	only	-	Feb	22	12:13:35s -0:13:35 -
    +Rule	sol87	1987	only	-	Feb	23	12:13:30s -0:13:30 -
    +Rule	sol87	1987	only	-	Feb	24	12:13:20s -0:13:20 -
    +Rule	sol87	1987	only	-	Feb	25	12:13:10s -0:13:10 -
    +Rule	sol87	1987	only	-	Feb	26	12:13:00s -0:13:00 -
    +Rule	sol87	1987	only	-	Feb	27	12:12:50s -0:12:50 -
    +Rule	sol87	1987	only	-	Feb	28	12:12:40s -0:12:40 -
    +Rule	sol87	1987	only	-	Mar	1	12:12:30s -0:12:30 -
    +Rule	sol87	1987	only	-	Mar	2	12:12:20s -0:12:20 -
    +Rule	sol87	1987	only	-	Mar	3	12:12:05s -0:12:05 -
    +Rule	sol87	1987	only	-	Mar	4	12:11:55s -0:11:55 -
    +Rule	sol87	1987	only	-	Mar	5	12:11:40s -0:11:40 -
    +Rule	sol87	1987	only	-	Mar	6	12:11:25s -0:11:25 -
    +Rule	sol87	1987	only	-	Mar	7	12:11:15s -0:11:15 -
    +Rule	sol87	1987	only	-	Mar	8	12:11:00s -0:11:00 -
    +Rule	sol87	1987	only	-	Mar	9	12:10:45s -0:10:45 -
    +Rule	sol87	1987	only	-	Mar	10	12:10:30s -0:10:30 -
    +Rule	sol87	1987	only	-	Mar	11	12:10:15s -0:10:15 -
    +Rule	sol87	1987	only	-	Mar	12	12:09:55s -0:09:55 -
    +Rule	sol87	1987	only	-	Mar	13	12:09:40s -0:09:40 -
    +Rule	sol87	1987	only	-	Mar	14	12:09:25s -0:09:25 -
    +Rule	sol87	1987	only	-	Mar	15	12:09:10s -0:09:10 -
    +Rule	sol87	1987	only	-	Mar	16	12:08:50s -0:08:50 -
    +Rule	sol87	1987	only	-	Mar	17	12:08:35s -0:08:35 -
    +Rule	sol87	1987	only	-	Mar	18	12:08:15s -0:08:15 -
    +Rule	sol87	1987	only	-	Mar	19	12:08:00s -0:08:00 -
    +Rule	sol87	1987	only	-	Mar	20	12:07:40s -0:07:40 -
    +Rule	sol87	1987	only	-	Mar	21	12:07:25s -0:07:25 -
    +Rule	sol87	1987	only	-	Mar	22	12:07:05s -0:07:05 -
    +Rule	sol87	1987	only	-	Mar	23	12:06:50s -0:06:50 -
    +Rule	sol87	1987	only	-	Mar	24	12:06:30s -0:06:30 -
    +Rule	sol87	1987	only	-	Mar	25	12:06:10s -0:06:10 -
    +Rule	sol87	1987	only	-	Mar	26	12:05:55s -0:05:55 -
    +Rule	sol87	1987	only	-	Mar	27	12:05:35s -0:05:35 -
    +Rule	sol87	1987	only	-	Mar	28	12:05:15s -0:05:15 -
    +Rule	sol87	1987	only	-	Mar	29	12:05:00s -0:05:00 -
    +Rule	sol87	1987	only	-	Mar	30	12:04:40s -0:04:40 -
    +Rule	sol87	1987	only	-	Mar	31	12:04:25s -0:04:25 -
    +Rule	sol87	1987	only	-	Apr	1	12:04:05s -0:04:05 -
    +Rule	sol87	1987	only	-	Apr	2	12:03:45s -0:03:45 -
    +Rule	sol87	1987	only	-	Apr	3	12:03:30s -0:03:30 -
    +Rule	sol87	1987	only	-	Apr	4	12:03:10s -0:03:10 -
    +Rule	sol87	1987	only	-	Apr	5	12:02:55s -0:02:55 -
    +Rule	sol87	1987	only	-	Apr	6	12:02:35s -0:02:35 -
    +Rule	sol87	1987	only	-	Apr	7	12:02:20s -0:02:20 -
    +Rule	sol87	1987	only	-	Apr	8	12:02:05s -0:02:05 -
    +Rule	sol87	1987	only	-	Apr	9	12:01:45s -0:01:45 -
    +Rule	sol87	1987	only	-	Apr	10	12:01:30s -0:01:30 -
    +Rule	sol87	1987	only	-	Apr	11	12:01:15s -0:01:15 -
    +Rule	sol87	1987	only	-	Apr	12	12:00:55s -0:00:55 -
    +Rule	sol87	1987	only	-	Apr	13	12:00:40s -0:00:40 -
    +Rule	sol87	1987	only	-	Apr	14	12:00:25s -0:00:25 -
    +Rule	sol87	1987	only	-	Apr	15	12:00:10s -0:00:10 -
    +Rule	sol87	1987	only	-	Apr	16	11:59:55s 0:00:05 -
    +Rule	sol87	1987	only	-	Apr	17	11:59:45s 0:00:15 -
    +Rule	sol87	1987	only	-	Apr	18	11:59:30s 0:00:30 -
    +Rule	sol87	1987	only	-	Apr	19	11:59:15s 0:00:45 -
    +Rule	sol87	1987	only	-	Apr	20	11:59:05s 0:00:55 -
    +Rule	sol87	1987	only	-	Apr	21	11:58:50s 0:01:10 -
    +Rule	sol87	1987	only	-	Apr	22	11:58:40s 0:01:20 -
    +Rule	sol87	1987	only	-	Apr	23	11:58:25s 0:01:35 -
    +Rule	sol87	1987	only	-	Apr	24	11:58:15s 0:01:45 -
    +Rule	sol87	1987	only	-	Apr	25	11:58:05s 0:01:55 -
    +Rule	sol87	1987	only	-	Apr	26	11:57:55s 0:02:05 -
    +Rule	sol87	1987	only	-	Apr	27	11:57:45s 0:02:15 -
    +Rule	sol87	1987	only	-	Apr	28	11:57:35s 0:02:25 -
    +Rule	sol87	1987	only	-	Apr	29	11:57:25s 0:02:35 -
    +Rule	sol87	1987	only	-	Apr	30	11:57:15s 0:02:45 -
    +Rule	sol87	1987	only	-	May	1	11:57:10s 0:02:50 -
    +Rule	sol87	1987	only	-	May	2	11:57:00s 0:03:00 -
    +Rule	sol87	1987	only	-	May	3	11:56:55s 0:03:05 -
    +Rule	sol87	1987	only	-	May	4	11:56:50s 0:03:10 -
    +Rule	sol87	1987	only	-	May	5	11:56:45s 0:03:15 -
    +Rule	sol87	1987	only	-	May	6	11:56:40s 0:03:20 -
    +Rule	sol87	1987	only	-	May	7	11:56:35s 0:03:25 -
    +Rule	sol87	1987	only	-	May	8	11:56:30s 0:03:30 -
    +Rule	sol87	1987	only	-	May	9	11:56:25s 0:03:35 -
    +Rule	sol87	1987	only	-	May	10	11:56:25s 0:03:35 -
    +Rule	sol87	1987	only	-	May	11	11:56:20s 0:03:40 -
    +Rule	sol87	1987	only	-	May	12	11:56:20s 0:03:40 -
    +Rule	sol87	1987	only	-	May	13	11:56:20s 0:03:40 -
    +Rule	sol87	1987	only	-	May	14	11:56:20s 0:03:40 -
    +Rule	sol87	1987	only	-	May	15	11:56:20s 0:03:40 -
    +Rule	sol87	1987	only	-	May	16	11:56:20s 0:03:40 -
    +Rule	sol87	1987	only	-	May	17	11:56:20s 0:03:40 -
    +Rule	sol87	1987	only	-	May	18	11:56:20s 0:03:40 -
    +Rule	sol87	1987	only	-	May	19	11:56:25s 0:03:35 -
    +Rule	sol87	1987	only	-	May	20	11:56:25s 0:03:35 -
    +Rule	sol87	1987	only	-	May	21	11:56:30s 0:03:30 -
    +Rule	sol87	1987	only	-	May	22	11:56:35s 0:03:25 -
    +Rule	sol87	1987	only	-	May	23	11:56:40s 0:03:20 -
    +Rule	sol87	1987	only	-	May	24	11:56:45s 0:03:15 -
    +Rule	sol87	1987	only	-	May	25	11:56:50s 0:03:10 -
    +Rule	sol87	1987	only	-	May	26	11:56:55s 0:03:05 -
    +Rule	sol87	1987	only	-	May	27	11:57:00s 0:03:00 -
    +Rule	sol87	1987	only	-	May	28	11:57:10s 0:02:50 -
    +Rule	sol87	1987	only	-	May	29	11:57:15s 0:02:45 -
    +Rule	sol87	1987	only	-	May	30	11:57:25s 0:02:35 -
    +Rule	sol87	1987	only	-	May	31	11:57:30s 0:02:30 -
    +Rule	sol87	1987	only	-	Jun	1	11:57:40s 0:02:20 -
    +Rule	sol87	1987	only	-	Jun	2	11:57:50s 0:02:10 -
    +Rule	sol87	1987	only	-	Jun	3	11:58:00s 0:02:00 -
    +Rule	sol87	1987	only	-	Jun	4	11:58:10s 0:01:50 -
    +Rule	sol87	1987	only	-	Jun	5	11:58:20s 0:01:40 -
    +Rule	sol87	1987	only	-	Jun	6	11:58:30s 0:01:30 -
    +Rule	sol87	1987	only	-	Jun	7	11:58:40s 0:01:20 -
    +Rule	sol87	1987	only	-	Jun	8	11:58:50s 0:01:10 -
    +Rule	sol87	1987	only	-	Jun	9	11:59:05s 0:00:55 -
    +Rule	sol87	1987	only	-	Jun	10	11:59:15s 0:00:45 -
    +Rule	sol87	1987	only	-	Jun	11	11:59:30s 0:00:30 -
    +Rule	sol87	1987	only	-	Jun	12	11:59:40s 0:00:20 -
    +Rule	sol87	1987	only	-	Jun	13	11:59:50s 0:00:10 -
    +Rule	sol87	1987	only	-	Jun	14	12:00:05s -0:00:05 -
    +Rule	sol87	1987	only	-	Jun	15	12:00:15s -0:00:15 -
    +Rule	sol87	1987	only	-	Jun	16	12:00:30s -0:00:30 -
    +Rule	sol87	1987	only	-	Jun	17	12:00:45s -0:00:45 -
    +Rule	sol87	1987	only	-	Jun	18	12:00:55s -0:00:55 -
    +Rule	sol87	1987	only	-	Jun	19	12:01:10s -0:01:10 -
    +Rule	sol87	1987	only	-	Jun	20	12:01:20s -0:01:20 -
    +Rule	sol87	1987	only	-	Jun	21	12:01:35s -0:01:35 -
    +Rule	sol87	1987	only	-	Jun	22	12:01:50s -0:01:50 -
    +Rule	sol87	1987	only	-	Jun	23	12:02:00s -0:02:00 -
    +Rule	sol87	1987	only	-	Jun	24	12:02:15s -0:02:15 -
    +Rule	sol87	1987	only	-	Jun	25	12:02:25s -0:02:25 -
    +Rule	sol87	1987	only	-	Jun	26	12:02:40s -0:02:40 -
    +Rule	sol87	1987	only	-	Jun	27	12:02:50s -0:02:50 -
    +Rule	sol87	1987	only	-	Jun	28	12:03:05s -0:03:05 -
    +Rule	sol87	1987	only	-	Jun	29	12:03:15s -0:03:15 -
    +Rule	sol87	1987	only	-	Jun	30	12:03:30s -0:03:30 -
    +Rule	sol87	1987	only	-	Jul	1	12:03:40s -0:03:40 -
    +Rule	sol87	1987	only	-	Jul	2	12:03:50s -0:03:50 -
    +Rule	sol87	1987	only	-	Jul	3	12:04:05s -0:04:05 -
    +Rule	sol87	1987	only	-	Jul	4	12:04:15s -0:04:15 -
    +Rule	sol87	1987	only	-	Jul	5	12:04:25s -0:04:25 -
    +Rule	sol87	1987	only	-	Jul	6	12:04:35s -0:04:35 -
    +Rule	sol87	1987	only	-	Jul	7	12:04:45s -0:04:45 -
    +Rule	sol87	1987	only	-	Jul	8	12:04:55s -0:04:55 -
    +Rule	sol87	1987	only	-	Jul	9	12:05:05s -0:05:05 -
    +Rule	sol87	1987	only	-	Jul	10	12:05:15s -0:05:15 -
    +Rule	sol87	1987	only	-	Jul	11	12:05:20s -0:05:20 -
    +Rule	sol87	1987	only	-	Jul	12	12:05:30s -0:05:30 -
    +Rule	sol87	1987	only	-	Jul	13	12:05:40s -0:05:40 -
    +Rule	sol87	1987	only	-	Jul	14	12:05:45s -0:05:45 -
    +Rule	sol87	1987	only	-	Jul	15	12:05:50s -0:05:50 -
    +Rule	sol87	1987	only	-	Jul	16	12:06:00s -0:06:00 -
    +Rule	sol87	1987	only	-	Jul	17	12:06:05s -0:06:05 -
    +Rule	sol87	1987	only	-	Jul	18	12:06:10s -0:06:10 -
    +Rule	sol87	1987	only	-	Jul	19	12:06:15s -0:06:15 -
    +Rule	sol87	1987	only	-	Jul	20	12:06:15s -0:06:15 -
    +Rule	sol87	1987	only	-	Jul	21	12:06:20s -0:06:20 -
    +Rule	sol87	1987	only	-	Jul	22	12:06:25s -0:06:25 -
    +Rule	sol87	1987	only	-	Jul	23	12:06:25s -0:06:25 -
    +Rule	sol87	1987	only	-	Jul	24	12:06:25s -0:06:25 -
    +Rule	sol87	1987	only	-	Jul	25	12:06:30s -0:06:30 -
    +Rule	sol87	1987	only	-	Jul	26	12:06:30s -0:06:30 -
    +Rule	sol87	1987	only	-	Jul	27	12:06:30s -0:06:30 -
    +Rule	sol87	1987	only	-	Jul	28	12:06:30s -0:06:30 -
    +Rule	sol87	1987	only	-	Jul	29	12:06:25s -0:06:25 -
    +Rule	sol87	1987	only	-	Jul	30	12:06:25s -0:06:25 -
    +Rule	sol87	1987	only	-	Jul	31	12:06:25s -0:06:25 -
    +Rule	sol87	1987	only	-	Aug	1	12:06:20s -0:06:20 -
    +Rule	sol87	1987	only	-	Aug	2	12:06:15s -0:06:15 -
    +Rule	sol87	1987	only	-	Aug	3	12:06:10s -0:06:10 -
    +Rule	sol87	1987	only	-	Aug	4	12:06:05s -0:06:05 -
    +Rule	sol87	1987	only	-	Aug	5	12:06:00s -0:06:00 -
    +Rule	sol87	1987	only	-	Aug	6	12:05:55s -0:05:55 -
    +Rule	sol87	1987	only	-	Aug	7	12:05:50s -0:05:50 -
    +Rule	sol87	1987	only	-	Aug	8	12:05:40s -0:05:40 -
    +Rule	sol87	1987	only	-	Aug	9	12:05:35s -0:05:35 -
    +Rule	sol87	1987	only	-	Aug	10	12:05:25s -0:05:25 -
    +Rule	sol87	1987	only	-	Aug	11	12:05:15s -0:05:15 -
    +Rule	sol87	1987	only	-	Aug	12	12:05:05s -0:05:05 -
    +Rule	sol87	1987	only	-	Aug	13	12:04:55s -0:04:55 -
    +Rule	sol87	1987	only	-	Aug	14	12:04:45s -0:04:45 -
    +Rule	sol87	1987	only	-	Aug	15	12:04:35s -0:04:35 -
    +Rule	sol87	1987	only	-	Aug	16	12:04:25s -0:04:25 -
    +Rule	sol87	1987	only	-	Aug	17	12:04:10s -0:04:10 -
    +Rule	sol87	1987	only	-	Aug	18	12:04:00s -0:04:00 -
    +Rule	sol87	1987	only	-	Aug	19	12:03:45s -0:03:45 -
    +Rule	sol87	1987	only	-	Aug	20	12:03:30s -0:03:30 -
    +Rule	sol87	1987	only	-	Aug	21	12:03:15s -0:03:15 -
    +Rule	sol87	1987	only	-	Aug	22	12:03:00s -0:03:00 -
    +Rule	sol87	1987	only	-	Aug	23	12:02:45s -0:02:45 -
    +Rule	sol87	1987	only	-	Aug	24	12:02:30s -0:02:30 -
    +Rule	sol87	1987	only	-	Aug	25	12:02:15s -0:02:15 -
    +Rule	sol87	1987	only	-	Aug	26	12:02:00s -0:02:00 -
    +Rule	sol87	1987	only	-	Aug	27	12:01:40s -0:01:40 -
    +Rule	sol87	1987	only	-	Aug	28	12:01:25s -0:01:25 -
    +Rule	sol87	1987	only	-	Aug	29	12:01:05s -0:01:05 -
    +Rule	sol87	1987	only	-	Aug	30	12:00:50s -0:00:50 -
    +Rule	sol87	1987	only	-	Aug	31	12:00:30s -0:00:30 -
    +Rule	sol87	1987	only	-	Sep	1	12:00:10s -0:00:10 -
    +Rule	sol87	1987	only	-	Sep	2	11:59:50s 0:00:10 -
    +Rule	sol87	1987	only	-	Sep	3	11:59:35s 0:00:25 -
    +Rule	sol87	1987	only	-	Sep	4	11:59:15s 0:00:45 -
    +Rule	sol87	1987	only	-	Sep	5	11:58:55s 0:01:05 -
    +Rule	sol87	1987	only	-	Sep	6	11:58:35s 0:01:25 -
    +Rule	sol87	1987	only	-	Sep	7	11:58:15s 0:01:45 -
    +Rule	sol87	1987	only	-	Sep	8	11:57:55s 0:02:05 -
    +Rule	sol87	1987	only	-	Sep	9	11:57:30s 0:02:30 -
    +Rule	sol87	1987	only	-	Sep	10	11:57:10s 0:02:50 -
    +Rule	sol87	1987	only	-	Sep	11	11:56:50s 0:03:10 -
    +Rule	sol87	1987	only	-	Sep	12	11:56:30s 0:03:30 -
    +Rule	sol87	1987	only	-	Sep	13	11:56:10s 0:03:50 -
    +Rule	sol87	1987	only	-	Sep	14	11:55:45s 0:04:15 -
    +Rule	sol87	1987	only	-	Sep	15	11:55:25s 0:04:35 -
    +Rule	sol87	1987	only	-	Sep	16	11:55:05s 0:04:55 -
    +Rule	sol87	1987	only	-	Sep	17	11:54:45s 0:05:15 -
    +Rule	sol87	1987	only	-	Sep	18	11:54:20s 0:05:40 -
    +Rule	sol87	1987	only	-	Sep	19	11:54:00s 0:06:00 -
    +Rule	sol87	1987	only	-	Sep	20	11:53:40s 0:06:20 -
    +Rule	sol87	1987	only	-	Sep	21	11:53:15s 0:06:45 -
    +Rule	sol87	1987	only	-	Sep	22	11:52:55s 0:07:05 -
    +Rule	sol87	1987	only	-	Sep	23	11:52:35s 0:07:25 -
    +Rule	sol87	1987	only	-	Sep	24	11:52:15s 0:07:45 -
    +Rule	sol87	1987	only	-	Sep	25	11:51:55s 0:08:05 -
    +Rule	sol87	1987	only	-	Sep	26	11:51:35s 0:08:25 -
    +Rule	sol87	1987	only	-	Sep	27	11:51:10s 0:08:50 -
    +Rule	sol87	1987	only	-	Sep	28	11:50:50s 0:09:10 -
    +Rule	sol87	1987	only	-	Sep	29	11:50:30s 0:09:30 -
    +Rule	sol87	1987	only	-	Sep	30	11:50:10s 0:09:50 -
    +Rule	sol87	1987	only	-	Oct	1	11:49:50s 0:10:10 -
    +Rule	sol87	1987	only	-	Oct	2	11:49:35s 0:10:25 -
    +Rule	sol87	1987	only	-	Oct	3	11:49:15s 0:10:45 -
    +Rule	sol87	1987	only	-	Oct	4	11:48:55s 0:11:05 -
    +Rule	sol87	1987	only	-	Oct	5	11:48:35s 0:11:25 -
    +Rule	sol87	1987	only	-	Oct	6	11:48:20s 0:11:40 -
    +Rule	sol87	1987	only	-	Oct	7	11:48:00s 0:12:00 -
    +Rule	sol87	1987	only	-	Oct	8	11:47:45s 0:12:15 -
    +Rule	sol87	1987	only	-	Oct	9	11:47:25s 0:12:35 -
    +Rule	sol87	1987	only	-	Oct	10	11:47:10s 0:12:50 -
    +Rule	sol87	1987	only	-	Oct	11	11:46:55s 0:13:05 -
    +Rule	sol87	1987	only	-	Oct	12	11:46:40s 0:13:20 -
    +Rule	sol87	1987	only	-	Oct	13	11:46:25s 0:13:35 -
    +Rule	sol87	1987	only	-	Oct	14	11:46:10s 0:13:50 -
    +Rule	sol87	1987	only	-	Oct	15	11:45:55s 0:14:05 -
    +Rule	sol87	1987	only	-	Oct	16	11:45:45s 0:14:15 -
    +Rule	sol87	1987	only	-	Oct	17	11:45:30s 0:14:30 -
    +Rule	sol87	1987	only	-	Oct	18	11:45:20s 0:14:40 -
    +Rule	sol87	1987	only	-	Oct	19	11:45:05s 0:14:55 -
    +Rule	sol87	1987	only	-	Oct	20	11:44:55s 0:15:05 -
    +Rule	sol87	1987	only	-	Oct	21	11:44:45s 0:15:15 -
    +Rule	sol87	1987	only	-	Oct	22	11:44:35s 0:15:25 -
    +Rule	sol87	1987	only	-	Oct	23	11:44:25s 0:15:35 -
    +Rule	sol87	1987	only	-	Oct	24	11:44:20s 0:15:40 -
    +Rule	sol87	1987	only	-	Oct	25	11:44:10s 0:15:50 -
    +Rule	sol87	1987	only	-	Oct	26	11:44:05s 0:15:55 -
    +Rule	sol87	1987	only	-	Oct	27	11:43:55s 0:16:05 -
    +Rule	sol87	1987	only	-	Oct	28	11:43:50s 0:16:10 -
    +Rule	sol87	1987	only	-	Oct	29	11:43:45s 0:16:15 -
    +Rule	sol87	1987	only	-	Oct	30	11:43:45s 0:16:15 -
    +Rule	sol87	1987	only	-	Oct	31	11:43:40s 0:16:20 -
    +Rule	sol87	1987	only	-	Nov	1	11:43:40s 0:16:20 -
    +Rule	sol87	1987	only	-	Nov	2	11:43:35s 0:16:25 -
    +Rule	sol87	1987	only	-	Nov	3	11:43:35s 0:16:25 -
    +Rule	sol87	1987	only	-	Nov	4	11:43:35s 0:16:25 -
    +Rule	sol87	1987	only	-	Nov	5	11:43:35s 0:16:25 -
    +Rule	sol87	1987	only	-	Nov	6	11:43:40s 0:16:20 -
    +Rule	sol87	1987	only	-	Nov	7	11:43:40s 0:16:20 -
    +Rule	sol87	1987	only	-	Nov	8	11:43:45s 0:16:15 -
    +Rule	sol87	1987	only	-	Nov	9	11:43:50s 0:16:10 -
    +Rule	sol87	1987	only	-	Nov	10	11:43:55s 0:16:05 -
    +Rule	sol87	1987	only	-	Nov	11	11:44:00s 0:16:00 -
    +Rule	sol87	1987	only	-	Nov	12	11:44:05s 0:15:55 -
    +Rule	sol87	1987	only	-	Nov	13	11:44:15s 0:15:45 -
    +Rule	sol87	1987	only	-	Nov	14	11:44:20s 0:15:40 -
    +Rule	sol87	1987	only	-	Nov	15	11:44:30s 0:15:30 -
    +Rule	sol87	1987	only	-	Nov	16	11:44:40s 0:15:20 -
    +Rule	sol87	1987	only	-	Nov	17	11:44:50s 0:15:10 -
    +Rule	sol87	1987	only	-	Nov	18	11:45:05s 0:14:55 -
    +Rule	sol87	1987	only	-	Nov	19	11:45:15s 0:14:45 -
    +Rule	sol87	1987	only	-	Nov	20	11:45:30s 0:14:30 -
    +Rule	sol87	1987	only	-	Nov	21	11:45:45s 0:14:15 -
    +Rule	sol87	1987	only	-	Nov	22	11:46:00s 0:14:00 -
    +Rule	sol87	1987	only	-	Nov	23	11:46:15s 0:13:45 -
    +Rule	sol87	1987	only	-	Nov	24	11:46:30s 0:13:30 -
    +Rule	sol87	1987	only	-	Nov	25	11:46:50s 0:13:10 -
    +Rule	sol87	1987	only	-	Nov	26	11:47:10s 0:12:50 -
    +Rule	sol87	1987	only	-	Nov	27	11:47:25s 0:12:35 -
    +Rule	sol87	1987	only	-	Nov	28	11:47:45s 0:12:15 -
    +Rule	sol87	1987	only	-	Nov	29	11:48:05s 0:11:55 -
    +Rule	sol87	1987	only	-	Nov	30	11:48:30s 0:11:30 -
    +Rule	sol87	1987	only	-	Dec	1	11:48:50s 0:11:10 -
    +Rule	sol87	1987	only	-	Dec	2	11:49:10s 0:10:50 -
    +Rule	sol87	1987	only	-	Dec	3	11:49:35s 0:10:25 -
    +Rule	sol87	1987	only	-	Dec	4	11:50:00s 0:10:00 -
    +Rule	sol87	1987	only	-	Dec	5	11:50:25s 0:09:35 -
    +Rule	sol87	1987	only	-	Dec	6	11:50:50s 0:09:10 -
    +Rule	sol87	1987	only	-	Dec	7	11:51:15s 0:08:45 -
    +Rule	sol87	1987	only	-	Dec	8	11:51:40s 0:08:20 -
    +Rule	sol87	1987	only	-	Dec	9	11:52:05s 0:07:55 -
    +Rule	sol87	1987	only	-	Dec	10	11:52:30s 0:07:30 -
    +Rule	sol87	1987	only	-	Dec	11	11:53:00s 0:07:00 -
    +Rule	sol87	1987	only	-	Dec	12	11:53:25s 0:06:35 -
    +Rule	sol87	1987	only	-	Dec	13	11:53:55s 0:06:05 -
    +Rule	sol87	1987	only	-	Dec	14	11:54:25s 0:05:35 -
    +Rule	sol87	1987	only	-	Dec	15	11:54:50s 0:05:10 -
    +Rule	sol87	1987	only	-	Dec	16	11:55:20s 0:04:40 -
    +Rule	sol87	1987	only	-	Dec	17	11:55:50s 0:04:10 -
    +Rule	sol87	1987	only	-	Dec	18	11:56:20s 0:03:40 -
    +Rule	sol87	1987	only	-	Dec	19	11:56:50s 0:03:10 -
    +Rule	sol87	1987	only	-	Dec	20	11:57:20s 0:02:40 -
    +Rule	sol87	1987	only	-	Dec	21	11:57:50s 0:02:10 -
    +Rule	sol87	1987	only	-	Dec	22	11:58:20s 0:01:40 -
    +Rule	sol87	1987	only	-	Dec	23	11:58:50s 0:01:10 -
    +Rule	sol87	1987	only	-	Dec	24	11:59:20s 0:00:40 -
    +Rule	sol87	1987	only	-	Dec	25	11:59:50s 0:00:10 -
    +Rule	sol87	1987	only	-	Dec	26	12:00:20s -0:00:20 -
    +Rule	sol87	1987	only	-	Dec	27	12:00:45s -0:00:45 -
    +Rule	sol87	1987	only	-	Dec	28	12:01:15s -0:01:15 -
    +Rule	sol87	1987	only	-	Dec	29	12:01:45s -0:01:45 -
    +Rule	sol87	1987	only	-	Dec	30	12:02:15s -0:02:15 -
    +Rule	sol87	1987	only	-	Dec	31	12:02:45s -0:02:45 -
    +
    +# Riyadh is at about 46 degrees 46 minutes East:  3 hrs, 7 mins, 4 secs
    +# Before and after 1987, we'll operate on local mean solar time.
    +
    +# Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
    +Zone	Asia/Riyadh87	3:07:04	-		zzz	1987
    +			3:07:04	sol87		zzz	1988
    +			3:07:04	-		zzz
    +# For backward compatibility...
    +Link	Asia/Riyadh87	Mideast/Riyadh87
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/solar88 b/jdk/test/sun/util/calendar/zi/tzdata/solar88
    new file mode 100644
    index 00000000000..71b60d5d74a
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/solar88
    @@ -0,0 +1,413 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# Apparent noon times below are for Riyadh; they're a bit off for other places.
    +# Times were computed using formulas in the U.S. Naval Observatory's
    +# Almanac for Computers 1988; the formulas "will give EqT to an accuracy of
    +# [plus or minus two] seconds during the current year."
    +#
    +# Rounding to the nearest five seconds results in fewer than
    +# 256 different "time types"--a limit that's faced because time types are
    +# stored on disk as unsigned chars.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	sol88	1988	only	-	Jan	1	12:03:15s -0:03:15 -
    +Rule	sol88	1988	only	-	Jan	2	12:03:40s -0:03:40 -
    +Rule	sol88	1988	only	-	Jan	3	12:04:10s -0:04:10 -
    +Rule	sol88	1988	only	-	Jan	4	12:04:40s -0:04:40 -
    +Rule	sol88	1988	only	-	Jan	5	12:05:05s -0:05:05 -
    +Rule	sol88	1988	only	-	Jan	6	12:05:30s -0:05:30 -
    +Rule	sol88	1988	only	-	Jan	7	12:06:00s -0:06:00 -
    +Rule	sol88	1988	only	-	Jan	8	12:06:25s -0:06:25 -
    +Rule	sol88	1988	only	-	Jan	9	12:06:50s -0:06:50 -
    +Rule	sol88	1988	only	-	Jan	10	12:07:15s -0:07:15 -
    +Rule	sol88	1988	only	-	Jan	11	12:07:40s -0:07:40 -
    +Rule	sol88	1988	only	-	Jan	12	12:08:05s -0:08:05 -
    +Rule	sol88	1988	only	-	Jan	13	12:08:25s -0:08:25 -
    +Rule	sol88	1988	only	-	Jan	14	12:08:50s -0:08:50 -
    +Rule	sol88	1988	only	-	Jan	15	12:09:10s -0:09:10 -
    +Rule	sol88	1988	only	-	Jan	16	12:09:30s -0:09:30 -
    +Rule	sol88	1988	only	-	Jan	17	12:09:50s -0:09:50 -
    +Rule	sol88	1988	only	-	Jan	18	12:10:10s -0:10:10 -
    +Rule	sol88	1988	only	-	Jan	19	12:10:30s -0:10:30 -
    +Rule	sol88	1988	only	-	Jan	20	12:10:50s -0:10:50 -
    +Rule	sol88	1988	only	-	Jan	21	12:11:05s -0:11:05 -
    +Rule	sol88	1988	only	-	Jan	22	12:11:25s -0:11:25 -
    +Rule	sol88	1988	only	-	Jan	23	12:11:40s -0:11:40 -
    +Rule	sol88	1988	only	-	Jan	24	12:11:55s -0:11:55 -
    +Rule	sol88	1988	only	-	Jan	25	12:12:10s -0:12:10 -
    +Rule	sol88	1988	only	-	Jan	26	12:12:25s -0:12:25 -
    +Rule	sol88	1988	only	-	Jan	27	12:12:40s -0:12:40 -
    +Rule	sol88	1988	only	-	Jan	28	12:12:50s -0:12:50 -
    +Rule	sol88	1988	only	-	Jan	29	12:13:00s -0:13:00 -
    +Rule	sol88	1988	only	-	Jan	30	12:13:10s -0:13:10 -
    +Rule	sol88	1988	only	-	Jan	31	12:13:20s -0:13:20 -
    +Rule	sol88	1988	only	-	Feb	1	12:13:30s -0:13:30 -
    +Rule	sol88	1988	only	-	Feb	2	12:13:40s -0:13:40 -
    +Rule	sol88	1988	only	-	Feb	3	12:13:45s -0:13:45 -
    +Rule	sol88	1988	only	-	Feb	4	12:13:55s -0:13:55 -
    +Rule	sol88	1988	only	-	Feb	5	12:14:00s -0:14:00 -
    +Rule	sol88	1988	only	-	Feb	6	12:14:05s -0:14:05 -
    +Rule	sol88	1988	only	-	Feb	7	12:14:10s -0:14:10 -
    +Rule	sol88	1988	only	-	Feb	8	12:14:10s -0:14:10 -
    +Rule	sol88	1988	only	-	Feb	9	12:14:15s -0:14:15 -
    +Rule	sol88	1988	only	-	Feb	10	12:14:15s -0:14:15 -
    +Rule	sol88	1988	only	-	Feb	11	12:14:15s -0:14:15 -
    +Rule	sol88	1988	only	-	Feb	12	12:14:15s -0:14:15 -
    +Rule	sol88	1988	only	-	Feb	13	12:14:15s -0:14:15 -
    +Rule	sol88	1988	only	-	Feb	14	12:14:15s -0:14:15 -
    +Rule	sol88	1988	only	-	Feb	15	12:14:10s -0:14:10 -
    +Rule	sol88	1988	only	-	Feb	16	12:14:10s -0:14:10 -
    +Rule	sol88	1988	only	-	Feb	17	12:14:05s -0:14:05 -
    +Rule	sol88	1988	only	-	Feb	18	12:14:00s -0:14:00 -
    +Rule	sol88	1988	only	-	Feb	19	12:13:55s -0:13:55 -
    +Rule	sol88	1988	only	-	Feb	20	12:13:50s -0:13:50 -
    +Rule	sol88	1988	only	-	Feb	21	12:13:45s -0:13:45 -
    +Rule	sol88	1988	only	-	Feb	22	12:13:40s -0:13:40 -
    +Rule	sol88	1988	only	-	Feb	23	12:13:30s -0:13:30 -
    +Rule	sol88	1988	only	-	Feb	24	12:13:20s -0:13:20 -
    +Rule	sol88	1988	only	-	Feb	25	12:13:15s -0:13:15 -
    +Rule	sol88	1988	only	-	Feb	26	12:13:05s -0:13:05 -
    +Rule	sol88	1988	only	-	Feb	27	12:12:55s -0:12:55 -
    +Rule	sol88	1988	only	-	Feb	28	12:12:45s -0:12:45 -
    +Rule	sol88	1988	only	-	Feb	29	12:12:30s -0:12:30 -
    +Rule	sol88	1988	only	-	Mar	1	12:12:20s -0:12:20 -
    +Rule	sol88	1988	only	-	Mar	2	12:12:10s -0:12:10 -
    +Rule	sol88	1988	only	-	Mar	3	12:11:55s -0:11:55 -
    +Rule	sol88	1988	only	-	Mar	4	12:11:45s -0:11:45 -
    +Rule	sol88	1988	only	-	Mar	5	12:11:30s -0:11:30 -
    +Rule	sol88	1988	only	-	Mar	6	12:11:15s -0:11:15 -
    +Rule	sol88	1988	only	-	Mar	7	12:11:00s -0:11:00 -
    +Rule	sol88	1988	only	-	Mar	8	12:10:45s -0:10:45 -
    +Rule	sol88	1988	only	-	Mar	9	12:10:30s -0:10:30 -
    +Rule	sol88	1988	only	-	Mar	10	12:10:15s -0:10:15 -
    +Rule	sol88	1988	only	-	Mar	11	12:10:00s -0:10:00 -
    +Rule	sol88	1988	only	-	Mar	12	12:09:45s -0:09:45 -
    +Rule	sol88	1988	only	-	Mar	13	12:09:30s -0:09:30 -
    +Rule	sol88	1988	only	-	Mar	14	12:09:10s -0:09:10 -
    +Rule	sol88	1988	only	-	Mar	15	12:08:55s -0:08:55 -
    +Rule	sol88	1988	only	-	Mar	16	12:08:40s -0:08:40 -
    +Rule	sol88	1988	only	-	Mar	17	12:08:20s -0:08:20 -
    +Rule	sol88	1988	only	-	Mar	18	12:08:05s -0:08:05 -
    +Rule	sol88	1988	only	-	Mar	19	12:07:45s -0:07:45 -
    +Rule	sol88	1988	only	-	Mar	20	12:07:30s -0:07:30 -
    +Rule	sol88	1988	only	-	Mar	21	12:07:10s -0:07:10 -
    +Rule	sol88	1988	only	-	Mar	22	12:06:50s -0:06:50 -
    +Rule	sol88	1988	only	-	Mar	23	12:06:35s -0:06:35 -
    +Rule	sol88	1988	only	-	Mar	24	12:06:15s -0:06:15 -
    +Rule	sol88	1988	only	-	Mar	25	12:06:00s -0:06:00 -
    +Rule	sol88	1988	only	-	Mar	26	12:05:40s -0:05:40 -
    +Rule	sol88	1988	only	-	Mar	27	12:05:20s -0:05:20 -
    +Rule	sol88	1988	only	-	Mar	28	12:05:05s -0:05:05 -
    +Rule	sol88	1988	only	-	Mar	29	12:04:45s -0:04:45 -
    +Rule	sol88	1988	only	-	Mar	30	12:04:25s -0:04:25 -
    +Rule	sol88	1988	only	-	Mar	31	12:04:10s -0:04:10 -
    +Rule	sol88	1988	only	-	Apr	1	12:03:50s -0:03:50 -
    +Rule	sol88	1988	only	-	Apr	2	12:03:35s -0:03:35 -
    +Rule	sol88	1988	only	-	Apr	3	12:03:15s -0:03:15 -
    +Rule	sol88	1988	only	-	Apr	4	12:03:00s -0:03:00 -
    +Rule	sol88	1988	only	-	Apr	5	12:02:40s -0:02:40 -
    +Rule	sol88	1988	only	-	Apr	6	12:02:25s -0:02:25 -
    +Rule	sol88	1988	only	-	Apr	7	12:02:05s -0:02:05 -
    +Rule	sol88	1988	only	-	Apr	8	12:01:50s -0:01:50 -
    +Rule	sol88	1988	only	-	Apr	9	12:01:35s -0:01:35 -
    +Rule	sol88	1988	only	-	Apr	10	12:01:15s -0:01:15 -
    +Rule	sol88	1988	only	-	Apr	11	12:01:00s -0:01:00 -
    +Rule	sol88	1988	only	-	Apr	12	12:00:45s -0:00:45 -
    +Rule	sol88	1988	only	-	Apr	13	12:00:30s -0:00:30 -
    +Rule	sol88	1988	only	-	Apr	14	12:00:15s -0:00:15 -
    +Rule	sol88	1988	only	-	Apr	15	12:00:00s 0:00:00 -
    +Rule	sol88	1988	only	-	Apr	16	11:59:45s 0:00:15 -
    +Rule	sol88	1988	only	-	Apr	17	11:59:30s 0:00:30 -
    +Rule	sol88	1988	only	-	Apr	18	11:59:20s 0:00:40 -
    +Rule	sol88	1988	only	-	Apr	19	11:59:05s 0:00:55 -
    +Rule	sol88	1988	only	-	Apr	20	11:58:55s 0:01:05 -
    +Rule	sol88	1988	only	-	Apr	21	11:58:40s 0:01:20 -
    +Rule	sol88	1988	only	-	Apr	22	11:58:30s 0:01:30 -
    +Rule	sol88	1988	only	-	Apr	23	11:58:15s 0:01:45 -
    +Rule	sol88	1988	only	-	Apr	24	11:58:05s 0:01:55 -
    +Rule	sol88	1988	only	-	Apr	25	11:57:55s 0:02:05 -
    +Rule	sol88	1988	only	-	Apr	26	11:57:45s 0:02:15 -
    +Rule	sol88	1988	only	-	Apr	27	11:57:35s 0:02:25 -
    +Rule	sol88	1988	only	-	Apr	28	11:57:30s 0:02:30 -
    +Rule	sol88	1988	only	-	Apr	29	11:57:20s 0:02:40 -
    +Rule	sol88	1988	only	-	Apr	30	11:57:10s 0:02:50 -
    +Rule	sol88	1988	only	-	May	1	11:57:05s 0:02:55 -
    +Rule	sol88	1988	only	-	May	2	11:56:55s 0:03:05 -
    +Rule	sol88	1988	only	-	May	3	11:56:50s 0:03:10 -
    +Rule	sol88	1988	only	-	May	4	11:56:45s 0:03:15 -
    +Rule	sol88	1988	only	-	May	5	11:56:40s 0:03:20 -
    +Rule	sol88	1988	only	-	May	6	11:56:35s 0:03:25 -
    +Rule	sol88	1988	only	-	May	7	11:56:30s 0:03:30 -
    +Rule	sol88	1988	only	-	May	8	11:56:25s 0:03:35 -
    +Rule	sol88	1988	only	-	May	9	11:56:25s 0:03:35 -
    +Rule	sol88	1988	only	-	May	10	11:56:20s 0:03:40 -
    +Rule	sol88	1988	only	-	May	11	11:56:20s 0:03:40 -
    +Rule	sol88	1988	only	-	May	12	11:56:20s 0:03:40 -
    +Rule	sol88	1988	only	-	May	13	11:56:20s 0:03:40 -
    +Rule	sol88	1988	only	-	May	14	11:56:20s 0:03:40 -
    +Rule	sol88	1988	only	-	May	15	11:56:20s 0:03:40 -
    +Rule	sol88	1988	only	-	May	16	11:56:20s 0:03:40 -
    +Rule	sol88	1988	only	-	May	17	11:56:20s 0:03:40 -
    +Rule	sol88	1988	only	-	May	18	11:56:25s 0:03:35 -
    +Rule	sol88	1988	only	-	May	19	11:56:25s 0:03:35 -
    +Rule	sol88	1988	only	-	May	20	11:56:30s 0:03:30 -
    +Rule	sol88	1988	only	-	May	21	11:56:35s 0:03:25 -
    +Rule	sol88	1988	only	-	May	22	11:56:40s 0:03:20 -
    +Rule	sol88	1988	only	-	May	23	11:56:45s 0:03:15 -
    +Rule	sol88	1988	only	-	May	24	11:56:50s 0:03:10 -
    +Rule	sol88	1988	only	-	May	25	11:56:55s 0:03:05 -
    +Rule	sol88	1988	only	-	May	26	11:57:00s 0:03:00 -
    +Rule	sol88	1988	only	-	May	27	11:57:05s 0:02:55 -
    +Rule	sol88	1988	only	-	May	28	11:57:15s 0:02:45 -
    +Rule	sol88	1988	only	-	May	29	11:57:20s 0:02:40 -
    +Rule	sol88	1988	only	-	May	30	11:57:30s 0:02:30 -
    +Rule	sol88	1988	only	-	May	31	11:57:40s 0:02:20 -
    +Rule	sol88	1988	only	-	Jun	1	11:57:50s 0:02:10 -
    +Rule	sol88	1988	only	-	Jun	2	11:57:55s 0:02:05 -
    +Rule	sol88	1988	only	-	Jun	3	11:58:05s 0:01:55 -
    +Rule	sol88	1988	only	-	Jun	4	11:58:15s 0:01:45 -
    +Rule	sol88	1988	only	-	Jun	5	11:58:30s 0:01:30 -
    +Rule	sol88	1988	only	-	Jun	6	11:58:40s 0:01:20 -
    +Rule	sol88	1988	only	-	Jun	7	11:58:50s 0:01:10 -
    +Rule	sol88	1988	only	-	Jun	8	11:59:00s 0:01:00 -
    +Rule	sol88	1988	only	-	Jun	9	11:59:15s 0:00:45 -
    +Rule	sol88	1988	only	-	Jun	10	11:59:25s 0:00:35 -
    +Rule	sol88	1988	only	-	Jun	11	11:59:35s 0:00:25 -
    +Rule	sol88	1988	only	-	Jun	12	11:59:50s 0:00:10 -
    +Rule	sol88	1988	only	-	Jun	13	12:00:00s 0:00:00 -
    +Rule	sol88	1988	only	-	Jun	14	12:00:15s -0:00:15 -
    +Rule	sol88	1988	only	-	Jun	15	12:00:25s -0:00:25 -
    +Rule	sol88	1988	only	-	Jun	16	12:00:40s -0:00:40 -
    +Rule	sol88	1988	only	-	Jun	17	12:00:55s -0:00:55 -
    +Rule	sol88	1988	only	-	Jun	18	12:01:05s -0:01:05 -
    +Rule	sol88	1988	only	-	Jun	19	12:01:20s -0:01:20 -
    +Rule	sol88	1988	only	-	Jun	20	12:01:30s -0:01:30 -
    +Rule	sol88	1988	only	-	Jun	21	12:01:45s -0:01:45 -
    +Rule	sol88	1988	only	-	Jun	22	12:02:00s -0:02:00 -
    +Rule	sol88	1988	only	-	Jun	23	12:02:10s -0:02:10 -
    +Rule	sol88	1988	only	-	Jun	24	12:02:25s -0:02:25 -
    +Rule	sol88	1988	only	-	Jun	25	12:02:35s -0:02:35 -
    +Rule	sol88	1988	only	-	Jun	26	12:02:50s -0:02:50 -
    +Rule	sol88	1988	only	-	Jun	27	12:03:00s -0:03:00 -
    +Rule	sol88	1988	only	-	Jun	28	12:03:15s -0:03:15 -
    +Rule	sol88	1988	only	-	Jun	29	12:03:25s -0:03:25 -
    +Rule	sol88	1988	only	-	Jun	30	12:03:40s -0:03:40 -
    +Rule	sol88	1988	only	-	Jul	1	12:03:50s -0:03:50 -
    +Rule	sol88	1988	only	-	Jul	2	12:04:00s -0:04:00 -
    +Rule	sol88	1988	only	-	Jul	3	12:04:10s -0:04:10 -
    +Rule	sol88	1988	only	-	Jul	4	12:04:25s -0:04:25 -
    +Rule	sol88	1988	only	-	Jul	5	12:04:35s -0:04:35 -
    +Rule	sol88	1988	only	-	Jul	6	12:04:45s -0:04:45 -
    +Rule	sol88	1988	only	-	Jul	7	12:04:55s -0:04:55 -
    +Rule	sol88	1988	only	-	Jul	8	12:05:05s -0:05:05 -
    +Rule	sol88	1988	only	-	Jul	9	12:05:10s -0:05:10 -
    +Rule	sol88	1988	only	-	Jul	10	12:05:20s -0:05:20 -
    +Rule	sol88	1988	only	-	Jul	11	12:05:30s -0:05:30 -
    +Rule	sol88	1988	only	-	Jul	12	12:05:35s -0:05:35 -
    +Rule	sol88	1988	only	-	Jul	13	12:05:45s -0:05:45 -
    +Rule	sol88	1988	only	-	Jul	14	12:05:50s -0:05:50 -
    +Rule	sol88	1988	only	-	Jul	15	12:05:55s -0:05:55 -
    +Rule	sol88	1988	only	-	Jul	16	12:06:00s -0:06:00 -
    +Rule	sol88	1988	only	-	Jul	17	12:06:05s -0:06:05 -
    +Rule	sol88	1988	only	-	Jul	18	12:06:10s -0:06:10 -
    +Rule	sol88	1988	only	-	Jul	19	12:06:15s -0:06:15 -
    +Rule	sol88	1988	only	-	Jul	20	12:06:20s -0:06:20 -
    +Rule	sol88	1988	only	-	Jul	21	12:06:25s -0:06:25 -
    +Rule	sol88	1988	only	-	Jul	22	12:06:25s -0:06:25 -
    +Rule	sol88	1988	only	-	Jul	23	12:06:25s -0:06:25 -
    +Rule	sol88	1988	only	-	Jul	24	12:06:30s -0:06:30 -
    +Rule	sol88	1988	only	-	Jul	25	12:06:30s -0:06:30 -
    +Rule	sol88	1988	only	-	Jul	26	12:06:30s -0:06:30 -
    +Rule	sol88	1988	only	-	Jul	27	12:06:30s -0:06:30 -
    +Rule	sol88	1988	only	-	Jul	28	12:06:30s -0:06:30 -
    +Rule	sol88	1988	only	-	Jul	29	12:06:25s -0:06:25 -
    +Rule	sol88	1988	only	-	Jul	30	12:06:25s -0:06:25 -
    +Rule	sol88	1988	only	-	Jul	31	12:06:20s -0:06:20 -
    +Rule	sol88	1988	only	-	Aug	1	12:06:15s -0:06:15 -
    +Rule	sol88	1988	only	-	Aug	2	12:06:15s -0:06:15 -
    +Rule	sol88	1988	only	-	Aug	3	12:06:10s -0:06:10 -
    +Rule	sol88	1988	only	-	Aug	4	12:06:05s -0:06:05 -
    +Rule	sol88	1988	only	-	Aug	5	12:05:55s -0:05:55 -
    +Rule	sol88	1988	only	-	Aug	6	12:05:50s -0:05:50 -
    +Rule	sol88	1988	only	-	Aug	7	12:05:45s -0:05:45 -
    +Rule	sol88	1988	only	-	Aug	8	12:05:35s -0:05:35 -
    +Rule	sol88	1988	only	-	Aug	9	12:05:25s -0:05:25 -
    +Rule	sol88	1988	only	-	Aug	10	12:05:20s -0:05:20 -
    +Rule	sol88	1988	only	-	Aug	11	12:05:10s -0:05:10 -
    +Rule	sol88	1988	only	-	Aug	12	12:05:00s -0:05:00 -
    +Rule	sol88	1988	only	-	Aug	13	12:04:50s -0:04:50 -
    +Rule	sol88	1988	only	-	Aug	14	12:04:35s -0:04:35 -
    +Rule	sol88	1988	only	-	Aug	15	12:04:25s -0:04:25 -
    +Rule	sol88	1988	only	-	Aug	16	12:04:15s -0:04:15 -
    +Rule	sol88	1988	only	-	Aug	17	12:04:00s -0:04:00 -
    +Rule	sol88	1988	only	-	Aug	18	12:03:50s -0:03:50 -
    +Rule	sol88	1988	only	-	Aug	19	12:03:35s -0:03:35 -
    +Rule	sol88	1988	only	-	Aug	20	12:03:20s -0:03:20 -
    +Rule	sol88	1988	only	-	Aug	21	12:03:05s -0:03:05 -
    +Rule	sol88	1988	only	-	Aug	22	12:02:50s -0:02:50 -
    +Rule	sol88	1988	only	-	Aug	23	12:02:35s -0:02:35 -
    +Rule	sol88	1988	only	-	Aug	24	12:02:20s -0:02:20 -
    +Rule	sol88	1988	only	-	Aug	25	12:02:00s -0:02:00 -
    +Rule	sol88	1988	only	-	Aug	26	12:01:45s -0:01:45 -
    +Rule	sol88	1988	only	-	Aug	27	12:01:30s -0:01:30 -
    +Rule	sol88	1988	only	-	Aug	28	12:01:10s -0:01:10 -
    +Rule	sol88	1988	only	-	Aug	29	12:00:50s -0:00:50 -
    +Rule	sol88	1988	only	-	Aug	30	12:00:35s -0:00:35 -
    +Rule	sol88	1988	only	-	Aug	31	12:00:15s -0:00:15 -
    +Rule	sol88	1988	only	-	Sep	1	11:59:55s 0:00:05 -
    +Rule	sol88	1988	only	-	Sep	2	11:59:35s 0:00:25 -
    +Rule	sol88	1988	only	-	Sep	3	11:59:20s 0:00:40 -
    +Rule	sol88	1988	only	-	Sep	4	11:59:00s 0:01:00 -
    +Rule	sol88	1988	only	-	Sep	5	11:58:40s 0:01:20 -
    +Rule	sol88	1988	only	-	Sep	6	11:58:20s 0:01:40 -
    +Rule	sol88	1988	only	-	Sep	7	11:58:00s 0:02:00 -
    +Rule	sol88	1988	only	-	Sep	8	11:57:35s 0:02:25 -
    +Rule	sol88	1988	only	-	Sep	9	11:57:15s 0:02:45 -
    +Rule	sol88	1988	only	-	Sep	10	11:56:55s 0:03:05 -
    +Rule	sol88	1988	only	-	Sep	11	11:56:35s 0:03:25 -
    +Rule	sol88	1988	only	-	Sep	12	11:56:15s 0:03:45 -
    +Rule	sol88	1988	only	-	Sep	13	11:55:50s 0:04:10 -
    +Rule	sol88	1988	only	-	Sep	14	11:55:30s 0:04:30 -
    +Rule	sol88	1988	only	-	Sep	15	11:55:10s 0:04:50 -
    +Rule	sol88	1988	only	-	Sep	16	11:54:50s 0:05:10 -
    +Rule	sol88	1988	only	-	Sep	17	11:54:25s 0:05:35 -
    +Rule	sol88	1988	only	-	Sep	18	11:54:05s 0:05:55 -
    +Rule	sol88	1988	only	-	Sep	19	11:53:45s 0:06:15 -
    +Rule	sol88	1988	only	-	Sep	20	11:53:25s 0:06:35 -
    +Rule	sol88	1988	only	-	Sep	21	11:53:00s 0:07:00 -
    +Rule	sol88	1988	only	-	Sep	22	11:52:40s 0:07:20 -
    +Rule	sol88	1988	only	-	Sep	23	11:52:20s 0:07:40 -
    +Rule	sol88	1988	only	-	Sep	24	11:52:00s 0:08:00 -
    +Rule	sol88	1988	only	-	Sep	25	11:51:40s 0:08:20 -
    +Rule	sol88	1988	only	-	Sep	26	11:51:15s 0:08:45 -
    +Rule	sol88	1988	only	-	Sep	27	11:50:55s 0:09:05 -
    +Rule	sol88	1988	only	-	Sep	28	11:50:35s 0:09:25 -
    +Rule	sol88	1988	only	-	Sep	29	11:50:15s 0:09:45 -
    +Rule	sol88	1988	only	-	Sep	30	11:49:55s 0:10:05 -
    +Rule	sol88	1988	only	-	Oct	1	11:49:35s 0:10:25 -
    +Rule	sol88	1988	only	-	Oct	2	11:49:20s 0:10:40 -
    +Rule	sol88	1988	only	-	Oct	3	11:49:00s 0:11:00 -
    +Rule	sol88	1988	only	-	Oct	4	11:48:40s 0:11:20 -
    +Rule	sol88	1988	only	-	Oct	5	11:48:25s 0:11:35 -
    +Rule	sol88	1988	only	-	Oct	6	11:48:05s 0:11:55 -
    +Rule	sol88	1988	only	-	Oct	7	11:47:50s 0:12:10 -
    +Rule	sol88	1988	only	-	Oct	8	11:47:30s 0:12:30 -
    +Rule	sol88	1988	only	-	Oct	9	11:47:15s 0:12:45 -
    +Rule	sol88	1988	only	-	Oct	10	11:47:00s 0:13:00 -
    +Rule	sol88	1988	only	-	Oct	11	11:46:45s 0:13:15 -
    +Rule	sol88	1988	only	-	Oct	12	11:46:30s 0:13:30 -
    +Rule	sol88	1988	only	-	Oct	13	11:46:15s 0:13:45 -
    +Rule	sol88	1988	only	-	Oct	14	11:46:00s 0:14:00 -
    +Rule	sol88	1988	only	-	Oct	15	11:45:45s 0:14:15 -
    +Rule	sol88	1988	only	-	Oct	16	11:45:35s 0:14:25 -
    +Rule	sol88	1988	only	-	Oct	17	11:45:20s 0:14:40 -
    +Rule	sol88	1988	only	-	Oct	18	11:45:10s 0:14:50 -
    +Rule	sol88	1988	only	-	Oct	19	11:45:00s 0:15:00 -
    +Rule	sol88	1988	only	-	Oct	20	11:44:45s 0:15:15 -
    +Rule	sol88	1988	only	-	Oct	21	11:44:40s 0:15:20 -
    +Rule	sol88	1988	only	-	Oct	22	11:44:30s 0:15:30 -
    +Rule	sol88	1988	only	-	Oct	23	11:44:20s 0:15:40 -
    +Rule	sol88	1988	only	-	Oct	24	11:44:10s 0:15:50 -
    +Rule	sol88	1988	only	-	Oct	25	11:44:05s 0:15:55 -
    +Rule	sol88	1988	only	-	Oct	26	11:44:00s 0:16:00 -
    +Rule	sol88	1988	only	-	Oct	27	11:43:55s 0:16:05 -
    +Rule	sol88	1988	only	-	Oct	28	11:43:50s 0:16:10 -
    +Rule	sol88	1988	only	-	Oct	29	11:43:45s 0:16:15 -
    +Rule	sol88	1988	only	-	Oct	30	11:43:40s 0:16:20 -
    +Rule	sol88	1988	only	-	Oct	31	11:43:40s 0:16:20 -
    +Rule	sol88	1988	only	-	Nov	1	11:43:35s 0:16:25 -
    +Rule	sol88	1988	only	-	Nov	2	11:43:35s 0:16:25 -
    +Rule	sol88	1988	only	-	Nov	3	11:43:35s 0:16:25 -
    +Rule	sol88	1988	only	-	Nov	4	11:43:35s 0:16:25 -
    +Rule	sol88	1988	only	-	Nov	5	11:43:40s 0:16:20 -
    +Rule	sol88	1988	only	-	Nov	6	11:43:40s 0:16:20 -
    +Rule	sol88	1988	only	-	Nov	7	11:43:45s 0:16:15 -
    +Rule	sol88	1988	only	-	Nov	8	11:43:45s 0:16:15 -
    +Rule	sol88	1988	only	-	Nov	9	11:43:50s 0:16:10 -
    +Rule	sol88	1988	only	-	Nov	10	11:44:00s 0:16:00 -
    +Rule	sol88	1988	only	-	Nov	11	11:44:05s 0:15:55 -
    +Rule	sol88	1988	only	-	Nov	12	11:44:10s 0:15:50 -
    +Rule	sol88	1988	only	-	Nov	13	11:44:20s 0:15:40 -
    +Rule	sol88	1988	only	-	Nov	14	11:44:30s 0:15:30 -
    +Rule	sol88	1988	only	-	Nov	15	11:44:40s 0:15:20 -
    +Rule	sol88	1988	only	-	Nov	16	11:44:50s 0:15:10 -
    +Rule	sol88	1988	only	-	Nov	17	11:45:00s 0:15:00 -
    +Rule	sol88	1988	only	-	Nov	18	11:45:15s 0:14:45 -
    +Rule	sol88	1988	only	-	Nov	19	11:45:25s 0:14:35 -
    +Rule	sol88	1988	only	-	Nov	20	11:45:40s 0:14:20 -
    +Rule	sol88	1988	only	-	Nov	21	11:45:55s 0:14:05 -
    +Rule	sol88	1988	only	-	Nov	22	11:46:10s 0:13:50 -
    +Rule	sol88	1988	only	-	Nov	23	11:46:30s 0:13:30 -
    +Rule	sol88	1988	only	-	Nov	24	11:46:45s 0:13:15 -
    +Rule	sol88	1988	only	-	Nov	25	11:47:05s 0:12:55 -
    +Rule	sol88	1988	only	-	Nov	26	11:47:20s 0:12:40 -
    +Rule	sol88	1988	only	-	Nov	27	11:47:40s 0:12:20 -
    +Rule	sol88	1988	only	-	Nov	28	11:48:00s 0:12:00 -
    +Rule	sol88	1988	only	-	Nov	29	11:48:25s 0:11:35 -
    +Rule	sol88	1988	only	-	Nov	30	11:48:45s 0:11:15 -
    +Rule	sol88	1988	only	-	Dec	1	11:49:05s 0:10:55 -
    +Rule	sol88	1988	only	-	Dec	2	11:49:30s 0:10:30 -
    +Rule	sol88	1988	only	-	Dec	3	11:49:55s 0:10:05 -
    +Rule	sol88	1988	only	-	Dec	4	11:50:15s 0:09:45 -
    +Rule	sol88	1988	only	-	Dec	5	11:50:40s 0:09:20 -
    +Rule	sol88	1988	only	-	Dec	6	11:51:05s 0:08:55 -
    +Rule	sol88	1988	only	-	Dec	7	11:51:35s 0:08:25 -
    +Rule	sol88	1988	only	-	Dec	8	11:52:00s 0:08:00 -
    +Rule	sol88	1988	only	-	Dec	9	11:52:25s 0:07:35 -
    +Rule	sol88	1988	only	-	Dec	10	11:52:55s 0:07:05 -
    +Rule	sol88	1988	only	-	Dec	11	11:53:20s 0:06:40 -
    +Rule	sol88	1988	only	-	Dec	12	11:53:50s 0:06:10 -
    +Rule	sol88	1988	only	-	Dec	13	11:54:15s 0:05:45 -
    +Rule	sol88	1988	only	-	Dec	14	11:54:45s 0:05:15 -
    +Rule	sol88	1988	only	-	Dec	15	11:55:15s 0:04:45 -
    +Rule	sol88	1988	only	-	Dec	16	11:55:45s 0:04:15 -
    +Rule	sol88	1988	only	-	Dec	17	11:56:15s 0:03:45 -
    +Rule	sol88	1988	only	-	Dec	18	11:56:40s 0:03:20 -
    +Rule	sol88	1988	only	-	Dec	19	11:57:10s 0:02:50 -
    +Rule	sol88	1988	only	-	Dec	20	11:57:40s 0:02:20 -
    +Rule	sol88	1988	only	-	Dec	21	11:58:10s 0:01:50 -
    +Rule	sol88	1988	only	-	Dec	22	11:58:40s 0:01:20 -
    +Rule	sol88	1988	only	-	Dec	23	11:59:10s 0:00:50 -
    +Rule	sol88	1988	only	-	Dec	24	11:59:40s 0:00:20 -
    +Rule	sol88	1988	only	-	Dec	25	12:00:10s -0:00:10 -
    +Rule	sol88	1988	only	-	Dec	26	12:00:40s -0:00:40 -
    +Rule	sol88	1988	only	-	Dec	27	12:01:10s -0:01:10 -
    +Rule	sol88	1988	only	-	Dec	28	12:01:40s -0:01:40 -
    +Rule	sol88	1988	only	-	Dec	29	12:02:10s -0:02:10 -
    +Rule	sol88	1988	only	-	Dec	30	12:02:35s -0:02:35 -
    +Rule	sol88	1988	only	-	Dec	31	12:03:05s -0:03:05 -
    +
    +# Riyadh is at about 46 degrees 46 minutes East:  3 hrs, 7 mins, 4 secs
    +# Before and after 1988, we'll operate on local mean solar time.
    +
    +# Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
    +Zone	Asia/Riyadh88	3:07:04	-		zzz	1988
    +			3:07:04	sol88		zzz	1989
    +			3:07:04	-		zzz
    +# For backward compatibility...
    +Link	Asia/Riyadh88	Mideast/Riyadh88
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/solar89 b/jdk/test/sun/util/calendar/zi/tzdata/solar89
    new file mode 100644
    index 00000000000..ae2bea8876a
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/solar89
    @@ -0,0 +1,418 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# Apparent noon times below are for Riyadh; they're a bit off for other places.
    +# Times were computed using a formula provided by the U. S. Naval Observatory:
    +#	eqt = -105.8 * sin(l) + 596.2 * sin(2 * l) + 4.4 * sin(3 * l)
    +#		-12.7 * sin(4 * l) - 429.0 * cos(l) - 2.1 * cos (2 * l)
    +#		+ 19.3 * cos(3 * l);
    +# where l is the "mean longitude of the Sun" given by
    +#	l = 279.642 degrees + 0.985647 * d
    +# and d is the interval in days from January 0, 0 hours Universal Time
    +# (equaling the day of the year plus the fraction of a day from zero hours).
    +# The accuracy of the formula is plus or minus three seconds.
    +#
    +# Rounding to the nearest five seconds results in fewer than
    +# 256 different "time types"--a limit that's faced because time types are
    +# stored on disk as unsigned chars.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	sol89	1989	only	-	Jan	1	12:03:35s -0:03:35 -
    +Rule	sol89	1989	only	-	Jan	2	12:04:05s -0:04:05 -
    +Rule	sol89	1989	only	-	Jan	3	12:04:30s -0:04:30 -
    +Rule	sol89	1989	only	-	Jan	4	12:05:00s -0:05:00 -
    +Rule	sol89	1989	only	-	Jan	5	12:05:25s -0:05:25 -
    +Rule	sol89	1989	only	-	Jan	6	12:05:50s -0:05:50 -
    +Rule	sol89	1989	only	-	Jan	7	12:06:15s -0:06:15 -
    +Rule	sol89	1989	only	-	Jan	8	12:06:45s -0:06:45 -
    +Rule	sol89	1989	only	-	Jan	9	12:07:10s -0:07:10 -
    +Rule	sol89	1989	only	-	Jan	10	12:07:35s -0:07:35 -
    +Rule	sol89	1989	only	-	Jan	11	12:07:55s -0:07:55 -
    +Rule	sol89	1989	only	-	Jan	12	12:08:20s -0:08:20 -
    +Rule	sol89	1989	only	-	Jan	13	12:08:45s -0:08:45 -
    +Rule	sol89	1989	only	-	Jan	14	12:09:05s -0:09:05 -
    +Rule	sol89	1989	only	-	Jan	15	12:09:25s -0:09:25 -
    +Rule	sol89	1989	only	-	Jan	16	12:09:45s -0:09:45 -
    +Rule	sol89	1989	only	-	Jan	17	12:10:05s -0:10:05 -
    +Rule	sol89	1989	only	-	Jan	18	12:10:25s -0:10:25 -
    +Rule	sol89	1989	only	-	Jan	19	12:10:45s -0:10:45 -
    +Rule	sol89	1989	only	-	Jan	20	12:11:05s -0:11:05 -
    +Rule	sol89	1989	only	-	Jan	21	12:11:20s -0:11:20 -
    +Rule	sol89	1989	only	-	Jan	22	12:11:35s -0:11:35 -
    +Rule	sol89	1989	only	-	Jan	23	12:11:55s -0:11:55 -
    +Rule	sol89	1989	only	-	Jan	24	12:12:10s -0:12:10 -
    +Rule	sol89	1989	only	-	Jan	25	12:12:20s -0:12:20 -
    +Rule	sol89	1989	only	-	Jan	26	12:12:35s -0:12:35 -
    +Rule	sol89	1989	only	-	Jan	27	12:12:50s -0:12:50 -
    +Rule	sol89	1989	only	-	Jan	28	12:13:00s -0:13:00 -
    +Rule	sol89	1989	only	-	Jan	29	12:13:10s -0:13:10 -
    +Rule	sol89	1989	only	-	Jan	30	12:13:20s -0:13:20 -
    +Rule	sol89	1989	only	-	Jan	31	12:13:30s -0:13:30 -
    +Rule	sol89	1989	only	-	Feb	1	12:13:40s -0:13:40 -
    +Rule	sol89	1989	only	-	Feb	2	12:13:45s -0:13:45 -
    +Rule	sol89	1989	only	-	Feb	3	12:13:55s -0:13:55 -
    +Rule	sol89	1989	only	-	Feb	4	12:14:00s -0:14:00 -
    +Rule	sol89	1989	only	-	Feb	5	12:14:05s -0:14:05 -
    +Rule	sol89	1989	only	-	Feb	6	12:14:10s -0:14:10 -
    +Rule	sol89	1989	only	-	Feb	7	12:14:10s -0:14:10 -
    +Rule	sol89	1989	only	-	Feb	8	12:14:15s -0:14:15 -
    +Rule	sol89	1989	only	-	Feb	9	12:14:15s -0:14:15 -
    +Rule	sol89	1989	only	-	Feb	10	12:14:20s -0:14:20 -
    +Rule	sol89	1989	only	-	Feb	11	12:14:20s -0:14:20 -
    +Rule	sol89	1989	only	-	Feb	12	12:14:20s -0:14:20 -
    +Rule	sol89	1989	only	-	Feb	13	12:14:15s -0:14:15 -
    +Rule	sol89	1989	only	-	Feb	14	12:14:15s -0:14:15 -
    +Rule	sol89	1989	only	-	Feb	15	12:14:10s -0:14:10 -
    +Rule	sol89	1989	only	-	Feb	16	12:14:10s -0:14:10 -
    +Rule	sol89	1989	only	-	Feb	17	12:14:05s -0:14:05 -
    +Rule	sol89	1989	only	-	Feb	18	12:14:00s -0:14:00 -
    +Rule	sol89	1989	only	-	Feb	19	12:13:55s -0:13:55 -
    +Rule	sol89	1989	only	-	Feb	20	12:13:50s -0:13:50 -
    +Rule	sol89	1989	only	-	Feb	21	12:13:40s -0:13:40 -
    +Rule	sol89	1989	only	-	Feb	22	12:13:35s -0:13:35 -
    +Rule	sol89	1989	only	-	Feb	23	12:13:25s -0:13:25 -
    +Rule	sol89	1989	only	-	Feb	24	12:13:15s -0:13:15 -
    +Rule	sol89	1989	only	-	Feb	25	12:13:05s -0:13:05 -
    +Rule	sol89	1989	only	-	Feb	26	12:12:55s -0:12:55 -
    +Rule	sol89	1989	only	-	Feb	27	12:12:45s -0:12:45 -
    +Rule	sol89	1989	only	-	Feb	28	12:12:35s -0:12:35 -
    +Rule	sol89	1989	only	-	Mar	1	12:12:25s -0:12:25 -
    +Rule	sol89	1989	only	-	Mar	2	12:12:10s -0:12:10 -
    +Rule	sol89	1989	only	-	Mar	3	12:12:00s -0:12:00 -
    +Rule	sol89	1989	only	-	Mar	4	12:11:45s -0:11:45 -
    +Rule	sol89	1989	only	-	Mar	5	12:11:35s -0:11:35 -
    +Rule	sol89	1989	only	-	Mar	6	12:11:20s -0:11:20 -
    +Rule	sol89	1989	only	-	Mar	7	12:11:05s -0:11:05 -
    +Rule	sol89	1989	only	-	Mar	8	12:10:50s -0:10:50 -
    +Rule	sol89	1989	only	-	Mar	9	12:10:35s -0:10:35 -
    +Rule	sol89	1989	only	-	Mar	10	12:10:20s -0:10:20 -
    +Rule	sol89	1989	only	-	Mar	11	12:10:05s -0:10:05 -
    +Rule	sol89	1989	only	-	Mar	12	12:09:50s -0:09:50 -
    +Rule	sol89	1989	only	-	Mar	13	12:09:30s -0:09:30 -
    +Rule	sol89	1989	only	-	Mar	14	12:09:15s -0:09:15 -
    +Rule	sol89	1989	only	-	Mar	15	12:09:00s -0:09:00 -
    +Rule	sol89	1989	only	-	Mar	16	12:08:40s -0:08:40 -
    +Rule	sol89	1989	only	-	Mar	17	12:08:25s -0:08:25 -
    +Rule	sol89	1989	only	-	Mar	18	12:08:05s -0:08:05 -
    +Rule	sol89	1989	only	-	Mar	19	12:07:50s -0:07:50 -
    +Rule	sol89	1989	only	-	Mar	20	12:07:30s -0:07:30 -
    +Rule	sol89	1989	only	-	Mar	21	12:07:15s -0:07:15 -
    +Rule	sol89	1989	only	-	Mar	22	12:06:55s -0:06:55 -
    +Rule	sol89	1989	only	-	Mar	23	12:06:35s -0:06:35 -
    +Rule	sol89	1989	only	-	Mar	24	12:06:20s -0:06:20 -
    +Rule	sol89	1989	only	-	Mar	25	12:06:00s -0:06:00 -
    +Rule	sol89	1989	only	-	Mar	26	12:05:40s -0:05:40 -
    +Rule	sol89	1989	only	-	Mar	27	12:05:25s -0:05:25 -
    +Rule	sol89	1989	only	-	Mar	28	12:05:05s -0:05:05 -
    +Rule	sol89	1989	only	-	Mar	29	12:04:50s -0:04:50 -
    +Rule	sol89	1989	only	-	Mar	30	12:04:30s -0:04:30 -
    +Rule	sol89	1989	only	-	Mar	31	12:04:10s -0:04:10 -
    +Rule	sol89	1989	only	-	Apr	1	12:03:55s -0:03:55 -
    +Rule	sol89	1989	only	-	Apr	2	12:03:35s -0:03:35 -
    +Rule	sol89	1989	only	-	Apr	3	12:03:20s -0:03:20 -
    +Rule	sol89	1989	only	-	Apr	4	12:03:00s -0:03:00 -
    +Rule	sol89	1989	only	-	Apr	5	12:02:45s -0:02:45 -
    +Rule	sol89	1989	only	-	Apr	6	12:02:25s -0:02:25 -
    +Rule	sol89	1989	only	-	Apr	7	12:02:10s -0:02:10 -
    +Rule	sol89	1989	only	-	Apr	8	12:01:50s -0:01:50 -
    +Rule	sol89	1989	only	-	Apr	9	12:01:35s -0:01:35 -
    +Rule	sol89	1989	only	-	Apr	10	12:01:20s -0:01:20 -
    +Rule	sol89	1989	only	-	Apr	11	12:01:05s -0:01:05 -
    +Rule	sol89	1989	only	-	Apr	12	12:00:50s -0:00:50 -
    +Rule	sol89	1989	only	-	Apr	13	12:00:35s -0:00:35 -
    +Rule	sol89	1989	only	-	Apr	14	12:00:20s -0:00:20 -
    +Rule	sol89	1989	only	-	Apr	15	12:00:05s -0:00:05 -
    +Rule	sol89	1989	only	-	Apr	16	11:59:50s 0:00:10 -
    +Rule	sol89	1989	only	-	Apr	17	11:59:35s 0:00:25 -
    +Rule	sol89	1989	only	-	Apr	18	11:59:20s 0:00:40 -
    +Rule	sol89	1989	only	-	Apr	19	11:59:10s 0:00:50 -
    +Rule	sol89	1989	only	-	Apr	20	11:58:55s 0:01:05 -
    +Rule	sol89	1989	only	-	Apr	21	11:58:45s 0:01:15 -
    +Rule	sol89	1989	only	-	Apr	22	11:58:30s 0:01:30 -
    +Rule	sol89	1989	only	-	Apr	23	11:58:20s 0:01:40 -
    +Rule	sol89	1989	only	-	Apr	24	11:58:10s 0:01:50 -
    +Rule	sol89	1989	only	-	Apr	25	11:58:00s 0:02:00 -
    +Rule	sol89	1989	only	-	Apr	26	11:57:50s 0:02:10 -
    +Rule	sol89	1989	only	-	Apr	27	11:57:40s 0:02:20 -
    +Rule	sol89	1989	only	-	Apr	28	11:57:30s 0:02:30 -
    +Rule	sol89	1989	only	-	Apr	29	11:57:20s 0:02:40 -
    +Rule	sol89	1989	only	-	Apr	30	11:57:15s 0:02:45 -
    +Rule	sol89	1989	only	-	May	1	11:57:05s 0:02:55 -
    +Rule	sol89	1989	only	-	May	2	11:57:00s 0:03:00 -
    +Rule	sol89	1989	only	-	May	3	11:56:50s 0:03:10 -
    +Rule	sol89	1989	only	-	May	4	11:56:45s 0:03:15 -
    +Rule	sol89	1989	only	-	May	5	11:56:40s 0:03:20 -
    +Rule	sol89	1989	only	-	May	6	11:56:35s 0:03:25 -
    +Rule	sol89	1989	only	-	May	7	11:56:30s 0:03:30 -
    +Rule	sol89	1989	only	-	May	8	11:56:30s 0:03:30 -
    +Rule	sol89	1989	only	-	May	9	11:56:25s 0:03:35 -
    +Rule	sol89	1989	only	-	May	10	11:56:25s 0:03:35 -
    +Rule	sol89	1989	only	-	May	11	11:56:20s 0:03:40 -
    +Rule	sol89	1989	only	-	May	12	11:56:20s 0:03:40 -
    +Rule	sol89	1989	only	-	May	13	11:56:20s 0:03:40 -
    +Rule	sol89	1989	only	-	May	14	11:56:20s 0:03:40 -
    +Rule	sol89	1989	only	-	May	15	11:56:20s 0:03:40 -
    +Rule	sol89	1989	only	-	May	16	11:56:20s 0:03:40 -
    +Rule	sol89	1989	only	-	May	17	11:56:20s 0:03:40 -
    +Rule	sol89	1989	only	-	May	18	11:56:25s 0:03:35 -
    +Rule	sol89	1989	only	-	May	19	11:56:25s 0:03:35 -
    +Rule	sol89	1989	only	-	May	20	11:56:30s 0:03:30 -
    +Rule	sol89	1989	only	-	May	21	11:56:35s 0:03:25 -
    +Rule	sol89	1989	only	-	May	22	11:56:35s 0:03:25 -
    +Rule	sol89	1989	only	-	May	23	11:56:40s 0:03:20 -
    +Rule	sol89	1989	only	-	May	24	11:56:45s 0:03:15 -
    +Rule	sol89	1989	only	-	May	25	11:56:55s 0:03:05 -
    +Rule	sol89	1989	only	-	May	26	11:57:00s 0:03:00 -
    +Rule	sol89	1989	only	-	May	27	11:57:05s 0:02:55 -
    +Rule	sol89	1989	only	-	May	28	11:57:15s 0:02:45 -
    +Rule	sol89	1989	only	-	May	29	11:57:20s 0:02:40 -
    +Rule	sol89	1989	only	-	May	30	11:57:30s 0:02:30 -
    +Rule	sol89	1989	only	-	May	31	11:57:35s 0:02:25 -
    +Rule	sol89	1989	only	-	Jun	1	11:57:45s 0:02:15 -
    +Rule	sol89	1989	only	-	Jun	2	11:57:55s 0:02:05 -
    +Rule	sol89	1989	only	-	Jun	3	11:58:05s 0:01:55 -
    +Rule	sol89	1989	only	-	Jun	4	11:58:15s 0:01:45 -
    +Rule	sol89	1989	only	-	Jun	5	11:58:25s 0:01:35 -
    +Rule	sol89	1989	only	-	Jun	6	11:58:35s 0:01:25 -
    +Rule	sol89	1989	only	-	Jun	7	11:58:45s 0:01:15 -
    +Rule	sol89	1989	only	-	Jun	8	11:59:00s 0:01:00 -
    +Rule	sol89	1989	only	-	Jun	9	11:59:10s 0:00:50 -
    +Rule	sol89	1989	only	-	Jun	10	11:59:20s 0:00:40 -
    +Rule	sol89	1989	only	-	Jun	11	11:59:35s 0:00:25 -
    +Rule	sol89	1989	only	-	Jun	12	11:59:45s 0:00:15 -
    +Rule	sol89	1989	only	-	Jun	13	12:00:00s 0:00:00 -
    +Rule	sol89	1989	only	-	Jun	14	12:00:10s -0:00:10 -
    +Rule	sol89	1989	only	-	Jun	15	12:00:25s -0:00:25 -
    +Rule	sol89	1989	only	-	Jun	16	12:00:35s -0:00:35 -
    +Rule	sol89	1989	only	-	Jun	17	12:00:50s -0:00:50 -
    +Rule	sol89	1989	only	-	Jun	18	12:01:05s -0:01:05 -
    +Rule	sol89	1989	only	-	Jun	19	12:01:15s -0:01:15 -
    +Rule	sol89	1989	only	-	Jun	20	12:01:30s -0:01:30 -
    +Rule	sol89	1989	only	-	Jun	21	12:01:40s -0:01:40 -
    +Rule	sol89	1989	only	-	Jun	22	12:01:55s -0:01:55 -
    +Rule	sol89	1989	only	-	Jun	23	12:02:10s -0:02:10 -
    +Rule	sol89	1989	only	-	Jun	24	12:02:20s -0:02:20 -
    +Rule	sol89	1989	only	-	Jun	25	12:02:35s -0:02:35 -
    +Rule	sol89	1989	only	-	Jun	26	12:02:45s -0:02:45 -
    +Rule	sol89	1989	only	-	Jun	27	12:03:00s -0:03:00 -
    +Rule	sol89	1989	only	-	Jun	28	12:03:10s -0:03:10 -
    +Rule	sol89	1989	only	-	Jun	29	12:03:25s -0:03:25 -
    +Rule	sol89	1989	only	-	Jun	30	12:03:35s -0:03:35 -
    +Rule	sol89	1989	only	-	Jul	1	12:03:45s -0:03:45 -
    +Rule	sol89	1989	only	-	Jul	2	12:04:00s -0:04:00 -
    +Rule	sol89	1989	only	-	Jul	3	12:04:10s -0:04:10 -
    +Rule	sol89	1989	only	-	Jul	4	12:04:20s -0:04:20 -
    +Rule	sol89	1989	only	-	Jul	5	12:04:30s -0:04:30 -
    +Rule	sol89	1989	only	-	Jul	6	12:04:40s -0:04:40 -
    +Rule	sol89	1989	only	-	Jul	7	12:04:50s -0:04:50 -
    +Rule	sol89	1989	only	-	Jul	8	12:05:00s -0:05:00 -
    +Rule	sol89	1989	only	-	Jul	9	12:05:10s -0:05:10 -
    +Rule	sol89	1989	only	-	Jul	10	12:05:20s -0:05:20 -
    +Rule	sol89	1989	only	-	Jul	11	12:05:25s -0:05:25 -
    +Rule	sol89	1989	only	-	Jul	12	12:05:35s -0:05:35 -
    +Rule	sol89	1989	only	-	Jul	13	12:05:40s -0:05:40 -
    +Rule	sol89	1989	only	-	Jul	14	12:05:50s -0:05:50 -
    +Rule	sol89	1989	only	-	Jul	15	12:05:55s -0:05:55 -
    +Rule	sol89	1989	only	-	Jul	16	12:06:00s -0:06:00 -
    +Rule	sol89	1989	only	-	Jul	17	12:06:05s -0:06:05 -
    +Rule	sol89	1989	only	-	Jul	18	12:06:10s -0:06:10 -
    +Rule	sol89	1989	only	-	Jul	19	12:06:15s -0:06:15 -
    +Rule	sol89	1989	only	-	Jul	20	12:06:20s -0:06:20 -
    +Rule	sol89	1989	only	-	Jul	21	12:06:20s -0:06:20 -
    +Rule	sol89	1989	only	-	Jul	22	12:06:25s -0:06:25 -
    +Rule	sol89	1989	only	-	Jul	23	12:06:25s -0:06:25 -
    +Rule	sol89	1989	only	-	Jul	24	12:06:30s -0:06:30 -
    +Rule	sol89	1989	only	-	Jul	25	12:06:30s -0:06:30 -
    +Rule	sol89	1989	only	-	Jul	26	12:06:30s -0:06:30 -
    +Rule	sol89	1989	only	-	Jul	27	12:06:30s -0:06:30 -
    +Rule	sol89	1989	only	-	Jul	28	12:06:30s -0:06:30 -
    +Rule	sol89	1989	only	-	Jul	29	12:06:25s -0:06:25 -
    +Rule	sol89	1989	only	-	Jul	30	12:06:25s -0:06:25 -
    +Rule	sol89	1989	only	-	Jul	31	12:06:20s -0:06:20 -
    +Rule	sol89	1989	only	-	Aug	1	12:06:20s -0:06:20 -
    +Rule	sol89	1989	only	-	Aug	2	12:06:15s -0:06:15 -
    +Rule	sol89	1989	only	-	Aug	3	12:06:10s -0:06:10 -
    +Rule	sol89	1989	only	-	Aug	4	12:06:05s -0:06:05 -
    +Rule	sol89	1989	only	-	Aug	5	12:06:00s -0:06:00 -
    +Rule	sol89	1989	only	-	Aug	6	12:05:50s -0:05:50 -
    +Rule	sol89	1989	only	-	Aug	7	12:05:45s -0:05:45 -
    +Rule	sol89	1989	only	-	Aug	8	12:05:35s -0:05:35 -
    +Rule	sol89	1989	only	-	Aug	9	12:05:30s -0:05:30 -
    +Rule	sol89	1989	only	-	Aug	10	12:05:20s -0:05:20 -
    +Rule	sol89	1989	only	-	Aug	11	12:05:10s -0:05:10 -
    +Rule	sol89	1989	only	-	Aug	12	12:05:00s -0:05:00 -
    +Rule	sol89	1989	only	-	Aug	13	12:04:50s -0:04:50 -
    +Rule	sol89	1989	only	-	Aug	14	12:04:40s -0:04:40 -
    +Rule	sol89	1989	only	-	Aug	15	12:04:30s -0:04:30 -
    +Rule	sol89	1989	only	-	Aug	16	12:04:15s -0:04:15 -
    +Rule	sol89	1989	only	-	Aug	17	12:04:05s -0:04:05 -
    +Rule	sol89	1989	only	-	Aug	18	12:03:50s -0:03:50 -
    +Rule	sol89	1989	only	-	Aug	19	12:03:35s -0:03:35 -
    +Rule	sol89	1989	only	-	Aug	20	12:03:25s -0:03:25 -
    +Rule	sol89	1989	only	-	Aug	21	12:03:10s -0:03:10 -
    +Rule	sol89	1989	only	-	Aug	22	12:02:55s -0:02:55 -
    +Rule	sol89	1989	only	-	Aug	23	12:02:40s -0:02:40 -
    +Rule	sol89	1989	only	-	Aug	24	12:02:20s -0:02:20 -
    +Rule	sol89	1989	only	-	Aug	25	12:02:05s -0:02:05 -
    +Rule	sol89	1989	only	-	Aug	26	12:01:50s -0:01:50 -
    +Rule	sol89	1989	only	-	Aug	27	12:01:30s -0:01:30 -
    +Rule	sol89	1989	only	-	Aug	28	12:01:15s -0:01:15 -
    +Rule	sol89	1989	only	-	Aug	29	12:00:55s -0:00:55 -
    +Rule	sol89	1989	only	-	Aug	30	12:00:40s -0:00:40 -
    +Rule	sol89	1989	only	-	Aug	31	12:00:20s -0:00:20 -
    +Rule	sol89	1989	only	-	Sep	1	12:00:00s 0:00:00 -
    +Rule	sol89	1989	only	-	Sep	2	11:59:45s 0:00:15 -
    +Rule	sol89	1989	only	-	Sep	3	11:59:25s 0:00:35 -
    +Rule	sol89	1989	only	-	Sep	4	11:59:05s 0:00:55 -
    +Rule	sol89	1989	only	-	Sep	5	11:58:45s 0:01:15 -
    +Rule	sol89	1989	only	-	Sep	6	11:58:25s 0:01:35 -
    +Rule	sol89	1989	only	-	Sep	7	11:58:05s 0:01:55 -
    +Rule	sol89	1989	only	-	Sep	8	11:57:45s 0:02:15 -
    +Rule	sol89	1989	only	-	Sep	9	11:57:20s 0:02:40 -
    +Rule	sol89	1989	only	-	Sep	10	11:57:00s 0:03:00 -
    +Rule	sol89	1989	only	-	Sep	11	11:56:40s 0:03:20 -
    +Rule	sol89	1989	only	-	Sep	12	11:56:20s 0:03:40 -
    +Rule	sol89	1989	only	-	Sep	13	11:56:00s 0:04:00 -
    +Rule	sol89	1989	only	-	Sep	14	11:55:35s 0:04:25 -
    +Rule	sol89	1989	only	-	Sep	15	11:55:15s 0:04:45 -
    +Rule	sol89	1989	only	-	Sep	16	11:54:55s 0:05:05 -
    +Rule	sol89	1989	only	-	Sep	17	11:54:35s 0:05:25 -
    +Rule	sol89	1989	only	-	Sep	18	11:54:10s 0:05:50 -
    +Rule	sol89	1989	only	-	Sep	19	11:53:50s 0:06:10 -
    +Rule	sol89	1989	only	-	Sep	20	11:53:30s 0:06:30 -
    +Rule	sol89	1989	only	-	Sep	21	11:53:10s 0:06:50 -
    +Rule	sol89	1989	only	-	Sep	22	11:52:45s 0:07:15 -
    +Rule	sol89	1989	only	-	Sep	23	11:52:25s 0:07:35 -
    +Rule	sol89	1989	only	-	Sep	24	11:52:05s 0:07:55 -
    +Rule	sol89	1989	only	-	Sep	25	11:51:45s 0:08:15 -
    +Rule	sol89	1989	only	-	Sep	26	11:51:25s 0:08:35 -
    +Rule	sol89	1989	only	-	Sep	27	11:51:05s 0:08:55 -
    +Rule	sol89	1989	only	-	Sep	28	11:50:40s 0:09:20 -
    +Rule	sol89	1989	only	-	Sep	29	11:50:20s 0:09:40 -
    +Rule	sol89	1989	only	-	Sep	30	11:50:00s 0:10:00 -
    +Rule	sol89	1989	only	-	Oct	1	11:49:45s 0:10:15 -
    +Rule	sol89	1989	only	-	Oct	2	11:49:25s 0:10:35 -
    +Rule	sol89	1989	only	-	Oct	3	11:49:05s 0:10:55 -
    +Rule	sol89	1989	only	-	Oct	4	11:48:45s 0:11:15 -
    +Rule	sol89	1989	only	-	Oct	5	11:48:30s 0:11:30 -
    +Rule	sol89	1989	only	-	Oct	6	11:48:10s 0:11:50 -
    +Rule	sol89	1989	only	-	Oct	7	11:47:50s 0:12:10 -
    +Rule	sol89	1989	only	-	Oct	8	11:47:35s 0:12:25 -
    +Rule	sol89	1989	only	-	Oct	9	11:47:20s 0:12:40 -
    +Rule	sol89	1989	only	-	Oct	10	11:47:00s 0:13:00 -
    +Rule	sol89	1989	only	-	Oct	11	11:46:45s 0:13:15 -
    +Rule	sol89	1989	only	-	Oct	12	11:46:30s 0:13:30 -
    +Rule	sol89	1989	only	-	Oct	13	11:46:15s 0:13:45 -
    +Rule	sol89	1989	only	-	Oct	14	11:46:00s 0:14:00 -
    +Rule	sol89	1989	only	-	Oct	15	11:45:50s 0:14:10 -
    +Rule	sol89	1989	only	-	Oct	16	11:45:35s 0:14:25 -
    +Rule	sol89	1989	only	-	Oct	17	11:45:20s 0:14:40 -
    +Rule	sol89	1989	only	-	Oct	18	11:45:10s 0:14:50 -
    +Rule	sol89	1989	only	-	Oct	19	11:45:00s 0:15:00 -
    +Rule	sol89	1989	only	-	Oct	20	11:44:50s 0:15:10 -
    +Rule	sol89	1989	only	-	Oct	21	11:44:40s 0:15:20 -
    +Rule	sol89	1989	only	-	Oct	22	11:44:30s 0:15:30 -
    +Rule	sol89	1989	only	-	Oct	23	11:44:20s 0:15:40 -
    +Rule	sol89	1989	only	-	Oct	24	11:44:10s 0:15:50 -
    +Rule	sol89	1989	only	-	Oct	25	11:44:05s 0:15:55 -
    +Rule	sol89	1989	only	-	Oct	26	11:44:00s 0:16:00 -
    +Rule	sol89	1989	only	-	Oct	27	11:43:50s 0:16:10 -
    +Rule	sol89	1989	only	-	Oct	28	11:43:45s 0:16:15 -
    +Rule	sol89	1989	only	-	Oct	29	11:43:40s 0:16:20 -
    +Rule	sol89	1989	only	-	Oct	30	11:43:40s 0:16:20 -
    +Rule	sol89	1989	only	-	Oct	31	11:43:35s 0:16:25 -
    +Rule	sol89	1989	only	-	Nov	1	11:43:35s 0:16:25 -
    +Rule	sol89	1989	only	-	Nov	2	11:43:35s 0:16:25 -
    +Rule	sol89	1989	only	-	Nov	3	11:43:30s 0:16:30 -
    +Rule	sol89	1989	only	-	Nov	4	11:43:35s 0:16:25 -
    +Rule	sol89	1989	only	-	Nov	5	11:43:35s 0:16:25 -
    +Rule	sol89	1989	only	-	Nov	6	11:43:35s 0:16:25 -
    +Rule	sol89	1989	only	-	Nov	7	11:43:40s 0:16:20 -
    +Rule	sol89	1989	only	-	Nov	8	11:43:45s 0:16:15 -
    +Rule	sol89	1989	only	-	Nov	9	11:43:50s 0:16:10 -
    +Rule	sol89	1989	only	-	Nov	10	11:43:55s 0:16:05 -
    +Rule	sol89	1989	only	-	Nov	11	11:44:00s 0:16:00 -
    +Rule	sol89	1989	only	-	Nov	12	11:44:05s 0:15:55 -
    +Rule	sol89	1989	only	-	Nov	13	11:44:15s 0:15:45 -
    +Rule	sol89	1989	only	-	Nov	14	11:44:25s 0:15:35 -
    +Rule	sol89	1989	only	-	Nov	15	11:44:35s 0:15:25 -
    +Rule	sol89	1989	only	-	Nov	16	11:44:45s 0:15:15 -
    +Rule	sol89	1989	only	-	Nov	17	11:44:55s 0:15:05 -
    +Rule	sol89	1989	only	-	Nov	18	11:45:10s 0:14:50 -
    +Rule	sol89	1989	only	-	Nov	19	11:45:20s 0:14:40 -
    +Rule	sol89	1989	only	-	Nov	20	11:45:35s 0:14:25 -
    +Rule	sol89	1989	only	-	Nov	21	11:45:50s 0:14:10 -
    +Rule	sol89	1989	only	-	Nov	22	11:46:05s 0:13:55 -
    +Rule	sol89	1989	only	-	Nov	23	11:46:25s 0:13:35 -
    +Rule	sol89	1989	only	-	Nov	24	11:46:40s 0:13:20 -
    +Rule	sol89	1989	only	-	Nov	25	11:47:00s 0:13:00 -
    +Rule	sol89	1989	only	-	Nov	26	11:47:20s 0:12:40 -
    +Rule	sol89	1989	only	-	Nov	27	11:47:35s 0:12:25 -
    +Rule	sol89	1989	only	-	Nov	28	11:47:55s 0:12:05 -
    +Rule	sol89	1989	only	-	Nov	29	11:48:20s 0:11:40 -
    +Rule	sol89	1989	only	-	Nov	30	11:48:40s 0:11:20 -
    +Rule	sol89	1989	only	-	Dec	1	11:49:00s 0:11:00 -
    +Rule	sol89	1989	only	-	Dec	2	11:49:25s 0:10:35 -
    +Rule	sol89	1989	only	-	Dec	3	11:49:50s 0:10:10 -
    +Rule	sol89	1989	only	-	Dec	4	11:50:15s 0:09:45 -
    +Rule	sol89	1989	only	-	Dec	5	11:50:35s 0:09:25 -
    +Rule	sol89	1989	only	-	Dec	6	11:51:00s 0:09:00 -
    +Rule	sol89	1989	only	-	Dec	7	11:51:30s 0:08:30 -
    +Rule	sol89	1989	only	-	Dec	8	11:51:55s 0:08:05 -
    +Rule	sol89	1989	only	-	Dec	9	11:52:20s 0:07:40 -
    +Rule	sol89	1989	only	-	Dec	10	11:52:50s 0:07:10 -
    +Rule	sol89	1989	only	-	Dec	11	11:53:15s 0:06:45 -
    +Rule	sol89	1989	only	-	Dec	12	11:53:45s 0:06:15 -
    +Rule	sol89	1989	only	-	Dec	13	11:54:10s 0:05:50 -
    +Rule	sol89	1989	only	-	Dec	14	11:54:40s 0:05:20 -
    +Rule	sol89	1989	only	-	Dec	15	11:55:10s 0:04:50 -
    +Rule	sol89	1989	only	-	Dec	16	11:55:40s 0:04:20 -
    +Rule	sol89	1989	only	-	Dec	17	11:56:05s 0:03:55 -
    +Rule	sol89	1989	only	-	Dec	18	11:56:35s 0:03:25 -
    +Rule	sol89	1989	only	-	Dec	19	11:57:05s 0:02:55 -
    +Rule	sol89	1989	only	-	Dec	20	11:57:35s 0:02:25 -
    +Rule	sol89	1989	only	-	Dec	21	11:58:05s 0:01:55 -
    +Rule	sol89	1989	only	-	Dec	22	11:58:35s 0:01:25 -
    +Rule	sol89	1989	only	-	Dec	23	11:59:05s 0:00:55 -
    +Rule	sol89	1989	only	-	Dec	24	11:59:35s 0:00:25 -
    +Rule	sol89	1989	only	-	Dec	25	12:00:05s -0:00:05 -
    +Rule	sol89	1989	only	-	Dec	26	12:00:35s -0:00:35 -
    +Rule	sol89	1989	only	-	Dec	27	12:01:05s -0:01:05 -
    +Rule	sol89	1989	only	-	Dec	28	12:01:35s -0:01:35 -
    +Rule	sol89	1989	only	-	Dec	29	12:02:00s -0:02:00 -
    +Rule	sol89	1989	only	-	Dec	30	12:02:30s -0:02:30 -
    +Rule	sol89	1989	only	-	Dec	31	12:03:00s -0:03:00 -
    +
    +# Riyadh is at about 46 degrees 46 minutes East:  3 hrs, 7 mins, 4 secs
    +# Before and after 1989, we'll operate on local mean solar time.
    +
    +# Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
    +Zone	Asia/Riyadh89	3:07:04	-		zzz	1989
    +			3:07:04	sol89		zzz	1990
    +			3:07:04	-		zzz
    +# For backward compatibility...
    +Link	Asia/Riyadh89	Mideast/Riyadh89
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/southamerica b/jdk/test/sun/util/calendar/zi/tzdata/southamerica
    new file mode 100644
    index 00000000000..0d6797eab6b
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/southamerica
    @@ -0,0 +1,1734 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# This data is by no means authoritative; if you think you know better,
    +# go ahead and edit the file (and please send any changes to
    +# tz@elsie.nci.nih.gov for general use in the future).
    +
    +# From Paul Eggert (2006-03-22):
    +# A good source for time zone historical data outside the U.S. is
    +# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
    +# San Diego: ACS Publications, Inc. (2003).
    +#
    +# Gwillim Law writes that a good source
    +# for recent time zone data is the International Air Transport
    +# Association's Standard Schedules Information Manual (IATA SSIM),
    +# published semiannually.  Law sent in several helpful summaries
    +# of the IATA's data after 1990.
    +#
    +# Except where otherwise noted, Shanks & Pottenger is the source for
    +# entries through 1990, and IATA SSIM is the source for entries afterwards.
    +#
    +# Earlier editions of these tables used the North American style (e.g. ARST and
    +# ARDT for Argentine Standard and Daylight Time), but the following quote
    +# suggests that it's better to use European style (e.g. ART and ARST).
    +#	I suggest the use of _Summer time_ instead of the more cumbersome
    +#	_daylight-saving time_.  _Summer time_ seems to be in general use
    +#	in Europe and South America.
    +#	-- E O Cutler, _New York Times_ (1937-02-14), quoted in
    +#	H L Mencken, _The American Language: Supplement I_ (1960), p 466
    +#
    +# Earlier editions of these tables also used the North American style
    +# for time zones in Brazil, but this was incorrect, as Brazilians say
    +# "summer time".  Reinaldo Goulart, a Sao Paulo businessman active in
    +# the railroad sector, writes (1999-07-06):
    +#	The subject of time zones is currently a matter of discussion/debate in
    +#	Brazil.  Let's say that "the Brasilia time" is considered the
    +#	"official time" because Brasilia is the capital city.
    +#	The other three time zones are called "Brasilia time "minus one" or
    +#	"plus one" or "plus two".  As far as I know there is no such
    +#	name/designation as "Eastern Time" or "Central Time".
    +# So I invented the following (English-language) abbreviations for now.
    +# Corrections are welcome!
    +#		std	dst
    +#	-2:00	FNT	FNST	Fernando de Noronha
    +#	-3:00	BRT	BRST	Brasilia
    +#	-4:00	AMT	AMST	Amazon
    +#	-5:00	ACT	ACST	Acre
    +
    +###############################################################################
    +
    +###############################################################################
    +
    +# Argentina
    +
    +# From Bob Devine (1988-01-28):
    +# Argentina: first Sunday in October to first Sunday in April since 1976.
    +# Double Summer time from 1969 to 1974.  Switches at midnight.
    +
    +# From U. S. Naval Observatory (1988-01-199):
    +# ARGENTINA           3 H BEHIND   UTC
    +
    +# From Hernan G. Otero (1995-06-26):
    +# I am sending modifications to the Argentine time zone table...
    +# AR was chosen because they are the ISO letters that represent Argentina.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Arg	1930	only	-	Dec	 1	0:00	1:00	S
    +Rule	Arg	1931	only	-	Apr	 1	0:00	0	-
    +Rule	Arg	1931	only	-	Oct	15	0:00	1:00	S
    +Rule	Arg	1932	1940	-	Mar	 1	0:00	0	-
    +Rule	Arg	1932	1939	-	Nov	 1	0:00	1:00	S
    +Rule	Arg	1940	only	-	Jul	 1	0:00	1:00	S
    +Rule	Arg	1941	only	-	Jun	15	0:00	0	-
    +Rule	Arg	1941	only	-	Oct	15	0:00	1:00	S
    +Rule	Arg	1943	only	-	Aug	 1	0:00	0	-
    +Rule	Arg	1943	only	-	Oct	15	0:00	1:00	S
    +Rule	Arg	1946	only	-	Mar	 1	0:00	0	-
    +Rule	Arg	1946	only	-	Oct	 1	0:00	1:00	S
    +Rule	Arg	1963	only	-	Oct	 1	0:00	0	-
    +Rule	Arg	1963	only	-	Dec	15	0:00	1:00	S
    +Rule	Arg	1964	1966	-	Mar	 1	0:00	0	-
    +Rule	Arg	1964	1966	-	Oct	15	0:00	1:00	S
    +Rule	Arg	1967	only	-	Apr	 2	0:00	0	-
    +Rule	Arg	1967	1968	-	Oct	Sun>=1	0:00	1:00	S
    +Rule	Arg	1968	1969	-	Apr	Sun>=1	0:00	0	-
    +Rule	Arg	1974	only	-	Jan	23	0:00	1:00	S
    +Rule	Arg	1974	only	-	May	 1	0:00	0	-
    +Rule	Arg	1988	only	-	Dec	 1	0:00	1:00	S
    +#
    +# From Hernan G. Otero (1995-06-26):
    +# These corrections were contributed by InterSoft Argentina S.A.,
    +# obtaining the data from the:
    +# Talleres de Hidrografia Naval Argentina
    +# (Argentine Naval Hydrography Institute)
    +Rule	Arg	1989	1993	-	Mar	Sun>=1	0:00	0	-
    +Rule	Arg	1989	1992	-	Oct	Sun>=15	0:00	1:00	S
    +#
    +# From Hernan G. Otero (1995-06-26):
    +# From this moment on, the law that mandated the daylight saving
    +# time corrections was derogated and no more modifications
    +# to the time zones (for daylight saving) are now made.
    +#
    +# From Rives McDow (2000-01-10):
    +# On October 3, 1999, 0:00 local, Argentina implemented daylight savings time,
    +# which did not result in the switch of a time zone, as they stayed 9 hours
    +# from the International Date Line.
    +Rule	Arg	1999	only	-	Oct	Sun>=1	0:00	1:00	S
    +# From Paul Eggert (2007-12-28):
    +# DST was set to expire on March 5, not March 3, but since it was converted
    +# to standard time on March 3 it's more convenient for us to pretend that
    +# it ended on March 3.
    +Rule	Arg	2000	only	-	Mar	3	0:00	0	-
    +#
    +# From Peter Gradelski via Steffen Thorsen (2000-03-01):
    +# We just checked with our Sao Paulo office and they say the government of
    +# Argentina decided not to become one of the countries that go on or off DST.
    +# So Buenos Aires should be -3 hours from GMT at all times.
    +#
    +# From Fabian L. Arce Jofre (2000-04-04):
    +# The law that claimed DST for Argentina was derogated by President Fernando
    +# de la Rua on March 2, 2000, because it would make people spend more energy
    +# in the winter time, rather than less.  The change took effect on March 3.
    +#
    +# From Mariano Absatz (2001-06-06):
    +# one of the major newspapers here in Argentina said that the 1999
    +# Timezone Law (which never was effectively applied) will (would?) be
    +# in effect.... The article is at
    +# http://ar.clarin.com/diario/2001-06-06/e-01701.htm
    +# ... The Law itself is "Ley No 25155", sanctioned on 1999-08-25, enacted
    +# 1999-09-17, and published 1999-09-21.  The official publication is at:
    +# http://www.boletin.jus.gov.ar/BON/Primera/1999/09-Septiembre/21/PDF/BO21-09-99LEG.PDF
    +# Regretfully, you have to subscribe (and pay) for the on-line version....
    +#
    +# (2001-06-12):
    +# the timezone for Argentina will not change next Sunday.
    +# Apparently it will do so on Sunday 24th....
    +# http://ar.clarin.com/diario/2001-06-12/s-03501.htm
    +#
    +# (2001-06-25):
    +# Last Friday (yes, the last working day before the date of the change), the
    +# Senate annulled the 1999 law that introduced the changes later postponed.
    +# http://www.clarin.com.ar/diario/2001-06-22/s-03601.htm
    +# It remains the vote of the Deputies..., but it will be the same....
    +# This kind of things had always been done this way in Argentina.
    +# We are still -03:00 all year round in all of the country.
    +#
    +# From Steffen Thorsen (2007-12-21):
    +# A user (Leonardo Chaim) reported that Argentina will adopt DST....
    +# all of the country (all Zone-entries) are affected.  News reports like
    +# http://www.lanacion.com.ar/opinion/nota.asp?nota_id=973037 indicate
    +# that Argentina will use DST next year as well, from October to
    +# March, although exact rules are not given.
    +#
    +# From Jesper Norgaard Welen (2007-12-26)
    +# The last hurdle of Argentina DST is over, the proposal was approved in
    +# the lower chamber too (Deputados) with a vote 192 for and 2 against.
    +# By the way thanks to Mariano Absatz and Daniel Mario Vega for the link to
    +# the original scanned proposal, where the dates and the zero hours are
    +# clear and unambiguous...This is the article about final approval:
    +# 
    +# http://www.lanacion.com.ar/politica/nota.asp?nota_id=973996
    +# 
    +#
    +# From Paul Eggert (2007-12-22):
    +# For dates after mid-2008, the following rules are my guesses and
    +# are quite possibly wrong, but are more likely than no DST at all.
    +
    +# From Alexander Krivenyshev (2008-09-05):
    +# As per message from Carlos Alberto Fonseca Arauz (Nicaragua),
    +# Argentina will start DST on Sunday October 19, 2008.
    +#
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_argentina03.html
    +# 
    +# OR
    +# 
    +# http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish)
    +# 
    +
    +# From Rodrigo Severo (2008-10-06):
    +# Here is some info available at a Gentoo bug related to TZ on Argentina's DST:
    +# ...
    +# ------- Comment #1 from [jmdocile]  2008-10-06 16:28 0000 -------
    +# Hi, there is a problem with timezone-data-2008e and maybe with
    +# timezone-data-2008f
    +# Argentinian law [Number] 25.155 is no longer valid.
    +# 
    +# http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm
    +# 
    +# The new one is law [Number] 26.350
    +# 
    +# http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm
    +# 
    +# So there is no summer time in Argentina for now.
    +
    +# From Mariano Absatz (2008-10-20):
    +# Decree 1693/2008 applies Law 26.350 for the summer 2008/2009 establishing DST in Argentina
    +# From 2008-10-19 until 2009-03-15
    +# 
    +# http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=16102008&pi=3&pf=4&s=0&sec=01
    +# 
    +#
    +# Decree 1705/2008 excepting 12 Provinces from applying DST in the summer 2008/2009:
    +# Catamarca, La Rioja, Mendoza, Salta, San Juan, San Luis, La Pampa, Neuquen, Rio Negro, Chubut, Santa Cruz
    +# and Tierra del Fuego
    +# 
    +# http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=17102008&pi=1&pf=1&s=0&sec=01
    +# 
    +#
    +# Press release 235 dated Saturday October 18th, from the Government of the Province of Jujuy saying
    +# it will not apply DST either (even when it was not included in Decree 1705/2008)
    +# 
    +# http://www.jujuy.gov.ar/index2/partes_prensa/18_10_08/235-181008.doc
    +# 
    +
    +# From fullinet (2009-10-18):
    +# As announced in
    +# 
    +# http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356
    +# 
    +# (an official .gob.ar) under title: "Sin Cambio de Hora" (english: "No hour change")
    +#
    +# "Por el momento, el Gobierno Nacional resolvio no modificar la hora
    +# oficial, decision que estaba en estudio para su implementacion el
    +# domingo 18 de octubre. Desde el Ministerio de Planificacion se anuncio
    +# que la Argentina hoy, en estas condiciones meteorologicas, no necesita
    +# la modificacion del huso horario, ya que 2009 nos encuentra con
    +# crecimiento en la produccion y distribucion energetica."
    +
    +Rule	Arg	2007	only	-	Dec	30	0:00	1:00	S
    +Rule	Arg	2008	2009	-	Mar	Sun>=15	0:00	0	-
    +Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
    +
    +# From Mariano Absatz (2004-05-21):
    +# Today it was officially published that the Province of Mendoza is changing
    +# its timezone this winter... starting tomorrow night....
    +# http://www.gobernac.mendoza.gov.ar/boletin/pdf/20040521-27158-normas.pdf
    +# From Paul Eggert (2004-05-24):
    +# It's Law No. 7,210.  This change is due to a public power emergency, so for
    +# now we'll assume it's for this year only.
    +#
    +# From Paul Eggert (2006-03-22):
    +# 
    +# Hora de verano para la Republica Argentina (2003-06-08)
    +#  says that standard time in Argentina from 1894-10-31
    +# to 1920-05-01 was -4:16:48.25.  Go with this more-precise value
    +# over Shanks & Pottenger.
    +#
    +# From Mariano Absatz (2004-06-05):
    +# These media articles from a major newspaper mostly cover the current state:
    +# http://www.lanacion.com.ar/04/05/27/de_604825.asp
    +# http://www.lanacion.com.ar/04/05/28/de_605203.asp
    +#
    +# The following eight (8) provinces pulled clocks back to UTC-04:00 at
    +# midnight Monday May 31st. (that is, the night between 05/31 and 06/01).
    +# Apparently, all nine provinces would go back to UTC-03:00 at the same
    +# time in October 17th.
    +#
    +# Catamarca, Chubut, La Rioja, San Juan, San Luis, Santa Cruz,
    +# Tierra del Fuego, Tucuman.
    +#
    +# From Mariano Absatz (2004-06-14):
    +# ... this weekend, the Province of Tucuman decided it'd go back to UTC-03:00
    +# yesterday midnight (that is, at 24:00 Saturday 12th), since the people's
    +# annoyance with the change is much higher than the power savings obtained....
    +#
    +# From Gwillim Law (2004-06-14):
    +# http://www.lanacion.com.ar/04/06/10/de_609078.asp ...
    +#     "The time change in Tierra del Fuego was a conflicted decision from
    +#   the start.  The government had decreed that the measure would take
    +#   effect on June 1, but a normative error forced the new time to begin
    +#   three days earlier, from a Saturday to a Sunday....
    +# Our understanding was that the change was originally scheduled to take place
    +# on June 1 at 00:00 in Chubut, Santa Cruz, Tierra del Fuego (and some other
    +# provinces).  Sunday was May 30, only two days earlier.  So the article
    +# contains a contradiction.  I would give more credence to the Saturday/Sunday
    +# date than the "three days earlier" phrase, and conclude that Tierra del
    +# Fuego set its clocks back at 2004-05-30 00:00.
    +#
    +# From Steffen Thorsen (2004-10-05):
    +# The previous law 7210 which changed the province of Mendoza's time zone
    +# back in May have been modified slightly in a new law 7277, which set the
    +# new end date to 2004-09-26 (original date was 2004-10-17).
    +# http://www.gobernac.mendoza.gov.ar/boletin/pdf/20040924-27244-normas.pdf
    +#
    +# From Mariano Absatz (2004-10-05):
    +# San Juan changed from UTC-03:00 to UTC-04:00 at midnight between
    +# Sunday, May 30th and Monday, May 31st.  It changed back to UTC-03:00
    +# at midnight between Saturday, July 24th and Sunday, July 25th....
    +# http://www.sanjuan.gov.ar/prensa/archivo/000329.html
    +# http://www.sanjuan.gov.ar/prensa/archivo/000426.html
    +# http://www.sanjuan.gov.ar/prensa/archivo/000441.html
    +
    +# From Alex Krivenyshev (2008-01-17):
    +# Here are articles that Argentina Province San Luis is planning to end DST
    +# as earlier as upcoming Monday January 21, 2008 or February 2008:
    +#
    +# Provincia argentina retrasa reloj y marca diferencia con resto del pais
    +# (Argentine Province delayed clock and mark difference with the rest of the
    +# country)
    +# 
    +# http://cl.invertia.com/noticias/noticia.aspx?idNoticia=200801171849_EFE_ET4373&idtel
    +# 
    +#
    +# Es inminente que en San Luis atrasen una hora los relojes
    +# (It is imminent in San Luis clocks one hour delay)
    +# 
    +# http://www.lagaceta.com.ar/vernotae.asp?id_nota=253414
    +# 
    +#
    +# 
    +# http://www.worldtimezone.net/dst_news/dst_news_argentina02.html
    +# 
    +
    +# From Jesper Norgaard Welen (2008-01-18):
    +# The page of the San Luis provincial government
    +# 
    +# http://www.sanluis.gov.ar/notas.asp?idCanal=0&id=22812
    +# 
    +# confirms what Alex Krivenyshev has earlier sent to the tz
    +# emailing list about that San Luis plans to return to standard
    +# time much earlier than the rest of the country. It also
    +# confirms that upon request the provinces San Juan and Mendoza
    +# refused to follow San Luis in this change.
    +#
    +# The change is supposed to take place Monday the 21.st at 0:00
    +# hours. As far as I understand it if this goes ahead, we need
    +# a new timezone for San Luis (although there are also documented
    +# independent changes in the southamerica file of San Luis in
    +# 1990 and 1991 which has not been confirmed).
    +
    +# From Jesper Norgaard Welen (2008-01-25):
    +# Unfortunately the below page has become defunct, about the San Luis
    +# time change. Perhaps because it now is part of a group of pages "Most
    +# important pages of 2008."
    +#
    +# You can use
    +# 
    +# http://www.sanluis.gov.ar/notas.asp?idCanal=8141&id=22834
    +# 
    +# instead it seems. Or use "Buscador" from the main page of the San Luis
    +# government, and fill in "huso" and click OK, and you will get 3 pages
    +# from which the first one is identical to the above.
    +
    +# From Mariano Absatz (2008-01-28):
    +# I can confirm that the Province of San Luis (and so far only that
    +# province) decided to go back to UTC-3 effective midnight Jan 20th 2008
    +# (that is, Monday 21st at 0:00 is the time the clocks were delayed back
    +# 1 hour), and they intend to keep UTC-3 as their timezone all year round
    +# (that is, unless they change their mind any minute now).
    +#
    +# So we'll have to add yet another city to 'southamerica' (I think San
    +# Luis city is the mos populated city in the Province, so it'd be
    +# America/Argentina/San_Luis... of course I can't remember if San Luis's
    +# history of particular changes goes along with Mendoza or San Juan :-(
    +# (I only remember not being able to collect hard facts about San Luis
    +# back in 2004, when these provinces changed to UTC-4 for a few days, I
    +# mailed them personally and never got an answer).
    +
    +# From Paul Eggert (2008-06-30):
    +# Unless otherwise specified, data are from Shanks & Pottenger through 1992,
    +# from the IATA otherwise.  As noted below, Shanks & Pottenger say that
    +# America/Cordoba split into 6 subregions during 1991/1992, one of which
    +# was America/San_Luis, but we haven't verified this yet so for now we'll
    +# keep America/Cordoba a single region rather than splitting it into the
    +# other 5 subregions.
    +
    +# From Mariano Absatz (2009-03-13):
    +# Yesterday (with our usual 2-day notice) the Province of San Luis
    +# decided that next Sunday instead of "staying" @utc-03:00 they will go
    +# to utc-04:00 until the second Saturday in October...
    +#
    +# The press release is at
    +# 
    +# http://www.sanluis.gov.ar/SL/Paginas/NoticiaDetalle.asp?TemaId=1&InfoPrensaId=3102
    +# 
    +# (I couldn't find the decree, but
    +# 
    +# www.sanluis.gov.ar
    +# 
    +# is the official page for the Province Government).
    +#
    +# There's also a note in only one of the major national papers (La Nación) at
    +# 
    +# http://www.lanacion.com.ar/nota.asp?nota_id=1107912
    +# 
    +#
    +# The press release says:
    +#  (...) anunció que el próximo domingo a las 00:00 los puntanos deberán
    +# atrasar una hora sus relojes.
    +#
    +# A partir de entonces, San Luis establecerá el huso horario propio de
    +# la Provincia. De esta manera, durante el periodo del calendario anual
    +# 2009, el cambio horario quedará comprendido entre las 00:00 del tercer
    +# domingo de marzo y las 24:00 del segundo sábado de octubre.
    +# Quick&dirty translation
    +# (...) announced that next Sunday, at 00:00, Puntanos (the San Luis
    +# inhabitants) will have to turn back one hour their clocks
    +#
    +# Since then, San Luis will establish its own Province timezone. Thus,
    +# during 2009, this timezone change will run from 00:00 the third Sunday
    +# in March until 24:00 of the second Saturday in October.
    +
    +# From Mariano Absatz (2009-10-16):
    +# ...the Province of San Luis is a case in itself.
    +#
    +# The Law at
    +# 
    +# is ambiguous because establishes a calendar from the 2nd Sunday in
    +# October at 0:00 thru the 2nd Saturday in March at 24:00 and the
    +# complement of that starting on the 2nd Sunday of March at 0:00 and
    +# ending on the 2nd Saturday of March at 24:00.
    +#
    +# This clearly breaks every time the 1st of March or October is a Sunday.
    +#
    +# IMHO, the "spirit of the Law" is to make the changes at 0:00 on the 2nd
    +# Sunday of October and March.
    +#
    +# The problem is that the changes in the rest of the Provinces that did
    +# change in 2007/2008, were made according to the Federal Law and Decrees
    +# that did so on the 3rd Sunday of October and March.
    +#
    +# In fact, San Luis actually switched from UTC-4 to UTC-3 last Sunday
    +# (October 11th) at 0:00.
    +#
    +# So I guess a new set of rules, besides "Arg", must be made and the last
    +# America/Argentina/San_Luis entries should change to use these...
    +#
    +# I'm enclosing a patch that does what I say... regretfully, the San Luis
    +# timezone must be called "WART/WARST" even when most of the time (like,
    +# right now) WARST == ART... that is, since last Sunday, all the country
    +# is using UTC-3, but in my patch, San Luis calls it "WARST" and the rest
    +# of the country calls it "ART".
    +# ...
    +
    +# From Alexander Krivenyshev (2010-04-09):
    +# According to news reports from El Diario de la Republica Province San
    +# Luis, Argentina (standard time UTC-04) will keep Daylight Saving Time
    +# after April 11, 2010--will continue to have same time as rest of
    +# Argentina (UTC-3) (no DST).
    +#
    +# Confirmaron la prórroga del huso horario de verano (Spanish)
    +# 
    +# http://www.eldiariodelarepublica.com/index.php?option=com_content&task=view&id=29383&Itemid=9
    +# 
    +# or (some English translation):
    +# 
    +# http://www.worldtimezone.com/dst_news/dst_news_argentina08.html
    +# 
    +
    +# From Mariano Absatz (2010-04-12):
    +# yes...I can confirm this...and given that San Luis keeps calling
    +# UTC-03:00 "summer time", we should't just let San Luis go back to "Arg"
    +# rules...San Luis is still using "Western ARgentina Time" and it got
    +# stuck on Summer daylight savings time even though the summer is over.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +#
    +# Buenos Aires (BA), Capital Federal (CF),
    +Zone America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 Oct 31
    +			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
    +			-4:00	-	ART	1930 Dec
    +			-4:00	Arg	AR%sT	1969 Oct  5
    +			-3:00	Arg	AR%sT	1999 Oct  3
    +			-4:00	Arg	AR%sT	2000 Mar  3
    +			-3:00	Arg	AR%sT
    +#
    +# Cordoba (CB), Santa Fe (SF), Entre Rios (ER), Corrientes (CN), Misiones (MN),
    +# Chaco (CC), Formosa (FM), Santiago del Estero (SE)
    +#
    +# Shanks & Pottenger also make the following claims, which we haven't verified:
    +# - Formosa switched to -3:00 on 1991-01-07.
    +# - Misiones switched to -3:00 on 1990-12-29.
    +# - Chaco switched to -3:00 on 1991-01-04.
    +# - Santiago del Estero switched to -4:00 on 1991-04-01,
    +#   then to -3:00 on 1991-04-26.
    +#
    +Zone America/Argentina/Cordoba -4:16:48 - LMT	1894 Oct 31
    +			-4:16:48 -	CMT	1920 May
    +			-4:00	-	ART	1930 Dec
    +			-4:00	Arg	AR%sT	1969 Oct  5
    +			-3:00	Arg	AR%sT	1991 Mar  3
    +			-4:00	-	WART	1991 Oct 20
    +			-3:00	Arg	AR%sT	1999 Oct  3
    +			-4:00	Arg	AR%sT	2000 Mar  3
    +			-3:00	Arg	AR%sT
    +#
    +# Salta (SA), La Pampa (LP), Neuquen (NQ), Rio Negro (RN)
    +Zone America/Argentina/Salta -4:21:40 - LMT	1894 Oct 31
    +			-4:16:48 -	CMT	1920 May
    +			-4:00	-	ART	1930 Dec
    +			-4:00	Arg	AR%sT	1969 Oct  5
    +			-3:00	Arg	AR%sT	1991 Mar  3
    +			-4:00	-	WART	1991 Oct 20
    +			-3:00	Arg	AR%sT	1999 Oct  3
    +			-4:00	Arg	AR%sT	2000 Mar  3
    +			-3:00	Arg	AR%sT	2008 Oct 18
    +			-3:00	-	ART
    +#
    +# Tucuman (TM)
    +Zone America/Argentina/Tucuman -4:20:52 - LMT	1894 Oct 31
    +			-4:16:48 -	CMT	1920 May
    +			-4:00	-	ART	1930 Dec
    +			-4:00	Arg	AR%sT	1969 Oct  5
    +			-3:00	Arg	AR%sT	1991 Mar  3
    +			-4:00	-	WART	1991 Oct 20
    +			-3:00	Arg	AR%sT	1999 Oct  3
    +			-4:00	Arg	AR%sT	2000 Mar  3
    +			-3:00	-	ART	2004 Jun  1
    +			-4:00	-	WART	2004 Jun 13
    +			-3:00	Arg	AR%sT
    +#
    +# La Rioja (LR)
    +Zone America/Argentina/La_Rioja -4:27:24 - LMT	1894 Oct 31
    +			-4:16:48 -	CMT	1920 May
    +			-4:00	-	ART	1930 Dec
    +			-4:00	Arg	AR%sT	1969 Oct  5
    +			-3:00	Arg	AR%sT	1991 Mar  1
    +			-4:00	-	WART	1991 May  7
    +			-3:00	Arg	AR%sT	1999 Oct  3
    +			-4:00	Arg	AR%sT	2000 Mar  3
    +			-3:00	-	ART	2004 Jun  1
    +			-4:00	-	WART	2004 Jun 20
    +			-3:00	Arg	AR%sT	2008 Oct 18
    +			-3:00	-	ART
    +#
    +# San Juan (SJ)
    +Zone America/Argentina/San_Juan -4:34:04 - LMT	1894 Oct 31
    +			-4:16:48 -	CMT	1920 May
    +			-4:00	-	ART	1930 Dec
    +			-4:00	Arg	AR%sT	1969 Oct  5
    +			-3:00	Arg	AR%sT	1991 Mar  1
    +			-4:00	-	WART	1991 May  7
    +			-3:00	Arg	AR%sT	1999 Oct  3
    +			-4:00	Arg	AR%sT	2000 Mar  3
    +			-3:00	-	ART	2004 May 31
    +			-4:00	-	WART	2004 Jul 25
    +			-3:00	Arg	AR%sT	2008 Oct 18
    +			-3:00	-	ART
    +#
    +# Jujuy (JY)
    +Zone America/Argentina/Jujuy -4:21:12 -	LMT	1894 Oct 31
    +			-4:16:48 -	CMT	1920 May
    +			-4:00	-	ART	1930 Dec
    +			-4:00	Arg	AR%sT	1969 Oct  5
    +			-3:00	Arg	AR%sT	1990 Mar  4
    +			-4:00	-	WART	1990 Oct 28
    +			-4:00	1:00	WARST	1991 Mar 17
    +			-4:00	-	WART	1991 Oct  6
    +			-3:00	1:00	ARST	1992
    +			-3:00	Arg	AR%sT	1999 Oct  3
    +			-4:00	Arg	AR%sT	2000 Mar  3
    +			-3:00	Arg	AR%sT	2008 Oct 18
    +			-3:00	-	ART
    +#
    +# Catamarca (CT), Chubut (CH)
    +Zone America/Argentina/Catamarca -4:23:08 - LMT	1894 Oct 31
    +			-4:16:48 -	CMT	1920 May
    +			-4:00	-	ART	1930 Dec
    +			-4:00	Arg	AR%sT	1969 Oct  5
    +			-3:00	Arg	AR%sT	1991 Mar  3
    +			-4:00	-	WART	1991 Oct 20
    +			-3:00	Arg	AR%sT	1999 Oct  3
    +			-4:00	Arg	AR%sT	2000 Mar  3
    +			-3:00	-	ART	2004 Jun  1
    +			-4:00	-	WART	2004 Jun 20
    +			-3:00	Arg	AR%sT	2008 Oct 18
    +			-3:00	-	ART
    +#
    +# Mendoza (MZ)
    +Zone America/Argentina/Mendoza -4:35:16 - LMT	1894 Oct 31
    +			-4:16:48 -	CMT	1920 May
    +			-4:00	-	ART	1930 Dec
    +			-4:00	Arg	AR%sT	1969 Oct  5
    +			-3:00	Arg	AR%sT	1990 Mar  4
    +			-4:00	-	WART	1990 Oct 15
    +			-4:00	1:00	WARST	1991 Mar  1
    +			-4:00	-	WART	1991 Oct 15
    +			-4:00	1:00	WARST	1992 Mar  1
    +			-4:00	-	WART	1992 Oct 18
    +			-3:00	Arg	AR%sT	1999 Oct  3
    +			-4:00	Arg	AR%sT	2000 Mar  3
    +			-3:00	-	ART	2004 May 23
    +			-4:00	-	WART	2004 Sep 26
    +			-3:00	Arg	AR%sT	2008 Oct 18
    +			-3:00	-	ART
    +#
    +# San Luis (SL)
    +
    +Rule	SanLuis	2008	2009	-	Mar	Sun>=8	0:00	0	-
    +Rule	SanLuis	2007	2009	-	Oct	Sun>=8	0:00	1:00	S
    +
    +Zone America/Argentina/San_Luis -4:25:24 - LMT	1894 Oct 31
    +			-4:16:48 -	CMT	1920 May
    +			-4:00	-	ART	1930 Dec
    +			-4:00	Arg	AR%sT	1969 Oct  5
    +			-3:00	Arg	AR%sT	1990
    +			-3:00	1:00	ARST	1990 Mar 14
    +			-4:00	-	WART	1990 Oct 15
    +			-4:00	1:00	WARST	1991 Mar  1
    +			-4:00	-	WART	1991 Jun  1
    +			-3:00	-	ART	1999 Oct  3
    +			-4:00	1:00	WARST	2000 Mar  3
    +			-3:00	-	ART	2004 May 31
    +			-4:00	-	WART	2004 Jul 25
    +			-3:00	Arg	AR%sT	2008 Jan 21
    +			-4:00	SanLuis	WAR%sT
    +#
    +# Santa Cruz (SC)
    +Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31
    +			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
    +			-4:00	-	ART	1930 Dec
    +			-4:00	Arg	AR%sT	1969 Oct  5
    +			-3:00	Arg	AR%sT	1999 Oct  3
    +			-4:00	Arg	AR%sT	2000 Mar  3
    +			-3:00	-	ART	2004 Jun  1
    +			-4:00	-	WART	2004 Jun 20
    +			-3:00	Arg	AR%sT	2008 Oct 18
    +			-3:00	-	ART
    +#
    +# Tierra del Fuego, Antartida e Islas del Atlantico Sur (TF)
    +Zone America/Argentina/Ushuaia -4:33:12 - LMT 1894 Oct 31
    +			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
    +			-4:00	-	ART	1930 Dec
    +			-4:00	Arg	AR%sT	1969 Oct  5
    +			-3:00	Arg	AR%sT	1999 Oct  3
    +			-4:00	Arg	AR%sT	2000 Mar  3
    +			-3:00	-	ART	2004 May 30
    +			-4:00	-	WART	2004 Jun 20
    +			-3:00	Arg	AR%sT	2008 Oct 18
    +			-3:00	-	ART
    +
    +# Aruba
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Aruba	-4:40:24 -	LMT	1912 Feb 12	# Oranjestad
    +			-4:30	-	ANT	1965 # Netherlands Antilles Time
    +			-4:00	-	AST
    +
    +# Bolivia
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/La_Paz	-4:32:36 -	LMT	1890
    +			-4:32:36 -	CMT	1931 Oct 15 # Calamarca MT
    +			-4:32:36 1:00	BOST	1932 Mar 21 # Bolivia ST
    +			-4:00	-	BOT	# Bolivia Time
    +
    +# Brazil
    +
    +# From Paul Eggert (1993-11-18):
    +# The mayor of Rio recently attempted to change the time zone rules
    +# just in his city, in order to leave more summer time for the tourist trade.
    +# The rule change lasted only part of the day;
    +# the federal government refused to follow the city's rules, and business
    +# was in a chaos, so the mayor backed down that afternoon.
    +
    +# From IATA SSIM (1996-02):
    +# _Only_ the following states in BR1 observe DST: Rio Grande do Sul (RS),
    +# Santa Catarina (SC), Parana (PR), Sao Paulo (SP), Rio de Janeiro (RJ),
    +# Espirito Santo (ES), Minas Gerais (MG), Bahia (BA), Goias (GO),
    +# Distrito Federal (DF), Tocantins (TO), Sergipe [SE] and Alagoas [AL].
    +# [The last three states are new to this issue of the IATA SSIM.]
    +
    +# From Gwillim Law (1996-10-07):
    +# Geography, history (Tocantins was part of Goias until 1989), and other
    +# sources of time zone information lead me to believe that AL, SE, and TO were
    +# always in BR1, and so the only change was whether or not they observed DST....
    +# The earliest issue of the SSIM I have is 2/91.  Each issue from then until
    +# 9/95 says that DST is observed only in the ten states I quoted from 9/95,
    +# along with Mato Grosso (MT) and Mato Grosso do Sul (MS), which are in BR2
    +# (UTC-4)....  The other two time zones given for Brazil are BR3, which is
    +# UTC-5, no DST, and applies only in the state of Acre (AC); and BR4, which is
    +# UTC-2, and applies to Fernando de Noronha (formerly FN, but I believe it's
    +# become part of the state of Pernambuco).  The boundary between BR1 and BR2
    +# has never been clearly stated.  They've simply been called East and West.
    +# However, some conclusions can be drawn from another IATA manual: the Airline
    +# Coding Directory, which lists close to 400 airports in Brazil.  For each
    +# airport it gives a time zone which is coded to the SSIM.  From that
    +# information, I'm led to conclude that the states of Amapa (AP), Ceara (CE),
    +# Maranhao (MA), Paraiba (PR), Pernambuco (PE), Piaui (PI), and Rio Grande do
    +# Norte (RN), and the eastern part of Para (PA) are all in BR1 without DST.
    +
    +# From Marcos Tadeu (1998-09-27):
    +# 
    +# Brazilian official page
    +# 
    +
    +# From Jesper Norgaard (2000-11-03):
    +# [For an official list of which regions in Brazil use which time zones, see:]
    +# http://pcdsh01.on.br/Fusbr.htm
    +# http://pcdsh01.on.br/Fusbrhv.htm
    +
    +# From Celso Doria via David Madeo (2002-10-09):
    +# The reason for the delay this year has to do with elections in Brazil.
    +#
    +# Unlike in the United States, elections in Brazil are 100% computerized and
    +# the results are known almost immediately.  Yesterday, it was the first
    +# round of the elections when 115 million Brazilians voted for President,
    +# Governor, Senators, Federal Deputies, and State Deputies.  Nobody is
    +# counting (or re-counting) votes anymore and we know there will be a second
    +# round for the Presidency and also for some Governors.  The 2nd round will
    +# take place on October 27th.
    +#
    +# The reason why the DST will only begin November 3rd is that the thousands
    +# of electoral machines used cannot have their time changed, and since the
    +# Constitution says the elections must begin at 8:00 AM and end at 5:00 PM,
    +# the Government decided to postpone DST, instead of changing the Constitution
    +# (maybe, for the next elections, it will be possible to change the clock)...
    +
    +# From Rodrigo Severo (2004-10-04):
    +# It's just the biannual change made necessary by the much hyped, supposedly
    +# modern Brazilian eletronic voting machines which, apparently, can't deal
    +# with a time change between the first and the second rounds of the elections.
    +
    +# From Steffen Thorsen (2007-09-20):
    +# Brazil will start DST on 2007-10-14 00:00 and end on 2008-02-17 00:00:
    +# http://www.mme.gov.br/site/news/detail.do;jsessionid=BBA06811AFCAAC28F0285210913513DA?newsId=13975
    +
    +# From Paul Schulze (2008-06-24):
    +# ...by law number 11.662 of April 24, 2008 (published in the "Diario
    +# Oficial da Uniao"...) in Brazil there are changes in the timezones,
    +# effective today (00:00am at June 24, 2008) as follows:
    +#
    +# a) The timezone UTC+5 is e[x]tinguished, with all the Acre state and the
    +# part of the Amazonas state that had this timezone now being put to the
    +# timezone UTC+4
    +# b) The whole Para state now is put at timezone UTC+3, instead of just
    +# part of it, as was before.
    +#
    +# This change follows a proposal of senator Tiao Viana of Acre state, that
    +# proposed it due to concerns about open television channels displaying
    +# programs inappropriate to youths in the states that had the timezone
    +# UTC+5 too early in the night. In the occasion, some more corrections
    +# were proposed, trying to unify the timezones of any given state. This
    +# change modifies timezone rules defined in decree 2.784 of 18 June,
    +# 1913.
    +
    +# From Rodrigo Severo (2008-06-24):
    +# Just correcting the URL:
    +# 
    +# https://www.in.gov.br/imprensa/visualiza/index.jsp?jornal=do&secao=1&pagina=1&data=25/04/2008
    +# 
    +#
    +# As a result of the above Decree I believe the America/Rio_Branco
    +# timezone shall be modified from UTC-5 to UTC-4 and a new timezone shall
    +# be created to represent the...west side of the Para State. I
    +# suggest this new timezone be called Santarem as the most
    +# important/populated city in the affected area.
    +#
    +# This new timezone would be the same as the Rio_Branco timezone up to
    +# the 2008/06/24 change which would be to UTC-3 instead of UTC-4.
    +
    +# From Alex Krivenyshev (2008-06-24):
    +# This is a quick reference page for New and Old Brazil Time Zones map.
    +# 
    +# http://www.worldtimezone.com/brazil-time-new-old.php
    +# 
    +#
    +# - 4 time zones replaced by 3 time zones-eliminating time zone UTC- 05
    +# (state Acre and the part of the Amazonas will be UTC/GMT- 04) - western
    +# part of Par state is moving to one timezone UTC- 03 (from UTC -04).
    +
    +# From Paul Eggert (2002-10-10):
    +# The official decrees referenced below are mostly taken from
    +# 
    +# Decretos sobre o Horario de Verao no Brasil
    +# .
    +
    +# From Steffen Thorsen (2008-08-29):
    +# As announced by the government and many newspapers in Brazil late
    +# yesterday, Brazil will start DST on 2008-10-19 (need to change rule) and
    +# it will end on 2009-02-15 (current rule for Brazil is fine). Based on
    +# past years experience with the elections, there was a good chance that
    +# the start was postponed to November, but it did not happen this year.
    +#
    +# It has not yet been posted to http://pcdsh01.on.br/DecHV.html
    +#
    +# An official page about it:
    +# 
    +# http://www.mme.gov.br/site/news/detail.do?newsId=16722
    +# 
    +# Note that this link does not always work directly, but must be accessed
    +# by going to
    +# 
    +# http://www.mme.gov.br/first
    +# 
    +#
    +# One example link that works directly:
    +# 
    +# http://jornale.com.br/index.php?option=com_content&task=view&id=13530&Itemid=54
    +# (Portuguese)
    +# 
    +#
    +# We have a written a short article about it as well:
    +# 
    +# http://www.timeanddate.com/news/time/brazil-dst-2008-2009.html
    +# 
    +#
    +# From Alexander Krivenyshev (2011-10-04):
    +# State Bahia will return to Daylight savings time this year after 8 years off.
    +# The announcement was made by Governor Jaques Wagner in an interview to a
    +# television station in Salvador.
    +
    +# In Portuguese:
    +# 
    +# http://g1.globo.com/bahia/noticia/2011/10/governador-jaques-wagner-confirma-horario-de-verao-na-bahia.html
    +#  and
    +# 
    +# http://noticias.terra.com.br/brasil/noticias/0,,OI5390887-EI8139,00-Bahia+volta+a+ter+horario+de+verao+apos+oito+anos.html
    +# 
    +
    +# From Guilherme Bernardes Rodrigues (2011-10-07):
    +# There is news in the media, however there is still no decree about it.
    +# I just send a e-mail to Zulmira Brandão at
    +# http://pcdsh01.on.br/ the
    +# oficial agency about time in Brazil, and she confirmed that the old rule is
    +# still in force.
    +
    +# From Guilherme Bernardes Rodrigues (2011-10-14)
    +# It's official, the President signed a decree that includes Bahia in summer
    +# time.
    +#	 [ and in a second message (same day): ]
    +# I found the decree.
    +#
    +# DECRETO No- 7.584, DE 13 DE OUTUBRO DE 2011
    +# Link :
    +# 
    +# http://www.in.gov.br/visualiza/index.jsp?data=13/10/2011&jornal=1000&pagina=6&totalArquivos=6
    +# 
    +
    +# From Kelley Cook (2012-10-16):
    +# The governor of state of Bahia in Brazil announced on Thursday that
    +# due to public pressure, he is reversing the DST policy they implemented
    +# last year and will not be going to Summer Time on October 21st....
    +# http://www.correio24horas.com.br/r/artigo/apos-pressoes-wagner-suspende-horario-de-verao-na-bahia
    +
    +# From Rodrigo Severo (2012-10-16):
    +# Tocantins state will have DST.
    +# http://noticias.terra.com.br/brasil/noticias/0,,OI6232536-EI306.html
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +# Decree 20,466 (1931-10-01)
    +# Decree 21,896 (1932-01-10)
    +Rule	Brazil	1931	only	-	Oct	 3	11:00	1:00	S
    +Rule	Brazil	1932	1933	-	Apr	 1	 0:00	0	-
    +Rule	Brazil	1932	only	-	Oct	 3	 0:00	1:00	S
    +# Decree 23,195 (1933-10-10)
    +# revoked DST.
    +# Decree 27,496 (1949-11-24)
    +# Decree 27,998 (1950-04-13)
    +Rule	Brazil	1949	1952	-	Dec	 1	 0:00	1:00	S
    +Rule	Brazil	1950	only	-	Apr	16	 1:00	0	-
    +Rule	Brazil	1951	1952	-	Apr	 1	 0:00	0	-
    +# Decree 32,308 (1953-02-24)
    +Rule	Brazil	1953	only	-	Mar	 1	 0:00	0	-
    +# Decree 34,724 (1953-11-30)
    +# revoked DST.
    +# Decree 52,700 (1963-10-18)
    +# established DST from 1963-10-23 00:00 to 1964-02-29 00:00
    +# in SP, RJ, GB, MG, ES, due to the prolongation of the drought.
    +# Decree 53,071 (1963-12-03)
    +# extended the above decree to all of the national territory on 12-09.
    +Rule	Brazil	1963	only	-	Dec	 9	 0:00	1:00	S
    +# Decree 53,604 (1964-02-25)
    +# extended summer time by one day to 1964-03-01 00:00 (start of school).
    +Rule	Brazil	1964	only	-	Mar	 1	 0:00	0	-
    +# Decree 55,639 (1965-01-27)
    +Rule	Brazil	1965	only	-	Jan	31	 0:00	1:00	S
    +Rule	Brazil	1965	only	-	Mar	31	 0:00	0	-
    +# Decree 57,303 (1965-11-22)
    +Rule	Brazil	1965	only	-	Dec	 1	 0:00	1:00	S
    +# Decree 57,843 (1966-02-18)
    +Rule	Brazil	1966	1968	-	Mar	 1	 0:00	0	-
    +Rule	Brazil	1966	1967	-	Nov	 1	 0:00	1:00	S
    +# Decree 63,429 (1968-10-15)
    +# revoked DST.
    +# Decree 91,698 (1985-09-27)
    +Rule	Brazil	1985	only	-	Nov	 2	 0:00	1:00	S
    +# Decree 92,310 (1986-01-21)
    +# Decree 92,463 (1986-03-13)
    +Rule	Brazil	1986	only	-	Mar	15	 0:00	0	-
    +# Decree 93,316 (1986-10-01)
    +Rule	Brazil	1986	only	-	Oct	25	 0:00	1:00	S
    +Rule	Brazil	1987	only	-	Feb	14	 0:00	0	-
    +# Decree 94,922 (1987-09-22)
    +Rule	Brazil	1987	only	-	Oct	25	 0:00	1:00	S
    +Rule	Brazil	1988	only	-	Feb	 7	 0:00	0	-
    +# Decree 96,676 (1988-09-12)
    +# except for the states of AC, AM, PA, RR, RO, and AP (then a territory)
    +Rule	Brazil	1988	only	-	Oct	16	 0:00	1:00	S
    +Rule	Brazil	1989	only	-	Jan	29	 0:00	0	-
    +# Decree 98,077 (1989-08-21)
    +# with the same exceptions
    +Rule	Brazil	1989	only	-	Oct	15	 0:00	1:00	S
    +Rule	Brazil	1990	only	-	Feb	11	 0:00	0	-
    +# Decree 99,530 (1990-09-17)
    +# adopted by RS, SC, PR, SP, RJ, ES, MG, GO, MS, DF.
    +# Decree 99,629 (1990-10-19) adds BA, MT.
    +Rule	Brazil	1990	only	-	Oct	21	 0:00	1:00	S
    +Rule	Brazil	1991	only	-	Feb	17	 0:00	0	-
    +# Unnumbered decree (1991-09-25)
    +# adopted by RS, SC, PR, SP, RJ, ES, MG, BA, GO, MT, MS, DF.
    +Rule	Brazil	1991	only	-	Oct	20	 0:00	1:00	S
    +Rule	Brazil	1992	only	-	Feb	 9	 0:00	0	-
    +# Unnumbered decree (1992-10-16)
    +# adopted by same states.
    +Rule	Brazil	1992	only	-	Oct	25	 0:00	1:00	S
    +Rule	Brazil	1993	only	-	Jan	31	 0:00	0	-
    +# Decree 942 (1993-09-28)
    +# adopted by same states, plus AM.
    +# Decree 1,252 (1994-09-22;
    +# web page corrected 2004-01-07) adopted by same states, minus AM.
    +# Decree 1,636 (1995-09-14)
    +# adopted by same states, plus MT and TO.
    +# Decree 1,674 (1995-10-13)
    +# adds AL, SE.
    +Rule	Brazil	1993	1995	-	Oct	Sun>=11	 0:00	1:00	S
    +Rule	Brazil	1994	1995	-	Feb	Sun>=15	 0:00	0	-
    +Rule	Brazil	1996	only	-	Feb	11	 0:00	0	-
    +# Decree 2,000 (1996-09-04)
    +# adopted by same states, minus AL, SE.
    +Rule	Brazil	1996	only	-	Oct	 6	 0:00	1:00	S
    +Rule	Brazil	1997	only	-	Feb	16	 0:00	0	-
    +# From Daniel C. Sobral (1998-02-12):
    +# In 1997, the DS began on October 6. The stated reason was that
    +# because international television networks ignored Brazil's policy on DS,
    +# they bought the wrong times on satellite for coverage of Pope's visit.
    +# This year, the ending date of DS was postponed to March 1
    +# to help dealing with the shortages of electric power.
    +#
    +# Decree 2,317 (1997-09-04), adopted by same states.
    +Rule	Brazil	1997	only	-	Oct	 6	 0:00	1:00	S
    +# Decree 2,495
    +# (1998-02-10)
    +Rule	Brazil	1998	only	-	Mar	 1	 0:00	0	-
    +# Decree 2,780 (1998-09-11)
    +# adopted by the same states as before.
    +Rule	Brazil	1998	only	-	Oct	11	 0:00	1:00	S
    +Rule	Brazil	1999	only	-	Feb	21	 0:00	0	-
    +# Decree 3,150
    +# (1999-08-23) adopted by same states.
    +# Decree 3,188 (1999-09-30)
    +# adds SE, AL, PB, PE, RN, CE, PI, MA and RR.
    +Rule	Brazil	1999	only	-	Oct	 3	 0:00	1:00	S
    +Rule	Brazil	2000	only	-	Feb	27	 0:00	0	-
    +# Decree 3,592 (2000-09-06)
    +# adopted by the same states as before.
    +# Decree 3,630 (2000-10-13)
    +# repeals DST in PE and RR, effective 2000-10-15 00:00.
    +# Decree 3,632 (2000-10-17)
    +# repeals DST in SE, AL, PB, RN, CE, PI and MA, effective 2000-10-22 00:00.
    +# Decree 3,916
    +# (2001-09-13) reestablishes DST in AL, CE, MA, PB, PE, PI, RN, SE.
    +Rule	Brazil	2000	2001	-	Oct	Sun>=8	 0:00	1:00	S
    +Rule	Brazil	2001	2006	-	Feb	Sun>=15	 0:00	0	-
    +# Decree 4,399 (2002-10-01) repeals DST in AL, CE, MA, PB, PE, PI, RN, SE.
    +# 4,399
    +Rule	Brazil	2002	only	-	Nov	 3	 0:00	1:00	S
    +# Decree 4,844 (2003-09-24; corrected 2003-09-26) repeals DST in BA, MT, TO.
    +# 4,844
    +Rule	Brazil	2003	only	-	Oct	19	 0:00	1:00	S
    +# Decree 5,223 (2004-10-01) reestablishes DST in MT.
    +# 5,223
    +Rule	Brazil	2004	only	-	Nov	 2	 0:00	1:00	S
    +# Decree 5,539 (2005-09-19),
    +# adopted by the same states as before.
    +Rule	Brazil	2005	only	-	Oct	16	 0:00	1:00	S
    +# Decree 5,920 (2006-10-03),
    +# adopted by the same states as before.
    +Rule	Brazil	2006	only	-	Nov	 5	 0:00	1:00	S
    +Rule	Brazil	2007	only	-	Feb	25	 0:00	0	-
    +# Decree 6,212 (2007-09-26),
    +# adopted by the same states as before.
    +Rule	Brazil	2007	only	-	Oct	Sun>=8	 0:00	1:00	S
    +# From Frederico A. C. Neves (2008-09-10):
    +# Acording to this decree
    +# 
    +# http://www.planalto.gov.br/ccivil_03/_Ato2007-2010/2008/Decreto/D6558.htm
    +# 
    +# [t]he DST period in Brazil now on will be from the 3rd Oct Sunday to the
    +# 3rd Feb Sunday. There is an exception on the return date when this is
    +# the Carnival Sunday then the return date will be the next Sunday...
    +Rule	Brazil	2008	max	-	Oct	Sun>=15	0:00	1:00	S
    +Rule	Brazil	2008	2011	-	Feb	Sun>=15	0:00	0	-
    +Rule	Brazil	2012	only	-	Feb	Sun>=22	0:00	0	-
    +Rule	Brazil	2013	2014	-	Feb	Sun>=15	0:00	0	-
    +Rule	Brazil	2015	only	-	Feb	Sun>=22	0:00	0	-
    +Rule	Brazil	2016	2022	-	Feb	Sun>=15	0:00	0	-
    +Rule	Brazil	2023	only	-	Feb	Sun>=22	0:00	0	-
    +Rule	Brazil	2024	2025	-	Feb	Sun>=15	0:00	0	-
    +Rule	Brazil	2026	only	-	Feb	Sun>=22	0:00	0	-
    +Rule	Brazil	2027	2033	-	Feb	Sun>=15	0:00	0	-
    +Rule	Brazil	2034	only	-	Feb	Sun>=22	0:00	0	-
    +Rule	Brazil	2035	2036	-	Feb	Sun>=15	0:00	0	-
    +Rule	Brazil	2037	only	-	Feb	Sun>=22	0:00	0	-
    +# From Arthur David Olson (2008-09-29):
    +# The next is wrong in some years but is better than nothing.
    +Rule	Brazil	2038	max	-	Feb	Sun>=15	0:00	0	-
    +
    +# The latest ruleset listed above says that the following states observe DST:
    +# DF, ES, GO, MG, MS, MT, PR, RJ, RS, SC, SP.
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +#
    +# Fernando de Noronha (administratively part of PE)
    +Zone America/Noronha	-2:09:40 -	LMT	1914
    +			-2:00	Brazil	FN%sT	1990 Sep 17
    +			-2:00	-	FNT	1999 Sep 30
    +			-2:00	Brazil	FN%sT	2000 Oct 15
    +			-2:00	-	FNT	2001 Sep 13
    +			-2:00	Brazil	FN%sT	2002 Oct  1
    +			-2:00	-	FNT
    +# Other Atlantic islands have no permanent settlement.
    +# These include Trindade and Martin Vaz (administratively part of ES),
    +# Atol das Rocas (RN), and Penedos de Sao Pedro e Sao Paulo (PE).
    +# Fernando de Noronha was a separate territory from 1942-09-02 to 1989-01-01;
    +# it also included the Penedos.
    +#
    +# Amapa (AP), east Para (PA)
    +# East Para includes Belem, Maraba, Serra Norte, and Sao Felix do Xingu.
    +# The division between east and west Para is the river Xingu.
    +# In the north a very small part from the river Javary (now Jari I guess,
    +# the border with Amapa) to the Amazon, then to the Xingu.
    +Zone America/Belem	-3:13:56 -	LMT	1914
    +			-3:00	Brazil	BR%sT	1988 Sep 12
    +			-3:00	-	BRT
    +#
    +# west Para (PA)
    +# West Para includes Altamira, Oribidos, Prainha, Oriximina, and Santarem.
    +Zone America/Santarem	-3:38:48 -	LMT	1914
    +			-4:00	Brazil	AM%sT	1988 Sep 12
    +			-4:00	-	AMT	2008 Jun 24 00:00
    +			-3:00	-	BRT
    +#
    +# Maranhao (MA), Piaui (PI), Ceara (CE), Rio Grande do Norte (RN),
    +# Paraiba (PB)
    +Zone America/Fortaleza	-2:34:00 -	LMT	1914
    +			-3:00	Brazil	BR%sT	1990 Sep 17
    +			-3:00	-	BRT	1999 Sep 30
    +			-3:00	Brazil	BR%sT	2000 Oct 22
    +			-3:00	-	BRT	2001 Sep 13
    +			-3:00	Brazil	BR%sT	2002 Oct  1
    +			-3:00	-	BRT
    +#
    +# Pernambuco (PE) (except Atlantic islands)
    +Zone America/Recife	-2:19:36 -	LMT	1914
    +			-3:00	Brazil	BR%sT	1990 Sep 17
    +			-3:00	-	BRT	1999 Sep 30
    +			-3:00	Brazil	BR%sT	2000 Oct 15
    +			-3:00	-	BRT	2001 Sep 13
    +			-3:00	Brazil	BR%sT	2002 Oct  1
    +			-3:00	-	BRT
    +#
    +# Tocantins (TO)
    +Zone America/Araguaina	-3:12:48 -	LMT	1914
    +			-3:00	Brazil	BR%sT	1990 Sep 17
    +			-3:00	-	BRT	1995 Sep 14
    +			-3:00	Brazil	BR%sT	2003 Sep 24
    +			-3:00	-	BRT	2012 Oct 21
    +			-3:00	Brazil	BR%sT
    +#
    +# Alagoas (AL), Sergipe (SE)
    +Zone America/Maceio	-2:22:52 -	LMT	1914
    +			-3:00	Brazil	BR%sT	1990 Sep 17
    +			-3:00	-	BRT	1995 Oct 13
    +			-3:00	Brazil	BR%sT	1996 Sep  4
    +			-3:00	-	BRT	1999 Sep 30
    +			-3:00	Brazil	BR%sT	2000 Oct 22
    +			-3:00	-	BRT	2001 Sep 13
    +			-3:00	Brazil	BR%sT	2002 Oct  1
    +			-3:00	-	BRT
    +#
    +# Bahia (BA)
    +# There are too many Salvadors elsewhere, so use America/Bahia instead
    +# of America/Salvador.
    +Zone America/Bahia	-2:34:04 -	LMT	1914
    +			-3:00	Brazil	BR%sT	2003 Sep 24
    +			-3:00	-	BRT	2011 Oct 16
    +			-3:00	Brazil	BR%sT	2012 Oct 21
    +			-3:00	-	BRT
    +#
    +# Goias (GO), Distrito Federal (DF), Minas Gerais (MG),
    +# Espirito Santo (ES), Rio de Janeiro (RJ), Sao Paulo (SP), Parana (PR),
    +# Santa Catarina (SC), Rio Grande do Sul (RS)
    +Zone America/Sao_Paulo	-3:06:28 -	LMT	1914
    +			-3:00	Brazil	BR%sT	1963 Oct 23 00:00
    +			-3:00	1:00	BRST	1964
    +			-3:00	Brazil	BR%sT
    +#
    +# Mato Grosso do Sul (MS)
    +Zone America/Campo_Grande -3:38:28 -	LMT	1914
    +			-4:00	Brazil	AM%sT
    +#
    +# Mato Grosso (MT)
    +Zone America/Cuiaba	-3:44:20 -	LMT	1914
    +			-4:00	Brazil	AM%sT	2003 Sep 24
    +			-4:00	-	AMT	2004 Oct  1
    +			-4:00	Brazil	AM%sT
    +#
    +# Rondonia (RO)
    +Zone America/Porto_Velho -4:15:36 -	LMT	1914
    +			-4:00	Brazil	AM%sT	1988 Sep 12
    +			-4:00	-	AMT
    +#
    +# Roraima (RR)
    +Zone America/Boa_Vista	-4:02:40 -	LMT	1914
    +			-4:00	Brazil	AM%sT	1988 Sep 12
    +			-4:00	-	AMT	1999 Sep 30
    +			-4:00	Brazil	AM%sT	2000 Oct 15
    +			-4:00	-	AMT
    +#
    +# east Amazonas (AM): Boca do Acre, Jutai, Manaus, Floriano Peixoto
    +# The great circle line from Tabatinga to Porto Acre divides
    +# east from west Amazonas.
    +Zone America/Manaus	-4:00:04 -	LMT	1914
    +			-4:00	Brazil	AM%sT	1988 Sep 12
    +			-4:00	-	AMT	1993 Sep 28
    +			-4:00	Brazil	AM%sT	1994 Sep 22
    +			-4:00	-	AMT
    +#
    +# west Amazonas (AM): Atalaia do Norte, Boca do Maoco, Benjamin Constant,
    +#	Eirunepe, Envira, Ipixuna
    +Zone America/Eirunepe	-4:39:28 -	LMT	1914
    +			-5:00	Brazil	AC%sT	1988 Sep 12
    +			-5:00	-	ACT	1993 Sep 28
    +			-5:00	Brazil	AC%sT	1994 Sep 22
    +			-5:00	-	ACT	2008 Jun 24 00:00
    +			-4:00	-	AMT
    +#
    +# Acre (AC)
    +Zone America/Rio_Branco	-4:31:12 -	LMT	1914
    +			-5:00	Brazil	AC%sT	1988 Sep 12
    +			-5:00	-	ACT	2008 Jun 24 00:00
    +			-4:00	-	AMT
    +
    +# Chile
    +
    +# From Eduardo Krell (1995-10-19):
    +# The law says to switch to DST at midnight [24:00] on the second SATURDAY
    +# of October....  The law is the same for March and October.
    +# (1998-09-29):
    +# Because of the drought this year, the government decided to go into
    +# DST earlier (saturday 9/26 at 24:00). This is a one-time change only ...
    +# (unless there's another dry season next year, I guess).
    +
    +# From Julio I. Pacheco Troncoso (1999-03-18):
    +# Because of the same drought, the government decided to end DST later,
    +# on April 3, (one-time change).
    +
    +# From Oscar van Vlijmen (2006-10-08):
    +# http://www.horaoficial.cl/cambio.htm
    +
    +# From Jesper Norgaard Welen (2006-10-08):
    +# I think that there are some obvious mistakes in the suggested link
    +# from Oscar van Vlijmen,... for instance entry 66 says that GMT-4
    +# ended 1990-09-12 while entry 67 only begins GMT-3 at 1990-09-15
    +# (they should have been 1990-09-15 and 1990-09-16 respectively), but
    +# anyhow it clears up some doubts too.
    +
    +# From Paul Eggert (2006-12-27):
    +# The following data for Chile and America/Santiago are from
    +#  (2006-09-20), transcribed by
    +# Jesper Norgaard Welen.  The data for Pacific/Easter are from Shanks
    +# & Pottenger, except with DST transitions after 1932 cloned from
    +# America/Santiago.  The pre-1980 Pacific/Easter data are dubious,
    +# but we have no other source.
    +
    +# From German Poo-Caaman~o (2008-03-03):
    +# Due to drought, Chile extends Daylight Time in three weeks.  This
    +# is one-time change (Saturday 3/29 at 24:00 for America/Santiago
    +# and Saturday 3/29 at 22:00 for Pacific/Easter)
    +# The Supreme Decree is located at
    +# 
    +# http://www.shoa.cl/servicios/supremo316.pdf
    +# 
    +# and the instructions for 2008 are located in:
    +# 
    +# http://www.horaoficial.cl/cambio.htm
    +# .
    +
    +# From Jose Miguel Garrido (2008-03-05):
    +# ...
    +# You could see the announces of the change on
    +# 
    +# http://www.shoa.cl/noticias/2008/04hora/hora.htm
    +# .
    +
    +# From Angel Chiang (2010-03-04):
    +# Subject: DST in Chile exceptionally extended to 3 April due to earthquake
    +# 
    +# http://www.gobiernodechile.cl/viewNoticia.aspx?idArticulo=30098
    +# 
    +# (in Spanish, last paragraph).
    +#
    +# This is breaking news. There should be more information available later.
    +
    +# From Arthur Daivd Olson (2010-03-06):
    +# Angel Chiang's message confirmed by Julio Pacheco; Julio provided a patch.
    +
    +# From Glenn Eychaner (2011-03-02): [geychaner@mac.com]
    +# It appears that the Chilean government has decided to postpone the
    +# change from summer time to winter time again, by three weeks to April
    +# 2nd:
    +# 
    +# http://www.emol.com/noticias/nacional/detalle/detallenoticias.asp?idnoticia=467651
    +# 
    +#
    +# This is not yet reflected in the offical "cambio de hora" site, but
    +# probably will be soon:
    +# 
    +# http://www.horaoficial.cl/cambio.htm
    +# 
    +
    +# From Arthur David Olson (2011-03-02):
    +# The emol.com article mentions a water shortage as the cause of the
    +# postponement, which may mean that it's not a permanent change.
    +
    +# From Glenn Eychaner (2011-03-28):
    +# The article:
    +# 
    +# http://diario.elmercurio.com/2011/03/28/_portada/_portada/noticias/7565897A-CA86-49E6-9E03-660B21A4883E.htm?id=3D{7565897A-CA86-49E6-9E03-660B21A4883E}
    +# 
    +#
    +# In English:
    +# Chile's clocks will go back an hour this year on the 7th of May instead
    +# of this Saturday. They will go forward again the 3rd Saturday in
    +# August, not in October as they have since 1968. This is a pilot plan
    +# which will be reevaluated in 2012.
    +
    +# From Mauricio Parada (2012-02-22), translated by Glenn Eychaner (2012-02-23):
    +# As stated in the website of the Chilean Energy Ministry
    +# http://www.minenergia.cl/ministerio/noticias/generales/gobierno-anuncia-fechas-de-cambio-de.html
    +# The Chilean Government has decided to postpone the entrance into winter time
    +# (to leave DST) from March 11 2012 to April 28th 2012. The decision has not
    +# been yet formalized but it will within the next days.
    +# Quote from the website communication:
    +#
    +# 6. For the year 2012, the dates of entry into winter time will be as follows:
    +# a. Saturday April 28, 2012, clocks should go back 60 minutes; that is, at
    +# 23:59:59, instead of passing to 0:00, the time should be adjusted to be 23:00
    +# of the same day.
    +# b. Saturday, September 1, 2012, clocks should go forward 60 minutes; that is,
    +# at 23:59:59, instead of passing to 0:00, the time should be adjusted to be
    +# 01:00 on September 2.
    +#
    +# Note that...this is yet another "temporary" change that will be reevaluated
    +# AGAIN in 2013.
    +
    +# NOTE: ChileAQ rules for Antarctic bases are stored separately in the
    +# 'antarctica' file.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Chile	1927	1932	-	Sep	 1	0:00	1:00	S
    +Rule	Chile	1928	1932	-	Apr	 1	0:00	0	-
    +Rule	Chile	1942	only	-	Jun	 1	4:00u	0	-
    +Rule	Chile	1942	only	-	Aug	 1	5:00u	1:00	S
    +Rule	Chile	1946	only	-	Jul	15	4:00u	1:00	S
    +Rule	Chile	1946	only	-	Sep	 1	3:00u	0:00	-
    +Rule	Chile	1947	only	-	Apr	 1	4:00u	0	-
    +Rule	Chile	1968	only	-	Nov	 3	4:00u	1:00	S
    +Rule	Chile	1969	only	-	Mar	30	3:00u	0	-
    +Rule	Chile	1969	only	-	Nov	23	4:00u	1:00	S
    +Rule	Chile	1970	only	-	Mar	29	3:00u	0	-
    +Rule	Chile	1971	only	-	Mar	14	3:00u	0	-
    +Rule	Chile	1970	1972	-	Oct	Sun>=9	4:00u	1:00	S
    +Rule	Chile	1972	1986	-	Mar	Sun>=9	3:00u	0	-
    +Rule	Chile	1973	only	-	Sep	30	4:00u	1:00	S
    +Rule	Chile	1974	1987	-	Oct	Sun>=9	4:00u	1:00	S
    +Rule	Chile	1987	only	-	Apr	12	3:00u	0	-
    +Rule	Chile	1988	1989	-	Mar	Sun>=9	3:00u	0	-
    +Rule	Chile	1988	only	-	Oct	Sun>=1	4:00u	1:00	S
    +Rule	Chile	1989	only	-	Oct	Sun>=9	4:00u	1:00	S
    +Rule	Chile	1990	only	-	Mar	18	3:00u	0	-
    +Rule	Chile	1990	only	-	Sep	16	4:00u	1:00	S
    +Rule	Chile	1991	1996	-	Mar	Sun>=9	3:00u	0	-
    +Rule	Chile	1991	1997	-	Oct	Sun>=9	4:00u	1:00	S
    +Rule	Chile	1997	only	-	Mar	30	3:00u	0	-
    +Rule	Chile	1998	only	-	Mar	Sun>=9	3:00u	0	-
    +Rule	Chile	1998	only	-	Sep	27	4:00u	1:00	S
    +Rule	Chile	1999	only	-	Apr	 4	3:00u	0	-
    +Rule	Chile	1999	2010	-	Oct	Sun>=9	4:00u	1:00	S
    +Rule	Chile	2000	2007	-	Mar	Sun>=9	3:00u	0	-
    +# N.B.: the end of March 29 in Chile is March 30 in Universal time,
    +# which is used below in specifying the transition.
    +Rule	Chile	2008	only	-	Mar	30	3:00u	0	-
    +Rule	Chile	2009	only	-	Mar	Sun>=9	3:00u	0	-
    +Rule	Chile	2010	only	-	Apr	Sun>=1	3:00u	0	-
    +Rule	Chile	2011	only	-	May	Sun>=2	3:00u	0	-
    +Rule	Chile	2011	only	-	Aug	Sun>=16	4:00u	1:00	S
    +Rule	Chile	2012	only	-	Apr	Sun>=23	3:00u	0	-
    +Rule	Chile	2012	only	-	Sep	Sun>=2	4:00u	1:00	S
    +Rule	Chile	2013	max	-	Mar	Sun>=9	3:00u	0	-
    +Rule	Chile	2013	max	-	Oct	Sun>=9	4:00u	1:00	S
    +# IATA SSIM anomalies: (1992-02) says 1992-03-14;
    +# (1996-09) says 1998-03-08.  Ignore these.
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Santiago	-4:42:46 -	LMT	1890
    +			-4:42:46 -	SMT	1910 	    # Santiago Mean Time
    +			-5:00	-	CLT	1916 Jul  1 # Chile Time
    +			-4:42:46 -	SMT	1918 Sep  1 # Santiago Mean Time
    +			-4:00	-	CLT	1919 Jul  1 # Chile Time
    +			-4:42:46 -	SMT	1927 Sep  1 # Santiago Mean Time
    +			-5:00	Chile	CL%sT	1947 May 22 # Chile Time
    +			-4:00	Chile	CL%sT
    +Zone Pacific/Easter	-7:17:44 -	LMT	1890
    +			-7:17:28 -	EMT	1932 Sep    # Easter Mean Time
    +			-7:00	Chile	EAS%sT	1982 Mar 13 21:00 # Easter I Time
    +			-6:00	Chile	EAS%sT
    +#
    +# Sala y Gomez Island is like Pacific/Easter.
    +# Other Chilean locations, including Juan Fernandez Is, San Ambrosio,
    +# San Felix, and Antarctic bases, are like America/Santiago.
    +
    +# Colombia
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	CO	1992	only	-	May	 3	0:00	1:00	S
    +Rule	CO	1993	only	-	Apr	 4	0:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Bogota	-4:56:20 -	LMT	1884 Mar 13
    +			-4:56:20 -	BMT	1914 Nov 23 # Bogota Mean Time
    +			-5:00	CO	CO%sT	# Colombia Time
    +# Malpelo, Providencia, San Andres
    +# no information; probably like America/Bogota
    +
    +# Curacao
    +#
    +# From Paul Eggert (2006-03-22):
    +# Shanks & Pottenger say that The Bottom and Philipsburg have been at
    +# -4:00 since standard time was introduced on 1912-03-02; and that
    +# Kralendijk and Rincon used Kralendijk Mean Time (-4:33:08) from
    +# 1912-02-02 to 1965-01-01.  The former is dubious, since S&P also say
    +# Saba Island has been like Curacao.
    +# This all predates our 1970 cutoff, though.
    +#
    +# By July 2007 Curacao and St Maarten are planned to become
    +# associated states within the Netherlands, much like Aruba;
    +# Bonaire, Saba and St Eustatius would become directly part of the
    +# Netherlands as Kingdom Islands.  This won't affect their time zones
    +# though, as far as we know.
    +#
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Curacao	-4:35:44 -	LMT	1912 Feb 12	# Willemstad
    +			-4:30	-	ANT	1965 # Netherlands Antilles Time
    +			-4:00	-	AST
    +
    +# From Arthur David Olson (2011-06-15):
    +# At least for now, use links for places with new iso3166 codes.
    +# The name "Lower Prince's Quarter" is both longer than fourteen charaters
    +# and contains an apostrophe; use "Lower_Princes" below.
    +
    +Link	America/Curacao	America/Lower_Princes # Sint Maarten
    +Link	America/Curacao	America/Kralendijk # Bonaire, Sint Estatius and Saba
    +
    +# Ecuador
    +#
    +# From Paul Eggert (2007-03-04):
    +# Apparently Ecuador had a failed experiment with DST in 1992.
    +#  (2007-02-27) and
    +#  (2006-11-06) both
    +# talk about "hora Sixto".  Leave this alone for now, as we have no data.
    +#
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Guayaquil	-5:19:20 -	LMT	1890
    +			-5:14:00 -	QMT	1931 # Quito Mean Time
    +			-5:00	-	ECT	     # Ecuador Time
    +Zone Pacific/Galapagos	-5:58:24 -	LMT	1931 # Puerto Baquerizo Moreno
    +			-5:00	-	ECT	1986
    +			-6:00	-	GALT	     # Galapagos Time
    +
    +# Falklands
    +
    +# From Paul Eggert (2006-03-22):
    +# Between 1990 and 2000 inclusive, Shanks & Pottenger and the IATA agree except
    +# the IATA gives 1996-09-08.  Go with Shanks & Pottenger.
    +
    +# From Falkland Islands Government Office, London (2001-01-22)
    +# via Jesper Norgaard:
    +# ... the clocks revert back to Local Mean Time at 2 am on Sunday 15
    +# April 2001 and advance one hour to summer time at 2 am on Sunday 2
    +# September.  It is anticipated that the clocks will revert back at 2
    +# am on Sunday 21 April 2002 and advance to summer time at 2 am on
    +# Sunday 1 September.
    +
    +# From Rives McDow (2001-02-13):
    +#
    +# I have communicated several times with people there, and the last
    +# time I had communications that was helpful was in 1998.  Here is
    +# what was said then:
    +#
    +# "The general rule was that Stanley used daylight saving and the Camp
    +# did not. However for various reasons many people in the Camp have
    +# started to use daylight saving (known locally as 'Stanley Time')
    +# There is no rule as to who uses daylight saving - it is a matter of
    +# personal choice and so it is impossible to draw a map showing who
    +# uses it and who does not. Any list would be out of date as soon as
    +# it was produced. This year daylight saving ended on April 18/19th
    +# and started again on September 12/13th.  I do not know what the rule
    +# is, but can find out if you like.  We do not change at the same time
    +# as UK or Chile."
    +#
    +# I did have in my notes that the rule was "Second Saturday in Sep at
    +# 0:00 until third Saturday in Apr at 0:00".  I think that this does
    +# not agree in some cases with Shanks; is this true?
    +#
    +# Also, there is no mention in the list that some areas in the
    +# Falklands do not use DST.  I have found in my communications there
    +# that these areas are on the western half of East Falkland and all of
    +# West Falkland.  Stanley is the only place that consistently observes
    +# DST.  Again, as in other places in the world, the farmers don't like
    +# it.  West Falkland is almost entirely sheep farmers.
    +#
    +# I know one lady there that keeps a list of which farm keeps DST and
    +# which doesn't each year.  She runs a shop in Stanley, and says that
    +# the list changes each year.  She uses it to communicate to her
    +# customers, catching them when they are home for lunch or dinner.
    +
    +# From Paul Eggert (2001-03-05):
    +# For now, we'll just record the time in Stanley, since we have no
    +# better info.
    +
    +# From Steffen Thorsen (2011-04-01):
    +# The Falkland Islands will not turn back clocks this winter, but stay on
    +# daylight saving time.
    +#
    +# One source:
    +# 
    +# http://www.falklandnews.com/public/story.cfm?get=5914&source=3
    +# 
    +#
    +# We have gotten this confirmed by a clerk of the legislative assembly:
    +# Normally the clocks revert to Local Mean Time (UTC/GMT -4 hours) on the
    +# third Sunday of April at 0200hrs and advance to Summer Time (UTC/GMT -3
    +# hours) on the first Sunday of September at 0200hrs.
    +#
    +# IMPORTANT NOTE: During 2011, on a trial basis, the Falkland Islands
    +# will not revert to local mean time, but clocks will remain on Summer
    +# time (UTC/GMT - 3 hours) throughout the whole of 2011.  Any long term
    +# change to local time following the trial period will be notified.
    +#
    +# From Andrew Newman (2012-02-24)
    +# A letter from Justin McPhee, Chief Executive,
    +# Cable & Wireless Falkland Islands (dated 2012-02-22)
    +# states...
    +#   The current Atlantic/Stanley entry under South America expects the
    +#   clocks to go back to standard Falklands Time (FKT) on the 15th April.
    +#   The database entry states that in 2011 Stanley was staying on fixed
    +#   summer time on a trial basis only.  FIG need to contact IANA and/or
    +#   the maintainers of the database to inform them we're adopting
    +#   the same policy this year and suggest recommendations for future years.
    +#
    +# For now we will assume permanent summer time for the Falklands
    +# until advised differently (to apply for 2012 and beyond, after the 2011
    +# experiment was apparently successful.)
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Falk	1937	1938	-	Sep	lastSun	0:00	1:00	S
    +Rule	Falk	1938	1942	-	Mar	Sun>=19	0:00	0	-
    +Rule	Falk	1939	only	-	Oct	1	0:00	1:00	S
    +Rule	Falk	1940	1942	-	Sep	lastSun	0:00	1:00	S
    +Rule	Falk	1943	only	-	Jan	1	0:00	0	-
    +Rule	Falk	1983	only	-	Sep	lastSun	0:00	1:00	S
    +Rule	Falk	1984	1985	-	Apr	lastSun	0:00	0	-
    +Rule	Falk	1984	only	-	Sep	16	0:00	1:00	S
    +Rule	Falk	1985	2000	-	Sep	Sun>=9	0:00	1:00	S
    +Rule	Falk	1986	2000	-	Apr	Sun>=16	0:00	0	-
    +Rule	Falk	2001	2010	-	Apr	Sun>=15	2:00	0	-
    +Rule	Falk	2001	2010	-	Sep	Sun>=1	2:00	1:00	S
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Atlantic/Stanley	-3:51:24 -	LMT	1890
    +			-3:51:24 -	SMT	1912 Mar 12  # Stanley Mean Time
    +			-4:00	Falk	FK%sT	1983 May     # Falkland Is Time
    +			-3:00	Falk	FK%sT	1985 Sep 15
    +			-4:00	Falk	FK%sT	2010 Sep 5 02:00
    +			-3:00	-	FKST
    +
    +# French Guiana
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Cayenne	-3:29:20 -	LMT	1911 Jul
    +			-4:00	-	GFT	1967 Oct # French Guiana Time
    +			-3:00	-	GFT
    +
    +# Guyana
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar	# Georgetown
    +			-3:45	-	GBGT	1966 May 26 # Br Guiana Time
    +			-3:45	-	GYT	1975 Jul 31 # Guyana Time
    +			-3:00	-	GYT	1991
    +# IATA SSIM (1996-06) says -4:00.  Assume a 1991 switch.
    +			-4:00	-	GYT
    +
    +# Paraguay
    +# From Paul Eggert (2006-03-22):
    +# Shanks & Pottenger say that spring transitions are from 01:00 -> 02:00,
    +# and autumn transitions are from 00:00 -> 23:00.  Go with pre-1999
    +# editions of Shanks, and with the IATA, who say transitions occur at 00:00.
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Para	1975	1988	-	Oct	 1	0:00	1:00	S
    +Rule	Para	1975	1978	-	Mar	 1	0:00	0	-
    +Rule	Para	1979	1991	-	Apr	 1	0:00	0	-
    +Rule	Para	1989	only	-	Oct	22	0:00	1:00	S
    +Rule	Para	1990	only	-	Oct	 1	0:00	1:00	S
    +Rule	Para	1991	only	-	Oct	 6	0:00	1:00	S
    +Rule	Para	1992	only	-	Mar	 1	0:00	0	-
    +Rule	Para	1992	only	-	Oct	 5	0:00	1:00	S
    +Rule	Para	1993	only	-	Mar	31	0:00	0	-
    +Rule	Para	1993	1995	-	Oct	 1	0:00	1:00	S
    +Rule	Para	1994	1995	-	Feb	lastSun	0:00	0	-
    +Rule	Para	1996	only	-	Mar	 1	0:00	0	-
    +# IATA SSIM (2000-02) says 1999-10-10; ignore this for now.
    +# From Steffen Thorsen (2000-10-02):
    +# I have three independent reports that Paraguay changed to DST this Sunday
    +# (10-01).
    +#
    +# Translated by Gwillim Law (2001-02-27) from
    +# 
    +# Noticias, a daily paper in Asuncion, Paraguay (2000-10-01)
    +# :
    +# Starting at 0:00 today, the clock will be set forward 60 minutes, in
    +# fulfillment of Decree No. 7,273 of the Executive Power....  The time change
    +# system has been operating for several years.  Formerly there was a separate
    +# decree each year; the new law has the same effect, but permanently.  Every
    +# year, the time will change on the first Sunday of October; likewise, the
    +# clock will be set back on the first Sunday of March.
    +#
    +Rule	Para	1996	2001	-	Oct	Sun>=1	0:00	1:00	S
    +# IATA SSIM (1997-09) says Mar 1; go with Shanks & Pottenger.
    +Rule	Para	1997	only	-	Feb	lastSun	0:00	0	-
    +# Shanks & Pottenger say 1999-02-28; IATA SSIM (1999-02) says 1999-02-27, but
    +# (1999-09) reports no date; go with above sources and Gerd Knops (2001-02-27).
    +Rule	Para	1998	2001	-	Mar	Sun>=1	0:00	0	-
    +# From Rives McDow (2002-02-28):
    +# A decree was issued in Paraguay (no. 16350) on 2002-02-26 that changed the
    +# dst method to be from the first Sunday in September to the first Sunday in
    +# April.
    +Rule	Para	2002	2004	-	Apr	Sun>=1	0:00	0	-
    +Rule	Para	2002	2003	-	Sep	Sun>=1	0:00	1:00	S
    +#
    +# From Jesper Norgaard Welen (2005-01-02):
    +# There are several sources that claim that Paraguay made
    +# a timezone rule change in autumn 2004.
    +# From Steffen Thorsen (2005-01-05):
    +# Decree 1,867 (2004-03-05)
    +# From Carlos Raul Perasso via Jesper Norgaard Welen (2006-10-13)
    +# 
    +Rule	Para	2004	2009	-	Oct	Sun>=15	0:00	1:00	S
    +Rule	Para	2005	2009	-	Mar	Sun>=8	0:00	0	-
    +# From Carlos Raul Perasso (2010-02-18):
    +# By decree number 3958 issued yesterday (
    +# 
    +# http://www.presidencia.gov.py/v1/wp-content/uploads/2010/02/decreto3958.pdf
    +# 
    +# )
    +# Paraguay changes its DST schedule, postponing the March rule to April and
    +# modifying the October date. The decree reads:
    +# ...
    +# Art. 1. It is hereby established that from the second Sunday of the month of
    +# April of this year (2010), the official time is to be set back 60 minutes,
    +# and that on the first Sunday of the month of October, it is to be set
    +# forward 60 minutes, in all the territory of the Paraguayan Republic.
    +# ...
    +Rule	Para	2010	max	-	Oct	Sun>=1	0:00	1:00	S
    +Rule	Para	2010	max	-	Apr	Sun>=8	0:00	0	-
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Asuncion	-3:50:40 -	LMT	1890
    +			-3:50:40 -	AMT	1931 Oct 10 # Asuncion Mean Time
    +			-4:00	-	PYT	1972 Oct # Paraguay Time
    +			-3:00	-	PYT	1974 Apr
    +			-4:00	Para	PY%sT
    +
    +# Peru
    +#
    +# 
    +# From Evelyn C. Leeper via Mark Brader (2003-10-26):
    +# When we were in Peru in 1985-1986, they apparently switched over
    +# sometime between December 29 and January 3 while we were on the Amazon.
    +#
    +# From Paul Eggert (2006-03-22):
    +# Shanks & Pottenger don't have this transition.  Assume 1986 was like 1987.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	Peru	1938	only	-	Jan	 1	0:00	1:00	S
    +Rule	Peru	1938	only	-	Apr	 1	0:00	0	-
    +Rule	Peru	1938	1939	-	Sep	lastSun	0:00	1:00	S
    +Rule	Peru	1939	1940	-	Mar	Sun>=24	0:00	0	-
    +Rule	Peru	1986	1987	-	Jan	 1	0:00	1:00	S
    +Rule	Peru	1986	1987	-	Apr	 1	0:00	0	-
    +Rule	Peru	1990	only	-	Jan	 1	0:00	1:00	S
    +Rule	Peru	1990	only	-	Apr	 1	0:00	0	-
    +# IATA is ambiguous for 1993/1995; go with Shanks & Pottenger.
    +Rule	Peru	1994	only	-	Jan	 1	0:00	1:00	S
    +Rule	Peru	1994	only	-	Apr	 1	0:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Lima	-5:08:12 -	LMT	1890
    +			-5:08:36 -	LMT	1908 Jul 28 # Lima Mean Time?
    +			-5:00	Peru	PE%sT	# Peru Time
    +
    +# South Georgia
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890		# Grytviken
    +			-2:00	-	GST	# South Georgia Time
    +
    +# South Sandwich Is
    +# uninhabited; scientific personnel have wintered
    +
    +# Suriname
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Paramaribo	-3:40:40 -	LMT	1911
    +			-3:40:52 -	PMT	1935     # Paramaribo Mean Time
    +			-3:40:36 -	PMT	1945 Oct # The capital moved?
    +			-3:30	-	NEGT	1975 Nov 20 # Dutch Guiana Time
    +			-3:30	-	SRT	1984 Oct # Suriname Time
    +			-3:00	-	SRT
    +
    +# Trinidad and Tobago
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Port_of_Spain -4:06:04 -	LMT	1912 Mar 2
    +			-4:00	-	AST
    +
    +# Uruguay
    +# From Paul Eggert (1993-11-18):
    +# Uruguay wins the prize for the strangest peacetime manipulation of the rules.
    +# From Shanks & Pottenger:
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +# Whitman gives 1923 Oct 1; go with Shanks & Pottenger.
    +Rule	Uruguay	1923	only	-	Oct	 2	 0:00	0:30	HS
    +Rule	Uruguay	1924	1926	-	Apr	 1	 0:00	0	-
    +Rule	Uruguay	1924	1925	-	Oct	 1	 0:00	0:30	HS
    +Rule	Uruguay	1933	1935	-	Oct	lastSun	 0:00	0:30	HS
    +# Shanks & Pottenger give 1935 Apr 1 0:00 & 1936 Mar 30 0:00; go with Whitman.
    +Rule	Uruguay	1934	1936	-	Mar	Sat>=25	23:30s	0	-
    +Rule	Uruguay	1936	only	-	Nov	 1	 0:00	0:30	HS
    +Rule	Uruguay	1937	1941	-	Mar	lastSun	 0:00	0	-
    +# Whitman gives 1937 Oct 3; go with Shanks & Pottenger.
    +Rule	Uruguay	1937	1940	-	Oct	lastSun	 0:00	0:30	HS
    +# Whitman gives 1941 Oct 24 - 1942 Mar 27, 1942 Dec 14 - 1943 Apr 13,
    +# and 1943 Apr 13 ``to present time''; go with Shanks & Pottenger.
    +Rule	Uruguay	1941	only	-	Aug	 1	 0:00	0:30	HS
    +Rule	Uruguay	1942	only	-	Jan	 1	 0:00	0	-
    +Rule	Uruguay	1942	only	-	Dec	14	 0:00	1:00	S
    +Rule	Uruguay	1943	only	-	Mar	14	 0:00	0	-
    +Rule	Uruguay	1959	only	-	May	24	 0:00	1:00	S
    +Rule	Uruguay	1959	only	-	Nov	15	 0:00	0	-
    +Rule	Uruguay	1960	only	-	Jan	17	 0:00	1:00	S
    +Rule	Uruguay	1960	only	-	Mar	 6	 0:00	0	-
    +Rule	Uruguay	1965	1967	-	Apr	Sun>=1	 0:00	1:00	S
    +Rule	Uruguay	1965	only	-	Sep	26	 0:00	0	-
    +Rule	Uruguay	1966	1967	-	Oct	31	 0:00	0	-
    +Rule	Uruguay	1968	1970	-	May	27	 0:00	0:30	HS
    +Rule	Uruguay	1968	1970	-	Dec	 2	 0:00	0	-
    +Rule	Uruguay	1972	only	-	Apr	24	 0:00	1:00	S
    +Rule	Uruguay	1972	only	-	Aug	15	 0:00	0	-
    +Rule	Uruguay	1974	only	-	Mar	10	 0:00	0:30	HS
    +Rule	Uruguay	1974	only	-	Dec	22	 0:00	1:00	S
    +Rule	Uruguay	1976	only	-	Oct	 1	 0:00	0	-
    +Rule	Uruguay	1977	only	-	Dec	 4	 0:00	1:00	S
    +Rule	Uruguay	1978	only	-	Apr	 1	 0:00	0	-
    +Rule	Uruguay	1979	only	-	Oct	 1	 0:00	1:00	S
    +Rule	Uruguay	1980	only	-	May	 1	 0:00	0	-
    +Rule	Uruguay	1987	only	-	Dec	14	 0:00	1:00	S
    +Rule	Uruguay	1988	only	-	Mar	14	 0:00	0	-
    +Rule	Uruguay	1988	only	-	Dec	11	 0:00	1:00	S
    +Rule	Uruguay	1989	only	-	Mar	12	 0:00	0	-
    +Rule	Uruguay	1989	only	-	Oct	29	 0:00	1:00	S
    +# Shanks & Pottenger say no DST was observed in 1990/1 and 1991/2,
    +# and that 1992/3's DST was from 10-25 to 03-01.  Go with IATA.
    +Rule	Uruguay	1990	1992	-	Mar	Sun>=1	 0:00	0	-
    +Rule	Uruguay	1990	1991	-	Oct	Sun>=21	 0:00	1:00	S
    +Rule	Uruguay	1992	only	-	Oct	18	 0:00	1:00	S
    +Rule	Uruguay	1993	only	-	Feb	28	 0:00	0	-
    +# From Eduardo Cota (2004-09-20):
    +# The uruguayan government has decreed a change in the local time....
    +# http://www.presidencia.gub.uy/decretos/2004091502.htm
    +Rule	Uruguay	2004	only	-	Sep	19	 0:00	1:00	S
    +# From Steffen Thorsen (2005-03-11):
    +# Uruguay's DST was scheduled to end on Sunday, 2005-03-13, but in order to
    +# save energy ... it was postponed two weeks....
    +# http://www.presidencia.gub.uy/_Web/noticias/2005/03/2005031005.htm
    +Rule	Uruguay	2005	only	-	Mar	27	 2:00	0	-
    +# From Eduardo Cota (2005-09-27):
    +# http://www.presidencia.gub.uy/_Web/decretos/2005/09/CM%20119_09%2009%202005_00001.PDF
    +# This means that from 2005-10-09 at 02:00 local time, until 2006-03-12 at
    +# 02:00 local time, official time in Uruguay will be at GMT -2.
    +Rule	Uruguay	2005	only	-	Oct	 9	 2:00	1:00	S
    +Rule	Uruguay	2006	only	-	Mar	12	 2:00	0	-
    +# From Jesper Norgaard Welen (2006-09-06):
    +# http://www.presidencia.gub.uy/_web/decretos/2006/09/CM%20210_08%2006%202006_00001.PDF
    +Rule	Uruguay	2006	max	-	Oct	Sun>=1	 2:00	1:00	S
    +Rule	Uruguay	2007	max	-	Mar	Sun>=8	 2:00	0	-
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone America/Montevideo	-3:44:44 -	LMT	1898 Jun 28
    +			-3:44:44 -	MMT	1920 May  1	# Montevideo MT
    +			-3:30	Uruguay	UY%sT	1942 Dec 14	# Uruguay Time
    +			-3:00	Uruguay	UY%sT
    +
    +# Venezuela
    +#
    +# From John Stainforth (2007-11-28):
    +# ... the change for Venezuela originally expected for 2007-12-31 has
    +# been brought forward to 2007-12-09.  The official announcement was
    +# published today in the "Gaceta Oficial de la Republica Bolivariana
    +# de Venezuela, numero 38.819" (official document for all laws or
    +# resolution publication)
    +# http://www.globovision.com/news.php?nid=72208
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	America/Caracas	-4:27:44 -	LMT	1890
    +			-4:27:40 -	CMT	1912 Feb 12 # Caracas Mean Time?
    +			-4:30	-	VET	1965	     # Venezuela Time
    +			-4:00	-	VET	2007 Dec  9 03:00
    +			-4:30	-	VET
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/systemv b/jdk/test/sun/util/calendar/zi/tzdata/systemv
    new file mode 100644
    index 00000000000..0b0a2665654
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/systemv
    @@ -0,0 +1,61 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +
    +# Old rules, should the need arise.
    +# No attempt is made to handle Newfoundland, since it cannot be expressed
    +# using the System V "TZ" scheme (half-hour offset), or anything outside
    +# North America (no support for non-standard DST start/end dates), nor
    +# the changes in the DST rules in the US after 1976 (which occurred after
    +# the old rules were written).
    +#
    +# If you need the old rules, uncomment ## lines.
    +# Compile this *without* leap second correction for true conformance.
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	SystemV	min	1973	-	Apr	lastSun	2:00	1:00	D
    +Rule	SystemV	min	1973	-	Oct	lastSun	2:00	0	S
    +Rule	SystemV	1974	only	-	Jan	6	2:00	1:00	D
    +Rule	SystemV	1974	only	-	Nov	lastSun	2:00	0	S
    +Rule	SystemV	1975	only	-	Feb	23	2:00	1:00	D
    +Rule	SystemV	1975	only	-	Oct	lastSun	2:00	0	S
    +Rule	SystemV	1976	max	-	Apr	lastSun	2:00	1:00	D
    +Rule	SystemV	1976	max	-	Oct	lastSun	2:00	0	S
    +
    +# Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
    +## Zone	SystemV/AST4ADT	-4:00	SystemV		A%sT
    +## Zone	SystemV/EST5EDT	-5:00	SystemV		E%sT
    +## Zone	SystemV/CST6CDT	-6:00	SystemV		C%sT
    +## Zone	SystemV/MST7MDT	-7:00	SystemV		M%sT
    +## Zone	SystemV/PST8PDT	-8:00	SystemV		P%sT
    +## Zone	SystemV/YST9YDT	-9:00	SystemV		Y%sT
    +## Zone	SystemV/AST4	-4:00	-		AST
    +## Zone	SystemV/EST5	-5:00	-		EST
    +## Zone	SystemV/CST6	-6:00	-		CST
    +## Zone	SystemV/MST7	-7:00	-		MST
    +## Zone	SystemV/PST8	-8:00	-		PST
    +## Zone	SystemV/YST9	-9:00	-		YST
    +## Zone	SystemV/HST10	-10:00	-		HST
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata/zone.tab b/jdk/test/sun/util/calendar/zi/tzdata/zone.tab
    new file mode 100644
    index 00000000000..ef380cd19fb
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata/zone.tab
    @@ -0,0 +1,464 @@
    +#
    +# 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.
    +#
    +# 
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
    +#
    +# TZ zone descriptions
    +#
    +# From Paul Eggert (1996-08-05):
    +#
    +# This file contains a table with the following columns:
    +# 1.  ISO 3166 2-character country code.  See the file `iso3166.tab'.
    +# 2.  Latitude and longitude of the zone's principal location
    +#     in ISO 6709 sign-degrees-minutes-seconds format,
    +#     either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS,
    +#     first latitude (+ is north), then longitude (+ is east).
    +# 3.  Zone name used in value of TZ environment variable.
    +# 4.  Comments; present if and only if the country has multiple rows.
    +#
    +# Columns are separated by a single tab.
    +# The table is sorted first by country, then an order within the country that
    +# (1) makes some geographical sense, and
    +# (2) puts the most populous zones first, where that does not contradict (1).
    +#
    +# Lines beginning with `#' are comments.
    +#
    +#country-
    +#code	coordinates	TZ			comments
    +AD	+4230+00131	Europe/Andorra
    +AE	+2518+05518	Asia/Dubai
    +AF	+3431+06912	Asia/Kabul
    +AG	+1703-06148	America/Antigua
    +AI	+1812-06304	America/Anguilla
    +AL	+4120+01950	Europe/Tirane
    +AM	+4011+04430	Asia/Yerevan
    +AO	-0848+01314	Africa/Luanda
    +AQ	-7750+16636	Antarctica/McMurdo	McMurdo Station, Ross Island
    +AQ	-9000+00000	Antarctica/South_Pole	Amundsen-Scott Station, South Pole
    +AQ	-6734-06808	Antarctica/Rothera	Rothera Station, Adelaide Island
    +AQ	-6448-06406	Antarctica/Palmer	Palmer Station, Anvers Island
    +AQ	-6736+06253	Antarctica/Mawson	Mawson Station, Holme Bay
    +AQ	-6835+07758	Antarctica/Davis	Davis Station, Vestfold Hills
    +AQ	-6617+11031	Antarctica/Casey	Casey Station, Bailey Peninsula
    +AQ	-7824+10654	Antarctica/Vostok	Vostok Station, Lake Vostok
    +AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville Station, Terre Adelie
    +AQ	-690022+0393524	Antarctica/Syowa	Syowa Station, E Ongul I
    +AQ	-5430+15857	Antarctica/Macquarie	Macquarie Island Station, Macquarie Island
    +AR	-3436-05827	America/Argentina/Buenos_Aires	Buenos Aires (BA, CF)
    +AR	-3124-06411	America/Argentina/Cordoba	most locations (CB, CC, CN, ER, FM, MN, SE, SF)
    +AR	-2447-06525	America/Argentina/Salta	(SA, LP, NQ, RN)
    +AR	-2411-06518	America/Argentina/Jujuy	Jujuy (JY)
    +AR	-2649-06513	America/Argentina/Tucuman	Tucuman (TM)
    +AR	-2828-06547	America/Argentina/Catamarca	Catamarca (CT), Chubut (CH)
    +AR	-2926-06651	America/Argentina/La_Rioja	La Rioja (LR)
    +AR	-3132-06831	America/Argentina/San_Juan	San Juan (SJ)
    +AR	-3253-06849	America/Argentina/Mendoza	Mendoza (MZ)
    +AR	-3319-06621	America/Argentina/San_Luis	San Luis (SL)
    +AR	-5138-06913	America/Argentina/Rio_Gallegos	Santa Cruz (SC)
    +AR	-5448-06818	America/Argentina/Ushuaia	Tierra del Fuego (TF)
    +AS	-1416-17042	Pacific/Pago_Pago
    +AT	+4813+01620	Europe/Vienna
    +AU	-3133+15905	Australia/Lord_Howe	Lord Howe Island
    +AU	-4253+14719	Australia/Hobart	Tasmania - most locations
    +AU	-3956+14352	Australia/Currie	Tasmania - King Island
    +AU	-3749+14458	Australia/Melbourne	Victoria
    +AU	-3352+15113	Australia/Sydney	New South Wales - most locations
    +AU	-3157+14127	Australia/Broken_Hill	New South Wales - Yancowinna
    +AU	-2728+15302	Australia/Brisbane	Queensland - most locations
    +AU	-2016+14900	Australia/Lindeman	Queensland - Holiday Islands
    +AU	-3455+13835	Australia/Adelaide	South Australia
    +AU	-1228+13050	Australia/Darwin	Northern Territory
    +AU	-3157+11551	Australia/Perth	Western Australia - most locations
    +AU	-3143+12852	Australia/Eucla	Western Australia - Eucla area
    +AW	+1230-06958	America/Aruba
    +AX	+6006+01957	Europe/Mariehamn
    +AZ	+4023+04951	Asia/Baku
    +BA	+4352+01825	Europe/Sarajevo
    +BB	+1306-05937	America/Barbados
    +BD	+2343+09025	Asia/Dhaka
    +BE	+5050+00420	Europe/Brussels
    +BF	+1222-00131	Africa/Ouagadougou
    +BG	+4241+02319	Europe/Sofia
    +BH	+2623+05035	Asia/Bahrain
    +BI	-0323+02922	Africa/Bujumbura
    +BJ	+0629+00237	Africa/Porto-Novo
    +BL	+1753-06251	America/St_Barthelemy
    +BM	+3217-06446	Atlantic/Bermuda
    +BN	+0456+11455	Asia/Brunei
    +BO	-1630-06809	America/La_Paz
    +BQ	+120903-0681636	America/Kralendijk
    +BR	-0351-03225	America/Noronha	Atlantic islands
    +BR	-0127-04829	America/Belem	Amapa, E Para
    +BR	-0343-03830	America/Fortaleza	NE Brazil (MA, PI, CE, RN, PB)
    +BR	-0803-03454	America/Recife	Pernambuco
    +BR	-0712-04812	America/Araguaina	Tocantins
    +BR	-0940-03543	America/Maceio	Alagoas, Sergipe
    +BR	-1259-03831	America/Bahia	Bahia
    +BR	-2332-04637	America/Sao_Paulo	S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS)
    +BR	-2027-05437	America/Campo_Grande	Mato Grosso do Sul
    +BR	-1535-05605	America/Cuiaba	Mato Grosso
    +BR	-0226-05452	America/Santarem	W Para
    +BR	-0846-06354	America/Porto_Velho	Rondonia
    +BR	+0249-06040	America/Boa_Vista	Roraima
    +BR	-0308-06001	America/Manaus	E Amazonas
    +BR	-0640-06952	America/Eirunepe	W Amazonas
    +BR	-0958-06748	America/Rio_Branco	Acre
    +BS	+2505-07721	America/Nassau
    +BT	+2728+08939	Asia/Thimphu
    +BW	-2439+02555	Africa/Gaborone
    +BY	+5354+02734	Europe/Minsk
    +BZ	+1730-08812	America/Belize
    +CA	+4734-05243	America/St_Johns	Newfoundland Time, including SE Labrador
    +CA	+4439-06336	America/Halifax	Atlantic Time - Nova Scotia (most places), PEI
    +CA	+4612-05957	America/Glace_Bay	Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971
    +CA	+4606-06447	America/Moncton	Atlantic Time - New Brunswick
    +CA	+5320-06025	America/Goose_Bay	Atlantic Time - Labrador - most locations
    +CA	+5125-05707	America/Blanc-Sablon	Atlantic Standard Time - Quebec - Lower North Shore
    +CA	+4531-07334	America/Montreal	Eastern Time - Quebec - most locations
    +CA	+4339-07923	America/Toronto	Eastern Time - Ontario - most locations
    +CA	+4901-08816	America/Nipigon	Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973
    +CA	+4823-08915	America/Thunder_Bay	Eastern Time - Thunder Bay, Ontario
    +CA	+6344-06828	America/Iqaluit	Eastern Time - east Nunavut - most locations
    +CA	+6608-06544	America/Pangnirtung	Eastern Time - Pangnirtung, Nunavut
    +CA	+744144-0944945	America/Resolute	Central Standard Time - Resolute, Nunavut
    +CA	+484531-0913718	America/Atikokan	Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut
    +CA	+624900-0920459	America/Rankin_Inlet	Central Time - central Nunavut
    +CA	+4953-09709	America/Winnipeg	Central Time - Manitoba & west Ontario
    +CA	+4843-09434	America/Rainy_River	Central Time - Rainy River & Fort Frances, Ontario
    +CA	+5024-10439	America/Regina	Central Standard Time - Saskatchewan - most locations
    +CA	+5017-10750	America/Swift_Current	Central Standard Time - Saskatchewan - midwest
    +CA	+5333-11328	America/Edmonton	Mountain Time - Alberta, east British Columbia & west Saskatchewan
    +CA	+690650-1050310	America/Cambridge_Bay	Mountain Time - west Nunavut
    +CA	+6227-11421	America/Yellowknife	Mountain Time - central Northwest Territories
    +CA	+682059-1334300	America/Inuvik	Mountain Time - west Northwest Territories
    +CA	+4906-11631	America/Creston	Mountain Standard Time - Creston, British Columbia
    +CA	+5946-12014	America/Dawson_Creek	Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia
    +CA	+4916-12307	America/Vancouver	Pacific Time - west British Columbia
    +CA	+6043-13503	America/Whitehorse	Pacific Time - south Yukon
    +CA	+6404-13925	America/Dawson	Pacific Time - north Yukon
    +CC	-1210+09655	Indian/Cocos
    +CD	-0418+01518	Africa/Kinshasa	west Dem. Rep. of Congo
    +CD	-1140+02728	Africa/Lubumbashi	east Dem. Rep. of Congo
    +CF	+0422+01835	Africa/Bangui
    +CG	-0416+01517	Africa/Brazzaville
    +CH	+4723+00832	Europe/Zurich
    +CI	+0519-00402	Africa/Abidjan
    +CK	-2114-15946	Pacific/Rarotonga
    +CL	-3327-07040	America/Santiago	most locations
    +CL	-2709-10926	Pacific/Easter	Easter Island & Sala y Gomez
    +CM	+0403+00942	Africa/Douala
    +CN	+3114+12128	Asia/Shanghai	east China - Beijing, Guangdong, Shanghai, etc.
    +CN	+4545+12641	Asia/Harbin	Heilongjiang (except Mohe), Jilin
    +CN	+2934+10635	Asia/Chongqing	central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc.
    +CN	+4348+08735	Asia/Urumqi	most of Tibet & Xinjiang
    +CN	+3929+07559	Asia/Kashgar	west Tibet & Xinjiang
    +CO	+0436-07405	America/Bogota
    +CR	+0956-08405	America/Costa_Rica
    +CU	+2308-08222	America/Havana
    +CV	+1455-02331	Atlantic/Cape_Verde
    +CW	+1211-06900	America/Curacao
    +CX	-1025+10543	Indian/Christmas
    +CY	+3510+03322	Asia/Nicosia
    +CZ	+5005+01426	Europe/Prague
    +DE	+5230+01322	Europe/Berlin
    +DJ	+1136+04309	Africa/Djibouti
    +DK	+5540+01235	Europe/Copenhagen
    +DM	+1518-06124	America/Dominica
    +DO	+1828-06954	America/Santo_Domingo
    +DZ	+3647+00303	Africa/Algiers
    +EC	-0210-07950	America/Guayaquil	mainland
    +EC	-0054-08936	Pacific/Galapagos	Galapagos Islands
    +EE	+5925+02445	Europe/Tallinn
    +EG	+3003+03115	Africa/Cairo
    +EH	+2709-01312	Africa/El_Aaiun
    +ER	+1520+03853	Africa/Asmara
    +ES	+4024-00341	Europe/Madrid	mainland
    +ES	+3553-00519	Africa/Ceuta	Ceuta & Melilla
    +ES	+2806-01524	Atlantic/Canary	Canary Islands
    +ET	+0902+03842	Africa/Addis_Ababa
    +FI	+6010+02458	Europe/Helsinki
    +FJ	-1808+17825	Pacific/Fiji
    +FK	-5142-05751	Atlantic/Stanley
    +FM	+0725+15147	Pacific/Chuuk	Chuuk (Truk) and Yap
    +FM	+0658+15813	Pacific/Pohnpei	Pohnpei (Ponape)
    +FM	+0519+16259	Pacific/Kosrae	Kosrae
    +FO	+6201-00646	Atlantic/Faroe
    +FR	+4852+00220	Europe/Paris
    +GA	+0023+00927	Africa/Libreville
    +GB	+513030-0000731	Europe/London
    +GD	+1203-06145	America/Grenada
    +GE	+4143+04449	Asia/Tbilisi
    +GF	+0456-05220	America/Cayenne
    +GG	+4927-00232	Europe/Guernsey
    +GH	+0533-00013	Africa/Accra
    +GI	+3608-00521	Europe/Gibraltar
    +GL	+6411-05144	America/Godthab	most locations
    +GL	+7646-01840	America/Danmarkshavn	east coast, north of Scoresbysund
    +GL	+7029-02158	America/Scoresbysund	Scoresbysund / Ittoqqortoormiit
    +GL	+7634-06847	America/Thule	Thule / Pituffik
    +GM	+1328-01639	Africa/Banjul
    +GN	+0931-01343	Africa/Conakry
    +GP	+1614-06132	America/Guadeloupe
    +GQ	+0345+00847	Africa/Malabo
    +GR	+3758+02343	Europe/Athens
    +GS	-5416-03632	Atlantic/South_Georgia
    +GT	+1438-09031	America/Guatemala
    +GU	+1328+14445	Pacific/Guam
    +GW	+1151-01535	Africa/Bissau
    +GY	+0648-05810	America/Guyana
    +HK	+2217+11409	Asia/Hong_Kong
    +HN	+1406-08713	America/Tegucigalpa
    +HR	+4548+01558	Europe/Zagreb
    +HT	+1832-07220	America/Port-au-Prince
    +HU	+4730+01905	Europe/Budapest
    +ID	-0610+10648	Asia/Jakarta	Java & Sumatra
    +ID	-0002+10920	Asia/Pontianak	west & central Borneo
    +ID	-0507+11924	Asia/Makassar	east & south Borneo, Sulawesi (Celebes), Bali, Nusa Tengarra, west Timor
    +ID	-0232+14042	Asia/Jayapura	west New Guinea (Irian Jaya) & Malukus (Moluccas)
    +IE	+5320-00615	Europe/Dublin
    +IL	+3146+03514	Asia/Jerusalem
    +IM	+5409-00428	Europe/Isle_of_Man
    +IN	+2232+08822	Asia/Kolkata
    +IO	-0720+07225	Indian/Chagos
    +IQ	+3321+04425	Asia/Baghdad
    +IR	+3540+05126	Asia/Tehran
    +IS	+6409-02151	Atlantic/Reykjavik
    +IT	+4154+01229	Europe/Rome
    +JE	+4912-00207	Europe/Jersey
    +JM	+1800-07648	America/Jamaica
    +JO	+3157+03556	Asia/Amman
    +JP	+353916+1394441	Asia/Tokyo
    +KE	-0117+03649	Africa/Nairobi
    +KG	+4254+07436	Asia/Bishkek
    +KH	+1133+10455	Asia/Phnom_Penh
    +KI	+0125+17300	Pacific/Tarawa	Gilbert Islands
    +KI	-0308-17105	Pacific/Enderbury	Phoenix Islands
    +KI	+0152-15720	Pacific/Kiritimati	Line Islands
    +KM	-1141+04316	Indian/Comoro
    +KN	+1718-06243	America/St_Kitts
    +KP	+3901+12545	Asia/Pyongyang
    +KR	+3733+12658	Asia/Seoul
    +KW	+2920+04759	Asia/Kuwait
    +KY	+1918-08123	America/Cayman
    +KZ	+4315+07657	Asia/Almaty	most locations
    +KZ	+4448+06528	Asia/Qyzylorda	Qyzylorda (Kyzylorda, Kzyl-Orda)
    +KZ	+5017+05710	Asia/Aqtobe	Aqtobe (Aktobe)
    +KZ	+4431+05016	Asia/Aqtau	Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau)
    +KZ	+5113+05121	Asia/Oral	West Kazakhstan
    +LA	+1758+10236	Asia/Vientiane
    +LB	+3353+03530	Asia/Beirut
    +LC	+1401-06100	America/St_Lucia
    +LI	+4709+00931	Europe/Vaduz
    +LK	+0656+07951	Asia/Colombo
    +LR	+0618-01047	Africa/Monrovia
    +LS	-2928+02730	Africa/Maseru
    +LT	+5441+02519	Europe/Vilnius
    +LU	+4936+00609	Europe/Luxembourg
    +LV	+5657+02406	Europe/Riga
    +LY	+3254+01311	Africa/Tripoli
    +MA	+3339-00735	Africa/Casablanca
    +MC	+4342+00723	Europe/Monaco
    +MD	+4700+02850	Europe/Chisinau
    +ME	+4226+01916	Europe/Podgorica
    +MF	+1804-06305	America/Marigot
    +MG	-1855+04731	Indian/Antananarivo
    +MH	+0709+17112	Pacific/Majuro	most locations
    +MH	+0905+16720	Pacific/Kwajalein	Kwajalein
    +MK	+4159+02126	Europe/Skopje
    +ML	+1239-00800	Africa/Bamako
    +MM	+1647+09610	Asia/Rangoon
    +MN	+4755+10653	Asia/Ulaanbaatar	most locations
    +MN	+4801+09139	Asia/Hovd	Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan
    +MN	+4804+11430	Asia/Choibalsan	Dornod, Sukhbaatar
    +MO	+2214+11335	Asia/Macau
    +MP	+1512+14545	Pacific/Saipan
    +MQ	+1436-06105	America/Martinique
    +MR	+1806-01557	Africa/Nouakchott
    +MS	+1643-06213	America/Montserrat
    +MT	+3554+01431	Europe/Malta
    +MU	-2010+05730	Indian/Mauritius
    +MV	+0410+07330	Indian/Maldives
    +MW	-1547+03500	Africa/Blantyre
    +MX	+1924-09909	America/Mexico_City	Central Time - most locations
    +MX	+2105-08646	America/Cancun	Central Time - Quintana Roo
    +MX	+2058-08937	America/Merida	Central Time - Campeche, Yucatan
    +MX	+2540-10019	America/Monterrey	Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border
    +MX	+2550-09730	America/Matamoros	US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border
    +MX	+2313-10625	America/Mazatlan	Mountain Time - S Baja, Nayarit, Sinaloa
    +MX	+2838-10605	America/Chihuahua	Mexican Mountain Time - Chihuahua away from US border
    +MX	+2934-10425	America/Ojinaga	US Mountain Time - Chihuahua near US border
    +MX	+2904-11058	America/Hermosillo	Mountain Standard Time - Sonora
    +MX	+3232-11701	America/Tijuana	US Pacific Time - Baja California near US border
    +MX	+3018-11452	America/Santa_Isabel	Mexican Pacific Time - Baja California away from US border
    +MX	+2048-10515	America/Bahia_Banderas	Mexican Central Time - Bahia de Banderas
    +MY	+0310+10142	Asia/Kuala_Lumpur	peninsular Malaysia
    +MY	+0133+11020	Asia/Kuching	Sabah & Sarawak
    +MZ	-2558+03235	Africa/Maputo
    +NA	-2234+01706	Africa/Windhoek
    +NC	-2216+16627	Pacific/Noumea
    +NE	+1331+00207	Africa/Niamey
    +NF	-2903+16758	Pacific/Norfolk
    +NG	+0627+00324	Africa/Lagos
    +NI	+1209-08617	America/Managua
    +NL	+5222+00454	Europe/Amsterdam
    +NO	+5955+01045	Europe/Oslo
    +NP	+2743+08519	Asia/Kathmandu
    +NR	-0031+16655	Pacific/Nauru
    +NU	-1901-16955	Pacific/Niue
    +NZ	-3652+17446	Pacific/Auckland	most locations
    +NZ	-4357-17633	Pacific/Chatham	Chatham Islands
    +OM	+2336+05835	Asia/Muscat
    +PA	+0858-07932	America/Panama
    +PE	-1203-07703	America/Lima
    +PF	-1732-14934	Pacific/Tahiti	Society Islands
    +PF	-0900-13930	Pacific/Marquesas	Marquesas Islands
    +PF	-2308-13457	Pacific/Gambier	Gambier Islands
    +PG	-0930+14710	Pacific/Port_Moresby
    +PH	+1435+12100	Asia/Manila
    +PK	+2452+06703	Asia/Karachi
    +PL	+5215+02100	Europe/Warsaw
    +PM	+4703-05620	America/Miquelon
    +PN	-2504-13005	Pacific/Pitcairn
    +PR	+182806-0660622	America/Puerto_Rico
    +PS	+3130+03428	Asia/Gaza	Gaza Strip
    +PS	+313200+0350542	Asia/Hebron	West Bank
    +PT	+3843-00908	Europe/Lisbon	mainland
    +PT	+3238-01654	Atlantic/Madeira	Madeira Islands
    +PT	+3744-02540	Atlantic/Azores	Azores
    +PW	+0720+13429	Pacific/Palau
    +PY	-2516-05740	America/Asuncion
    +QA	+2517+05132	Asia/Qatar
    +RE	-2052+05528	Indian/Reunion
    +RO	+4426+02606	Europe/Bucharest
    +RS	+4450+02030	Europe/Belgrade
    +RU	+5443+02030	Europe/Kaliningrad	Moscow-01 - Kaliningrad
    +RU	+5545+03735	Europe/Moscow	Moscow+00 - west Russia
    +RU	+4844+04425	Europe/Volgograd	Moscow+00 - Caspian Sea
    +RU	+5312+05009	Europe/Samara	Moscow+00 - Samara, Udmurtia
    +RU	+5651+06036	Asia/Yekaterinburg	Moscow+02 - Urals
    +RU	+5500+07324	Asia/Omsk	Moscow+03 - west Siberia
    +RU	+5502+08255	Asia/Novosibirsk	Moscow+03 - Novosibirsk
    +RU	+5345+08707	Asia/Novokuznetsk	Moscow+03 - Novokuznetsk
    +RU	+5601+09250	Asia/Krasnoyarsk	Moscow+04 - Yenisei River
    +RU	+5216+10420	Asia/Irkutsk	Moscow+05 - Lake Baikal
    +RU	+6200+12940	Asia/Yakutsk	Moscow+06 - Lena River
    +RU	+4310+13156	Asia/Vladivostok	Moscow+07 - Amur River
    +RU	+4658+14242	Asia/Sakhalin	Moscow+07 - Sakhalin Island
    +RU	+5934+15048	Asia/Magadan	Moscow+08 - Magadan
    +RU	+5301+15839	Asia/Kamchatka	Moscow+08 - Kamchatka
    +RU	+6445+17729	Asia/Anadyr	Moscow+08 - Bering Sea
    +RW	-0157+03004	Africa/Kigali
    +SA	+2438+04643	Asia/Riyadh
    +SB	-0932+16012	Pacific/Guadalcanal
    +SC	-0440+05528	Indian/Mahe
    +SD	+1536+03232	Africa/Khartoum
    +SE	+5920+01803	Europe/Stockholm
    +SG	+0117+10351	Asia/Singapore
    +SH	-1555-00542	Atlantic/St_Helena
    +SI	+4603+01431	Europe/Ljubljana
    +SJ	+7800+01600	Arctic/Longyearbyen
    +SK	+4809+01707	Europe/Bratislava
    +SL	+0830-01315	Africa/Freetown
    +SM	+4355+01228	Europe/San_Marino
    +SN	+1440-01726	Africa/Dakar
    +SO	+0204+04522	Africa/Mogadishu
    +SR	+0550-05510	America/Paramaribo
    +SS	+0451+03136	Africa/Juba
    +ST	+0020+00644	Africa/Sao_Tome
    +SV	+1342-08912	America/El_Salvador
    +SX	+180305-0630250	America/Lower_Princes
    +SY	+3330+03618	Asia/Damascus
    +SZ	-2618+03106	Africa/Mbabane
    +TC	+2128-07108	America/Grand_Turk
    +TD	+1207+01503	Africa/Ndjamena
    +TF	-492110+0701303	Indian/Kerguelen
    +TG	+0608+00113	Africa/Lome
    +TH	+1345+10031	Asia/Bangkok
    +TJ	+3835+06848	Asia/Dushanbe
    +TK	-0922-17114	Pacific/Fakaofo
    +TL	-0833+12535	Asia/Dili
    +TM	+3757+05823	Asia/Ashgabat
    +TN	+3648+01011	Africa/Tunis
    +TO	-2110-17510	Pacific/Tongatapu
    +TR	+4101+02858	Europe/Istanbul
    +TT	+1039-06131	America/Port_of_Spain
    +TV	-0831+17913	Pacific/Funafuti
    +TW	+2503+12130	Asia/Taipei
    +TZ	-0648+03917	Africa/Dar_es_Salaam
    +UA	+5026+03031	Europe/Kiev	most locations
    +UA	+4837+02218	Europe/Uzhgorod	Ruthenia
    +UA	+4750+03510	Europe/Zaporozhye	Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk
    +UA	+4457+03406	Europe/Simferopol	central Crimea
    +UG	+0019+03225	Africa/Kampala
    +UM	+1645-16931	Pacific/Johnston	Johnston Atoll
    +UM	+2813-17722	Pacific/Midway	Midway Islands
    +UM	+1917+16637	Pacific/Wake	Wake Island
    +US	+404251-0740023	America/New_York	Eastern Time
    +US	+421953-0830245	America/Detroit	Eastern Time - Michigan - most locations
    +US	+381515-0854534	America/Kentucky/Louisville	Eastern Time - Kentucky - Louisville area
    +US	+364947-0845057	America/Kentucky/Monticello	Eastern Time - Kentucky - Wayne County
    +US	+394606-0860929	America/Indiana/Indianapolis	Eastern Time - Indiana - most locations
    +US	+384038-0873143	America/Indiana/Vincennes	Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties
    +US	+410305-0863611	America/Indiana/Winamac	Eastern Time - Indiana - Pulaski County
    +US	+382232-0862041	America/Indiana/Marengo	Eastern Time - Indiana - Crawford County
    +US	+382931-0871643	America/Indiana/Petersburg	Eastern Time - Indiana - Pike County
    +US	+384452-0850402	America/Indiana/Vevay	Eastern Time - Indiana - Switzerland County
    +US	+415100-0873900	America/Chicago	Central Time
    +US	+375711-0864541	America/Indiana/Tell_City	Central Time - Indiana - Perry County
    +US	+411745-0863730	America/Indiana/Knox	Central Time - Indiana - Starke County
    +US	+450628-0873651	America/Menominee	Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties
    +US	+470659-1011757	America/North_Dakota/Center	Central Time - North Dakota - Oliver County
    +US	+465042-1012439	America/North_Dakota/New_Salem	Central Time - North Dakota - Morton County (except Mandan area)
    +US	+471551-1014640	America/North_Dakota/Beulah	Central Time - North Dakota - Mercer County
    +US	+394421-1045903	America/Denver	Mountain Time
    +US	+433649-1161209	America/Boise	Mountain Time - south Idaho & east Oregon
    +US	+364708-1084111	America/Shiprock	Mountain Time - Navajo
    +US	+332654-1120424	America/Phoenix	Mountain Standard Time - Arizona
    +US	+340308-1181434	America/Los_Angeles	Pacific Time
    +US	+611305-1495401	America/Anchorage	Alaska Time
    +US	+581807-1342511	America/Juneau	Alaska Time - Alaska panhandle
    +US	+571035-1351807	America/Sitka	Alaska Time - southeast Alaska panhandle
    +US	+593249-1394338	America/Yakutat	Alaska Time - Alaska panhandle neck
    +US	+643004-1652423	America/Nome	Alaska Time - west Alaska
    +US	+515248-1763929	America/Adak	Aleutian Islands
    +US	+550737-1313435	America/Metlakatla	Metlakatla Time - Annette Island
    +US	+211825-1575130	Pacific/Honolulu	Hawaii
    +UY	-3453-05611	America/Montevideo
    +UZ	+3940+06648	Asia/Samarkand	west Uzbekistan
    +UZ	+4120+06918	Asia/Tashkent	east Uzbekistan
    +VA	+415408+0122711	Europe/Vatican
    +VC	+1309-06114	America/St_Vincent
    +VE	+1030-06656	America/Caracas
    +VG	+1827-06437	America/Tortola
    +VI	+1821-06456	America/St_Thomas
    +VN	+1045+10640	Asia/Ho_Chi_Minh
    +VU	-1740+16825	Pacific/Efate
    +WF	-1318-17610	Pacific/Wallis
    +WS	-1350-17144	Pacific/Apia
    +YE	+1245+04512	Asia/Aden
    +YT	-1247+04514	Indian/Mayotte
    +ZA	-2615+02800	Africa/Johannesburg
    +ZM	-1525+02817	Africa/Lusaka
    +ZW	-1750+03103	Africa/Harare
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata_jdk/gmt b/jdk/test/sun/util/calendar/zi/tzdata_jdk/gmt
    new file mode 100644
    index 00000000000..0be31797d7f
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata_jdk/gmt
    @@ -0,0 +1,27 @@
    +#
    +# Copyright (c) 2000, 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.
    +#
    +
    +# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
    +Zone	GMT		0:00	-	GMT
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata_jdk/jdk11_backward b/jdk/test/sun/util/calendar/zi/tzdata_jdk/jdk11_backward
    new file mode 100644
    index 00000000000..4869516f8dc
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata_jdk/jdk11_backward
    @@ -0,0 +1,80 @@
    +#
    +# Copyright (c) 2000, 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.
    +#
    +# JDK 1.1.x compatible time zone IDs
    +#
    +
    +Link Australia/Darwin ACT
    +Link Australia/Sydney AET
    +Link America/Argentina/Buenos_Aires AGT
    +Link Africa/Cairo ART
    +Link America/Anchorage AST
    +Link America/Sao_Paulo BET
    +Link Asia/Dhaka BST
    +Link Africa/Harare CAT
    +Link America/St_Johns CNT
    +Link America/Chicago CST
    +Link Asia/Shanghai CTT
    +Link Africa/Addis_Ababa EAT
    +Link Europe/Paris ECT
    +Link America/New_York EST
    +Link Pacific/Honolulu HST
    +Link America/Indianapolis IET
    +Link Asia/Calcutta IST
    +Link Asia/Tokyo JST
    +Link Pacific/Apia MIT
    +Link America/Denver MST
    +Link Asia/Yerevan NET
    +Link Pacific/Auckland NST
    +Link Asia/Karachi PLT
    +Link America/Phoenix PNT
    +Link America/Puerto_Rico PRT
    +Link America/Los_Angeles PST
    +Link Pacific/Guadalcanal SST
    +Link Asia/Saigon VST
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	SystemV	min	1973	-	Apr	lastSun	2:00	1:00	D
    +Rule	SystemV	min	1973	-	Oct	lastSun	2:00	0	S
    +Rule	SystemV	1974	only	-	Jan	6	2:00	1:00	D
    +Rule	SystemV	1974	only	-	Nov	lastSun	2:00	0	S
    +Rule	SystemV	1975	only	-	Feb	23	2:00	1:00	D
    +Rule	SystemV	1975	only	-	Oct	lastSun	2:00	0	S
    +Rule	SystemV	1976	max	-	Apr	lastSun	2:00	1:00	D
    +Rule	SystemV	1976	max	-	Oct	lastSun	2:00	0	S
    +
    +# Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
    +Zone	SystemV/AST4ADT	-4:00	SystemV		A%sT
    +Zone	SystemV/EST5EDT	-5:00	SystemV		E%sT
    +Zone	SystemV/CST6CDT	-6:00	SystemV		C%sT
    +Zone	SystemV/MST7MDT	-7:00	SystemV		M%sT
    +Zone	SystemV/PST8PDT	-8:00	SystemV		P%sT
    +Zone	SystemV/YST9YDT	-9:00	SystemV		Y%sT
    +Zone	SystemV/AST4	-4:00	-		AST
    +Zone	SystemV/EST5	-5:00	-		EST
    +Zone	SystemV/CST6	-6:00	-		CST
    +Zone	SystemV/MST7	-7:00	-		MST
    +Zone	SystemV/PST8	-8:00	-		PST
    +Zone	SystemV/YST9	-9:00	-		YST
    +Zone	SystemV/HST10	-10:00	-		HST
    diff --git a/jdk/test/sun/util/calendar/zi/tzdata_jdk/jdk11_full_backward b/jdk/test/sun/util/calendar/zi/tzdata_jdk/jdk11_full_backward
    new file mode 100644
    index 00000000000..321180aa100
    --- /dev/null
    +++ b/jdk/test/sun/util/calendar/zi/tzdata_jdk/jdk11_full_backward
    @@ -0,0 +1,93 @@
    +#
    +# Copyright (c) 2001, 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.
    +#
    +# JDK 1.1.x compatible time zone IDs
    +#
    +
    +Link Australia/Darwin ACT
    +Link Australia/Sydney AET
    +Link America/Argentina/Buenos_Aires AGT
    +Link Africa/Cairo ART
    +Link America/Anchorage AST
    +Link America/Sao_Paulo BET
    +Link Asia/Dhaka BST
    +Link Africa/Harare CAT
    +Link America/St_Johns CNT
    +Link America/Chicago CST
    +Link Asia/Shanghai CTT
    +Link Africa/Addis_Ababa EAT
    +Link Europe/Paris ECT
    +Link America/New_York EST
    +Link Pacific/Honolulu HST
    +Link America/Indiana/Indianapolis IET
    +Link Asia/Calcutta IST
    +Link Asia/Tokyo JST
    +Link Pacific/Apia MIT
    +Link America/Denver MST
    +Link Asia/Yerevan NET
    +Link Pacific/Auckland NST
    +Link Asia/Karachi PLT
    +Link America/Phoenix PNT
    +Link America/Puerto_Rico PRT
    +Link America/Los_Angeles PST
    +Link Pacific/Guadalcanal SST
    +Link Asia/Saigon VST
    +
    +# The follwong link is required to generate JDK 1.2.x and 1.3.x
    +# compatible zones. In the Olson public source, MET is defined as
    +# GMT+1:00 with the C-Eur rules. In JDK, MET is defined as an alias
    +# of Asia/Tehran. This line must be removed if a full set of Olson
    +# zones is generated. Otherwise, MET appears twice in the
    +# ZoneInfoMappings.IDs table.
    +Link Asia/Tehran MET
    +
    +# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
    +Rule	SystemV	min	1973	-	Apr	lastSun	2:00	1:00	D
    +Rule	SystemV	min	1973	-	Oct	lastSun	2:00	0	S
    +Rule	SystemV	1974	only	-	Jan	6	2:00	1:00	D
    +Rule	SystemV	1974	only	-	Nov	lastSun	2:00	0	S
    +Rule	SystemV	1975	only	-	Feb	23	2:00	1:00	D
    +Rule	SystemV	1975	only	-	Oct	lastSun	2:00	0	S
    +Rule	SystemV	1976	max	-	Apr	lastSun	2:00	1:00	D
    +Rule	SystemV	1976	max	-	Oct	lastSun	2:00	0	S
    +
    +# Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
    +Zone	SystemV/AST4ADT	-4:00	SystemV		A%sT
    +Zone	SystemV/EST5EDT	-5:00	SystemV		E%sT
    +Zone	SystemV/CST6CDT	-6:00	SystemV		C%sT
    +Zone	SystemV/MST7MDT	-7:00	SystemV		M%sT
    +Zone	SystemV/PST8PDT	-8:00	SystemV		P%sT
    +Zone	SystemV/YST9YDT	-9:00	SystemV		Y%sT
    +Zone	SystemV/AST4	-4:00	-		AST
    +Zone	SystemV/EST5	-5:00	-		EST
    +Zone	SystemV/CST6	-6:00	-		CST
    +Zone	SystemV/MST7	-7:00	-		MST
    +Zone	SystemV/PST8	-8:00	-		PST
    +Zone	SystemV/YST9	-9:00	-		YST
    +Zone	SystemV/HST10	-10:00	-		HST
    +
    +#
    +# For the UTC change in Mustang
    +#
    +Link GMT UTC
    
    From 7ca3c9dd848ea25f514f6debd3518f58cc6d4fae Mon Sep 17 00:00:00 2001
    From: Phil Race 
    Date: Tue, 12 Feb 2013 09:58:21 -0800
    Subject: [PATCH 140/158] 8007748: MacOSX build error : cast of type 'SEL' to
     'uintptr_t' (aka 'unsigned long') is deprecated; use sel_getName instead
    
    Reviewed-by: anthony
    ---
     jdk/src/macosx/native/jobjc/src/core/native/SEL.m | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/jdk/src/macosx/native/jobjc/src/core/native/SEL.m b/jdk/src/macosx/native/jobjc/src/core/native/SEL.m
    index 970a5d30bcf..ebbcf254082 100644
    --- a/jdk/src/macosx/native/jobjc/src/core/native/SEL.m
    +++ b/jdk/src/macosx/native/jobjc/src/core/native/SEL.m
    @@ -34,7 +34,7 @@ JNIEXPORT jlong JNICALL Java_com_apple_jobjc_SEL_getSelectorPtr
         const char *selNameAsChars = (*env)->GetStringUTFChars(env, selName, JNI_FALSE);
         const SEL sel = sel_registerName(selNameAsChars);
         (*env)->ReleaseStringUTFChars(env, selName, selNameAsChars);
    -    return ptr_to_jlong(sel);
    +    return ptr_to_jlong((void*)sel);
     }
     
     JNIEXPORT jstring JNICALL Java_com_apple_jobjc_SEL_getSelectorName
    
    From 4e7de85e4d6522f40ef392874e9e79173df3f457 Mon Sep 17 00:00:00 2001
    From: Zhengyu Gu 
    Date: Tue, 12 Feb 2013 14:47:36 -0500
    Subject: [PATCH 141/158] 8006691: Remove jvm_version_info->is_kernel_jvm field
    
    Remove is_kernel_jvm field in jvm_version_info structure, as kernel VM has been deprecated
    
    Reviewed-by: mchung
    ---
     jdk/src/share/javavm/export/jvm.h | 3 +--
     1 file changed, 1 insertion(+), 2 deletions(-)
    
    diff --git a/jdk/src/share/javavm/export/jvm.h b/jdk/src/share/javavm/export/jvm.h
    index 56a8abb03cc..1f785f1a108 100644
    --- a/jdk/src/share/javavm/export/jvm.h
    +++ b/jdk/src/share/javavm/export/jvm.h
    @@ -1401,8 +1401,7 @@ typedef struct {
          * the new bit is also added in the main/baseline.
          */
         unsigned int is_attach_supported : 1;
    -    unsigned int is_kernel_jvm : 1;
    -    unsigned int : 30;
    +    unsigned int : 31;
         unsigned int : 32;
         unsigned int : 32;
     } jvm_version_info;
    
    From e0eba88c1b4264060cb1f36758fab06cfdf2458d Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?Joel=20Borggr=C3=A9n-Franck?= 
    Date: Wed, 13 Feb 2013 10:36:36 +0100
    Subject: [PATCH 142/158] 8007278: Rename
     j.l.r.AnnotatedElement.getAnnotations(Class) to getAnnotationsByType(Class)
    
    Reviewed-by: darcy, abuckley
    ---
     jdk/src/share/classes/java/lang/Class.java    |  7 +-
     jdk/src/share/classes/java/lang/Package.java  | 11 ++-
     .../java/lang/reflect/AccessibleObject.java   | 15 ++--
     .../java/lang/reflect/AnnotatedElement.java   | 87 +++++++++++++------
     .../classes/java/lang/reflect/Executable.java |  3 +-
     .../classes/java/lang/reflect/Field.java      |  3 +-
     .../classes/java/lang/reflect/Parameter.java  |  8 +-
     .../annotation/AnnotatedTypeFactory.java      |  6 +-
     .../reflectiveObjects/TypeVariableImpl.java   |  8 +-
     .../lang/annotation/TypeParamAnnotation.java  |  4 +-
     .../RepeatedUnitTest.java                     | 40 ++++-----
     11 files changed, 120 insertions(+), 72 deletions(-)
    
    diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java
    index dab6c98e47a..671d04a65c7 100644
    --- a/jdk/src/share/classes/java/lang/Class.java
    +++ b/jdk/src/share/classes/java/lang/Class.java
    @@ -3087,7 +3087,8 @@ public final
          * @throws NullPointerException {@inheritDoc}
          * @since 1.8
          */
    -    public  A[] getAnnotations(Class annotationClass) {
    +    @Override
    +    public  A[] getAnnotationsByType(Class annotationClass) {
             Objects.requireNonNull(annotationClass);
     
             initAnnotationsIfNecessary();
    @@ -3106,6 +3107,7 @@ public final
          * @throws NullPointerException {@inheritDoc}
          * @since 1.8
          */
    +    @Override
         @SuppressWarnings("unchecked")
         public  A getDeclaredAnnotation(Class annotationClass) {
             Objects.requireNonNull(annotationClass);
    @@ -3118,7 +3120,8 @@ public final
          * @throws NullPointerException {@inheritDoc}
          * @since 1.8
          */
    -    public  A[] getDeclaredAnnotations(Class annotationClass) {
    +    @Override
    +    public  A[] getDeclaredAnnotationsByType(Class annotationClass) {
             Objects.requireNonNull(annotationClass);
     
             initAnnotationsIfNecessary();
    diff --git a/jdk/src/share/classes/java/lang/Package.java b/jdk/src/share/classes/java/lang/Package.java
    index 234f807181a..b9776f478db 100644
    --- a/jdk/src/share/classes/java/lang/Package.java
    +++ b/jdk/src/share/classes/java/lang/Package.java
    @@ -389,8 +389,9 @@ public class Package implements java.lang.reflect.AnnotatedElement {
          * @throws NullPointerException {@inheritDoc}
          * @since 1.8
          */
    -    public   A[] getAnnotations(Class annotationClass) {
    -        return getPackageInfo().getAnnotations(annotationClass);
    +    @Override
    +    public   A[] getAnnotationsByType(Class annotationClass) {
    +        return getPackageInfo().getAnnotationsByType(annotationClass);
         }
     
         /**
    @@ -404,6 +405,7 @@ public class Package implements java.lang.reflect.AnnotatedElement {
          * @throws NullPointerException {@inheritDoc}
          * @since 1.8
          */
    +    @Override
         public  A getDeclaredAnnotation(Class annotationClass) {
             return getPackageInfo().getDeclaredAnnotation(annotationClass);
         }
    @@ -412,8 +414,9 @@ public class Package implements java.lang.reflect.AnnotatedElement {
          * @throws NullPointerException {@inheritDoc}
          * @since 1.8
          */
    -    public  A[] getDeclaredAnnotations(Class annotationClass) {
    -        return getPackageInfo().getDeclaredAnnotations(annotationClass);
    +    @Override
    +    public  A[] getDeclaredAnnotationsByType(Class annotationClass) {
    +        return getPackageInfo().getDeclaredAnnotationsByType(annotationClass);
         }
     
         /**
    diff --git a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java
    index 9986aef6cf7..d198d939d4b 100644
    --- a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java
    +++ b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.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
    @@ -184,7 +184,8 @@ public class AccessibleObject implements AnnotatedElement {
          * @throws NullPointerException {@inheritDoc}
          * @since 1.8
          */
    -    public  T[] getAnnotations(Class annotationClass) {
    +    @Override
    +    public  T[] getAnnotationsByType(Class annotationClass) {
             throw new AssertionError("All subclasses should override this method");
         }
     
    @@ -199,6 +200,7 @@ public class AccessibleObject implements AnnotatedElement {
          * @throws NullPointerException {@inheritDoc}
          * @since 1.8
          */
    +    @Override
         public  T getDeclaredAnnotation(Class annotationClass) {
             // Only annotations on classes are inherited, for all other
             // objects getDeclaredAnnotation is the same as
    @@ -210,11 +212,12 @@ public class AccessibleObject implements AnnotatedElement {
          * @throws NullPointerException {@inheritDoc}
          * @since 1.8
          */
    -    public  T[] getDeclaredAnnotations(Class annotationClass) {
    +    @Override
    +    public  T[] getDeclaredAnnotationsByType(Class annotationClass) {
             // Only annotations on classes are inherited, for all other
    -        // objects getDeclaredAnnotations is the same as
    -        // getAnnotations.
    -        return getAnnotations(annotationClass);
    +        // objects getDeclaredAnnotationsByType is the same as
    +        // getAnnotationsByType.
    +        return getAnnotationsByType(annotationClass);
         }
     
         /**
    diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java
    index 85472ff5b00..d6cffec2f28 100644
    --- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java
    +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java
    @@ -35,22 +35,43 @@ import java.lang.annotation.Annotation;
      * arrays returned by accessors for array-valued enum members; it will
      * have no affect on the arrays returned to other callers.
      *
    - * 

    An annotation A is directly present on an element E if the - * RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations attribute - * associated with E either: + *

    The {@link #getAnnotationsByType(Class)} and {@link + * #getDeclaredAnnotationsByType(Class)} methods support multiple + * annotations of the same type on an element. If the argument to either method + * is a repeatable annotation type (JLS 9.6), then the method will "look + * through" a container annotation (JLS 9.7) which was generated at + * compile-time to wrap multiple annotations of the argument type. + * + *

    The terms directly present and present are used + * throughout this interface to describe precisely which annotations are + * returned by methods: + * *

      - *
    • contains A; or - *
    • for invocations of get[Declared]Annotations(Class), - * contains A or exactly one annotation C whose type is the containing - * annotation type of A's type (JLS 9.6) and whose value element contains A + *
    • An annotation A is directly present on an element E if E is + * associated with a RuntimeVisibleAnnotations or + * RuntimeVisibleParameterAnnotations attribute, and: + * + *
        + *
      • for an invocation of {@code get[Declared]Annotation(Class)} or + * {@code get[Declared]Annotations()}, the attribute contains A. + * + *
      • for an invocation of {@code get[Declared]AnnotationsByType(Class)}, the + * attribute either contains A or, if the type of A is repeatable, contains + * exactly one annotation whose value element contains A and whose type is the + * containing annotation type of A's type (JLS 9.6). *
      * - *

      An annotation A is present on an element E if either: + *

      + *

    • An annotation A is present on an element E if either: + * *
        *
      • A is directly present on E; or - *
      • There are no annotations of A's type which are directly present - * on E, and E is a class, and A's type is inheritable (JLS 9.6.3.3), and A is - * present on the superclass of E + * + *
      • A is not directly present on E, and E is a class, and A's type + * is inheritable (JLS 9.6.3.3), and A is present on the superclass of + * E. + *
      + * *
    * *

    If an annotation returned by a method in this interface contains @@ -119,12 +140,19 @@ public interface AnnotatedElement { T getAnnotation(Class annotationClass); /** - * Returns an array of all this element's annotations for the - * specified type if one or more of such annotation is present, - * else an array of length zero. + * Returns annotations that are present on this element. * - * The caller of this method is free to modify the returned array; - * it will have no effect on the arrays returned to other callers. + * If there are no annotations present on this element, the return + * value is an array of length 0. + * + * The difference between this method and {@link #getAnnotation(Class)} + * is that this method detects if its argument is a repeatable + * annotation type (JLS 9.6), and if so, attempts to find one or + * more annotations of that type by "looking through" a container + * annotation. + * + * The caller of this method is free to modify the returned array; it will + * have no effect on the arrays returned to other callers. * * @param annotationClass the Class object corresponding to the * annotation type @@ -133,7 +161,7 @@ public interface AnnotatedElement { * @throws NullPointerException if the given annotation class is null * @since 1.8 */ - T[] getAnnotations(Class annotationClass); + T[] getAnnotationsByType(Class annotationClass); /** * Returns annotations that are present on this element. @@ -165,16 +193,21 @@ public interface AnnotatedElement { */ T getDeclaredAnnotation(Class annotationClass); - /** - * Returns an array of all this element's annotations for the - * specified type if one or more of such annotation is directly - * present, else an array of length zero. + /** + * Returns annotations that are directly present on this element. + * This method ignores inherited annotations. * - * This method ignores inherited annotations. (Returns - * an array of length zero if no annotations are directly present - * on this element.) The caller of this method is free to modify - * the returned array; it will have no effect on the arrays - * returned to other callers. + * If there are no annotations directly present on this element, + * the return value is an array of length 0. + * + * The difference between this method and {@link + * #getDeclaredAnnotation(Class)} is that this method detects if its + * argument is a repeatable annotation type (JLS 9.6), and if so, + * attempts to find one or more annotations of that type by "looking + * through" a container annotation. + * + * The caller of this method is free to modify the returned array; it will + * have no effect on the arrays returned to other callers. * * @param annotationClass the Class object corresponding to the * annotation type @@ -183,7 +216,7 @@ public interface AnnotatedElement { * @throws NullPointerException if the given annotation class is null * @since 1.8 */ - T[] getDeclaredAnnotations(Class annotationClass); + T[] getDeclaredAnnotationsByType(Class annotationClass); /** * Returns annotations that are directly present on this element. diff --git a/jdk/src/share/classes/java/lang/reflect/Executable.java b/jdk/src/share/classes/java/lang/reflect/Executable.java index 4c785e3e87f..83b5e9c87a4 100644 --- a/jdk/src/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java @@ -449,7 +449,8 @@ public abstract class Executable extends AccessibleObject * @throws NullPointerException {@inheritDoc} * @since 1.8 */ - public T[] getAnnotations(Class annotationClass) { + @Override + public T[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass); diff --git a/jdk/src/share/classes/java/lang/reflect/Field.java b/jdk/src/share/classes/java/lang/reflect/Field.java index df38832eb15..be13b076832 100644 --- a/jdk/src/share/classes/java/lang/reflect/Field.java +++ b/jdk/src/share/classes/java/lang/reflect/Field.java @@ -1029,7 +1029,8 @@ class Field extends AccessibleObject implements Member { * @throws NullPointerException {@inheritDoc} * @since 1.8 */ - public T[] getAnnotations(Class annotationClass) { + @Override + public T[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass); diff --git a/jdk/src/share/classes/java/lang/reflect/Parameter.java b/jdk/src/share/classes/java/lang/reflect/Parameter.java index 3ecd7c674ea..9c808310c0c 100644 --- a/jdk/src/share/classes/java/lang/reflect/Parameter.java +++ b/jdk/src/share/classes/java/lang/reflect/Parameter.java @@ -258,7 +258,8 @@ public final class Parameter implements AnnotatedElement { * {@inheritDoc} * @throws NullPointerException {@inheritDoc} */ - public T[] getAnnotations(Class annotationClass) { + @Override + public T[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass); @@ -284,11 +285,12 @@ public final class Parameter implements AnnotatedElement { /** * @throws NullPointerException {@inheritDoc} */ - public T[] getDeclaredAnnotations(Class annotationClass) { + @Override + public T[] getDeclaredAnnotationsByType(Class annotationClass) { // Only annotations on classes are inherited, for all other // objects getDeclaredAnnotations is the same as // getAnnotations. - return getAnnotations(annotationClass); + return getAnnotationsByType(annotationClass); } /** diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java index e0524e849dc..e9f3f957c09 100644 --- a/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java @@ -148,8 +148,8 @@ public class AnnotatedTypeFactory { } @Override - public final T[] getAnnotations(Class annotation) { - return getDeclaredAnnotations(annotation); + public final T[] getAnnotationsByType(Class annotation) { + return getDeclaredAnnotationsByType(annotation); } @Override @@ -164,7 +164,7 @@ public class AnnotatedTypeFactory { } @Override - public T[] getDeclaredAnnotations(Class annotation) { + public T[] getDeclaredAnnotationsByType(Class annotation) { return AnnotationSupport.getMultipleAnnotations(annotations, annotation); } diff --git a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java index 528658d0d16..0b1a13ee74e 100644 --- a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java +++ b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java @@ -200,14 +200,16 @@ public class TypeVariableImpl return getAnnotation(annotationClass); } - public T[] getAnnotations(Class annotationClass) { + @Override + public T[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); return AnnotationSupport.getMultipleAnnotations(mapAnnotations(getAnnotations()), annotationClass); } - public T[] getDeclaredAnnotations(Class annotationClass) { + @Override + public T[] getDeclaredAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); - return getAnnotations(annotationClass); + return getAnnotationsByType(annotationClass); } public Annotation[] getAnnotations() { diff --git a/jdk/test/java/lang/annotation/TypeParamAnnotation.java b/jdk/test/java/lang/annotation/TypeParamAnnotation.java index 50457ec46b1..694d83dcd35 100644 --- a/jdk/test/java/lang/annotation/TypeParamAnnotation.java +++ b/jdk/test/java/lang/annotation/TypeParamAnnotation.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8004698 + * @bug 8004698 8007278 * @summary Unit test for annotations on TypeVariables */ @@ -93,7 +93,7 @@ public class TypeParamAnnotation { private static void testGetAnnos() throws Exception { TypeVariable[] ts = TypeParam.class.getDeclaredMethod("foo").getTypeParameters(); ParamAnno2[] as; - as = ts[0].getAnnotations(ParamAnno2.class); + as = ts[0].getAnnotationsByType(ParamAnno2.class); check(as.length == 1); check(as[0].value() == 3); } diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java b/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java index 10e3d746261..674f37fbb56 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7154390 8005712 + * @bug 7154390 8005712 8007278 * @summary Unit test for repeated annotation reflection * * @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java @@ -76,7 +76,7 @@ public class RepeatedUnitTest { check(1 == countAnnotation(e, NonRepeated.class)); - nr = e.getAnnotations(NonRepeated.class)[0]; + nr = e.getAnnotationsByType(NonRepeated.class)[0]; check(nr.value() == 10); check(1 == containsAnnotationOfType(e.getAnnotations(), NonRepeated.class)); @@ -87,9 +87,9 @@ public class RepeatedUnitTest { check(c == null); check(2 == countAnnotation(e, Containee.class)); - c = e.getAnnotations(Containee.class)[0]; + c = e.getAnnotationsByType(Containee.class)[0]; check(c.value() == 1); - c = e.getAnnotations(Containee.class)[1]; + c = e.getAnnotationsByType(Containee.class)[1]; check(c.value() == 2); check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class)); @@ -98,7 +98,7 @@ public class RepeatedUnitTest { static void packageContainer(AnnotatedElement e) { Container cr = e.getAnnotation(Container.class); check(null != cr); - check(1 == containsAnnotationOfType(e.getAnnotations(Container.class), Container.class)); + check(1 == containsAnnotationOfType(e.getAnnotationsByType(Container.class), Container.class)); check(1 == countAnnotation(e, Container.class)); } @@ -123,10 +123,10 @@ public class RepeatedUnitTest { check(1 == countAnnotation(e, NonRepeated.class)); check(1 == countAnnotation(e, InheritedNonRepeated.class)); - check(e.getAnnotations(Containee.class)[2].value() == 300); - check(e.getAnnotations(InheritedContainee.class)[2].value() == 300); - check(e.getAnnotations(InheritedNonRepeated.class)[0].value() == 200); - check(e.getAnnotations(NonRepeated.class)[0].value() == 100); + check(e.getAnnotationsByType(Containee.class)[2].value() == 300); + check(e.getAnnotationsByType(InheritedContainee.class)[2].value() == 300); + check(e.getAnnotationsByType(InheritedNonRepeated.class)[0].value() == 200); + check(e.getAnnotationsByType(NonRepeated.class)[0].value() == 100); } static void inheritedMe3() { @@ -138,8 +138,8 @@ public class RepeatedUnitTest { check(0 == countAnnotation(e, Container.class)); check(1 == countAnnotation(e, InheritedContainer.class)); - check(e.getAnnotations(InheritedContainee.class)[2].value() == 350); - check(e.getAnnotations(InheritedNonRepeated.class)[0].value() == 15); + check(e.getAnnotationsByType(InheritedContainee.class)[2].value() == 350); + check(e.getAnnotationsByType(InheritedNonRepeated.class)[0].value() == 15); } static void inheritedMe4() { @@ -153,24 +153,24 @@ public class RepeatedUnitTest { check(1 == countAnnotation(e, NonRepeated.class)); check(1 == countAnnotation(e, InheritedNonRepeated.class)); - check(e.getAnnotations(Containee.class)[2].value() == 3000); - check(e.getAnnotations(InheritedContainee.class)[2].value() == 3000); - check(e.getAnnotations(InheritedNonRepeated.class)[0].value() == 2000); - check(e.getAnnotations(NonRepeated.class)[0].value() == 1000); + check(e.getAnnotationsByType(Containee.class)[2].value() == 3000); + check(e.getAnnotationsByType(InheritedContainee.class)[2].value() == 3000); + check(e.getAnnotationsByType(InheritedNonRepeated.class)[0].value() == 2000); + check(e.getAnnotationsByType(NonRepeated.class)[0].value() == 1000); } static void checkMultiplier(AnnotatedElement e, int m) { // Basic sanity of non-repeating getAnnotation(Class) check(e.getAnnotation(NonRepeated.class).value() == 5 * m); - // Check count of annotations returned from getAnnotations(Class) + // Check count of annotations returned from getAnnotationsByType(Class) check(4 == countAnnotation(e, Containee.class)); check(1 == countAnnotation(e, Container.class)); check(1 == countAnnotation(e, NonRepeated.class)); - // Check contents of array returned from getAnnotations(Class) - check(e.getAnnotations(Containee.class)[2].value() == 3 * m); - check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m); + // Check contents of array returned from getAnnotationsByType(Class) + check(e.getAnnotationsByType(Containee.class)[2].value() == 3 * m); + check(e.getAnnotationsByType(NonRepeated.class)[0].value() == 5 * m); // Check getAnnotation(Class) check(e.getAnnotation(Containee.class) == null); @@ -187,7 +187,7 @@ public class RepeatedUnitTest { } static int countAnnotation(AnnotatedElement e, Class c) { - return containsAnnotationOfType(e.getAnnotations(c), c); + return containsAnnotationOfType(e.getAnnotationsByType(c), c); } static int containsAnnotationOfType(A[] l, Class a) { From 30a25e41d228e7b26787b538268dee7796efcd72 Mon Sep 17 00:00:00 2001 From: Vera Akulova Date: Wed, 13 Feb 2013 18:01:18 +0400 Subject: [PATCH 143/158] 7161759: TEST_BUG: java/awt/Frame/WindowDragTest/WindowDragTest.java fails to compile, should be modified Added @build Util jtreg tag Reviewed-by: serb, alexsch --- jdk/test/java/awt/Frame/WindowDragTest/WindowDragTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jdk/test/java/awt/Frame/WindowDragTest/WindowDragTest.java b/jdk/test/java/awt/Frame/WindowDragTest/WindowDragTest.java index 127a49e607d..e7b0970b0fc 100644 --- a/jdk/test/java/awt/Frame/WindowDragTest/WindowDragTest.java +++ b/jdk/test/java/awt/Frame/WindowDragTest/WindowDragTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -23,10 +23,11 @@ /* @test - @bug 7128738 + @bug 7128738 7161759 @summary dragged dialog freezes system on dispose @author Oleg Pekhovskiy: area=awt.toplevel @library ../../regtesthelpers + @build Util @run main WindowDragTest */ From dfdd79f3eee03868cccdbb84f2159a7fa42a598f Mon Sep 17 00:00:00 2001 From: Vera Akulova Date: Wed, 13 Feb 2013 19:06:31 +0400 Subject: [PATCH 144/158] 7132383: [macosx] bug6596966.java should be adapted for Mac Reviewed-by: serb, alexsch --- .../swing/JLabel/6596966/bug6596966.java | 24 +++++++++----- jdk/test/javax/swing/regtesthelpers/Util.java | 33 ++++++++++++++++++- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/jdk/test/javax/swing/JLabel/6596966/bug6596966.java b/jdk/test/javax/swing/JLabel/6596966/bug6596966.java index 5e94459bcb7..361cebcd24f 100644 --- a/jdk/test/javax/swing/JLabel/6596966/bug6596966.java +++ b/jdk/test/javax/swing/JLabel/6596966/bug6596966.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -24,16 +24,17 @@ /* @test @bug 6596966 @summary Some JFileChooser mnemonics do not work with sticky keys + @library ../../regtesthelpers + @build Util @run main bug6596966 @author Pavel Porvatov */ - -import sun.awt.SunToolkit; - -import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent; +import java.util.ArrayList; +import javax.swing.*; +import sun.awt.SunToolkit; public class bug6596966 { private static JFrame frame; @@ -71,11 +72,14 @@ public class bug6596966 { toolkit.realSync(); - robot.keyPress(KeyEvent.VK_ALT); + ArrayList keys = Util.getSystemMnemonicKeyCodes(); + for (int i = 0; i < keys.size(); ++i) { + robot.keyPress(keys.get(i)); + } + robot.keyPress(KeyEvent.VK_L); toolkit.realSync(); - toolkit.getSystemEventQueue().postEvent(new KeyEvent(label, KeyEvent.KEY_RELEASED, EventQueue.getMostRecentEventTime(), 0, KeyEvent.VK_L, 'L')); @@ -90,7 +94,11 @@ public class bug6596966 { } }); } finally { - robot.keyRelease(KeyEvent.VK_ALT); + robot.keyRelease(KeyEvent.VK_L); + for (int i = 0; i < keys.size(); ++i) { + robot.keyRelease(keys.get(i)); + } + toolkit.realSync(); } } } diff --git a/jdk/test/javax/swing/regtesthelpers/Util.java b/jdk/test/javax/swing/regtesthelpers/Util.java index a9df4934583..df7ab7ade80 100644 --- a/jdk/test/javax/swing/regtesthelpers/Util.java +++ b/jdk/test/javax/swing/regtesthelpers/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -23,11 +23,13 @@ import javax.swing.*; import java.awt.*; +import java.awt.event.*; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.Callable; +import sun.swing.*; /** *

    This class contains utilities useful for regression testing. @@ -212,4 +214,33 @@ public class Util { return result.get(0); } + /** + * Gets key codes from system mnemonic key mask + * @return key codes list + */ + public static ArrayList getSystemMnemonicKeyCodes() { + return Util.getKeyCodesFromKeyMask(SwingUtilities2.getSystemMnemonicKeyMask()); + } + + /** + * Gets the key codes list from modifiers + * @param modifiers an integer combination of the modifier constants + * @return key codes list + */ + public static ArrayList getKeyCodesFromKeyMask(int modifiers) { + ArrayList result = new ArrayList<>(); + if ((modifiers & InputEvent.CTRL_MASK) != 0) { + result.add(KeyEvent.VK_CONTROL); + } + if ((modifiers & InputEvent.ALT_MASK) != 0) { + result.add(KeyEvent.VK_ALT); + } + if ((modifiers & InputEvent.SHIFT_MASK) != 0) { + result.add(KeyEvent.VK_SHIFT); + } + if ((modifiers & InputEvent.META_MASK) != 0) { + result.add(KeyEvent.VK_META); + } + return result; + } } From f44592861ca62ec51148e93cf130662840540edd Mon Sep 17 00:00:00 2001 From: Vladislav Karnaukhov Date: Wed, 13 Feb 2013 19:23:09 +0400 Subject: [PATCH 145/158] 4199622: RFE: JComboBox shouldn't sending ActionEvents for keyboard navigation Reviewed-by: alexp, alexsch --- .../swing/plaf/basic/BasicComboBoxUI.java | 63 +++-- .../swing/plaf/basic/BasicLookAndFeel.java | 3 +- .../swing/JComboBox/4199622/bug4199622.java | 243 ++++++++++++++++++ 3 files changed, 290 insertions(+), 19 deletions(-) create mode 100644 jdk/test/javax/swing/JComboBox/4199622/bug4199622.java diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java index 269bd34afc3..b31f7606b8e 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, 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 @@ -1120,7 +1120,9 @@ public class BasicComboBoxUI extends ComboBoxUI { listBox.setSelectedIndex( si + 1 ); listBox.ensureIndexIsVisible( si + 1 ); if ( !isTableCellEditor ) { - comboBox.setSelectedIndex(si+1); + if (!(UIManager.getBoolean("ComboBox.noActionOnKeyNavigation") && comboBox.isPopupVisible())) { + comboBox.setSelectedIndex(si+1); + } } comboBox.repaint(); } @@ -1144,7 +1146,9 @@ public class BasicComboBoxUI extends ComboBoxUI { listBox.setSelectedIndex( si - 1 ); listBox.ensureIndexIsVisible( si - 1 ); if ( !isTableCellEditor ) { - comboBox.setSelectedIndex(si-1); + if (!(UIManager.getBoolean("ComboBox.noActionOnKeyNavigation") && comboBox.isPopupVisible())) { + comboBox.setSelectedIndex(si-1); + } } comboBox.repaint(); } @@ -1490,7 +1494,13 @@ public class BasicComboBoxUI extends ComboBoxUI { key == HOME || key == END) { int index = getNextIndex(comboBox, key); if (index >= 0 && index < comboBox.getItemCount()) { - comboBox.setSelectedIndex(index); + if (UIManager.getBoolean("ComboBox.noActionOnKeyNavigation") && comboBox.isPopupVisible()) { + ui.listBox.setSelectedIndex(index); + ui.listBox.ensureIndexIsVisible(index); + comboBox.repaint(); + } else { + comboBox.setSelectedIndex(index); + } } } else if (key == DOWN) { @@ -1558,22 +1568,33 @@ public class BasicComboBoxUI extends ComboBoxUI { else if (key == ENTER) { if (comboBox.isPopupVisible()) { - // Forces the selection of the list item - boolean isEnterSelectablePopup = - UIManager.getBoolean("ComboBox.isEnterSelectablePopup"); - if (!comboBox.isEditable() || isEnterSelectablePopup - || ui.isTableCellEditor) { + // If ComboBox.noActionOnKeyNavigation is set, + // forse selection of list item + if (UIManager.getBoolean("ComboBox.noActionOnKeyNavigation")) { Object listItem = ui.popup.getList().getSelectedValue(); if (listItem != null) { - // Use the selected value from popup - // to set the selected item in combo box, - // but ensure before that JComboBox.actionPerformed() - // won't use editor's value to set the selected item comboBox.getEditor().setItem(listItem); comboBox.setSelectedItem(listItem); } + comboBox.setPopupVisible(false); + } else { + // Forces the selection of the list item + boolean isEnterSelectablePopup = + UIManager.getBoolean("ComboBox.isEnterSelectablePopup"); + if (!comboBox.isEditable() || isEnterSelectablePopup + || ui.isTableCellEditor) { + Object listItem = ui.popup.getList().getSelectedValue(); + if (listItem != null) { + // Use the selected value from popup + // to set the selected item in combo box, + // but ensure before that JComboBox.actionPerformed() + // won't use editor's value to set the selected item + comboBox.getEditor().setItem(listItem); + comboBox.setSelectedItem(listItem); + } + } + comboBox.setPopupVisible(false); } - comboBox.setPopupVisible(false); } else { // Hide combo box if it is a table cell editor @@ -1604,14 +1625,20 @@ public class BasicComboBoxUI extends ComboBoxUI { } private int getNextIndex(JComboBox comboBox, String key) { + int listHeight = comboBox.getMaximumRowCount(); + + int selectedIndex = comboBox.getSelectedIndex(); + if (UIManager.getBoolean("ComboBox.noActionOnKeyNavigation") + && (comboBox.getUI() instanceof BasicComboBoxUI)) { + selectedIndex = ((BasicComboBoxUI) comboBox.getUI()).listBox.getSelectedIndex(); + } + if (key == PAGE_UP) { - int listHeight = comboBox.getMaximumRowCount(); - int index = comboBox.getSelectedIndex() - listHeight; + int index = selectedIndex - listHeight; return (index < 0 ? 0: index); } else if (key == PAGE_DOWN) { - int listHeight = comboBox.getMaximumRowCount(); - int index = comboBox.getSelectedIndex() + listHeight; + int index = selectedIndex + listHeight; int max = comboBox.getItemCount(); return (index < max ? index: max-1); } diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java index 5a9135844bc..2e808c4b566 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, 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 @@ -861,6 +861,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel implements Serializab "END", "endPassThrough", "ENTER", "enterPressed" }), + "ComboBox.noActionOnKeyNavigation", Boolean.FALSE, // *** FileChooser diff --git a/jdk/test/javax/swing/JComboBox/4199622/bug4199622.java b/jdk/test/javax/swing/JComboBox/4199622/bug4199622.java new file mode 100644 index 00000000000..2c7deddb31b --- /dev/null +++ b/jdk/test/javax/swing/JComboBox/4199622/bug4199622.java @@ -0,0 +1,243 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* @test + @bug 4199622 + @summary RFE: JComboBox shouldn't send ActionEvents for keyboard navigation + @author Vladislav Karnaukhov + @run main bug4199622 +*/ + +import com.sun.java.swing.plaf.windows.WindowsLookAndFeel; +import sun.awt.OSInfo; +import sun.awt.SunToolkit; + +import javax.swing.*; +import javax.swing.plaf.metal.MetalLookAndFeel; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.lang.reflect.InvocationTargetException; + +public class bug4199622 extends JFrame implements ActionListener { + + static final int nElems = 20; + static JComboBox cb = null; + + bug4199622(LookAndFeel laf) { + super(); + + try { + UIManager.setLookAndFeel(laf); + } catch (UnsupportedLookAndFeelException e) { + throw new RuntimeException("Test failed", e); + } + + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + cb = new JComboBox<>(); + for (int i = 0; i < nElems; i++) { + cb.addItem(String.valueOf(i + 1)); + } + cb.addActionListener(this); + add(cb); + + setSize(300, 300); + pack(); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (UIManager.getBoolean("ComboBox.noActionOnKeyNavigation") && cb.isPopupVisible()) { + throw new RuntimeException("Test failed. actionPerformed generated"); + } + } + + static Robot robot = null; + static SunToolkit toolkit = null; + + static void doTest() { + if (robot == null) { + try { + robot = new Robot(); + robot.setAutoDelay(20); + } catch (AWTException e) { + throw new RuntimeException("Can't create robot. Test failed", e); + } + } + + toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + if (toolkit == null) { + throw new RuntimeException("Can't get the toolkit. Test failed"); + } + toolkit.realSync(); + + doActualTest(); + + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + cb.hidePopup(); + cb.setEditable(true); + cb.updateUI(); + } + }); + } catch (InterruptedException e) { + throw new RuntimeException("Test failed", e); + } catch (InvocationTargetException e) { + throw new RuntimeException("Test failed", e); + } + + toolkit.realSync(); + doActualTest(); + } + + static void doActualTest() { + UIManager.put("ComboBox.noActionOnKeyNavigation", true); + doTestUpDown(); + UIManager.put("ComboBox.noActionOnKeyNavigation", false); + doTestUpDown(); + + UIManager.put("ComboBox.noActionOnKeyNavigation", true); + doTestPgUpDown(); + UIManager.put("ComboBox.noActionOnKeyNavigation", false); + doTestPgUpDown(); + + UIManager.put("ComboBox.noActionOnKeyNavigation", true); + doTestHomeEnd(); + UIManager.put("ComboBox.noActionOnKeyNavigation", false); + doTestHomeEnd(); + } + + static void doTestHomeEnd() { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + cb.hidePopup(); + cb.setSelectedIndex(0); + } + }); + } catch (InterruptedException e) { + throw new RuntimeException("Test failed", e); + } catch (InvocationTargetException e) { + throw new RuntimeException("Test failed", e); + } + toolkit.realSync(); + + robot.keyPress(KeyEvent.VK_END); + toolkit.realSync(); + robot.keyPress(KeyEvent.VK_HOME); + toolkit.realSync(); + } + + static void doTestUpDown() { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + cb.hidePopup(); + cb.setSelectedIndex(0); + } + }); + } catch (InterruptedException e) { + throw new RuntimeException("Test failed", e); + } catch (InvocationTargetException e) { + throw new RuntimeException("Test failed", e); + } + toolkit.realSync(); + + for (int i = 0; i < nElems; i++) { + robot.keyPress(KeyEvent.VK_DOWN); + toolkit.realSync(); + } + + for (int i = 0; i < nElems; i++) { + robot.keyPress(KeyEvent.VK_UP); + toolkit.realSync(); + } + } + + static void doTestPgUpDown() { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + cb.hidePopup(); + cb.setSelectedIndex(0); + } + }); + } catch (InterruptedException e) { + throw new RuntimeException("Test failed", e); + } catch (InvocationTargetException e) { + throw new RuntimeException("Test failed", e); + } + toolkit.realSync(); + + int listHeight = cb.getMaximumRowCount(); + for (int i = 0; i < nElems; i += listHeight) { + robot.keyPress(KeyEvent.VK_PAGE_DOWN); + toolkit.realSync(); + } + + for (int i = 0; i < nElems; i += listHeight) { + robot.keyPress(KeyEvent.VK_PAGE_UP); + toolkit.realSync(); + } + } + + public static void main(String[] args) { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + bug4199622 test = new bug4199622(new MetalLookAndFeel()); + test.setVisible(true); + } + }); + } catch (InterruptedException e) { + throw new RuntimeException("Test failed", e); + } catch (InvocationTargetException e) { + throw new RuntimeException("Test failed", e); + } + doTest(); + + if (OSInfo.getOSType() == OSInfo.OSType.WINDOWS) { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + bug4199622 test = new bug4199622(new WindowsLookAndFeel()); + test.setVisible(true); + } + }); + } catch (InterruptedException e) { + throw new RuntimeException("Test failed", e); + } catch (InvocationTargetException e) { + throw new RuntimeException("Test failed", e); + } + doTest(); + } + } +} From 42b8720beff94cc6d87975d08ff2e5c77d294dab Mon Sep 17 00:00:00 2001 From: Petr Pchelko Date: Wed, 13 Feb 2013 15:27:29 +0000 Subject: [PATCH 146/158] 7079260: InputContext leaks memory Replaced strong refs with weak refs Reviewed-by: art, serb --- .../sun/awt/im/CompositionAreaHandler.java | 15 ++- .../classes/sun/awt/X11InputMethod.java | 13 +- .../InputContextMemoryLeakTest.java | 112 ++++++++++++++++++ jdk/test/java/awt/regtesthelpers/Util.java | 7 ++ 4 files changed, 135 insertions(+), 12 deletions(-) create mode 100644 jdk/test/java/awt/im/memoryleak/InputContextMemoryLeakTest.java diff --git a/jdk/src/share/classes/sun/awt/im/CompositionAreaHandler.java b/jdk/src/share/classes/sun/awt/im/CompositionAreaHandler.java index 6ae4a957ce2..1d661c4b9ba 100644 --- a/jdk/src/share/classes/sun/awt/im/CompositionAreaHandler.java +++ b/jdk/src/share/classes/sun/awt/im/CompositionAreaHandler.java @@ -33,6 +33,7 @@ import java.awt.event.InputMethodListener; import java.awt.font.TextAttribute; import java.awt.font.TextHitInfo; import java.awt.im.InputMethodRequests; +import java.lang.ref.WeakReference; import java.text.AttributedCharacterIterator; import java.text.AttributedCharacterIterator.Attribute; import java.text.AttributedString; @@ -55,7 +56,7 @@ class CompositionAreaHandler implements InputMethodListener, private AttributedCharacterIterator composedText; private TextHitInfo caret = null; - private Component clientComponent = null; + private WeakReference clientComponent = new WeakReference<>(null); private InputMethodContext inputMethodContext; /** @@ -76,8 +77,9 @@ class CompositionAreaHandler implements InputMethodListener, } // If the client component is an active client using below-the-spot style, then // make the composition window undecorated without a title bar. - if(clientComponent!=null){ - InputMethodRequests req = clientComponent.getInputMethodRequests(); + Component client = clientComponent.get(); + if(client != null){ + InputMethodRequests req = client.getInputMethodRequests(); if (req != null && inputMethodContext.useBelowTheSpotInput()) { setCompositionAreaUndecorated(true); } @@ -86,7 +88,7 @@ class CompositionAreaHandler implements InputMethodListener, } void setClientComponent(Component clientComponent) { - this.clientComponent = clientComponent; + this.clientComponent = new WeakReference<>(clientComponent); } /** @@ -256,8 +258,9 @@ class CompositionAreaHandler implements InputMethodListener, * the composed text are forwarded to the client component. */ InputMethodRequests getClientInputMethodRequests() { - if (clientComponent != null) { - return clientComponent.getInputMethodRequests(); + Component client = clientComponent.get(); + if (client != null) { + return client.getInputMethodRequests(); } return null; diff --git a/jdk/src/solaris/classes/sun/awt/X11InputMethod.java b/jdk/src/solaris/classes/sun/awt/X11InputMethod.java index b2a62c60ce8..b1939a67d9b 100644 --- a/jdk/src/solaris/classes/sun/awt/X11InputMethod.java +++ b/jdk/src/solaris/classes/sun/awt/X11InputMethod.java @@ -57,6 +57,7 @@ import java.io.File; import java.io.FileReader; import java.io.BufferedReader; import java.io.IOException; +import java.lang.ref.WeakReference; import sun.util.logging.PlatformLogger; import java.util.StringTokenizer; import java.util.regex.Pattern; @@ -104,7 +105,7 @@ public abstract class X11InputMethod extends InputMethodAdapter { //reset the XIC if necessary private boolean needResetXIC = false; - private Component needResetXICClient = null; + private WeakReference needResetXICClient = new WeakReference<>(null); // The use of compositionEnableSupported is to reduce unnecessary // native calls if set/isCompositionEnabled @@ -272,14 +273,14 @@ public abstract class X11InputMethod extends InputMethodAdapter { called on the passive client when endComposition is called. */ if (needResetXIC && haveActiveClient() && - getClientComponent() != needResetXICClient){ + getClientComponent() != needResetXICClient.get()){ resetXIC(); // needs to reset the last xic focussed component. lastXICFocussedComponent = null; isLastXICActive = false; - needResetXICClient = null; + needResetXICClient.clear(); needResetXIC = false; } } @@ -417,7 +418,7 @@ public abstract class X11InputMethod extends InputMethodAdapter { isLastXICActive = false; resetXIC(); - needResetXICClient = null; + needResetXICClient.clear(); needResetXIC = false; } } @@ -478,7 +479,7 @@ public abstract class X11InputMethod extends InputMethodAdapter { disableInputMethod(); if (needResetXIC) { resetXIC(); - needResetXICClient = null; + needResetXICClient.clear(); needResetXIC = false; } } @@ -877,7 +878,7 @@ public abstract class X11InputMethod extends InputMethodAdapter { boolean active = haveActiveClient(); if (active && composedText == null && committedText == null){ needResetXIC = true; - needResetXICClient = getClientComponent(); + needResetXICClient = new WeakReference<>(getClientComponent()); return; } diff --git a/jdk/test/java/awt/im/memoryleak/InputContextMemoryLeakTest.java b/jdk/test/java/awt/im/memoryleak/InputContextMemoryLeakTest.java new file mode 100644 index 00000000000..04e4a333cdd --- /dev/null +++ b/jdk/test/java/awt/im/memoryleak/InputContextMemoryLeakTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +import java.awt.FlowLayout; +import java.awt.Robot; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import test.java.awt.regtesthelpers.Util; + +/* + @test + @bug 7079260 + @summary XInputContext leaks memory by needRecetXXIClient field + @author Petr Pchelko + @library ../../regtesthelpers + @build Util + @compile InputContextMemoryLeakTest.java + @run main/othervm -Xmx20M InputContextMemoryLeakTest + */ +public class InputContextMemoryLeakTest { + + private static JFrame frame; + private static WeakReference text; + private static WeakReference p; + private static JButton button; + + public static void init() throws Throwable { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame = new JFrame(); + frame.setLayout(new FlowLayout()); + JPanel p1 = new JPanel(); + button = new JButton("Test"); + p1.add(button); + frame.add(p1); + text = new WeakReference(new JTextField("Text")); + p = new WeakReference(new JPanel(new FlowLayout())); + p.get().add(text.get()); + frame.add(p.get()); + frame.setBounds(500, 400, 200, 200); + frame.setVisible(true); + } + }); + + Util.focusComponent(text.get(), 500); + Util.clickOnComp(button, new Robot()); + //References to objects testes for memory leak are stored in Util. + //Need to clean them + Util.cleanUp(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame.remove(p.get()); + } + }); + + Util.waitForIdle(null); + //After the next caret blink it automatically TextField references + Thread.sleep(text.get().getCaret().getBlinkRate() * 2); + Util.waitForIdle(null); + assertGC(); + } + + public static void assertGC() throws Throwable { + List alloc = new ArrayList(); + int size = 1024 * 10; + while (true) { + try { + alloc.add(new byte[size]); + } catch (OutOfMemoryError err) { + break; + } + } + alloc = null; + if (text.get() != null) { + throw new Exception("Test failed: JTextField was not collected"); + } + } + + public static void main(String args[]) throws Throwable { + init(); + } +} diff --git a/jdk/test/java/awt/regtesthelpers/Util.java b/jdk/test/java/awt/regtesthelpers/Util.java index ebbfdf90463..90b28222552 100644 --- a/jdk/test/java/awt/regtesthelpers/Util.java +++ b/jdk/test/java/awt/regtesthelpers/Util.java @@ -463,6 +463,13 @@ public final class Util { return -1; } + //Cleans all the references + public static void cleanUp() { + apListener = null; + fgListener = null; + wgfListener = null; + } + //////////////////////////// // Some stuff to test focus. From 959ddfce4a7840aa855d6351961badff298a2c29 Mon Sep 17 00:00:00 2001 From: Petr Pchelko Date: Wed, 13 Feb 2013 15:32:50 +0000 Subject: [PATCH 147/158] 8005629: javac warnings compiling java.awt.EventDispatchThread and sun.awt.X11.XIconWindow Removed macosx specific workaround from shared code and made macosx use public API Reviewed-by: art, serb --- .../classes/sun/lwawt/macosx/CPrinterJob.java | 36 +++++++++++++---- .../sun/lwawt/macosx/EventDispatchAccess.java | 39 ------------------- jdk/src/macosx/native/sun/awt/CPrinterJob.m | 25 ------------ .../classes/java/awt/EventDispatchThread.java | 28 ------------- .../classes/sun/awt/X11/XIconWindow.java | 2 +- 5 files changed, 30 insertions(+), 100 deletions(-) delete mode 100644 jdk/src/macosx/classes/sun/lwawt/macosx/EventDispatchAccess.java diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java index 56f5ac7ecc6..791182c1565 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterJob.java @@ -30,6 +30,8 @@ import java.awt.*; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.print.*; +import java.security.AccessController; +import java.security.PrivilegedAction; import javax.print.*; import javax.print.attribute.PrintRequestAttributeSet; @@ -47,6 +49,8 @@ public class CPrinterJob extends RasterPrinterJob { private static String sShouldNotReachHere = "Should not reach here."; + private volatile SecondaryLoop printingLoop; + private boolean noDefaultPrinter = false; private static Font defaultFont; @@ -160,11 +164,22 @@ public class CPrinterJob extends RasterPrinterJob { volatile boolean onEventThread; + @Override + protected void cancelDoc() throws PrinterAbortException { + super.cancelDoc(); + if (printingLoop != null) { + printingLoop.exit(); + } + } + private void completePrintLoop() { Runnable r = new Runnable() { public void run() { synchronized(this) { performingPrinting = false; } + if (printingLoop != null) { + printingLoop.exit(); + } }}; if (onEventThread) { @@ -219,17 +234,21 @@ public class CPrinterJob extends RasterPrinterJob { onEventThread = true; + printingLoop = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public SecondaryLoop run() { + return Toolkit.getDefaultToolkit() + .getSystemEventQueue() + .createSecondaryLoop(); + } + }); + try { // Fire off the print rendering loop on the AppKit thread, and don't have // it wait and block this thread. if (printLoop(false, firstPage, lastPage)) { - // Fire off the EventConditional that will what until the condition is met, - // but will still process AWTEvent's as they occur. - new EventDispatchAccess() { - public boolean evaluate() { - return performingPrinting; - } - }.pumpEventsAndWait(); + // Start a secondary loop on EDT until printing operation is finished or cancelled + printingLoop.enter(); } } catch (Exception e) { e.printStackTrace(); @@ -253,6 +272,9 @@ public class CPrinterJob extends RasterPrinterJob { performingPrinting = false; notify(); } + if (printingLoop != null) { + printingLoop.exit(); + } } // Normalize the collated, # copies, numPages, first/last pages. Need to diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/EventDispatchAccess.java b/jdk/src/macosx/classes/sun/lwawt/macosx/EventDispatchAccess.java deleted file mode 100644 index 1124d123757..00000000000 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/EventDispatchAccess.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 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 sun.lwawt.macosx; - -// This exists strictly to work around the fact that java.awt.Conditional isn't a public class. -// It uses java reflection to get the EventDispatchThread class and call a MacOSX only -// method on it. -// -// NOTE: This uses reflection in its implementation, so it is not for performance critical code. -// -// See java.awt.EventDispatchThread and apple.awt.CPrintJob for more. -// -public abstract class EventDispatchAccess { - public native void pumpEventsAndWait(); - public abstract boolean evaluate(); -} diff --git a/jdk/src/macosx/native/sun/awt/CPrinterJob.m b/jdk/src/macosx/native/sun/awt/CPrinterJob.m index 52976f31d26..3935240ff78 100644 --- a/jdk/src/macosx/native/sun/awt/CPrinterJob.m +++ b/jdk/src/macosx/native/sun/awt/CPrinterJob.m @@ -383,31 +383,6 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj } } -/* - * Class: sun_lwawt_macosx_EventDispatchAccess - * Method: pumpEventsAndWait - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_sun_lwawt_macosx_EventDispatchAccess_pumpEventsAndWait -(JNIEnv *env, jobject eda) -{ - static JNF_CLASS_CACHE(jc_Thread, "java/lang/Thread"); - static JNF_STATIC_MEMBER_CACHE(jm_currentThread, jc_Thread, "currentThread", "()Ljava/lang/Thread;"); - static JNF_CLASS_CACHE(jc_EventDispatchThread, "java/awt/EventDispatchThread"); - static JNF_MEMBER_CACHE(jm_macosxGetConditional, jc_EventDispatchThread, "_macosxGetConditional", "(Ljava/lang/Object;)Ljava/awt/Conditional;"); - static JNF_MEMBER_CACHE(jm_pumpEvents, jc_EventDispatchThread, "pumpEvents", "(Ljava/awt/Conditional;)V"); - -JNF_COCOA_DURING(env); - - jobject thread = JNFCallStaticObjectMethod(env, jm_currentThread); - jobject conditional = JNFCallObjectMethod(env, thread, jm_macosxGetConditional, eda); - if (conditional != NULL) { - JNFCallVoidMethod(env, thread, jm_pumpEvents, conditional); - } - -JNF_COCOA_HANDLE(env); -} - /* * Class: sun_lwawt_macosx_CPrinterJob * Method: abortDoc diff --git a/jdk/src/share/classes/java/awt/EventDispatchThread.java b/jdk/src/share/classes/java/awt/EventDispatchThread.java index 427ad7efeb7..c707f02abdb 100644 --- a/jdk/src/share/classes/java/awt/EventDispatchThread.java +++ b/jdk/src/share/classes/java/awt/EventDispatchThread.java @@ -107,34 +107,6 @@ class EventDispatchThread extends Thread { } } - // MacOSX change: - // This was added because this class (and java.awt.Conditional) are package private. - // There are certain instances where classes in other packages need to block the - // AWTEventQueue while still allowing it to process events. This uses reflection - // to call back into the caller in order to remove dependencies. - // - // NOTE: This uses reflection in its implementation, so it is not for performance critical code. - // - // cond is an instance of sun.lwawt.macosx.EventDispatchAccess - // - private Conditional _macosxGetConditional(final Object cond) { - try { - return new Conditional() { - final Method evaluateMethod = Class.forName("sun.lwawt.macosx.EventDispatchAccess").getMethod("evaluate", null); - public boolean evaluate() { - try { - return ((Boolean)evaluateMethod.invoke(cond, null)).booleanValue(); - } catch (Exception e) { - return false; - } - } - }; - } catch (Exception e) { - return new Conditional() { public boolean evaluate() { return false; } }; - } - } - - void pumpEvents(Conditional cond) { pumpEvents(ANY_EVENT, cond); } diff --git a/jdk/src/solaris/classes/sun/awt/X11/XIconWindow.java b/jdk/src/solaris/classes/sun/awt/X11/XIconWindow.java index 1d0e55d31ef..bf521db3b72 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XIconWindow.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XIconWindow.java @@ -92,7 +92,7 @@ public class XIconWindow extends XBaseWindow { } XIconSize[] sizeList = getIconSizes(); - log.finest("Icon sizes: {0}", sizeList); + log.finest("Icon sizes: {0}", (Object[]) sizeList); if (sizeList == null) { // No icon sizes so we simply fall back to 16x16 return new Dimension(16, 16); From 3d55cc1e02cd93a83c24f0426f6a9fcaa3089c0a Mon Sep 17 00:00:00 2001 From: Vinnie Ryan Date: Wed, 13 Feb 2013 16:01:26 +0000 Subject: [PATCH 148/158] 8007934: algorithm parameters for PBE Scheme 2 not decoded correctly in PKCS12 keystore Reviewed-by: mullan --- .../sun/security/pkcs12/PKCS12KeyStore.java | 49 ++++++---- jdk/test/java/security/KeyStore/PBETest.java | 95 +++++++++++++++---- 2 files changed, 111 insertions(+), 33 deletions(-) diff --git a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java index d40e033d9f0..32f1da53afa 100644 --- a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java +++ b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java @@ -326,7 +326,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { DerValue val = new DerValue(encrInfo.getAlgorithm().encode()); DerInputStream in = val.toDerInputStream(); algOid = in.getOID(); - algParams = parseAlgParameters(in); + algParams = parseAlgParameters(algOid, in); } catch (IOException ioe) { UnrecoverableKeyException uke = @@ -342,7 +342,8 @@ public final class PKCS12KeyStore extends KeyStoreSpi { try { // Use JCE SecretKey skey = getPBEKey(password); - Cipher cipher = Cipher.getInstance(algOid.toString()); + Cipher cipher = Cipher.getInstance( + mapPBEParamsToAlgorithm(algOid, algParams)); cipher.init(Cipher.DECRYPT_MODE, skey, algParams); keyInfo = cipher.doFinal(encryptedKey); break; @@ -759,8 +760,8 @@ public final class PKCS12KeyStore extends KeyStoreSpi { /* * parse Algorithm Parameters */ - private AlgorithmParameters parseAlgParameters(DerInputStream in) - throws IOException + private AlgorithmParameters parseAlgParameters(ObjectIdentifier algorithm, + DerInputStream in) throws IOException { AlgorithmParameters algParams = null; try { @@ -774,7 +775,11 @@ public final class PKCS12KeyStore extends KeyStoreSpi { } } if (params != null) { - algParams = AlgorithmParameters.getInstance("PBE"); + if (algorithm.equals(pbes2_OID)) { + algParams = AlgorithmParameters.getInstance("PBES2"); + } else { + algParams = AlgorithmParameters.getInstance("PBE"); + } algParams.init(params.toByteArray()); } } catch (Exception e) { @@ -834,13 +839,6 @@ public final class PKCS12KeyStore extends KeyStoreSpi { } else { algParams = getAlgorithmParameters(algorithm); } - ObjectIdentifier pbeOID = mapPBEAlgorithmToOID(algorithm); - if (pbeOID != null) { - algid = new AlgorithmId(pbeOID, algParams); - } else { - throw new IOException("PBE algorithm '" + algorithm + - " 'is not supported for key entry protection"); - } } else { // Check default key protection algorithm for PKCS12 keystores algorithm = AccessController.doPrivileged( @@ -856,12 +854,16 @@ public final class PKCS12KeyStore extends KeyStoreSpi { return prop; } }); - if (algorithm == null) { + if (algorithm == null || algorithm.isEmpty()) { algorithm = "PBEWithSHA1AndDESede"; } algParams = getAlgorithmParameters(algorithm); - algid = new AlgorithmId(pbeWithSHAAnd3KeyTripleDESCBC_OID, - algParams); + } + + ObjectIdentifier pbeOID = mapPBEAlgorithmToOID(algorithm); + if (pbeOID == null) { + throw new IOException("PBE algorithm '" + algorithm + + " 'is not supported for key entry protection"); } // Use JCE @@ -869,6 +871,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { Cipher cipher = Cipher.getInstance(algorithm); cipher.init(Cipher.ENCRYPT_MODE, skey, algParams); byte[] encryptedKey = cipher.doFinal(data); + algid = new AlgorithmId(pbeOID, cipher.getParameters()); if (debug != null) { debug.println(" (Cipher algorithm: " + cipher.getAlgorithm() + @@ -894,7 +897,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { /* * Map a PBE algorithm name onto its object identifier */ - private ObjectIdentifier mapPBEAlgorithmToOID(String algorithm) + private static ObjectIdentifier mapPBEAlgorithmToOID(String algorithm) throws NoSuchAlgorithmException { // Check for PBES2 algorithms if (algorithm.toLowerCase().startsWith("pbewithhmacsha")) { @@ -903,6 +906,18 @@ public final class PKCS12KeyStore extends KeyStoreSpi { return AlgorithmId.get(algorithm).getOID(); } + /* + * Map a PBE algorithm parameters onto its algorithm name + */ + private static String mapPBEParamsToAlgorithm(ObjectIdentifier algorithm, + AlgorithmParameters algParams) throws NoSuchAlgorithmException { + // Check for PBES2 algorithms + if (algorithm.equals(pbes2_OID) && algParams != null) { + return algParams.toString(); + } + return algorithm.toString(); + } + /** * Assigns the given certificate to the given alias. * @@ -1933,7 +1948,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { // parse Algorithm parameters DerInputStream in = seq[1].toDerInputStream(); ObjectIdentifier algOid = in.getOID(); - AlgorithmParameters algParams = parseAlgParameters(in); + AlgorithmParameters algParams = parseAlgParameters(algOid, in); while (true) { try { diff --git a/jdk/test/java/security/KeyStore/PBETest.java b/jdk/test/java/security/KeyStore/PBETest.java index 2186165ea68..671e001a876 100644 --- a/jdk/test/java/security/KeyStore/PBETest.java +++ b/jdk/test/java/security/KeyStore/PBETest.java @@ -29,6 +29,7 @@ import java.io.*; import java.security.*; +import javax.crypto.*; import javax.crypto.spec.*; // Retrieve a keystore entry, protected by the default encryption algorithm. @@ -36,13 +37,20 @@ import javax.crypto.spec.*; public class PBETest { private final static String DIR = System.getProperty("test.src", "."); - //private static final String PBE_ALGO = "PBEWithHmacSHA1AndAES_128"; - private static final String PBE_ALGO = "PBEWithSHA1AndDESede"; + private final static String KEY_PROTECTION_PROPERTY = + "keystore.PKCS12.keyProtectionAlgorithm"; + private static final String[] PBE_ALGOS = { + "PBEWithSHA1AndDESede", + "PBEWithHmacSHA1AndAES_128", + "PBEWithHmacSHA224AndAES_128", + "PBEWithHmacSHA256AndAES_128", + "PBEWithHmacSHA384AndAES_128", + "PBEWithHmacSHA512AndAES_128" + }; private static final char[] PASSWORD = "passphrase".toCharArray(); private static final String KEYSTORE_TYPE = "JKS"; private static final String KEYSTORE = DIR + "/keystore.jks"; private static final String NEW_KEYSTORE_TYPE = "PKCS12"; - private static final String NEW_KEYSTORE = PBE_ALGO + ".p12"; private static final String ALIAS = "vajra"; private static final byte[] IV = { @@ -55,32 +63,87 @@ public class PBETest { private static final int ITERATION_COUNT = 1024; public static void main(String[] args) throws Exception { + for (String algo : PBE_ALGOS) { + String filename = algo + ".p12"; + main0(algo, filename, true); + main0(algo, filename, false); + Security.setProperty(KEY_PROTECTION_PROPERTY, algo); + main0(null, "PBE.p12", false); + Security.setProperty(KEY_PROTECTION_PROPERTY, ""); + } + main0(null, "default.p12", false); // default algorithm + } - new File(NEW_KEYSTORE).delete(); + private static void main0(String algo, String filename, boolean useParams) + throws Exception { KeyStore keystore = load(KEYSTORE_TYPE, KEYSTORE, PASSWORD); KeyStore.Entry entry = keystore.getEntry(ALIAS, new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry named '" + ALIAS + "'"); + System.out.println("Retrieved key entry named '" + ALIAS + "'"); + Key originalKey = null; + if (entry instanceof KeyStore.PrivateKeyEntry) { + originalKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey(); + } else if (entry instanceof KeyStore.SecretKeyEntry) { + originalKey = ((KeyStore.SecretKeyEntry) entry).getSecretKey(); + } // Set entry KeyStore keystore2 = load(NEW_KEYSTORE_TYPE, null, null); - keystore2.setEntry(ALIAS, entry, - new KeyStore.PasswordProtection(PASSWORD, PBE_ALGO, - new PBEParameterSpec(SALT, ITERATION_COUNT, - new IvParameterSpec(IV)))); - System.out.println("Encrypted entry using: " + PBE_ALGO); + if (useParams) { + keystore2.setEntry(ALIAS, entry, + new KeyStore.PasswordProtection(PASSWORD, algo, + new PBEParameterSpec(SALT, ITERATION_COUNT, + new IvParameterSpec(IV)))); + System.out.println("Encrypted key entry using: " + algo + + " (with PBE parameters)"); + } else if (algo != null) { + keystore2.setEntry(ALIAS, entry, + new KeyStore.PasswordProtection(PASSWORD, algo, null)); + System.out.println("Encrypted key entry using: " + algo + + " (without PBE parameters)"); + } else { + keystore2.setEntry(ALIAS, entry, + new KeyStore.PasswordProtection(PASSWORD)); + String prop = Security.getProperty(KEY_PROTECTION_PROPERTY); + if (prop == null || prop.isEmpty()) { + System.out.println("Encrypted key entry using: " + + "default PKCS12 key protection algorithm"); + } else { + System.out.println("Encrypted key entry using: " + + "keyProtectionAlgorithm=" + prop); + } + } - try (FileOutputStream outStream = new FileOutputStream(NEW_KEYSTORE)) { - System.out.println("Storing keystore to: " + NEW_KEYSTORE); + try (FileOutputStream outStream = new FileOutputStream(filename)) { + System.out.println("Storing keystore to: " + filename); keystore2.store(outStream, PASSWORD); } - keystore2 = load(NEW_KEYSTORE_TYPE, NEW_KEYSTORE, PASSWORD); - entry = keystore2.getEntry(ALIAS, - new KeyStore.PasswordProtection(PASSWORD)); - System.out.println("Retrieved entry named '" + ALIAS + "'"); + try { + keystore2 = load(NEW_KEYSTORE_TYPE, filename, PASSWORD); + entry = keystore2.getEntry(ALIAS, + new KeyStore.PasswordProtection(PASSWORD)); + Key key; + if (entry instanceof KeyStore.PrivateKeyEntry) { + key = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey(); + } else if (entry instanceof KeyStore.SecretKeyEntry) { + key = ((KeyStore.SecretKeyEntry) entry).getSecretKey(); + } else { + throw new Exception("Failed to retrieve key entry"); + } + if (originalKey.equals(key)) { + System.out.println("Retrieved key entry named '" + ALIAS + "'"); + System.out.println(); + } else { + throw new Exception( + "Failed: recovered key does not match the original key"); + } + + } finally { + new File(filename).delete(); + } } private static KeyStore load(String type, String path, char[] password) From 403e23ec706a8840ca0b51f759383e61c1174356 Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Wed, 13 Feb 2013 21:06:30 +0400 Subject: [PATCH 149/158] 8008095: TEST_BUG: JDK-8002048 one more testcase failure on Solaris Fixed couple of more Solaris shell incompatibilities Reviewed-by: chegar --- jdk/test/sun/management/jdp/JdpTest.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/jdk/test/sun/management/jdp/JdpTest.sh b/jdk/test/sun/management/jdp/JdpTest.sh index b92f6e9d0d3..dfdea7c1938 100644 --- a/jdk/test/sun/management/jdp/JdpTest.sh +++ b/jdk/test/sun/management/jdp/JdpTest.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh -x # Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -51,7 +51,7 @@ _do_compile(){ # sun.* packages is not included to symbol file lib/ct.sym so we have # to ignore it - if [ ! -f ${_testclasses} ] + if [ ! -d ${_testclasses} ] then mkdir -p ${_testclasses} fi @@ -295,12 +295,12 @@ do esac done -if [ ${_compile} = "yes" ] +if [ "${_compile}" = "yes" ] then _do_compile fi -if [ ${_jtreg} = "yes" ] +if [ "${_jtreg}" = "yes" ] then _testclasses=${TESTCLASSES} _testsrc=${TESTSRC} @@ -309,7 +309,7 @@ fi # Make sure _tesclasses is absolute path tt=`echo ${_testclasses} | sed -e 's,/,,'` -if [ ${tt} = ${_testclasses} ] +if [ "${tt}" = "${_testclasses}" ] then _testclasses="${_pwd}/${_testclasses}" fi @@ -319,7 +319,7 @@ _policyname="${_testclasses}/policy" rm -f ${_logname} rm -f ${_policyname} -if [ -e ${_testsrc}/policy.tpl ] +if [ -f ${_testsrc}/policy.tpl ] then cat ${_testsrc}/policy.tpl | \ From 8f58ebc26139f8ac32660be3486467111ba6d209 Mon Sep 17 00:00:00 2001 From: Vinnie Ryan Date: Wed, 13 Feb 2013 19:40:51 +0000 Subject: [PATCH 150/158] 8007755: Support the logical grouping of keystores Reviewed-by: mullan --- .../share/classes/java/security/KeyStore.java | 144 +++ .../sun/security/provider/DomainKeyStore.java | 900 ++++++++++++++++++ .../sun/security/provider/PolicyParser.java | 213 ++++- .../classes/sun/security/provider/Sun.java | 7 +- .../sun/security/provider/SunEntries.java | 1 + .../classes/sun/security/util/Resources.java | 2 + .../security/provider/KeyStore/DKSTest.java | 203 ++++ .../sun/security/provider/KeyStore/DKSTest.sh | 84 ++ .../security/provider/KeyStore/domains.cfg | 65 ++ .../security/tools/keytool/AltProviderPath.sh | 10 +- .../security/tools/keytool/DummyProvider.java | 2 +- 11 files changed, 1614 insertions(+), 17 deletions(-) create mode 100644 jdk/src/share/classes/sun/security/provider/DomainKeyStore.java create mode 100644 jdk/test/sun/security/provider/KeyStore/DKSTest.java create mode 100644 jdk/test/sun/security/provider/KeyStore/DKSTest.sh create mode 100644 jdk/test/sun/security/provider/KeyStore/domains.cfg diff --git a/jdk/src/share/classes/java/security/KeyStore.java b/jdk/src/share/classes/java/security/KeyStore.java index 96565684b0e..75d405771a7 100644 --- a/jdk/src/share/classes/java/security/KeyStore.java +++ b/jdk/src/share/classes/java/security/KeyStore.java @@ -218,6 +218,150 @@ public class KeyStore { public ProtectionParameter getProtectionParameter(); } + /** + * Configuration data that specifies the keystores in a keystore domain. + * A keystore domain is a collection of keystores that are presented as a + * single logical keystore. The configuration data is used during + * {@code KeyStore} + * {@link #load(KeyStore.LoadStoreParameter) load} and + * {@link #store(KeyStore.LoadStoreParameter) store} operations. + *

    + * The following syntax is supported for configuration data: + *

    +     *
    +     *     domain  [ ...] {
    +     *         keystore  [ ...] ;
    +     *         ...
    +     *     };
    +     *     ...
    +     *
    +     * 
    + * where {@code domainName} and {@code keystoreName} are identifiers + * and {@code property} is a key/value pairing. The key and value are + * separated by an 'equals' symbol and the value is enclosed in double + * quotes. A property value may be either a printable string or a binary + * string of colon-separated pairs of hexadecimal digits. Multi-valued + * properties are represented as a comma-separated list of values, + * enclosed in square brackets. + * See {@link Arrays#toString(java.lang.Object[])}. + *

    + * To ensure that keystore entries are uniquely identified, each + * entry's alias is prefixed by its {@code keystoreName} followed + * by the entry name separator and each {@code keystoreName} must be + * unique within its domain. Entry name prefixes are omitted when + * storing a keystore. + *

    + * Properties are context-sensitive: properties that apply to + * all the keystores in a domain are located in the domain clause, + * and properties that apply only to a specific keystore are located + * in that keystore's clause. + * Unless otherwise specified, a property in a keystore clause overrides + * a property of the same name in the domain clause. All property names + * are case-insensitive. The following properties are supported: + *

    + *
    {@code keystoreType=""}
    + *
    The keystore type.
    + *
    {@code keystoreURI=""}
    + *
    The keystore location.
    + *
    {@code keystoreProviderName=""}
    + *
    The name of the keystore's JCE provider.
    + *
    {@code keystorePasswordEnv=""}
    + *
    The environment variable that stores a keystore password. + * Alternatively, passwords may be supplied to the constructor + * method in a {@code Map}.
    + *
    {@code entryNameSeparator=""}
    + *
    The separator between a keystore name prefix and an entry name. + * When specified, it applies to all the entries in a domain. + * Its default value is a space.
    + *
    + *

    + * For example, configuration data for a simple keystore domain + * comprising three keystores is shown below: + *

    +     *
    +     * domain app1 {
    +     *     keystore app1-truststore
    +     *         keystoreURI="file:///app1/etc/truststore.jks"
    +     *
    +     *     keystore system-truststore
    +     *         keystoreURI="${java.home}/lib/security/cacerts"
    +     *
    +     *     keystore app1-keystore
    +     *         keystoreType="PKCS12"
    +     *         keystoreURI="file:///app1/etc/keystore.p12"
    +     * };
    +     *
    +     * 
    + * @since 1.8 + */ + public static final class DomainLoadStoreParameter + implements LoadStoreParameter { + + private final URI configuration; + private final Map protectionParams; + + /** + * Constructs a DomainLoadStoreParameter for a keystore domain with + * the parameters used to protect keystore data. + * + * @param configuration identifier for the domain configuration data. + * The name of the target domain should be specified in the + * {@code java.net.URI} fragment component when it is necessary + * to distinguish between several domain configurations at the + * same location. + * + * @param protectionParams the map from keystore name to the parameter + * used to protect keystore data. + * A {@code java.util.Collections.EMPTY_MAP} should be used + * when protection parameters are not required or when they have + * been specified by properties in the domain configuration data. + * It is cloned to prevent subsequent modification. + * + * @exception NullPointerExcetion if {@code configuration} or + * {@code protectionParams} is {@code null} + */ + public DomainLoadStoreParameter(URI configuration, + Map protectionParams) { + if (configuration == null || protectionParams == null) { + throw new NullPointerException("invalid null input"); + } + this.configuration = configuration; + this.protectionParams = + Collections.unmodifiableMap(new HashMap<>(protectionParams)); + } + + /** + * Gets the identifier for the domain configuration data. + * + * @return the identifier for the configuration data + */ + public URI getConfiguration() { + return configuration; + } + + /** + * Gets the keystore protection parameters for keystores in this + * domain. + * + * @return an unmodifiable map of keystore names to protection + * parameters + */ + public Map getProtectionParams() { + return protectionParams; + } + + /** + * Gets the keystore protection parameters for this domain. + * Keystore domains do not support a protection parameter. + * + * @return always returns {@code null} + */ + @Override + public KeyStore.ProtectionParameter getProtectionParameter() { + return null; + } + } + /** * A marker interface for keystore protection parameters. * diff --git a/jdk/src/share/classes/sun/security/provider/DomainKeyStore.java b/jdk/src/share/classes/sun/security/provider/DomainKeyStore.java new file mode 100644 index 00000000000..ae0dbfb067c --- /dev/null +++ b/jdk/src/share/classes/sun/security/provider/DomainKeyStore.java @@ -0,0 +1,900 @@ +/* + * Copyright (c) 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 + * 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.provider; + +import java.io.*; +import java.net.*; +import java.security.*; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.cert.CertificateException; +import java.util.*; + +import sun.misc.IOUtils; +import sun.security.pkcs.EncryptedPrivateKeyInfo; +import sun.security.util.PolicyUtil; + +/** + * This class provides the domain keystore type identified as "DKS". + * DKS presents a collection of separate keystores as a single logical keystore. + * The collection of keystores is specified in a domain configuration file which + * is passed to DKS in a {@link KeyStore.DomainLoadStoreParameter}. + *

    + * The following properties are supported: + *

    + *
    {@code keystoreType=""}
    + *
    The keystore type.
    + *
    {@code keystoreURI=""}
    + *
    The keystore location.
    + *
    {@code keystoreProviderName=""}
    + *
    The name of the keystore's JCE provider.
    + *
    {@code keystorePasswordEnv=""}
    + *
    The environment variable that stores a keystore password. + *
    {@code entryNameSeparator=""}
    + *
    The separator between a keystore name prefix and an entry name. + * When specified, it applies to all the entries in a domain. + * Its default value is a space.
    + *
    + * + * @since 1.8 + */ + +abstract class DomainKeyStore extends KeyStoreSpi { + + // regular DKS + public static final class DKS extends DomainKeyStore { + String convertAlias(String alias) { + return alias.toLowerCase(Locale.ENGLISH); + } + } + + // DKS property names + private static final String ENTRY_NAME_SEPARATOR = "entrynameseparator"; + private static final String KEYSTORE_PROVIDER_NAME = "keystoreprovidername"; + private static final String KEYSTORE_TYPE = "keystoretype"; + private static final String KEYSTORE_URI = "keystoreuri"; + private static final String KEYSTORE_PASSWORD_ENV = "keystorepasswordenv"; + + // RegEx meta characters + private static final String REGEX_META = ".$|()[{^?*+\\"; + + // Default prefix for keystores loaded-by-stream + private static final String DEFAULT_STREAM_PREFIX = "iostream"; + private int streamCounter = 1; + private String entryNameSeparator = " "; + private String entryNameSeparatorRegEx = " "; + + // Default keystore type + private static final String DEFAULT_KEYSTORE_TYPE = + KeyStore.getDefaultType(); + + // Domain keystores + private final Map keystores = new HashMap<>(); + + DomainKeyStore() { + } + + // convert an alias to internal form, overridden in subclasses: + // lower case for regular DKS + abstract String convertAlias(String alias); + + /** + * Returns the key associated with the given alias, using the given + * password to recover it. + * + * @param alias the alias name + * @param password the password for recovering the key + * + * @return the requested key, or null if the given alias does not exist + * or does not identify a key entry. + * + * @exception NoSuchAlgorithmException if the algorithm for recovering the + * key cannot be found + * @exception UnrecoverableKeyException if the key cannot be recovered + * (e.g., the given password is wrong). + */ + public Key engineGetKey(String alias, char[] password) + throws NoSuchAlgorithmException, UnrecoverableKeyException + { + AbstractMap.SimpleEntry> pair = + getKeystoresForReading(alias); + Key key = null; + + try { + String entryAlias = pair.getKey(); + for (KeyStore keystore : pair.getValue()) { + key = keystore.getKey(entryAlias, password); + if (key != null) { + break; + } + } + } catch (KeyStoreException e) { + throw new IllegalStateException(e); + } + + return key; + } + + /** + * Returns the certificate chain associated with the given alias. + * + * @param alias the alias name + * + * @return the certificate chain (ordered with the user's certificate first + * and the root certificate authority last), or null if the given alias + * does not exist or does not contain a certificate chain (i.e., the given + * alias identifies either a trusted certificate entry or a + * key entry without a certificate chain). + */ + public Certificate[] engineGetCertificateChain(String alias) { + + AbstractMap.SimpleEntry> pair = + getKeystoresForReading(alias); + Certificate[] chain = null; + + try { + String entryAlias = pair.getKey(); + for (KeyStore keystore : pair.getValue()) { + chain = keystore.getCertificateChain(entryAlias); + if (chain != null) { + break; + } + } + } catch (KeyStoreException e) { + throw new IllegalStateException(e); + } + + return chain; + } + + /** + * Returns the certificate associated with the given alias. + * + *

    If the given alias name identifies a + * trusted certificate entry, the certificate associated with that + * entry is returned. If the given alias name identifies a + * key entry, the first element of the certificate chain of that + * entry is returned, or null if that entry does not have a certificate + * chain. + * + * @param alias the alias name + * + * @return the certificate, or null if the given alias does not exist or + * does not contain a certificate. + */ + public Certificate engineGetCertificate(String alias) { + + AbstractMap.SimpleEntry> pair = + getKeystoresForReading(alias); + Certificate cert = null; + + try { + String entryAlias = pair.getKey(); + for (KeyStore keystore : pair.getValue()) { + cert = keystore.getCertificate(entryAlias); + if (cert != null) { + break; + } + } + } catch (KeyStoreException e) { + throw new IllegalStateException(e); + } + + return cert; + } + + /** + * Returns the creation date of the entry identified by the given alias. + * + * @param alias the alias name + * + * @return the creation date of this entry, or null if the given alias does + * not exist + */ + public Date engineGetCreationDate(String alias) { + + AbstractMap.SimpleEntry> pair = + getKeystoresForReading(alias); + Date date = null; + + try { + String entryAlias = pair.getKey(); + for (KeyStore keystore : pair.getValue()) { + date = keystore.getCreationDate(entryAlias); + if (date != null) { + break; + } + } + } catch (KeyStoreException e) { + throw new IllegalStateException(e); + } + + return date; + } + + /** + * Assigns the given private key to the given alias, protecting + * it with the given password as defined in PKCS8. + * + *

    The given java.security.PrivateKey key must + * be accompanied by a certificate chain certifying the + * corresponding public key. + * + *

    If the given alias already exists, the keystore information + * associated with it is overridden by the given key and certificate + * chain. + * + * @param alias the alias name + * @param key the private key to be associated with the alias + * @param password the password to protect the key + * @param chain the certificate chain for the corresponding public + * key (only required if the given key is of type + * java.security.PrivateKey). + * + * @exception KeyStoreException if the given key is not a private key, + * cannot be protected, or this operation fails for some other reason + */ + public void engineSetKeyEntry(String alias, Key key, char[] password, + Certificate[] chain) + throws KeyStoreException + { + AbstractMap.SimpleEntry> pair = + getKeystoreForWriting(alias); + + if (pair == null) { + throw new KeyStoreException("Error setting key entry for '" + + alias + "'"); + } + String entryAlias = pair.getKey(); + Map.Entry keystore = pair.getValue(); + keystore.getValue().setKeyEntry(entryAlias, key, password, chain); + } + + /** + * Assigns the given key (that has already been protected) to the given + * alias. + * + *

    If the protected key is of type + * java.security.PrivateKey, it must be accompanied by a + * certificate chain certifying the corresponding public key. If the + * underlying keystore implementation is of type jks, + * key must be encoded as an + * EncryptedPrivateKeyInfo as defined in the PKCS #8 standard. + * + *

    If the given alias already exists, the keystore information + * associated with it is overridden by the given key (and possibly + * certificate chain). + * + * @param alias the alias name + * @param key the key (in protected format) to be associated with the alias + * @param chain the certificate chain for the corresponding public + * key (only useful if the protected key is of type + * java.security.PrivateKey). + * + * @exception KeyStoreException if this operation fails. + */ + public void engineSetKeyEntry(String alias, byte[] key, + Certificate[] chain) + throws KeyStoreException + { + AbstractMap.SimpleEntry> pair = + getKeystoreForWriting(alias); + + if (pair == null) { + throw new KeyStoreException( + "Error setting protected key entry for '" + alias + "'"); + } + String entryAlias = pair.getKey(); + Map.Entry keystore = pair.getValue(); + keystore.getValue().setKeyEntry(entryAlias, key, chain); + } + + /** + * Assigns the given certificate to the given alias. + * + *

    If the given alias already exists in this keystore and identifies a + * trusted certificate entry, the certificate associated with it is + * overridden by the given certificate. + * + * @param alias the alias name + * @param cert the certificate + * + * @exception KeyStoreException if the given alias already exists and does + * not identify a trusted certificate entry, or this operation + * fails for some other reason. + */ + public void engineSetCertificateEntry(String alias, Certificate cert) + throws KeyStoreException + { + AbstractMap.SimpleEntry> pair = + getKeystoreForWriting(alias); + + if (pair == null) { + throw new KeyStoreException("Error setting certificate entry for '" + + alias + "'"); + } + String entryAlias = pair.getKey(); + Map.Entry keystore = pair.getValue(); + keystore.getValue().setCertificateEntry(entryAlias, cert); + } + + /** + * Deletes the entry identified by the given alias from this keystore. + * + * @param alias the alias name + * + * @exception KeyStoreException if the entry cannot be removed. + */ + public void engineDeleteEntry(String alias) throws KeyStoreException + { + AbstractMap.SimpleEntry> pair = + getKeystoreForWriting(alias); + + if (pair == null) { + throw new KeyStoreException("Error deleting entry for '" + alias + + "'"); + } + String entryAlias = pair.getKey(); + Map.Entry keystore = pair.getValue(); + keystore.getValue().deleteEntry(entryAlias); + } + + /** + * Lists all the alias names of this keystore. + * + * @return enumeration of the alias names + */ + public Enumeration engineAliases() { + final Iterator> iterator = + keystores.entrySet().iterator(); + + return new Enumeration() { + private int index = 0; + private Map.Entry keystoresEntry = null; + private String prefix = null; + private Enumeration aliases = null; + + public boolean hasMoreElements() { + try { + if (aliases == null) { + if (iterator.hasNext()) { + keystoresEntry = iterator.next(); + prefix = keystoresEntry.getKey() + + entryNameSeparator; + aliases = keystoresEntry.getValue().aliases(); + } else { + return false; + } + } + if (aliases.hasMoreElements()) { + return true; + } else { + if (iterator.hasNext()) { + keystoresEntry = iterator.next(); + prefix = keystoresEntry.getKey() + + entryNameSeparator; + aliases = keystoresEntry.getValue().aliases(); + } else { + return false; + } + } + } catch (KeyStoreException e) { + return false; + } + + return aliases.hasMoreElements(); + } + + public String nextElement() { + if (hasMoreElements()) { + return prefix + aliases.nextElement(); + } + throw new NoSuchElementException(); + } + }; + } + + /** + * Checks if the given alias exists in this keystore. + * + * @param alias the alias name + * + * @return true if the alias exists, false otherwise + */ + public boolean engineContainsAlias(String alias) { + + AbstractMap.SimpleEntry> pair = + getKeystoresForReading(alias); + + try { + String entryAlias = pair.getKey(); + for (KeyStore keystore : pair.getValue()) { + if (keystore.containsAlias(entryAlias)) { + return true; + } + } + } catch (KeyStoreException e) { + throw new IllegalStateException(e); + } + + return false; + } + + /** + * Retrieves the number of entries in this keystore. + * + * @return the number of entries in this keystore + */ + public int engineSize() { + + int size = 0; + try { + for (KeyStore keystore : keystores.values()) { + size += keystore.size(); + } + } catch (KeyStoreException e) { + throw new IllegalStateException(e); + } + + return size; + } + + /** + * Returns true if the entry identified by the given alias is a + * key entry, and false otherwise. + * + * @return true if the entry identified by the given alias is a + * key entry, false otherwise. + */ + public boolean engineIsKeyEntry(String alias) { + + AbstractMap.SimpleEntry> pair = + getKeystoresForReading(alias); + + try { + String entryAlias = pair.getKey(); + for (KeyStore keystore : pair.getValue()) { + if (keystore.isKeyEntry(entryAlias)) { + return true; + } + } + } catch (KeyStoreException e) { + throw new IllegalStateException(e); + } + + return false; + } + + /** + * Returns true if the entry identified by the given alias is a + * trusted certificate entry, and false otherwise. + * + * @return true if the entry identified by the given alias is a + * trusted certificate entry, false otherwise. + */ + public boolean engineIsCertificateEntry(String alias) { + + AbstractMap.SimpleEntry> pair = + getKeystoresForReading(alias); + + try { + String entryAlias = pair.getKey(); + for (KeyStore keystore : pair.getValue()) { + if (keystore.isCertificateEntry(entryAlias)) { + return true; + } + } + } catch (KeyStoreException e) { + throw new IllegalStateException(e); + } + + return false; + } + + /* + * Returns a keystore entry alias and a list of target keystores. + * When the supplied alias prefix identifies a keystore then that single + * keystore is returned. When no alias prefix is supplied then all the + * keystores are returned. + */ + private AbstractMap.SimpleEntry> + getKeystoresForReading(String alias) { + + String[] splits = alias.split(this.entryNameSeparatorRegEx, 2); + if (splits.length == 2) { // prefixed alias + KeyStore keystore = keystores.get(splits[0]); + if (keystore != null) { + return new AbstractMap.SimpleEntry<>(splits[1], + (Collection) Collections.singleton(keystore)); + } + } else if (splits.length == 1) { // unprefixed alias + // Check all keystores for the first occurrence of the alias + return new AbstractMap.SimpleEntry<>(alias, keystores.values()); + } + return new AbstractMap.SimpleEntry<>("", + (Collection) Collections.emptyList()); + } + + /* + * Returns a keystore entry alias and a single target keystore. + * An alias prefix must be supplied. + */ + private + AbstractMap.SimpleEntry> + getKeystoreForWriting(String alias) { + + String[] splits = alias.split(this.entryNameSeparator, 2); + if (splits.length == 2) { // prefixed alias + KeyStore keystore = keystores.get(splits[0]); + if (keystore != null) { + return new AbstractMap.SimpleEntry<>(splits[1], + new AbstractMap.SimpleEntry<>(splits[0], keystore)); + } + } + return null; + } + + /** + * Returns the (alias) name of the first keystore entry whose certificate + * matches the given certificate. + * + *

    This method attempts to match the given certificate with each + * keystore entry. If the entry being considered + * is a trusted certificate entry, the given certificate is + * compared to that entry's certificate. If the entry being considered is + * a key entry, the given certificate is compared to the first + * element of that entry's certificate chain (if a chain exists). + * + * @param cert the certificate to match with. + * + * @return the (alias) name of the first entry with matching certificate, + * or null if no such entry exists in this keystore. + */ + public String engineGetCertificateAlias(Certificate cert) { + + try { + + String alias = null; + for (KeyStore keystore : keystores.values()) { + if ((alias = keystore.getCertificateAlias(cert)) != null) { + break; + } + } + return alias; + + } catch (KeyStoreException e) { + throw new IllegalStateException(e); + } + } + + /** + * Stores this keystore to the given output stream, and protects its + * integrity with the given password. + * + * @param stream the output stream to which this keystore is written. + * @param password the password to generate the keystore integrity check + * + * @exception IOException if there was an I/O problem with data + * @exception NoSuchAlgorithmException if the appropriate data integrity + * algorithm could not be found + * @exception CertificateException if any of the certificates included in + * the keystore data could not be stored + */ + public void engineStore(OutputStream stream, char[] password) + throws IOException, NoSuchAlgorithmException, CertificateException + { + // Support storing to a stream only when a single keystore has been + // configured + try { + if (keystores.size() == 1) { + keystores.values().iterator().next().store(stream, password); + return; + } + } catch (KeyStoreException e) { + throw new IllegalStateException(e); + } + + throw new UnsupportedOperationException( + "This keystore must be stored using a " + + "KeyStore.DomainLoadStoreParameter"); + } + + @Override + public void engineStore(KeyStore.LoadStoreParameter param) + throws IOException, NoSuchAlgorithmException, CertificateException + { + if (param instanceof KeyStore.DomainLoadStoreParameter) { + KeyStore.DomainLoadStoreParameter domainParameter = + (KeyStore.DomainLoadStoreParameter) param; + List builders = getBuilders( + domainParameter.getConfiguration(), + domainParameter.getProtectionParams()); + + for (KeyStoreBuilderComponents builder : builders) { + + try { + + KeyStore.ProtectionParameter pp = builder.protection; + if (!(pp instanceof KeyStore.PasswordProtection)) { + throw new KeyStoreException( + new IllegalArgumentException("ProtectionParameter" + + " must be a KeyStore.PasswordPartection")); + } + char[] password = + ((KeyStore.PasswordProtection) builder.protection) + .getPassword(); + + // Store the keystores + KeyStore keystore = keystores.get(builder.name); + keystore.store(new FileOutputStream(builder.file), + password); + + } catch (KeyStoreException e) { + throw new IOException(e); + } + } + } else { + throw new UnsupportedOperationException( + "This keystore must be stored using a " + + "KeyStore.DomainLoadStoreParameter"); + } + } + + /** + * Loads the keystore from the given input stream. + * + *

    If a password is given, it is used to check the integrity of the + * keystore data. Otherwise, the integrity of the keystore is not checked. + * + * @param stream the input stream from which the keystore is loaded + * @param password the (optional) password used to check the integrity of + * the keystore. + * + * @exception IOException if there is an I/O or format problem with the + * keystore data + * @exception NoSuchAlgorithmException if the algorithm used to check + * the integrity of the keystore cannot be found + * @exception CertificateException if any of the certificates in the + * keystore could not be loaded + */ + public void engineLoad(InputStream stream, char[] password) + throws IOException, NoSuchAlgorithmException, CertificateException + { + // Support loading from a stream only for a JKS or default type keystore + try { + KeyStore keystore = null; + + try { + keystore = KeyStore.getInstance("JKS"); + keystore.load(stream, password); + + } catch (Exception e) { + // Retry + if (!"JKS".equalsIgnoreCase(DEFAULT_KEYSTORE_TYPE)) { + keystore = KeyStore.getInstance(DEFAULT_KEYSTORE_TYPE); + keystore.load(stream, password); + } else { + throw e; + } + } + String keystoreName = DEFAULT_STREAM_PREFIX + streamCounter++; + keystores.put(keystoreName, keystore); + + } catch (Exception e) { + throw new UnsupportedOperationException( + "This keystore must be loaded using a " + + "KeyStore.DomainLoadStoreParameter"); + } + } + + @Override + public void engineLoad(KeyStore.LoadStoreParameter param) + throws IOException, NoSuchAlgorithmException, CertificateException + { + if (param instanceof KeyStore.DomainLoadStoreParameter) { + KeyStore.DomainLoadStoreParameter domainParameter = + (KeyStore.DomainLoadStoreParameter) param; + List builders = getBuilders( + domainParameter.getConfiguration(), + domainParameter.getProtectionParams()); + + for (KeyStoreBuilderComponents builder : builders) { + + try { + // Load the keystores (file-based and non-file-based) + if (builder.file != null) { + keystores.put(builder.name, + KeyStore.Builder.newInstance(builder.type, + builder.provider, builder.file, + builder.protection) + .getKeyStore()); + } else { + keystores.put(builder.name, + KeyStore.Builder.newInstance(builder.type, + builder.provider, builder.protection) + .getKeyStore()); + } + } catch (KeyStoreException e) { + throw new IOException(e); + } + } + } else { + throw new UnsupportedOperationException( + "This keystore must be loaded using a " + + "KeyStore.DomainLoadStoreParameter"); + } + } + + /* + * Parse a keystore domain configuration file and associated collection + * of keystore passwords to create a collection of KeyStore.Builder. + */ + private List getBuilders(URI configuration, + Map passwords) + throws IOException { + + PolicyParser parser = new PolicyParser(true); // expand properties + Collection domains = null; + List builders = new ArrayList<>(); + String uriDomain = configuration.getFragment(); + + try (InputStreamReader configurationReader = + new InputStreamReader( + PolicyUtil.getInputStream(configuration.toURL()), "UTF-8")) { + parser.read(configurationReader); + domains = parser.getDomainEntries(); + + } catch (MalformedURLException mue) { + throw new IOException(mue); + + } catch (PolicyParser.ParsingException pe) { + throw new IOException(pe); + } + + for (PolicyParser.DomainEntry domain : domains) { + Map domainProperties = domain.getProperties(); + + if (uriDomain != null && + (!uriDomain.equalsIgnoreCase(domain.getName()))) { + continue; // skip this domain + } + + if (domainProperties.containsKey(ENTRY_NAME_SEPARATOR)) { + this.entryNameSeparator = + domainProperties.get(ENTRY_NAME_SEPARATOR); + // escape any regex meta characters + char ch = 0; + StringBuilder s = new StringBuilder(); + for (int i = 0; i < this.entryNameSeparator.length(); i++) { + ch = this.entryNameSeparator.charAt(i); + if (REGEX_META.indexOf(ch) != -1) { + s.append('\\'); + } + s.append(ch); + } + this.entryNameSeparatorRegEx = s.toString(); + } + + Collection keystores = + domain.getEntries(); + for (PolicyParser.KeyStoreEntry keystore : keystores) { + String keystoreName = keystore.getName(); + Map properties = + new HashMap<>(domainProperties); + properties.putAll(keystore.getProperties()); + + String keystoreType = DEFAULT_KEYSTORE_TYPE; + if (properties.containsKey(KEYSTORE_TYPE)) { + keystoreType = properties.get(KEYSTORE_TYPE); + } + + Provider keystoreProvider = null; + if (properties.containsKey(KEYSTORE_PROVIDER_NAME)) { + String keystoreProviderName = + properties.get(KEYSTORE_PROVIDER_NAME); + keystoreProvider = + Security.getProvider(keystoreProviderName); + if (keystoreProvider == null) { + throw new IOException("Error locating JCE provider: " + + keystoreProviderName); + } + } + + File keystoreFile = null; + if (properties.containsKey(KEYSTORE_URI)) { + String uri = properties.get(KEYSTORE_URI); + + try { + if (uri.startsWith("file://")) { + keystoreFile = new File(new URI(uri)); + } else { + keystoreFile = new File(uri); + } + + } catch (URISyntaxException | IllegalArgumentException e) { + throw new IOException( + "Error processing keystore property: " + + "keystoreURI=\"" + uri + "\"", e); + } + } + + KeyStore.ProtectionParameter keystoreProtection = null; + if (passwords.containsKey(keystoreName)) { + keystoreProtection = passwords.get(keystoreName); + + } else if (properties.containsKey(KEYSTORE_PASSWORD_ENV)) { + String env = properties.get(KEYSTORE_PASSWORD_ENV); + String pwd = System.getenv(env); + if (pwd != null) { + keystoreProtection = + new KeyStore.PasswordProtection(pwd.toCharArray()); + } else { + throw new IOException( + "Error processing keystore property: " + + "keystorePasswordEnv=\"" + env + "\""); + } + } else { + keystoreProtection = new KeyStore.PasswordProtection(null); + } + + builders.add(new KeyStoreBuilderComponents(keystoreName, + keystoreType, keystoreProvider, keystoreFile, + keystoreProtection)); + } + break; // skip other domains + } + if (builders.isEmpty()) { + throw new IOException("Error locating domain configuration data " + + "for: " + configuration); + } + + return builders; + } + +/* + * Utility class that holds the components used to construct a KeyStore.Builder + */ +class KeyStoreBuilderComponents { + String name; + String type; + Provider provider; + File file; + KeyStore.ProtectionParameter protection; + + KeyStoreBuilderComponents(String name, String type, Provider provider, + File file, KeyStore.ProtectionParameter protection) { + this.name = name; + this.type = type; + this.provider = provider; + this.file = file; + this.protection = protection; + } +} +} diff --git a/jdk/src/share/classes/sun/security/provider/PolicyParser.java b/jdk/src/share/classes/sun/security/provider/PolicyParser.java index b5247c76f9a..b13345f7c55 100644 --- a/jdk/src/share/classes/sun/security/provider/PolicyParser.java +++ b/jdk/src/share/classes/sun/security/provider/PolicyParser.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 @@ -32,12 +32,7 @@ import java.net.URL; import java.security.GeneralSecurityException; import java.security.Principal; import java.text.MessageFormat; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Vector; -import java.util.StringTokenizer; +import java.util.*; import javax.security.auth.x500.X500Principal; import sun.security.util.Debug; @@ -97,6 +92,7 @@ public class PolicyParser { private Vector grantEntries; + private Map domainEntries; // Convenience variables for parsing private static final Debug debug = Debug.getInstance("parser", @@ -195,9 +191,10 @@ public class PolicyParser { */ lookahead = st.nextToken(); + GrantEntry ge = null; while (lookahead != StreamTokenizer.TT_EOF) { if (peek("grant")) { - GrantEntry ge = parseGrantEntry(); + ge = parseGrantEntry(); // could be null if we couldn't expand a property if (ge != null) add(ge); @@ -209,6 +206,24 @@ public class PolicyParser { // only one keystore passwordURL per policy file, others will be // ignored parseStorePassURL(); + } else if (ge == null && keyStoreUrlString == null && + storePassURL == null && peek("domain")) { + if (domainEntries == null) { + domainEntries = new TreeMap<>(); + } + DomainEntry de = parseDomainEntry(); + if (de != null) { + String domainName = de.getName(); + if (!domainEntries.containsKey(domainName)) { + domainEntries.put(domainName, de); + } else { + MessageFormat form = + new MessageFormat(ResourcesMgr.getString( + "duplicate.keystore.domain.name")); + Object[] source = {domainName}; + throw new ParsingException(form.format(source)); + } + } } else { // error? } @@ -304,6 +319,10 @@ public class PolicyParser { return grantEntries.elements(); } + public Collection getDomainEntries() { + return domainEntries.values(); + } + /** * write out the policy */ @@ -633,6 +652,67 @@ public class PolicyParser { return e; } + /** + * parse a domain entry + */ + private DomainEntry parseDomainEntry() + throws ParsingException, IOException + { + boolean ignoreEntry = false; + DomainEntry domainEntry; + String name = null; + Map properties = new HashMap<>(); + + match("domain"); + name = match("domain name"); + + while(!peek("{")) { + // get the domain properties + properties = parseProperties("{"); + } + match("{"); + domainEntry = new DomainEntry(name, properties); + + while(!peek("}")) { + + match("keystore"); + name = match("keystore name"); + // get the keystore properties + if (!peek("}")) { + properties = parseProperties(";"); + } + match(";"); + domainEntry.add(new KeyStoreEntry(name, properties)); + } + match("}"); + + return (ignoreEntry == true) ? null : domainEntry; + } + + /* + * Return a collection of domain properties or keystore properties. + */ + private Map parseProperties(String terminator) + throws ParsingException, IOException { + + Map properties = new HashMap<>(); + String key; + String value; + while (!peek(terminator)) { + key = match("property name"); + match("="); + + try { + value = expand(match("quoted string")); + } catch (PropertyExpander.ExpandException peee) { + throw new IOException(peee.getLocalizedMessage()); + } + properties.put(key.toLowerCase(), value); + } + + return properties; + } + // package-private: used by PolicyFile for static policy static String[] parseExtDirs(String codebase, int start) { @@ -708,6 +788,10 @@ public class PolicyParser { if (expect.equalsIgnoreCase("*")) found = true; break; + case ';': + if (expect.equalsIgnoreCase(";")) + found = true; + break; default: } @@ -739,6 +823,11 @@ public class PolicyParser { } else if (expect.equalsIgnoreCase("principal type")) { value = st.sval; lookahead = st.nextToken(); + } else if (expect.equalsIgnoreCase("domain name") || + expect.equalsIgnoreCase("keystore name") || + expect.equalsIgnoreCase("property name")) { + value = st.sval; + lookahead = st.nextToken(); } else { throw new ParsingException(st.lineno(), expect, st.sval); @@ -788,6 +877,12 @@ public class PolicyParser { else throw new ParsingException(st.lineno(), expect, "*"); break; + case '=': + if (expect.equalsIgnoreCase("=")) + lookahead = st.nextToken(); + else + throw new ParsingException(st.lineno(), expect, "="); + break; default: throw new ParsingException(st.lineno(), expect, new String(new char[] {(char)lookahead})); @@ -1185,6 +1280,108 @@ public class PolicyParser { } } + /** + * Each domain entry in the keystore domain configuration file is + * represented by a DomainEntry object. + */ + static class DomainEntry { + private final String name; + private final Map properties; + private final Map entries; + + DomainEntry(String name, Map properties) { + this.name = name; + this.properties = properties; + entries = new HashMap<>(); + } + + String getName() { + return name; + } + + Map getProperties() { + return properties; + } + + Collection getEntries() { + return entries.values(); + } + + void add(KeyStoreEntry entry) throws ParsingException { + String keystoreName = entry.getName(); + if (!entries.containsKey(keystoreName)) { + entries.put(keystoreName, entry); + } else { + MessageFormat form = new MessageFormat(ResourcesMgr.getString( + "duplicate.keystore.name")); + Object[] source = {keystoreName}; + throw new ParsingException(form.format(source)); + } + } + + @Override + public String toString() { + StringBuilder s = + new StringBuilder("\ndomain ").append(name); + + if (properties != null) { + for (Map.Entry property : + properties.entrySet()) { + s.append("\n ").append(property.getKey()).append('=') + .append(property.getValue()); + } + } + s.append(" {\n"); + + if (entries != null) { + for (KeyStoreEntry entry : entries.values()) { + s.append(entry).append("\n"); + } + } + s.append("}"); + + return s.toString(); + } + } + + /** + * Each keystore entry in the keystore domain configuration file is + * represented by a KeyStoreEntry object. + */ + + static class KeyStoreEntry { + private final String name; + private final Map properties; + + KeyStoreEntry(String name, Map properties) { + this.name = name; + this.properties = properties; + } + + String getName() { + return name; + } + + Map getProperties() { + return properties; + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder("\n keystore ").append(name); + if (properties != null) { + for (Map.Entry property : + properties.entrySet()) { + s.append("\n ").append(property.getKey()).append('=') + .append(property.getValue()); + } + } + s.append(";"); + + return s.toString(); + } + } + public static class ParsingException extends GeneralSecurityException { private static final long serialVersionUID = -4330692689482574072L; diff --git a/jdk/src/share/classes/sun/security/provider/Sun.java b/jdk/src/share/classes/sun/security/provider/Sun.java index 20edc86b275..4af2be50864 100644 --- a/jdk/src/share/classes/sun/security/provider/Sun.java +++ b/jdk/src/share/classes/sun/security/provider/Sun.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 @@ -40,13 +40,14 @@ public final class Sun extends Provider { private static final String INFO = "SUN " + "(DSA key/parameter generation; DSA signing; SHA-1, MD5 digests; " + - "SecureRandom; X.509 certificates; JKS keystore; PKIX CertPathValidator; " + + "SecureRandom; X.509 certificates; JKS & DKS keystores; " + + "PKIX CertPathValidator; " + "PKIX CertPathBuilder; LDAP, Collection CertStores, JavaPolicy Policy; " + "JavaLoginConfig Configuration)"; public Sun() { /* We are the SUN provider */ - super("SUN", 1.7, INFO); + super("SUN", 1.8, INFO); // if there is no security manager installed, put directly into // the provider. Otherwise, create a temporary map and use a diff --git a/jdk/src/share/classes/sun/security/provider/SunEntries.java b/jdk/src/share/classes/sun/security/provider/SunEntries.java index 3876acbf3be..daa4e96760c 100644 --- a/jdk/src/share/classes/sun/security/provider/SunEntries.java +++ b/jdk/src/share/classes/sun/security/provider/SunEntries.java @@ -208,6 +208,7 @@ final class SunEntries { map.put("KeyStore.JKS", "sun.security.provider.JavaKeyStore$JKS"); map.put("KeyStore.CaseExactJKS", "sun.security.provider.JavaKeyStore$CaseExactJKS"); + map.put("KeyStore.DKS", "sun.security.provider.DomainKeyStore$DKS"); /* * Policy diff --git a/jdk/src/share/classes/sun/security/util/Resources.java b/jdk/src/share/classes/sun/security/util/Resources.java index ef073b0a1fd..50028264d14 100644 --- a/jdk/src/share/classes/sun/security/util/Resources.java +++ b/jdk/src/share/classes/sun/security/util/Resources.java @@ -127,6 +127,8 @@ public class Resources extends java.util.ListResourceBundle { {"multiple.Codebase.expressions", "multiple Codebase expressions"}, {"multiple.SignedBy.expressions","multiple SignedBy expressions"}, + {"duplicate.keystore.domain.name","duplicate keystore domain name: {0}"}, + {"duplicate.keystore.name","duplicate keystore name: {0}"}, {"SignedBy.has.empty.alias","SignedBy has empty alias"}, {"can.not.specify.Principal.with.a.wildcard.class.without.a.wildcard.name", "can not specify Principal with a wildcard class without a wildcard name"}, diff --git a/jdk/test/sun/security/provider/KeyStore/DKSTest.java b/jdk/test/sun/security/provider/KeyStore/DKSTest.java new file mode 100644 index 00000000000..c2b6baf3a42 --- /dev/null +++ b/jdk/test/sun/security/provider/KeyStore/DKSTest.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * see ./DKSTest.sh + */ + +import java.io.*; +import java.net.*; +import java.security.*; +import java.security.KeyStore; +import java.security.cert.*; +import java.security.cert.Certificate; +import java.util.*; + +// Load and store entries in domain keystores + +public class DKSTest { + + private static final String TEST_SRC = System.getProperty("test.src"); + private static final String CERT = TEST_SRC + "/../../pkcs12/trusted.pem"; + private static final String CONFIG = "file://" + TEST_SRC + "/domains.cfg"; + private static final Map PASSWORDS = + new HashMap() {{ + put("keystore", + new KeyStore.PasswordProtection("test123".toCharArray())); + put("policy_keystore", + new KeyStore.PasswordProtection( + "Alias.password".toCharArray())); + put("pw_keystore", + new KeyStore.PasswordProtection("test12".toCharArray())); + put("eckeystore1", + new KeyStore.PasswordProtection("password".toCharArray())); + put("eckeystore2", + new KeyStore.PasswordProtection("password".toCharArray())); + put("truststore", + new KeyStore.PasswordProtection("changeit".toCharArray())); + put("empty", + new KeyStore.PasswordProtection("passphrase".toCharArray())); + }}; + + public static void main(String[] args) throws Exception { + try { + main0(); + } finally { + // cleanup + new File(TEST_SRC + "/empty.jks").delete(); + new File(TEST_SRC + "/Alias.keystore_tmp").delete(); + new File(TEST_SRC + "/pw.jks_tmp").delete(); + new File(TEST_SRC + "/secp256r1server-secp384r1ca.p12_tmp").delete(); + new File(TEST_SRC + "/sect193r1server-rsa1024ca.p12_tmp").delete(); + } + } + + private static void main0() throws Exception { + /* + * domain keystore: system + */ + URI config = new URI(CONFIG + "#system"); + int cacertsCount; + int expected; + KeyStore keystore = KeyStore.getInstance("DKS"); + // load entries + keystore.load( + new KeyStore.DomainLoadStoreParameter(config, PASSWORDS)); + cacertsCount = expected = keystore.size(); + System.out.println("\nLoading domain keystore: " + config + "\t[" + + expected + " entries]"); + checkEntries(keystore, expected); + + /* + * domain keystore: system_plus + */ + config = new URI(CONFIG + "#system_plus"); + expected = cacertsCount + 1; + keystore = KeyStore.getInstance("DKS"); + // load entries + keystore.load( + new KeyStore.DomainLoadStoreParameter(config, PASSWORDS)); + System.out.println("\nLoading domain keystore: " + config + "\t[" + + expected + " entries]"); + checkEntries(keystore, expected); + + /* + * domain keystore: system_env + */ + config = new URI(CONFIG + "#system_env"); + expected = 1 + cacertsCount; + keystore = KeyStore.getInstance("DKS"); + // load entries + keystore.load( + new KeyStore.DomainLoadStoreParameter(config, + Collections.emptyMap())); + System.out.println("\nLoading domain keystore: " + config + "\t[" + + expected + " entries]"); + checkEntries(keystore, expected); + + /* + * domain keystore: empty + */ + KeyStore empty = KeyStore.getInstance("JKS"); + empty.load(null, null); + + try (OutputStream outStream = + new FileOutputStream(TEST_SRC + "/empty.jks")) { + empty.store(outStream, "passphrase".toCharArray()); + } + config = new URI(CONFIG + "#empty"); + expected = 0; + keystore = KeyStore.getInstance("DKS"); + // load entries + keystore.load( + new KeyStore.DomainLoadStoreParameter(config, PASSWORDS)); + System.out.println("\nLoading domain keystore: " + config + "\t[" + + expected + " entries]"); + checkEntries(keystore, expected); + + /* + * domain keystore: keystores + */ + config = new URI(CONFIG + "#keystores"); + expected = 2 + 1 + 1 + 1; + keystore = KeyStore.getInstance("DKS"); + // load entries + keystore.load( + new KeyStore.DomainLoadStoreParameter(config, PASSWORDS)); + System.out.println("\nLoading domain keystore: " + config + "\t[" + + expected + " entries]"); + checkEntries(keystore, expected); + // set a new trusted certificate entry + Certificate cert = loadCertificate(CERT); + String alias = "pw_keystore tmp-cert"; + System.out.println("Setting new trusted certificate entry: " + alias); + keystore.setEntry(alias, + new KeyStore.TrustedCertificateEntry(cert), null); + expected++; + // store entries + config = new URI(CONFIG + "#keystores_tmp"); + System.out.println("Storing domain keystore: " + config + "\t[" + + expected + " entries]"); + keystore.store( + new KeyStore.DomainLoadStoreParameter(config, PASSWORDS)); + keystore = KeyStore.getInstance("DKS"); + // reload entries + keystore.load( + new KeyStore.DomainLoadStoreParameter(config, PASSWORDS)); + System.out.println("Reloading domain keystore: " + config + "\t[" + + expected + " entries]"); + checkEntries(keystore, expected); + // get the new trusted certificate entry + System.out.println("Getting new trusted certificate entry: " + alias); + if (!keystore.isCertificateEntry(alias)) { + throw new Exception("Error: cannot retrieve certificate entry: " + + alias); + } + keystore.setEntry(alias, + new KeyStore.TrustedCertificateEntry(cert), null); + } + + private static void checkEntries(KeyStore keystore, int expected) + throws Exception { + int i = 0; + for (String alias : Collections.list(keystore.aliases())) { + System.out.print("."); + i++; + } + System.out.println(); + if (expected != i) { + throw new Exception("Error: unexpected entry count in keystore: " + + "loaded=" + i + ", expected=" + expected); + } + } + + private static Certificate loadCertificate(String certFile) + throws Exception { + X509Certificate cert = null; + try (FileInputStream certStream = new FileInputStream(certFile)) { + CertificateFactory factory = + CertificateFactory.getInstance("X.509"); + return factory.generateCertificate(certStream); + } + } +} diff --git a/jdk/test/sun/security/provider/KeyStore/DKSTest.sh b/jdk/test/sun/security/provider/KeyStore/DKSTest.sh new file mode 100644 index 00000000000..b789e414140 --- /dev/null +++ b/jdk/test/sun/security/provider/KeyStore/DKSTest.sh @@ -0,0 +1,84 @@ +#! /bin/sh + +# +# Copyright (c) 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 +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# 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. +# + +# @test +# @bug 8007755 +# @summary Support the logical grouping of keystores + +# set a few environment variables so that the shell-script can run stand-alone +# in the source directory +if [ "${TESTSRC}" = "" ] ; then + TESTSRC="." +fi + +if [ "${TESTCLASSES}" = "" ] ; then + TESTCLASSES="." +fi + +if [ "${TESTJAVA}" = "" ] ; then + echo "TESTJAVA not set. Test cannot execute." + echo "FAILED!!!" + exit 1 +fi + +if [ "${COMPILEJAVA}" = "" ]; then + COMPILEJAVA="${TESTJAVA}" +fi + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + SunOS ) + PS=":" + FS="/" + ;; + Linux ) + PS=":" + FS="/" + ;; + Darwin ) + PS=":" + FS="/" + ;; + CYGWIN* ) + PS=";" + FS="/" + ;; + Windows* ) + PS=";" + FS="\\" + ;; + * ) + echo "Unrecognized system!" + exit 1; + ;; +esac + +${COMPILEJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}DKSTest.java + +KEYSTORE_PWD=test12 TRUSTSTORE_PWD=changeit \ + ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Dtest.src=${TESTSRC} DKSTest + +exit $status diff --git a/jdk/test/sun/security/provider/KeyStore/domains.cfg b/jdk/test/sun/security/provider/KeyStore/domains.cfg new file mode 100644 index 00000000000..203d9d007ca --- /dev/null +++ b/jdk/test/sun/security/provider/KeyStore/domains.cfg @@ -0,0 +1,65 @@ +// domain containing a single keystore +domain system { + keystore truststore + keystoreType="JKS" + keystoreURI="${java.home}/lib/security/cacerts"; +}; + +// domain containing two JKS keystores +domain system_plus { + keystore truststore + keystoreType="JKS" + keystoreURI="${java.home}/lib/security/cacerts"; + keystore pw_keystore + keystoreType="JKS" + keystoreURI="${test.src}/pw.jks"; +}; + +// domain containing a mixture of keystores +domain keystores + keystoreType="PKCS12" { + keystore policy_keystore + keystoreType="JKS" + keystoreURI="${test.src}/../PolicyFile/Alias.keystore"; + keystore pw_keystore + keystoreType="CaseExactJKS" + keystoreURI="${test.src}/pw.jks"; + keystore eckeystore1 + keystoreURI="${test.src}/../../pkcs11/ec/pkcs12/sect193r1server-rsa1024ca.p12"; + keystore eckeystore2 + keystoreURI="${test.src}/../../pkcs11/ec/pkcs12/secp256r1server-secp384r1ca.p12"; +}; + +// domain containing a mixture of keystores +domain keystores_tmp + keystoreType="PKCS12" { + keystore policy_keystore + keystoreType="JKS" + keystoreURI="${test.src}/Alias.keystore_tmp"; + keystore pw_keystore + keystoreType="CaseExactJKS" + keystoreURI="${test.src}/pw.jks_tmp"; + keystore eckeystore1 + keystoreURI="${test.src}/sect193r1server-rsa1024ca.p12_tmp"; + keystore eckeystore2 + keystoreURI="${test.src}/secp256r1server-secp384r1ca.p12_tmp"; +}; + +// domain where passwords are supplied via environment variables +domain system_env + keystoreType="JKS" + keystorePasswordEnv="KEYSTORE_PWD" { + keystore env_keystore + keystoreURI="${test.src}/pw.jks"; + keystore env_truststore + keystoreURI="${java.home}/lib/security/cacerts" + keystorePasswordEnv="TRUSTSTORE_PWD"; +}; + +// empty domain +domain empty + keystoreType="JKS" + keystoreProviderName="SUN" { + keystore empty + keystoreURI="${test.src}/empty.jks"; +}; diff --git a/jdk/test/sun/security/tools/keytool/AltProviderPath.sh b/jdk/test/sun/security/tools/keytool/AltProviderPath.sh index 067a5eb7bf0..82bc65787ab 100644 --- a/jdk/test/sun/security/tools/keytool/AltProviderPath.sh +++ b/jdk/test/sun/security/tools/keytool/AltProviderPath.sh @@ -73,7 +73,7 @@ ${TESTJAVA}${FS}bin${FS}keytool -genkey -v -alias dummyTestCA \ -keyalg "RSA" -keysize 1024 -sigalg "ShA1WithRSA" \ -dname "cn=Dummy Test CA, ou=JSN, o=JavaSoft, c=US" -validity 3650 \ -keypass storepass -keystore keystoreCA.dks -storepass storepass \ - -storetype "dks" -provider "org.test.dummy.DummyProvider" \ + -storetype "dummyks" -provider "org.test.dummy.DummyProvider" \ -providerPath ${TESTCLASSES} if [ $? -ne 0 ]; then @@ -82,7 +82,7 @@ fi #Change keystore password ${TESTJAVA}${FS}bin${FS}keytool -storepasswd -new storepass2 \ - -keystore keystoreCA.dks -storetype "dks" -storepass storepass \ + -keystore keystoreCA.dks -storetype "dummyks" -storepass storepass \ -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES} if [ $? -ne 0 ]; then @@ -93,7 +93,7 @@ fi #Change keystore key password ${TESTJAVA}${FS}bin${FS}keytool -keypasswd -alias "dummyTestCA" \ -keypass storepass -new keypass -keystore keystoreCA.dks \ - -storetype "dks" -storepass storepass2 \ + -storetype "dummyks" -storepass storepass2 \ -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES} if [ $? -ne 0 ]; then @@ -102,7 +102,7 @@ fi #Export certificate ${TESTJAVA}${FS}bin${FS}keytool -v -export -rfc -alias "dummyTestCA" \ - -file "dummyTestCA.der" -keystore keystoreCA.dks -storetype "dks" \ + -file "dummyTestCA.der" -keystore keystoreCA.dks -storetype "dummyks" \ -storepass storepass2 -provider "org.test.dummy.DummyProvider" \ -providerPath ${TESTCLASSES} @@ -112,7 +112,7 @@ fi #list keystore ${TESTJAVA}${FS}bin${FS}keytool -v -list -keystore keystoreCA.dks \ - -storetype "dks" -storepass storepass2 \ + -storetype "dummyks" -storepass storepass2 \ -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES} if [ $? -ne 0 ]; then diff --git a/jdk/test/sun/security/tools/keytool/DummyProvider.java b/jdk/test/sun/security/tools/keytool/DummyProvider.java index ae714702051..0c7ce10d587 100644 --- a/jdk/test/sun/security/tools/keytool/DummyProvider.java +++ b/jdk/test/sun/security/tools/keytool/DummyProvider.java @@ -40,7 +40,7 @@ public class DummyProvider extends Provider { // // KeyStore // - put("KeyStore.DKS", "sun.security.provider.JavaKeyStore$JKS"); + put("KeyStore.DummyKS", "sun.security.provider.JavaKeyStore$JKS"); // // Signature engines From 48a592be5a11afd43a08cd92ba40a525ae8bf7e2 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Wed, 13 Feb 2013 11:49:34 -0800 Subject: [PATCH 151/158] 8008161: Regression: j.u.TimeZone.getAvailableIDs(rawOffset) returns non-sorted list To return a sorted list Reviewed-by: lancea, naoto --- .../sun/util/calendar/ZoneInfoFile.java | 8 +++++++- .../sun/util/calendar/zi/TestZoneInfo310.java | 20 ++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/sun/util/calendar/ZoneInfoFile.java b/jdk/src/share/classes/sun/util/calendar/ZoneInfoFile.java index ab1cf5c6dc9..2bddab21f2d 100644 --- a/jdk/src/share/classes/sun/util/calendar/ZoneInfoFile.java +++ b/jdk/src/share/classes/sun/util/calendar/ZoneInfoFile.java @@ -92,7 +92,13 @@ public final class ZoneInfoFile { ids.add(id); } } - return ids.toArray(new String[ids.size()]); + // It appears the "zi" implementation returns the + // sorted list, though the specification does not + // specify it. Keep the same behavior for better + // compatibility. + String[] list = ids.toArray(new String[ids.size()]); + Arrays.sort(list); + return list; } public static ZoneInfo getZoneInfo(String zoneId) { diff --git a/jdk/test/sun/util/calendar/zi/TestZoneInfo310.java b/jdk/test/sun/util/calendar/zi/TestZoneInfo310.java index c9e2bd9e6f7..f1191c6e90c 100644 --- a/jdk/test/sun/util/calendar/zi/TestZoneInfo310.java +++ b/jdk/test/sun/util/calendar/zi/TestZoneInfo310.java @@ -23,7 +23,7 @@ /* *@test - *@bug 8007572 + *@bug 8007572 8008161 *@summary Test whether the TimeZone generated from JSR310 tzdb is the same *as the one from the tz data from javazic */ @@ -156,6 +156,24 @@ public class TestZoneInfo310 { sun.util.calendar.ZoneInfoFile.getVersion(), ver); throw new RuntimeException("Version test failed"); } + + // test getAvailableIDs(raw); + zids_new = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000); + //Arrays.sort(zids_new); + zids_old = ZoneInfoOld.getAvailableIDs(-8 * 60 * 60 * 1000); + if (!Arrays.equals(zids_new, zids_old)) { + System.out.println("------------------------"); + System.out.println("NEW.getAvailableIDs(-8:00)"); + for (String zid : zids_new) { + System.out.println(zid); + } + System.out.println("------------------------"); + System.out.println("OLD.getAvailableIDs(-8:00)"); + for (String zid : zids_old) { + System.out.println(zid); + } + throw new RuntimeException(" FAILED: availableIds(offset) don't match"); + } } private static void delete(File f) { From 4c2a4c9b4addb83531c2b781bb52ff7861922368 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Wed, 13 Feb 2013 12:56:46 -0800 Subject: [PATCH 152/158] 8005750: [parfait] Memory leak at jdk/src/share/bin/parse_manifest.c Reviewed-by: jjh --- jdk/src/share/bin/parse_manifest.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/bin/parse_manifest.c b/jdk/src/share/bin/parse_manifest.c index 61c5b883081..61b0bbf4884 100644 --- a/jdk/src/share/bin/parse_manifest.c +++ b/jdk/src/share/bin/parse_manifest.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -106,8 +106,9 @@ inflate_file(int fd, zentry *entry, int *size_out) *size_out = (int)entry->isize; } return (out); - } else - return (NULL); + } + free(in); + return (NULL); } static jboolean zip64_present = JNI_FALSE; From db31a896d88bc059633fc521ebdfebdd7df9a596 Mon Sep 17 00:00:00 2001 From: Bharadwaj Yadavalli Date: Wed, 13 Feb 2013 16:09:13 -0500 Subject: [PATCH 153/158] 8007888: jdk fix default method: VerifyError: Illegal use of nonvirtual Recognize VM generated method in old verifier. With 8004967 Reviewed-by: coleenp, acorn --- jdk/src/share/javavm/export/jvm.h | 7 +++++++ jdk/src/share/native/common/check_code.c | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/javavm/export/jvm.h b/jdk/src/share/javavm/export/jvm.h index 1f785f1a108..44b0be576d4 100644 --- a/jdk/src/share/javavm/export/jvm.h +++ b/jdk/src/share/javavm/export/jvm.h @@ -821,6 +821,13 @@ JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cb, int index); JNIEXPORT jboolean JNICALL JVM_IsConstructorIx(JNIEnv *env, jclass cb, int index); +/* + * Is the given method generated by the VM. + * The method is identified by method_index. + */ +JNIEXPORT jboolean JNICALL +JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cb, int index); + /* * Returns the name of a given method in UTF format. * The result remains valid until JVM_ReleaseUTF is called. diff --git a/jdk/src/share/native/common/check_code.c b/jdk/src/share/native/common/check_code.c index c5e8855ee68..c761a3d9158 100644 --- a/jdk/src/share/native/common/check_code.c +++ b/jdk/src/share/native/common/check_code.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, 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 @@ -983,6 +983,12 @@ verify_method(context_type *context, jclass cb, int method_index, CCerror(context, "Inconsistent access bits."); } + // If this method is an overpass method, which is generated by the VM, + // we trust the code and no check needs to be done. + if (JVM_IsVMGeneratedMethodIx(env, cb, method_index)) { + return; + } + /* Run through the code. Mark the start of each instruction, and give * the instruction a number */ for (i = 0, offset = 0; offset < code_length; i++) { From ba9cf66b4823464b0e2ec9207b0bf5c7d3179ff5 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Wed, 13 Feb 2013 13:22:31 -0800 Subject: [PATCH 154/158] 8007935: java/lang/instrument/RedefineSubclassWithTwoInterfaces.sh should use $COMPILEJAVA for javac Reviewed-by: sspitsyn, alanb --- .../instrument/RedefineSubclassWithTwoInterfaces.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfaces.sh b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfaces.sh index 8e1c81f3c17..6deb7ce6e44 100644 --- a/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfaces.sh +++ b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfaces.sh @@ -23,6 +23,7 @@ # @test # @bug 7182152 +# @bug 8007935 # @summary Redefine a subclass that implements two interfaces and # verify that the right methods are called. # @author Daniel D. Daugherty @@ -38,6 +39,12 @@ then exit 1 fi +if [ "${COMPILEJAVA}" = "" ] +then + COMPILEJAVA="${TESTJAVA}" +fi +echo "COMPILEJAVA=${COMPILEJAVA}" + if [ "${TESTSRC}" = "" ] then echo "TESTSRC not set. Test cannot execute. Failed." @@ -50,7 +57,7 @@ then exit 1 fi -JAVAC="${TESTJAVA}"/bin/javac +JAVAC="${COMPILEJAVA}"/bin/javac JAVA="${TESTJAVA}"/bin/java echo "INFO: building the replacement classes." @@ -59,7 +66,8 @@ cp "${TESTSRC}"/RedefineSubclassWithTwoInterfacesTarget_1.java \ RedefineSubclassWithTwoInterfacesTarget.java cp "${TESTSRC}"/RedefineSubclassWithTwoInterfacesImpl_1.java \ RedefineSubclassWithTwoInterfacesImpl.java -"${JAVAC}" -cp "${TESTCLASSES}" -d . \ +"${JAVAC}" ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \ + -cp "${TESTCLASSES}" -d . \ RedefineSubclassWithTwoInterfacesTarget.java \ RedefineSubclassWithTwoInterfacesImpl.java status="$?" From 20987e6144293bd6be3e3be2e852a48cc7b16f70 Mon Sep 17 00:00:00 2001 From: Jia-Hong Chen Date: Wed, 13 Feb 2013 15:06:47 -0800 Subject: [PATCH 155/158] 8008017: The fix for 8005129 does not build on Windows Reviewed-by: prr, jgodinez --- jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_16ext.c | 4 ++-- jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_16nw.c | 4 ++-- jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_8ext.c | 4 ++-- jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_8nw.c | 4 ++-- jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_u16ext.c | 4 ++-- jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_u16nw.c | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_16ext.c b/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_16ext.c index 845f9a56a22..70f3831bcc2 100644 --- a/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_16ext.c +++ b/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_16ext.c @@ -1884,10 +1884,10 @@ mlib_status CONV_FUNC_MxN mlib_s32 nchannel, chan1, chan2; mlib_s32 i, j, c, swid; d64_2x32 dd; - GET_SRC_DST_PARAMETERS(DTYPE); - mlib_status status = MLIB_SUCCESS; + GET_SRC_DST_PARAMETERS(DTYPE); + if (scale > 30) { fscale *= 1.0/(1 << 30); scale -= 30; diff --git a/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_16nw.c b/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_16nw.c index 57dbca4c848..7fc3d5e0464 100644 --- a/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_16nw.c +++ b/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_16nw.c @@ -1651,10 +1651,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, DEF_VARS(DTYPE); mlib_s32 chan2; mlib_s32 *buffo, *buffi; - GET_SRC_DST_PARAMETERS(DTYPE); - mlib_status status = MLIB_SUCCESS; + GET_SRC_DST_PARAMETERS(DTYPE); + if (scale > 30) { fscale *= 1.0/(1 << 30); scale -= 30; diff --git a/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_8ext.c b/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_8ext.c index 961ade907b0..1ca321e1237 100644 --- a/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_8ext.c +++ b/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_8ext.c @@ -1884,10 +1884,10 @@ mlib_status CONV_FUNC_MxN mlib_s32 nchannel, chan1, chan2; mlib_s32 i, j, c, swid; d64_2x32 dd; - GET_SRC_DST_PARAMETERS(DTYPE); - mlib_status status = MLIB_SUCCESS; + GET_SRC_DST_PARAMETERS(DTYPE); + if (scale > 30) { fscale *= 1.0/(1 << 30); scale -= 30; diff --git a/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_8nw.c b/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_8nw.c index 1f94eabba66..5c4de68db69 100644 --- a/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_8nw.c +++ b/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_8nw.c @@ -1652,10 +1652,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, DEF_VARS(DTYPE); mlib_s32 chan2; mlib_s32 *buffo, *buffi; - GET_SRC_DST_PARAMETERS(DTYPE); - mlib_status status = MLIB_SUCCESS; + GET_SRC_DST_PARAMETERS(DTYPE); + if (scale > 30) { fscale *= 1.0/(1 << 30); scale -= 30; diff --git a/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_u16ext.c b/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_u16ext.c index 9fb835c83fe..0369f57b250 100644 --- a/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_u16ext.c +++ b/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_u16ext.c @@ -1884,10 +1884,10 @@ mlib_status CONV_FUNC_MxN mlib_s32 nchannel, chan1, chan2; mlib_s32 i, j, c, swid; d64_2x32 dd; - GET_SRC_DST_PARAMETERS(DTYPE); - mlib_status status = MLIB_SUCCESS; + GET_SRC_DST_PARAMETERS(DTYPE); + if (scale > 30) { fscale *= 1.0/(1 << 30); scale -= 30; diff --git a/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_u16nw.c b/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_u16nw.c index 68578a27af9..fe159095545 100644 --- a/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_u16nw.c +++ b/jdk/src/share/native/sun/awt/medialib/mlib_ImageConv_u16nw.c @@ -1651,10 +1651,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, DEF_VARS(DTYPE); mlib_s32 chan2; mlib_s32 *buffo, *buffi; - GET_SRC_DST_PARAMETERS(DTYPE); - mlib_status status = MLIB_SUCCESS; + GET_SRC_DST_PARAMETERS(DTYPE); + if (scale > 30) { fscale *= 1.0/(1 << 30); scale -= 30; From 828d2063d29152bedaf9f4f53aa1c851b979e6ba Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 18:38:33 +0200 Subject: [PATCH 156/158] Added tag jdk8-b75 for changeset f1478a6d25fd --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 261cb1ea200..54784e72850 100644 --- a/.hgtags +++ b/.hgtags @@ -196,3 +196,4 @@ a41ada2ed4ef735449531c6ebe6cec593d890a1c jdk8-b71 6725b3961f987cf40f446d1c11cd324a3bec545f jdk8-b72 fe94b40ffd9390f6cffcdf51c0389b0e6dde0c13 jdk8-b73 f627eff819628822a0777af8062244352f2a29cf jdk8-b74 +f1478a6d25fddd311a84dcbfac50824cc1858bdd jdk8-b75 From 918f015f183b159968b360ca0308c78d9cc2c454 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 18:39:14 +0200 Subject: [PATCH 157/158] Added tag jdk8-b76 for changeset f407160c280d --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 54784e72850..602ce40b2cb 100644 --- a/.hgtags +++ b/.hgtags @@ -197,3 +197,4 @@ a41ada2ed4ef735449531c6ebe6cec593d890a1c jdk8-b71 fe94b40ffd9390f6cffcdf51c0389b0e6dde0c13 jdk8-b73 f627eff819628822a0777af8062244352f2a29cf jdk8-b74 f1478a6d25fddd311a84dcbfac50824cc1858bdd jdk8-b75 +f407160c280d1c5b00d314c535441ac26f195fee jdk8-b76 From 14251d648086938593a96e80d3dc7dde2af5a192 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 14 Feb 2013 11:44:09 -0800 Subject: [PATCH 158/158] Added tag jdk8-b77 for changeset e587650e9aa6 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index ea4808559e0..6622885bcd8 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -198,3 +198,4 @@ a996b57e554198f4592a5f3c30f2f9f4075e545d jdk8-b70 57d5d954462831ac353a1f40d3bb05ddb4620952 jdk8-b74 4a67fdb752b7d6329d9be9c28d3f9d6cf7eb9a3c jdk8-b75 3a263052866137b645ab86498a43693ff5c19e69 jdk8-b76 +b2fc8e31cecc35b76188e821d4c5dc0e0b74ac24 jdk8-b77

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ + +public class DPrinter { + protected final PrintWriter out; + protected final Trees trees; + protected Printer printer; + protected boolean showEmptyItems = true; + protected boolean showNulls = true; + protected boolean showPositions = false; + protected boolean showSrc; + protected boolean showTreeSymbols; + protected boolean showTreeTypes; + protected int maxSrcLength = 32; + protected Locale locale = Locale.getDefault(); + protected static final String NULL = "#null"; + + // + + public static DPrinter instance(Context context) { + DPrinter dp = context.get(DPrinter.class); + if (dp == null) { + dp = new DPrinter(context); + } + return dp; + + } + + protected DPrinter(Context context) { + context.put(DPrinter.class, this); + out = context.get(Log.outKey); + trees = JavacTrees.instance(context); + } + + public DPrinter(PrintWriter out, Trees trees) { + this.out = out; + this.trees = trees; + } + + public DPrinter emptyItems(boolean showEmptyItems) { + this.showEmptyItems = showEmptyItems; + return this; + } + + public DPrinter nulls(boolean showNulls) { + this.showNulls = showNulls; + return this; + } + + public DPrinter positions(boolean showPositions) { + this.showPositions = showPositions; + return this; + } + + public DPrinter source(boolean showSrc) { + this.showSrc = showSrc; + return this; + } + + public DPrinter source(int maxSrcLength) { + this.showSrc = true; + this.maxSrcLength = maxSrcLength; + return this; + } + + public DPrinter treeSymbols(boolean showTreeSymbols) { + this.showTreeSymbols = showTreeSymbols; + return this; + } + + public DPrinter treeTypes(boolean showTreeTypes) { + this.showTreeTypes = showTreeTypes; + return this; + } + + public DPrinter typeSymbolPrinter(Printer p) { + printer = p; + return this; + } + + // + + // + + protected enum Details { + /** A one-line non-recursive summary */ + SUMMARY, + /** Multi-line, possibly recursive. */ + FULL + }; + + public void printAnnotations(String label, Annotations annotations) { + printAnnotations(label, annotations, Details.FULL); + } + + protected void printAnnotations(String label, Annotations annotations, Details details) { + if (annotations == null) { + printNull(label); + } else { + // no SUMMARY format currently available to use + + // use reflection to get at private fields + Object DECL_NOT_STARTED = getField(null, Annotations.class, "DECL_NOT_STARTED"); + Object DECL_IN_PROGRESS = getField(null, Annotations.class, "DECL_IN_PROGRESS"); + Object attributes = getField(annotations, Annotations.class, "attributes"); + Object type_attributes = getField(annotations, Annotations.class, "type_attributes"); + + if (!showEmptyItems) { + if (attributes instanceof List && ((List) attributes).isEmpty() + && attributes != DECL_NOT_STARTED + && attributes != DECL_IN_PROGRESS + && type_attributes instanceof List && ((List) type_attributes).isEmpty()) + return; + } + + printString(label, ""); + + indent(+1); + if (attributes == DECL_NOT_STARTED) + printString("attributes", "DECL_NOT_STARTED"); + else if (attributes == DECL_IN_PROGRESS) + printString("attributes", "DECL_IN_PROGRESS"); + else if (attributes instanceof List) + printList("attributes", (List) attributes); + else + printObject("attributes", attributes, Details.SUMMARY); + + if (attributes instanceof List) + printList("type_attributes", (List) type_attributes); + else + printObject("type_attributes", type_attributes, Details.SUMMARY); + indent(-1); + } + } + + public void printAttribute(String label, Attribute attr) { + if (attr == null) { + printNull(label); + } else { + printString(label, attr.getClass().getSimpleName()); + + indent(+1); + attr.accept(attrVisitor); + indent(-1); + } + } + + public void printFileObject(String label, FileObject fo) { + if (fo == null) { + printNull(label); + } else { + printString(label, fo.getName()); + } + } + + protected void printImplClass(T item, Class stdImplClass) { + if (item.getClass() != stdImplClass) + printString("impl", item.getClass().getName()); + } + + public void printInt(String label, int i) { + printString(label, String.valueOf(i)); + } + + public void printList(String label, List list) { + if (list == null) { + printNull(label); + } else if (!list.isEmpty() || showEmptyItems) { + printString(label, "[" + list.size() + "]"); + + indent(+1); + int i = 0; + for (Object item: list) { + printObject(String.valueOf(i++), item, Details.FULL); + } + indent(-1); + } + } + + public void printName(String label, Name name) { + if (name == null) { + printNull(label); + } else { + printString(label, name.toString()); + } + } + + public void printNull(String label) { + if (showNulls) + printString(label, NULL); + } + + protected void printObject(String label, Object item, Details details) { + if (item == null) { + printNull(label); + } else if (item instanceof Attribute) { + printAttribute(label, (Attribute) item); + } else if (item instanceof Symbol) { + printSymbol(label, (Symbol) item, details); + } else if (item instanceof Type) { + printType(label, (Type) item, details); + } else if (item instanceof JCTree) { + printTree(label, (JCTree) item); + } else if (item instanceof List) { + printList(label, (List) item); + } else if (item instanceof Name) { + printName(label, (Name) item); + } else { + printString(label, String.valueOf(item)); + } + } + + public void printScope(String label, Scope scope) { + printScope(label, scope, Details.FULL); + } + + public void printScope(String label, Scope scope, Details details) { + if (scope == null) { + printNull(label); + } else { + switch (details) { + case SUMMARY: { + indent(); + out.print(label); + out.print(": ["); + String sep = ""; + for (Symbol sym: scope.getElements()) { + out.print(sep); + out.print(sym.name); + sep = ","; + } + out.println("]"); + break; + } + + case FULL: { + indent(); + out.println(label); + + indent(+1); + printImplClass(scope, Scope.class); + printSymbol("owner", scope.owner, Details.SUMMARY); + printScope("next", scope.next, Details.SUMMARY); + printObject("shared", getField(scope, Scope.class, "shared"), Details.SUMMARY); + if (scope instanceof CompoundScope) { + printObject("subScopes", + getField(scope, CompoundScope.class, "subScopes"), + Details.FULL); + } else { + for (Symbol sym : scope.getElements()) { + printSymbol(sym.name.toString(), sym, Details.SUMMARY); + } + } + indent(-1); + break; + } + } + } + } + + public void printSource(String label, JCTree tree) { + printString(label, Pretty.toSimpleString(tree, maxSrcLength)); + } + + public void printString(String label, String text) { + indent(); + out.print(label); + out.print(": "); + out.print(text); + out.println(); + } + + public void printSymbol(String label, Symbol symbol) { + printSymbol(label, symbol, Details.FULL); + } + + protected void printSymbol(String label, Symbol sym, Details details) { + if (sym == null) { + printNull(label); + } else { + switch (details) { + case SUMMARY: + printString(label, toString(sym)); + break; + + case FULL: + indent(); + out.print(label); + out.println(": " + String.format("0x%x", sym.kind) + + "--" + Kinds.kindName(sym).name() + + " " + sym.getKind() + + " " + sym.name + + " " + String.format("#%x", sym.hashCode())); + + indent(+1); + if (showSrc) { + JCTree tree = (JCTree) trees.getTree(sym); + if (tree != null) + printSource("src", tree); + } + printString("flags", String.format("0x%x--%s", + sym.flags_field, Flags.toString(sym.flags_field))); + printObject("completer", sym.completer, Details.SUMMARY); // what if too long? + printSymbol("owner", sym.owner, Details.SUMMARY); + printType("type", sym.type, Details.SUMMARY); + printType("erasure", sym.erasure_field, Details.SUMMARY); + sym.accept(symVisitor, true); + printAnnotations("annotations", sym.annotations, Details.SUMMARY); + indent(-1); + } + } + } + + protected String toString(Symbol sym) { + return (printer != null) ? printer.visit(sym, locale) : String.valueOf(sym); + } + + protected void printTree(String label, JCTree tree) { + if (tree == null) { + printNull(label); + } else { + indent(); + out.print(label + ": " + tree.getTag()); + if (showPositions) { + // We can always get start position, but to get end position + // and/or line+offset, we would need a JCCompilationUnit + out.print(" pos:" + tree.pos); + } + if (showTreeTypes && tree.type != null) + out.print(" type:" + toString(tree.type)); + Symbol sym; + if (showTreeSymbols && (sym = TreeInfo.symbolFor(tree)) != null) + out.print(" sym:" + toString(sym)); + out.println(); + + indent(+1); + if (showSrc) { + indent(); + out.println("src: " + Pretty.toSimpleString(tree, maxSrcLength)); + } + tree.accept(treeVisitor); + indent(-1); + } + } + + public void printType(String label, Type type) { + printType(label, type, Details.FULL); + } + + protected void printType(String label, Type type, Details details) { + if (type == null) + printNull(label); + else { + switch (details) { + case SUMMARY: + printString(label, toString(type)); + break; + + case FULL: + indent(); + out.print(label); + out.println(": " + type.getTag() + + " " + String.format("#%x", type.hashCode())); + + indent(+1); + printSymbol("tsym", type.tsym, Details.SUMMARY); + printObject("constValue", type.constValue(), Details.SUMMARY); + type.accept(typeVisitor, true); + indent(-1); + } + } + } + + protected String toString(Type type) { + return (printer != null) ? printer.visit(type, locale) : String.valueOf(type); + } + + private int indent = 0; + + protected void indent() { + for (int i = 0; i < indent; i++) { + out.print(" "); + } + } + + protected void indent(int n) { + indent += n; + } + + protected Object getField(Object o, Class clazz, String name) { + try { + Field f = clazz.getDeclaredField(name); + boolean prev = f.isAccessible(); + f.setAccessible(true); + try { + return f.get(o); + } finally { + f.setAccessible(prev); + } + } catch (ReflectiveOperationException e) { + return e; + } catch (SecurityException e) { + return e; + } + } + + // + + // + + protected JCTree.Visitor treeVisitor = new TreeVisitor(); + + /** + * Default visitor class for JCTree (AST) objects. + */ + public class TreeVisitor extends JCTree.Visitor { + @Override + public void visitTopLevel(JCCompilationUnit tree) { + printList("packageAnnotations", tree.packageAnnotations); + printTree("pid", tree.pid); + printList("defs", tree.defs); + } + + @Override + public void visitImport(JCImport tree) { + printTree("qualid", tree.qualid); + } + + @Override + public void visitClassDef(JCClassDecl tree) { + printName("name", tree.name); + printTree("mods", tree.mods); + printList("typarams", tree.typarams); + printTree("extending", tree.extending); + printList("implementing", tree.implementing); + printList("defs", tree.defs); + } + + @Override + public void visitMethodDef(JCMethodDecl tree) { + printName("name", tree.name); + printTree("mods", tree.mods); + printTree("restype", tree.restype); + printList("typarams", tree.typarams); + printTree("recvparam", tree.recvparam); + printList("params", tree.params); + printList("thrown", tree.thrown); + printTree("defaultValue", tree.defaultValue); + printTree("body", tree.body); + } + + @Override + public void visitVarDef(JCVariableDecl tree) { + printName("name", tree.name); + printTree("mods", tree.mods); + printTree("vartype", tree.vartype); + printTree("init", tree.init); + } + + @Override + public void visitSkip(JCSkip tree) { + } + + @Override + public void visitBlock(JCBlock tree) { + printList("stats", tree.stats); + } + + @Override + public void visitDoLoop(JCDoWhileLoop tree) { + printTree("body", tree.body); + printTree("cond", tree.cond); + } + + @Override + public void visitWhileLoop(JCWhileLoop tree) { + printTree("cond", tree.cond); + printTree("body", tree.body); + } + + @Override + public void visitForLoop(JCForLoop tree) { + printList("init", tree.init); + printTree("cond", tree.cond); + printList("step", tree.step); + printTree("body", tree.body); + } + + @Override + public void visitForeachLoop(JCEnhancedForLoop tree) { + printTree("var", tree.var); + printTree("expr", tree.expr); + printTree("body", tree.body); + } + + @Override + public void visitLabelled(JCLabeledStatement tree) { + printTree("body", tree.body); + } + + @Override + public void visitSwitch(JCSwitch tree) { + printTree("selector", tree.selector); + printList("cases", tree.cases); + } + + @Override + public void visitCase(JCCase tree) { + printTree("pat", tree.pat); + printList("stats", tree.stats); + } + + @Override + public void visitSynchronized(JCSynchronized tree) { + printTree("lock", tree.lock); + printTree("body", tree.body); + } + + @Override + public void visitTry(JCTry tree) { + printList("resources", tree.resources); + printTree("body", tree.body); + printList("catchers", tree.catchers); + printTree("finalizer", tree.finalizer); + } + + @Override + public void visitCatch(JCCatch tree) { + printTree("param", tree.param); + printTree("body", tree.body); + } + + @Override + public void visitConditional(JCConditional tree) { + printTree("cond", tree.cond); + printTree("truepart", tree.truepart); + printTree("falsepart", tree.falsepart); + } + + @Override + public void visitIf(JCIf tree) { + printTree("cond", tree.cond); + printTree("thenpart", tree.thenpart); + printTree("elsepart", tree.elsepart); + } + + @Override + public void visitExec(JCExpressionStatement tree) { + printTree("expr", tree.expr); + } + + @Override + public void visitBreak(JCBreak tree) { + printName("label", tree.label); + } + + @Override + public void visitContinue(JCContinue tree) { + printName("label", tree.label); + } + + @Override + public void visitReturn(JCReturn tree) { + printTree("expr", tree.expr); + } + + @Override + public void visitThrow(JCThrow tree) { + printTree("expr", tree.expr); + } + + @Override + public void visitAssert(JCAssert tree) { + printTree("cond", tree.cond); + printTree("detail", tree.detail); + } + + @Override + public void visitApply(JCMethodInvocation tree) { + printList("typeargs", tree.typeargs); + printTree("meth", tree.meth); + printList("args", tree.args); + } + + @Override + public void visitNewClass(JCNewClass tree) { + printTree("encl", tree.encl); + printList("typeargs", tree.typeargs); + printTree("clazz", tree.clazz); + printList("args", tree.args); + printTree("def", tree.def); + } + + @Override + public void visitNewArray(JCNewArray tree) { + printList("annotations", tree.annotations); + printTree("elemtype", tree.elemtype); + printList("dims", tree.dims); + printList("dimAnnotations", tree.dimAnnotations); + printList("elems", tree.elems); + } + + @Override + public void visitLambda(JCLambda tree) { + printTree("body", tree.body); + printList("params", tree.params); + } + + @Override + public void visitParens(JCParens tree) { + printTree("expr", tree.expr); + } + + @Override + public void visitAssign(JCAssign tree) { + printTree("lhs", tree.lhs); + printTree("rhs", tree.rhs); + } + + @Override + public void visitAssignop(JCAssignOp tree) { + printTree("lhs", tree.lhs); + printTree("rhs", tree.rhs); + } + + @Override + public void visitUnary(JCUnary tree) { + printTree("arg", tree.arg); + } + + @Override + public void visitBinary(JCBinary tree) { + printTree("lhs", tree.lhs); + printTree("rhs", tree.rhs); + } + + @Override + public void visitTypeCast(JCTypeCast tree) { + printTree("clazz", tree.clazz); + printTree("expr", tree.expr); + } + + @Override + public void visitTypeTest(JCInstanceOf tree) { + printTree("expr", tree.expr); + printTree("clazz", tree.clazz); + } + + @Override + public void visitIndexed(JCArrayAccess tree) { + printTree("indexed", tree.indexed); + printTree("index", tree.index); + } + + @Override + public void visitSelect(JCFieldAccess tree) { + printTree("selected", tree.selected); + } + + @Override + public void visitReference(JCMemberReference tree) { + printTree("expr", tree.expr); + printList("typeargs", tree.typeargs); + } + + @Override + public void visitIdent(JCIdent tree) { + printName("name", tree.name); + } + + @Override + public void visitLiteral(JCLiteral tree) { + printString("value", Pretty.toSimpleString(tree, 32)); + } + + @Override + public void visitTypeIdent(JCPrimitiveTypeTree tree) { + printString("typetag", tree.typetag.name()); + } + + @Override + public void visitTypeArray(JCArrayTypeTree tree) { + printTree("elemtype", tree.elemtype); + } + + @Override + public void visitTypeApply(JCTypeApply tree) { + printTree("clazz", tree.clazz); + printList("arguments", tree.arguments); + } + + @Override + public void visitTypeUnion(JCTypeUnion tree) { + printList("alternatives", tree.alternatives); + } + + @Override + public void visitTypeIntersection(JCTypeIntersection tree) { + printList("bounds", tree.bounds); + } + + @Override + public void visitTypeParameter(JCTypeParameter tree) { + printName("name", tree.name); + printList("annotations", tree.annotations); + printList("bounds", tree.bounds); + } + + @Override + public void visitWildcard(JCWildcard tree) { + printTree("kind", tree.kind); + printTree("inner", tree.inner); + } + + @Override + public void visitTypeBoundKind(TypeBoundKind tree) { + printString("kind", tree.kind.name()); + } + + @Override + public void visitModifiers(JCModifiers tree) { + printList("annotations", tree.annotations); + printString("flags", String.valueOf(Flags.asFlagSet(tree.flags))); + } + + @Override + public void visitAnnotation(JCAnnotation tree) { + printTree("annotationType", tree.annotationType); + printList("args", tree.args); + } + + @Override + public void visitAnnotatedType(JCAnnotatedType tree) { + printList("annotations", tree.annotations); + printTree("underlyingType", tree.underlyingType); + } + + @Override + public void visitErroneous(JCErroneous tree) { + printList("errs", tree.errs); + } + + @Override + public void visitLetExpr(LetExpr tree) { + printList("defs", tree.defs); + printTree("expr", tree.expr); + } + + @Override + public void visitTree(JCTree tree) { + Assert.error(); + } + } + + // + + // + + protected Symbol.Visitor symVisitor = new SymbolVisitor(); + + /** + * Default visitor class for Symbol objects. + * Note: each visitXYZ method ends by calling the corresponding + * visit method for its superclass. + */ + class SymbolVisitor implements Symbol.Visitor { + @Override + public Void visitClassSymbol(ClassSymbol sym, Boolean impl) { + if (impl) printImplClass(sym, ClassSymbol.class); + printName("fullname", sym.fullname); + printName("flatname", sym.flatname); + printScope("members", sym.members_field); + printFileObject("sourcefile", sym.sourcefile); + printFileObject("classfile", sym.classfile); + // trans-local? + // pool? + return visitTypeSymbol(sym, false); + } + + @Override + public Void visitMethodSymbol(MethodSymbol sym, Boolean impl) { + if (impl) printImplClass(sym, MethodSymbol.class); + // code + printList("params", sym.params); + printList("savedParameterNames", sym.savedParameterNames); + return visitSymbol(sym, false); + } + + @Override + public Void visitPackageSymbol(PackageSymbol sym, Boolean impl) { + if (impl) printImplClass(sym, PackageSymbol.class); + printName("fullname", sym.fullname); + printScope("members", sym.members_field); + printSymbol("package-info", sym.package_info, Details.SUMMARY); + return visitTypeSymbol(sym, false); + } + + @Override + public Void visitOperatorSymbol(OperatorSymbol sym, Boolean impl) { + if (impl) printImplClass(sym, OperatorSymbol.class); + printInt("opcode", sym.opcode); + return visitMethodSymbol(sym, false); + } + + @Override + public Void visitVarSymbol(VarSymbol sym, Boolean impl) { + if (impl) printImplClass(sym, VarSymbol.class); + printInt("pos", sym.pos); + printInt("adm", sym.adr); + // data is a private field, and the standard accessors may + // mutate it as part of lazy evaluation. Therefore, use + // reflection to get the raw data. + printObject("data", getField(sym, VarSymbol.class, "data"), Details.SUMMARY); + return visitSymbol(sym, false); + } + + @Override + public Void visitTypeSymbol(TypeSymbol sym, Boolean impl) { + if (impl) printImplClass(sym, TypeSymbol.class); + return visitSymbol(sym, false); + } + + @Override + public Void visitSymbol(Symbol sym, Boolean impl) { + if (impl) printImplClass(sym, Symbol.class); + return null; + } + } + + // + + // + + protected Type.Visitor typeVisitor = new TypeVisitor(); + + /** + * Default visitor class for Type objects. + * Note: each visitXYZ method ends by calling the corresponding + * visit method for its superclass. + */ + public class TypeVisitor implements Type.Visitor { + public Void visitAnnotatedType(AnnotatedType type, Boolean impl) { + if (impl) printImplClass(type, AnnotatedType.class); + printList("typeAnnotations", type.typeAnnotations); + printType("underlyingType", type.underlyingType, Details.FULL); + return visitType(type, false); + } + + public Void visitArrayType(ArrayType type, Boolean impl) { + if (impl) printImplClass(type, ArrayType.class); + printType("elemType", type.elemtype, Details.FULL); + return visitType(type, false); + } + + public Void visitCapturedType(CapturedType type, Boolean impl) { + if (impl) printImplClass(type, CapturedType.class); + printType("wildcard", type.wildcard, Details.FULL); + return visitTypeVar(type, false); + } + + public Void visitClassType(ClassType type, Boolean impl) { + if (impl) printImplClass(type, ClassType.class); + printType("outer", type.getEnclosingType(), Details.SUMMARY); + printList("typarams", type.typarams_field); + printList("allparams", type.allparams_field); + printType("supertype", type.supertype_field, Details.SUMMARY); + printList("interfaces", type.interfaces_field); + printList("allinterfaces", type.all_interfaces_field); + return visitType(type, false); + } + + public Void visitErrorType(ErrorType type, Boolean impl) { + if (impl) printImplClass(type, ErrorType.class); + printType("originalType", type.getOriginalType(), Details.FULL); + return visitClassType(type, false); + } + + public Void visitForAll(ForAll type, Boolean impl) { + if (impl) printImplClass(type, ForAll.class); + printList("tvars", type.tvars); + return visitDelegatedType(type); + } + + public Void visitMethodType(MethodType type, Boolean impl) { + if (impl) printImplClass(type, MethodType.class); + printList("argtypes", type.argtypes); + printType("restype", type.restype, Details.FULL); + printList("thrown", type.thrown); + return visitType(type, false); + } + + public Void visitPackageType(PackageType type, Boolean impl) { + if (impl) printImplClass(type, PackageType.class); + return visitType(type, false); + } + + public Void visitTypeVar(TypeVar type, Boolean impl) { + if (impl) printImplClass(type, TypeVar.class); + // For TypeVars (and not subtypes), the bound should always be + // null or bot. So, only print the bound for subtypes of TypeVar, + // or if the bound is (erroneously) not null or bot. + if (!type.hasTag(TypeTag.TYPEVAR) + || !(type.bound == null || type.bound.hasTag(TypeTag.BOT))) { + printType("bound", type.bound, Details.FULL); + } + printType("lower", type.lower, Details.FULL); + return visitType(type, false); + } + + public Void visitUndetVar(UndetVar type, Boolean impl) { + if (impl) printImplClass(type, UndetVar.class); + for (UndetVar.InferenceBound ib: UndetVar.InferenceBound.values()) + printList("bounds." + ib, type.getBounds(ib)); + printType("inst", type.inst, Details.SUMMARY); + return visitDelegatedType(type); + } + + public Void visitWildcardType(WildcardType type, Boolean impl) { + if (impl) printImplClass(type, WildcardType.class); + printType("type", type.type, Details.SUMMARY); + printString("kind", type.kind.name()); + printType("bound", type.bound, Details.SUMMARY); + return visitType(type, false); + } + + protected Void visitDelegatedType(DelegatedType type) { + printType("qtype", type.qtype, Details.FULL); + return visitType(type, false); + } + + public Void visitType(Type type, Boolean impl) { + if (impl) printImplClass(type, Type.class); + return null; + } + } + + // + + // + + protected Attribute.Visitor attrVisitor = new AttributeVisitor(); + + /** + * Default visitor class for Attribute (annotation) objects. + */ + public class AttributeVisitor implements Attribute.Visitor { + + public void visitConstant(Attribute.Constant a) { + printObject("value", a.value, Details.SUMMARY); + visitAttribute(a); + } + + public void visitClass(Attribute.Class a) { + printObject("classType", a.classType, Details.SUMMARY); + visitAttribute(a); + } + + public void visitCompound(Attribute.Compound a) { + if (a instanceof Attribute.TypeCompound) { + Attribute.TypeCompound ta = (Attribute.TypeCompound) a; + // consider a custom printer? + printObject("position", ta.position, Details.SUMMARY); + } + printObject("synthesized", a.isSynthesized(), Details.SUMMARY); + printList("values", a.values); + visitAttribute(a); + } + + public void visitArray(Attribute.Array a) { + printList("values", Arrays.asList(a.values)); + visitAttribute(a); + } + + public void visitEnum(Attribute.Enum a) { + printSymbol("value", a.value, Details.SUMMARY); + visitAttribute(a); + } + + public void visitError(Attribute.Error a) { + visitAttribute(a); + } + + public void visitAttribute(Attribute a) { + printType("type", a.type, Details.SUMMARY); + } + + } + // + + // + + /** + * Utility class to invoke DPrinter from the command line. + */ + static class Main { + public static void main(String... args) throws IOException { + PrintWriter out = new PrintWriter(System.out); + try { + if (args.length == 0) + usage(out); + else + new Main().run(out, args); + } finally { + out.flush(); + } + } + + static void usage(PrintWriter out) { + out.println("Usage:"); + out.println(" java " + Main.class.getName() + " mode [options] [javac-options]"); + out.println("where options include:"); + out.println(" -before PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); + out.println(" -after PARSE|ENTER|ANALYZE|GENERATE|ANNOTATION_PROCESSING|ANNOTATION_PROCESSING_ROUND"); + out.println(" -showPositions"); + out.println(" -showSource"); + out.println(" -showTreeSymbols"); + out.println(" -showTreeTypes"); + out.println(" -hideEmptyItems"); + out.println(" -hideNulls"); + } + + void run(PrintWriter out, String... args) throws IOException { + JavaCompiler c = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fm = c.getStandardFileManager(null, null, null); + + // DPrinter options + final Set before = EnumSet.noneOf(TaskEvent.Kind.class); + final Set after = EnumSet.noneOf(TaskEvent.Kind.class); + boolean showPositions = false; + boolean showSource = false; + boolean showTreeSymbols = false; + boolean showTreeTypes = false; + boolean showEmptyItems = true; + boolean showNulls = true; + + // javac options + Collection options = new ArrayList(); + Collection files = new ArrayList(); + String classpath = null; + String classoutdir = null; + + final Handler h = getHandlers().get(args[0]); + if (h == null) + throw new IllegalArgumentException(args[0]); + + for (int i = 1; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("-before") && i + 1 < args.length) { + before.add(getKind(args[++i])); + } else if (arg.equals("-after") && i + 1 < args.length) { + after.add(getKind(args[++i])); + } else if (arg.equals("-showPositions")) { + showPositions = true; + } else if (arg.equals("-showSource")) { + showSource = true; + } else if (arg.equals("-showTreeSymbols")) { + showTreeSymbols = true; + } else if (arg.equals("-showTreeTypes")) { + showTreeTypes = true; + } else if (arg.equals("-hideEmptyLists")) { + showEmptyItems = false; + } else if (arg.equals("-hideNulls")) { + showNulls = false; + } else if (arg.equals("-classpath") && i + 1 < args.length) { + classpath = args[++i]; + } else if (arg.equals("-d") && i + 1 < args.length) { + classoutdir = args[++i]; + } else if (arg.startsWith("-")) { + int n = c.isSupportedOption(arg); + if (n < 0) throw new IllegalArgumentException(arg); + options.add(arg); + while (n > 0) options.add(args[++i]); + } else if (arg.endsWith(".java")) { + files.add(new File(arg)); + } + } + + if (classoutdir != null) { + fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(classoutdir))); + } + + if (classpath != null) { + Collection path = new ArrayList(); + for (String p: classpath.split(File.pathSeparator)) { + if (p.isEmpty()) continue; + File f = new File(p); + if (f.exists()) path.add(f); + } + fm.setLocation(StandardLocation.CLASS_PATH, path); + } + Iterable fos = fm.getJavaFileObjectsFromFiles(files); + + JavacTask task = (JavacTask) c.getTask(out, fm, null, options, null, fos); + final Trees trees = Trees.instance(task); + + final DPrinter dprinter = new DPrinter(out, trees); + dprinter.source(showSource) + .emptyItems(showEmptyItems) + .nulls(showNulls) + .positions(showPositions) + .treeSymbols(showTreeSymbols) + .treeTypes(showTreeTypes); + + if (before.isEmpty() && after.isEmpty()) { + if (h.name.equals("trees") && !showTreeSymbols && !showTreeTypes) + after.add(TaskEvent.Kind.PARSE); + else + after.add(TaskEvent.Kind.ANALYZE); + } + + task.addTaskListener(new TaskListener() { + public void started(TaskEvent e) { + if (before.contains(e.getKind())) + handle(e); + } + + public void finished(TaskEvent e) { + if (after.contains(e.getKind())) + handle(e); + } + + private void handle(TaskEvent e) { + switch (e.getKind()) { + case PARSE: + case ENTER: + h.handle(e.getSourceFile().getName(), + (JCTree) e.getCompilationUnit(), + dprinter); + break; + + default: + TypeElement elem = e.getTypeElement(); + h.handle(elem.toString(), + (JCTree) trees.getTree(elem), + dprinter); + break; + } + } + }); + + task.call(); + } + + TaskEvent.Kind getKind(String s) { + return TaskEvent.Kind.valueOf(s.toUpperCase()); + } + + static protected abstract class Handler { + final String name; + Handler(String name) { + this.name = name; + } + abstract void handle(String label, JCTree tree, DPrinter dprinter); + } + + Map getHandlers() { + Map map = new HashMap(); + for (Handler h: defaultHandlers) { + map.put(h.name, h); + } + return map; + } + + protected final Handler[] defaultHandlers = { + new Handler("trees") { + @Override + void handle(String name, JCTree tree, DPrinter dprinter) { + dprinter.printTree(name, tree); + dprinter.out.println(); + } + }, + + new Handler("symbols") { + @Override + void handle(String name, JCTree tree, final DPrinter dprinter) { + TreeScanner ds = new TreeScanner() { + @Override + public void visitClassDef(JCClassDecl tree) { + visitDecl(tree, tree.sym); + super.visitClassDef(tree); + } + + @Override + public void visitMethodDef(JCMethodDecl tree) { + visitDecl(tree, tree.sym); + super.visitMethodDef(tree); + } + + @Override + public void visitVarDef(JCVariableDecl tree) { + visitDecl(tree, tree.sym); + super.visitVarDef(tree); + } + + void visitDecl(JCTree tree, Symbol sym) { + dprinter.printSymbol(sym.name.toString(), sym); + dprinter.out.println(); + } + }; + ds.scan(tree); + } + }, + + new Handler("types") { + @Override + void handle(String name, JCTree tree, final DPrinter dprinter) { + TreeScanner ts = new TreeScanner() { + @Override + public void scan(JCTree tree) { + if (tree == null) { + return; + } + if (tree.type != null) { + String label = Pretty.toSimpleString(tree); + dprinter.printType(label, tree.type); + dprinter.out.println(); + } + super.scan(tree); + } + }; + ts.scan(tree); + } + } + }; + } + + // + +} From 34e17268605994c714d5e02c25da4d5b37df96f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Borggr=C3=A9n-Franck?= Date: Thu, 31 Jan 2013 10:10:34 +0100 Subject: [PATCH 023/158] 8005712: Simplify support for repeating annotations in j.l.r.AnnotatedElement 8004919: AnnotationSupport uses possibly half-constructed AnnotationType instances Implements the simplified semantics for repeating annotations and removes the incorrect obtaining of an AnnotationType Reviewed-by: darcy, abuckley --- jdk/src/share/classes/java/lang/Class.java | 20 +-- jdk/src/share/classes/java/lang/System.java | 4 - .../java/lang/reflect/AnnotatedElement.java | 54 +++++-- .../classes/java/lang/reflect/Executable.java | 6 +- .../classes/java/lang/reflect/Field.java | 5 +- .../classes/java/lang/reflect/Parameter.java | 3 +- .../classes/sun/misc/JavaLangAccess.java | 5 - .../reflect/annotation/AnnotationSupport.java | 143 ++++-------------- .../RepeatedUnitTest.java | 23 ++- .../subpackage/Containee.java | 3 +- .../subpackage/Container.java | 3 +- .../subpackage/InheritedContainee.java | 3 +- .../subpackage/InheritedContainer.java | 3 +- 13 files changed, 98 insertions(+), 177 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index 87f78530899..31e2294ebf6 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -3075,11 +3075,12 @@ public final * @throws NullPointerException {@inheritDoc} * @since 1.5 */ + @SuppressWarnings("unchecked") public A getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); initAnnotationsIfNecessary(); - return AnnotationSupport.getOneAnnotation(annotations, annotationClass); + return (A) annotations.get(annotationClass); } /** @@ -3108,18 +3109,19 @@ public final */ public Annotation[] getAnnotations() { initAnnotationsIfNecessary(); - return AnnotationSupport.unpackToArray(annotations); + return AnnotationParser.toArray(annotations); } /** * @throws NullPointerException {@inheritDoc} * @since 1.8 */ + @SuppressWarnings("unchecked") public A getDeclaredAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); initAnnotationsIfNecessary(); - return AnnotationSupport.getOneAnnotation(declaredAnnotations, annotationClass); + return (A) declaredAnnotations.get(annotationClass); } /** @@ -3138,17 +3140,7 @@ public final */ public Annotation[] getDeclaredAnnotations() { initAnnotationsIfNecessary(); - return AnnotationSupport.unpackToArray(declaredAnnotations); - } - - /** Returns one "directly" present annotation or null */ - A getDirectDeclaredAnnotation(Class annotationClass) { - Objects.requireNonNull(annotationClass); - - initAnnotationsIfNecessary(); - @SuppressWarnings("unchecked") // TODO check safe - A ret = (A)declaredAnnotations.get(annotationClass); - return ret; + return AnnotationParser.toArray(declaredAnnotations); } // Annotations cache diff --git a/jdk/src/share/classes/java/lang/System.java b/jdk/src/share/classes/java/lang/System.java index d901e992b9a..45ea7190ae8 100644 --- a/jdk/src/share/classes/java/lang/System.java +++ b/jdk/src/share/classes/java/lang/System.java @@ -25,7 +25,6 @@ package java.lang; import java.io.*; -import java.lang.annotation.Annotation; import java.lang.reflect.Executable; import java.util.Properties; import java.util.PropertyPermission; @@ -1197,9 +1196,6 @@ public final class System { public AnnotationType getAnnotationType(Class klass) { return klass.getAnnotationType(); } - public A getDirectDeclaredAnnotation(Class klass, Class anno) { - return klass.getDirectDeclaredAnnotation(anno); - } public byte[] getRawClassTypeAnnotations(Class klass) { return klass.getRawTypeAnnotations(); } diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java index 58a07350f36..e7de9429b0c 100644 --- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -35,6 +35,24 @@ import java.lang.annotation.Annotation; * arrays returned by accessors for array-valued enum members; it will * have no affect on the arrays returned to other callers. * + *