changeset 757:3c4561f955f3

Merge
author lana
date Thu, 07 Aug 2008 22:24:26 -0700
parents 15be3e891e97 1d3a19f9a015
children 3d3ef4073bdd
files make/tools/winver/Makefile make/tools/winver/bin/winver.exe make/tools/winver/src/StdAfx.cpp make/tools/winver/src/StdAfx.h make/tools/winver/src/winver.cpp src/share/classes/com/sun/jmx/mbeanserver/OpenConverter.java src/share/classes/javax/management/ToQueryString.java src/share/classes/sun/font/FontManager.java src/share/classes/sun/font/TrueTypeFont.java src/solaris/classes/sun/print/IPPPrintService.java test/javax/management/Introspector/LegacyIntrospectorTest.java
diffstat 1128 files changed, 54020 insertions(+), 4958 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Thu Aug 07 11:19:06 2008 -0700
+++ b/.hgtags	Thu Aug 07 22:24:26 2008 -0700
@@ -2,3 +2,8 @@
 75fca0b0ab83ab1392e615910cea020f66535390 jdk7-b25
 fb57027902e04ecafceae31a605e69b436c23d57 jdk7-b26
 3e599d98875ddf919c8ea11cff9b3a99ba631a9b jdk7-b27
+02e4c5348592a8d7fc2cba28bc5f8e35c0e17277 jdk7-b28
+e21f4266466cd1306b176aaa08b2cd8337a9be3d jdk7-b29
+b6d6877c1155621a175dccd12dc14c54f938fb8b jdk7-b30
+b7474b739d13bacd9972f88ac91f6350b7b0be12 jdk7-b31
+c51121419e30eac5f0fbbce45ff1711c4ce0de28 jdk7-b32
--- a/make/com/sun/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/com/sun/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/com/sun/java/pack/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/com/sun/java/pack/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -97,9 +97,6 @@
 	/D "J2SE_FTYPE=0x1L"
 
   RES = $(OBJDIR)/$(PGRM).res
-
-  # Files built here do not compile with warning level 3 if warnings are fatal
-  COMPILER_WARNINGS_FATAL=false
 else
   LDOUTPUT = -o #Have a space 
   LDDFLAGS += -lc
--- a/make/com/sun/security/auth/module/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/com/sun/security/auth/module/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -55,9 +55,6 @@
     EXTRA_LIBS += netapi32.lib user32.lib mpr.lib
   endif #fdlibm
   # code generates errors when compiled at warning level 3 and warnings are fatal
-  ifeq ($(ARCH_DATA_MODEL), 64)
-    COMPILER_WARNINGS_FATAL=false
-  endif # ARCH_DATA_MODEL
 endif # windows
 
 ifeq ($(PLATFORM), solaris)
--- a/make/common/Defs-linux.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/Defs-linux.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -149,10 +149,9 @@
 PIC_CODE_LARGE = -fPIC
 PIC_CODE_SMALL = -fpic
 GLOBAL_KPIC = $(PIC_CODE_LARGE)
+CFLAGS_COMMON   += $(GLOBAL_KPIC) $(GCC_WARNINGS)
 ifeq ($(ARCH), amd64)
-   CFLAGS_COMMON   += $(GLOBAL_KPIC) $(GCC_WARNINGS) -pipe
-else
-   CFLAGS_COMMON   += $(GLOBAL_KPIC) $(GCC_WARNINGS)
+ CFLAGS_COMMON += -pipe
 endif
 
 # Linux 64bit machines use Dwarf2, which can be HUGE, have fastdebug use -g1
--- a/make/common/Defs-solaris.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/Defs-solaris.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1995-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1995-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # 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,6 +40,9 @@
 #   LDLIBS        (set $(EXTRA_LIBS) instead)
 #   LDLIBS_COMMON (set $(EXTRA_LIBS) instead)
 #   LINTFLAGS     (set $(OTHER_LINTFLAGS) instead)
+#
+# Note: CPPFLAGS are used in C and C++ compiles.
+#
 
 # Get shared JDK settings
 include $(JDK_MAKE_SHARED_DIR)/Defs.gmk
@@ -112,6 +115,10 @@
 #                       Required with many of the source files.
 #       -mt             Assume multi-threaded (important)
 #
+# The more unusual options to the Sun C compiler:
+#       +w              Print more warnings
+#       +w2             Maximum warnings
+#
 
 #
 # Debug flag for C and C++ compiler
@@ -140,15 +147,34 @@
   CXXFLAGS_DEBUG_OPTION  = -g0  $(CC_FASTDEBUG_OPT)
 endif
 
-CFLAGS_COMMON   = -v -mt -L$(OBJDIR) -xc99=%none
+CFLAGS_COMMON   = -L$(OBJDIR)
+
+# Do not allow C99 language features like declarations in code etc.
+CFLAGS_COMMON  += -xc99=%none
+
+# Allow C++ comments in C code
 CFLAGS_COMMON  += -xCC
-CFLAGS_COMMON  += -errshort=tags
+
+# Show error message tags on errors
+CFLAGS_COMMON   += -errshort=tags
+CXXFLAGS_COMMON += -errtags=yes
+
+# Optimization flags
 CFLAGS_OPT      = $(POPT)
+
+# Debug version flags
 CFLAGS_DBG      = $(CFLAGS_DEBUG_OPTION)
-CFLAGS_COMMON  +=  -Xa $(CFLAGS_REQUIRED)
+
+# Required C compiler flags
+CFLAGS_COMMON  += -Xa $(CFLAGS_REQUIRED)
+
+# Maximum warnings all the time
+CXXFLAGS_COMMON += +w
+CFLAGS_COMMON   += -v
 
 # Assume MT behavior all the time (important)
-CXXFLAGS_COMMON  = -mt
+CXXFLAGS_COMMON += -mt
+CFLAGS_COMMON   += -mt
 
 # Assume no C++ exceptions are used
 CXXFLAGS_COMMON += -features=no%except -DCC_NOEX
@@ -197,7 +223,6 @@
 
 # Lint Flags:
 #	-Xa			ANSI C plus K&R, favor ANSI rules
-#       -Xarch=XXX		Same as 'cc -xarch=XXX'
 #	-fd			report on old style func defs
 #	-errchk=structarg	report on 64bit struct args by value
 #	-errchk=longptr64	report on 64bit to 32bit issues (ignores casts)
@@ -206,6 +231,7 @@
 #	-x			suppress unused externs
 #	-u			suppress extern func/vars used/defined
 #	-errfmt=simple		use one line errors with position info
+#       $(LINT_XARCH_OPTION)    See Compiler-sun.gwk
 
 LINTFLAGS_COMMON  = -Xa
 LINTFLAGS_COMMON += -fd 
@@ -224,42 +250,12 @@
 #    Tell the compilers to never generate globalized names, all the time.
 CFLAGS_COMMON += -W0,-noglobal
 
-# Arch specific settings (determines type of .o files and instruction set)
-ifeq ($(ARCH_FAMILY), sparc)
-  ifdef VIS_NEEDED
-    XARCH_VALUE/32=v8plusa
-    XARCH_VALUE/64=v9a
-  else 
-    # Someday this should change to improve optimization on UltraSPARC
-    #    and abandon the old v8-only machines like the SPARCstation 10.
-    #    Indications with Mustang is that alacrity runs do not show a
-    #    big improvement using v8plus over v8, but other benchmarks might.
-    XARCH_VALUE/32=v8
-    XARCH_VALUE/64=v9
-  endif
-endif
-ifeq ($(ARCH_FAMILY), i586)
-  XARCH_VALUE/64=amd64
-  XARCH_VALUE/32=
-endif
-
-# Arch value based on current data model being built
-XARCH_VALUE=$(XARCH_VALUE/$(ARCH_DATA_MODEL))
-ifneq ($(XARCH_VALUE), )
-  # The actual compiler -xarch options to use
-  XARCH_OPTION/32 = -xarch=$(XARCH_VALUE/32)
-  XARCH_OPTION/64 = -xarch=$(XARCH_VALUE/64)
-  XARCH_OPTION    = $(XARCH_OPTION/$(ARCH_DATA_MODEL))
-endif
-
-# If we have a specific -xarch value to use, add it
-ifdef XARCH_OPTION
-  CFLAGS_COMMON    += $(XARCH_OPTION)
-  CXXFLAGS_COMMON  += $(XARCH_OPTION)
-  ASFLAGS_COMMON   += $(XARCH_OPTION)
-  EXTRA_LIBS       += $(XARCH_OPTION)
-  LINTFLAGS_COMMON += -Xarch=$(XARCH_VALUE)
-endif
+# If we have a specific arch value to use, add it
+CFLAGS_COMMON    += $(XARCH_OPTION)
+CXXFLAGS_COMMON  += $(XARCH_OPTION)
+ASFLAGS_COMMON   += $(AS_XARCH_OPTION)
+EXTRA_LIBS       += $(XARCH_OPTION)
+LINTFLAGS_COMMON += $(LINT_XARCH_OPTION)
 
 #
 # uncomment the following to build with PERTURBALOT set
@@ -267,8 +263,8 @@
 # OTHER_CFLAGS += -DPERTURBALOT
 #
 
-CPPFLAGS_COMMON = -D$(ARCH_FAMILY) -D__solaris__ -D_REENTRANT 
-CPPFLAGS_OPT    = 
+CPPFLAGS_COMMON = -D__solaris__  -D$(ARCH_FAMILY)
+CPPFLAGS_OPT    = -DNDEBUG
 CPPFLAGS_DBG    = -DDEBUG
 
 ifeq ($(ARCH_FAMILY), i586)
--- a/make/common/Defs-windows.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/Defs-windows.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -283,7 +283,7 @@
 ifeq ($(ARCH), amd64)
   CPPFLAGS_COMMON += -D_AMD64_ -Damd64
 else
-  CPPFLAGS_COMMON += -DWIN32 -D_X86_ -Dx86 
+  CPPFLAGS_COMMON += -D_X86_ -Dx86 
 endif
 CPPFLAGS_COMMON += -DWIN32_LEAN_AND_MEAN
 
@@ -293,16 +293,23 @@
 CFLAGS_COMMON += -Fd$(OBJDIR)/$(basename $(@F)).pdb -Fm$(OBJDIR)/$(basename $(@F)).map
 
 #
+# Use -wdNNNN to disable warning NNNN.
+#   C4800 is a warning about bool performance casts (can't make go away)
+#
+COMPILER_WARNINGS_TO_IGNORE = 4800
+CFLAGS_COMMON += $(COMPILER_WARNINGS_TO_IGNORE:%=-wd%)
+
+#
 # Add warnings and extra on 64bit issues
 #
 ifeq ($(ARCH_DATA_MODEL), 64)
   CFLAGS_COMMON += -Wp64 
 endif
-CFLAGS_COMMON += -W$(COMPILER_WARNING_LEVEL)
 
 #
 # Treat compiler warnings as errors, if requested
 #
+CFLAGS_COMMON += -W$(COMPILER_WARNING_LEVEL)
 ifeq ($(COMPILER_WARNINGS_FATAL),true)
   CFLAGS_COMMON += -WX
 endif
@@ -352,17 +359,9 @@
   #    BUILD_WIN_SA=1
   # on the make command.
   ifdef BUILD_WIN_SA
-    ifeq ($(ARCH), amd64)
-      INCLUDE_SA = true
-    else
-      INCLUDE_SA = true
-    endif
+    INCLUDE_SA = true
   else
-    ifeq ($(ARCH), amd64)
-      INCLUDE_SA = false
-    else
-      INCLUDE_SA = false
-    endif
+    INCLUDE_SA = false
   endif
 endif
 
@@ -404,7 +403,6 @@
 else
   JDK_UPDATE_VER := 0
 endif
-JDK_VER = $(JDK_MINOR_VERSION),$(JDK_MICRO_VERSION),$(JDK_UPDATE_VER),$(COOKED_BUILD_NUMBER)
 
 RC_FLAGS = /l 0x409 /r
 
@@ -414,15 +412,23 @@
   RC_FLAGS += $(MS_RC_DEBUG_OPTION)
 endif 
 
-ifndef COPYRIGHT_YEAR
-    COPYRIGHT_YEAR = 2007 
-endif
+# Values for the RC variables defined in RC_FLAGS
+JDK_RC_BUILD_ID = $(FULL_VERSION)
+JDK_RC_COMPANY = $(COMPANY_NAME)
+JDK_RC_COMPONENT = $(PRODUCT_NAME) $(JDK_RC_PLATFORM_NAME) binary
+JDK_RC_VER = \
+    $(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION).$(JDK_UPDATE_VER).$(COOKED_BUILD_NUMBER)
+JDK_RC_COPYRIGHT = Copyright \xA9 $(COPYRIGHT_YEAR)
+JDK_RC_NAME = \
+    $(PRODUCT_NAME) $(JDK_RC_PLATFORM_NAME) $(JDK_MINOR_VERSION) $(JDK_UPDATE_META_TAG)
+JDK_RC_FVER = \
+    $(JDK_MINOR_VERSION),$(JDK_MICRO_VERSION),$(JDK_UPDATE_VER),$(COOKED_BUILD_NUMBER)
 
 # J2SE name required here
-RC_FLAGS += -d "J2SE_BUILD_ID=$(FULL_VERSION)" \
-            -d "J2SE_COMPANY=$(COMPANY_NAME)" \
-            -d "J2SE_COMPONENT=$(PRODUCT_NAME) Platform SE binary" \
-            -d "J2SE_VER=$(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION).$(JDK_UPDATE_VER).$(COOKED_BUILD_NUMBER)" \
-            -d "J2SE_COPYRIGHT=Copyright \xA9 $(COPYRIGHT_YEAR)" \
-            -d "J2SE_NAME=$(PRODUCT_NAME) Platform SE $(JDK_MINOR_VERSION) $(JDK_UPDATE_META_TAG)" \
-            -d "J2SE_FVER=$(JDK_VER)"
+RC_FLAGS += -d "J2SE_BUILD_ID=$(JDK_RC_BUILD_ID)" \
+            -d "J2SE_COMPANY=$(JDK_RC_COMPANY)" \
+            -d "J2SE_COMPONENT=$(JDK_RC_COMPONENT)" \
+            -d "J2SE_VER=$(JDK_RC_VER)" \
+            -d "J2SE_COPYRIGHT=$(JDK_RC_COPYRIGHT)" \
+            -d "J2SE_NAME=$(JDK_RC_NAME)" \
+            -d "J2SE_FVER=$(JDK_RC_FVER)"
--- a/make/common/Defs.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/Defs.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1995-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1995-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -703,7 +703,7 @@
 ifdef ALT_COPYRIGHT_YEAR
   COPYRIGHT_YEAR = $(ALT_COPYRIGHT_YEAR)
 else
-  COPYRIGHT_YEAR = $(shell $(DATE) '+%Y')
+  COPYRIGHT_YEAR := $(shell $(DATE) '+%Y')
 endif
 
 # Install of imported file (JDK_IMPORT_PATH, or some other external location)
--- a/make/common/Release.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/Release.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -369,6 +369,7 @@
 	com/sun/jarsigner	\
 	com/sun/mirror		\
 	com/sun/source          \
+	com/sun/tools/classfile \
 	com/sun/tools/doclets   \
 	com/sun/tools/example/debug/expr \
 	com/sun/tools/example/debug/tty  \
@@ -378,6 +379,7 @@
 	com/sun/tools/javadoc   \
 	com/sun/tools/apt       \
 	com/sun/tools/javah     \
+	com/sun/tools/javap     \
 	com/sun/tools/corba     \
 	com/sun/tools/internal/xjc       \
 	com/sun/tools/internal/ws       \
@@ -568,6 +570,8 @@
 	$(ECHO) "sun/tools/java/" >> $@
 	$(ECHO) "sun/tools/javac/" >> $@
 	$(ECHO) "sun/tools/javap/" >> $@
+	$(ECHO) "com/sun/tools/classfile/" >> $@
+	$(ECHO) "com/sun/tools/javap/" >> $@
 	$(ECHO) "sun/tools/jconsole/" >> $@
 	$(ECHO) "sun/tools/jps/" >> $@
 	$(ECHO) "sun/tools/jstat/" >> $@
@@ -1236,7 +1240,6 @@
 	$(RM) $(TEMPDIR)/rebase.input
 endif
 	$(RM) -r $(JDK_IMAGE_DIR)
-	$(RM) -r $(JDK_DEBUG_IMAGE_DIR)
 	$(RM) -r $(JRE_IMAGE_DIR)
 
 images images-clobber::
--- a/make/common/Rules.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/Rules.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1995-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1995-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/common/internal/BinaryPlugs.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/internal/BinaryPlugs.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/common/internal/Defs-langtools.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/internal/Defs-langtools.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # 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,13 +31,15 @@
       javax/tools
 
 IMPORT_TOOLS_PACKAGES +=            \
+      com/sun/javadoc               \
       com/sun/mirror                \
       com/sun/source                \
       com/sun/tools/apt             \
+      com/sun/tools/classfile       \
+      com/sun/tools/doclets         \
       com/sun/tools/javac           \
+      com/sun/tools/javadoc         \
       com/sun/tools/javah           \
-      com/sun/tools/javadoc         \
-      com/sun/tools/doclets         \
-      com/sun/javadoc               \
+      com/sun/tools/javap           \
       sun/tools/javap
 
--- a/make/common/shared/Compiler-gcc.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/shared/Compiler-gcc.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -73,23 +73,18 @@
     REQUIRED_CC_VER = 4.0
     REQUIRED_GCC_VER = 4.0.*
   else
-  ifeq ($(ARCH_DATA_MODEL), 32)
-    # i586
     REQUIRED_CC_VER = 3.2
-    REQUIRED_GCC_VER = 3.2.1*
-    REQUIRED_GCC_VER_INT = 3.2.1-7a
-  else
-  ifeq ($(ARCH), amd64)
-    # amd64
-    REQUIRED_CC_VER = 3.2
-    REQUIRED_GCC_VER = 3.2.*
-  endif
-  ifeq ($(ARCH), ia64)
-    # ia64
-    REQUIRED_CC_VER = 3.2
-    REQUIRED_GCC_VER = 2.9[56789].*
-  endif
-  endif
+    ifeq ($(ARCH_DATA_MODEL), 32)
+      REQUIRED_GCC_VER = 3.2.1*
+      REQUIRED_GCC_VER_INT = 3.2.1-7a
+    else
+      ifeq ($(ARCH), amd64)
+        REQUIRED_GCC_VER = 3.2.*
+      endif
+      ifeq ($(ARCH), ia64)
+        REQUIRED_GCC_VER = 2.9[56789].*
+      endif
+    endif
   endif
   # Option used to create a shared library
   SHARED_LIBRARY_FLAG = -shared -mimpure-text
--- a/make/common/shared/Compiler-msvc.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/shared/Compiler-msvc.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/common/shared/Compiler-sun.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/shared/Compiler-sun.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # 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,9 @@
 
 # Sun Studio Compiler settings specific to Solaris
 ifeq ($(PLATFORM), solaris)
+  # FIXUP: Change to SS12 when validated
+  #COMPILER_VERSION=SS12
+  #REQUIRED_CC_VER=5.9
   COMPILER_VERSION=SS11
   REQUIRED_CC_VER=5.8
   CC             = $(COMPILER_PATH)cc
@@ -51,8 +54,8 @@
 # Sun Studio Compiler settings specific to Linux
 ifeq ($(PLATFORM), linux)
   # This has not been tested
-  COMPILER_VERSION=SS11
-  REQUIRED_CC_VER=5.8
+  COMPILER_VERSION=SS12
+  REQUIRED_CC_VER=5.9
   CC             = $(COMPILER_PATH)cc
   CPP            = $(COMPILER_PATH)cc -E
   CXX            = $(COMPILER_PATH)CC
@@ -74,3 +77,58 @@
 _CC_VER :=$(shell $(CC) -V 2>&1 | $(HEAD) -n 1)
 CC_VER  :=$(call GetVersion,"$(_CC_VER)")
 
+# Arch specific settings (determines type of .o files and instruction set)
+#  Starting in SS12 (5.9), the arch options changed.
+#  The assembler /usr/ccs/bin/as wants older SS11 (5.8) style options.
+#   Note: We need to have both 32 and 64 values at all times for awt Makefiles.
+#
+XARCH_OPTION_OLD/32 =
+XARCH_OPTION_OLD/64 =
+XARCH_OPTION_NEW/32 = -m32
+XARCH_OPTION_NEW/64 = -m64
+# Lint options are slightly different
+LINT_XARCH_OPTION_OLD/32 =
+LINT_XARCH_OPTION_OLD/64 =
+LINT_XARCH_OPTION_NEW/32 = -m32
+LINT_XARCH_OPTION_NEW/64 = -m64
+ifeq ($(ARCH_FAMILY), sparc)
+  ifdef VIS_NEEDED
+    XARCH_OPTION_OLD/32 += -xarch=v8plusa
+    XARCH_OPTION_OLD/64 += -xarch=v9a
+    XARCH_OPTION_NEW/32 += -xarch=sparcvis
+    XARCH_OPTION_NEW/64 += -xarch=sparcvis
+  else
+    # Someday this should change to improve optimization on UltraSPARC
+    #    and abandon v8, even change to sparcvis or sparcvis2, this
+    #    abandons machines like the SPARCstation 10.
+    #    Indications with jdk6 is that alacrity runs do not show a
+    #    big improvement using v8plus over v8, but other benchmarks might.
+    XARCH_OPTION_OLD/32 += -xarch=v8
+    XARCH_OPTION_OLD/64 += -xarch=v9
+    # Note that this new option (SS12+) effectively means v8plus
+    XARCH_OPTION_NEW/32 += -xarch=sparc
+    XARCH_OPTION_NEW/64 += -xarch=sparc
+  endif
+  LINT_XARCH_OPTION_OLD/64 += -Xarch=v9
+endif
+ifeq ($(ARCH_FAMILY), i586)
+  XARCH_OPTION_OLD/64      += -xarch=amd64
+  LINT_XARCH_OPTION_OLD/64 += -Xarch=amd64
+endif
+# Pick the options we want based on the compiler being used.
+ifeq ($(shell expr $(CC_VER) \>= 5.9), 1)
+  XARCH_OPTION/32 = $(XARCH_OPTION_NEW/32)
+  XARCH_OPTION/64 = $(XARCH_OPTION_NEW/64)
+  LINT_XARCH_OPTION/32 = $(LINT_XARCH_OPTION_NEW/32)
+  LINT_XARCH_OPTION/64 = $(LINT_XARCH_OPTION_NEW/64)
+else
+  XARCH_OPTION/32 = $(XARCH_OPTION_OLD/32)
+  XARCH_OPTION/64 = $(XARCH_OPTION_OLD/64)
+  LINT_XARCH_OPTION/32 = $(LINT_XARCH_OPTION_OLD/32)
+  LINT_XARCH_OPTION/64 = $(LINT_XARCH_OPTION_OLD/64)
+endif
+XARCH_OPTION = $(XARCH_OPTION/$(ARCH_DATA_MODEL))
+LINT_XARCH_OPTION = $(LINT_XARCH_OPTION/$(ARCH_DATA_MODEL))
+# The /usr/ccs/bin/as assembler always wants the older SS11 (5.8) options.
+AS_XARCH_OPTION = $(XARCH_OPTION_OLD/$(ARCH_DATA_MODEL))
+
--- a/make/common/shared/Defs-control.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/shared/Defs-control.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1995-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1995-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/common/shared/Defs-java.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/shared/Defs-java.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -107,7 +107,10 @@
 ifeq ($(DEBUG_CLASSFILES),true)
   JAVACFLAGS += -g
 endif
-ifeq ($(COMPILER_WARNINGS_FATAL), true)
+ifeq ($(JAVAC_MAX_WARNINGS), true)
+  JAVACFLAGS  += -Xlint:all
+endif
+ifeq ($(JAVAC_WARNINGS_FATAL), true)
   JAVACFLAGS  += -Werror
 endif
 
@@ -180,7 +183,10 @@
 # The javac options supplied to the boot javac is limited. This compiler
 #   should only be used to build the 'make/tools' sources, which are not
 #   class files that end up in the classes directory.
-ifeq ($(COMPILER_WARNINGS_FATAL), true)
+ifeq ($(JAVAC_MAX_WARNINGS), true)
+  BOOT_JAVACFLAGS  += -Xlint:all
+endif
+ifeq ($(JAVAC_WARNINGS_FATAL), true)
   BOOT_JAVACFLAGS  += -Werror
 endif
 BOOT_JAVACFLAGS  += -encoding ascii
--- a/make/common/shared/Defs-utils.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/shared/Defs-utils.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2005-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/common/shared/Defs.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/shared/Defs.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -188,16 +188,18 @@
 endif
 
 # Default names
-LAUNCHER_NAME = java
-PRODUCT_NAME = Java(TM)
-PRODUCT_SUFFIX = SE Runtime Environment
-COMPANY_NAME = Sun Microsystems, Inc.
-
 ifdef OPENJDK
   LAUNCHER_NAME = openjdk
   PRODUCT_NAME = OpenJDK
   PRODUCT_SUFFIX = Runtime Environment
-  COMPANY_NAME =
+  JDK_RC_PLATFORM_NAME = Platform
+  COMPANY_NAME = N/A
+else
+  LAUNCHER_NAME = java
+  PRODUCT_NAME = Java(TM)
+  PRODUCT_SUFFIX = SE Runtime Environment
+  JDK_RC_PLATFORM_NAME = Platform SE
+  COMPANY_NAME = Sun Microsystems, Inc.
 endif
 
 RUNTIME_NAME = $(PRODUCT_NAME) $(PRODUCT_SUFFIX)
--- a/make/common/shared/Platform.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/shared/Platform.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -72,7 +72,6 @@
 #     ISA_DIR                     solaris only: /sparcv9 or /amd64
 #     LIBARCH32                   solaris only: sparc or i386
 #     LIBARCH64                   solaris only: sparcv9 or amd64
-#     REQUIRED_WINDOWS_NAME       windows only: basic name of windows 
 #     REQUIRED_WINDOWS_VERSION    windows only: specific version of windows 
 #     USING_CYGWIN                windows only: true or false
 #     WINDOWS_NT_VERSION_STRING   windows only: long version name
@@ -311,19 +310,11 @@
     endif
   endif
   export ARCH_DATA_MODEL
-  # LIBARCH is used to preserve the jre/lib/i386 directory name for 32-bit intel
-  ARCH=i586
-  LIBARCH=i386
-  # Value of Java os.arch property
-  ARCHPROP=x86
-  REQUIRED_WINDOWS_NAME=Windows Professional 2000
-  REQUIRED_WINDOWS_VERSION=5 0 Service Pack 4
   ifeq ($(ARCH_DATA_MODEL), 64)
     # If the user wants to perform a cross compile build then they must
     # - set ARCH_DATA_MODEL=64 and either
     #      + set ARCH to ia64 or amd64, or
-    REQUIRED_WINDOWS_NAME=Windows Server 2003
-    REQUIRED_WINDOWS_VERSION=5 2 Service Pack 1
+    REQUIRED_WINDOWS_VERSION=Server 2003 Enterprise x64 Edition
     ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)), AMD64)
       ARCH=amd64
     else
@@ -332,6 +323,14 @@
     LIBARCH=$(ARCH)
     # Value of Java os.arch property
     ARCHPROP=$(LIBARCH)
+  else
+    REQUIRED_WINDOWS_VERSION=2000 or Unknown
+    #REQUIRED_WINDOWS_VERSION=XP Professional
+    # LIBARCH is used to preserve the jre/lib/i386 directory name for 32-bit intel
+    ARCH=i586
+    LIBARCH=i386
+    # Value of Java os.arch property
+    ARCHPROP=x86
   endif
   ARCH_FAMILY = $(ARCH)
   # Where is unwanted output to be delivered?
@@ -374,35 +373,41 @@
   REQUIRED_DXSDK_VER = 0x0900
   OS_VENDOR = Microsoft
   # How much RAM does this machine have:
-  ifeq ($(USING_CYGWIN),true)
-    # CYGWIN has the 'free' utility
-    _MB_OF_MEMORY := \
-	 $(shell free -m | grep Mem: | awk '{print $$2;}' )
-  else
-    # Windows 2000 has the mem utility, but two memory areas
-    #    extended memory is what is beyond 1024M
-    _B_OF_EXT_MEMORY := \
-	 $(shell mem 2> $(DEV_NULL) | grep 'total contiguous extended memory' | awk '{print $$1;}')
-    ifeq ($(_B_OF_EXT_MEMORY),)
-      _B_OF_MEMORY := \
-	 $(shell mem 2> $(DEV_NULL) | grep 'total conventional memory' | awk '{print $$1;}')
+  ifeq ($(JDK_HAS_MEM_INFO),)
+    ifeq ($(USING_CYGWIN),true)
+      # CYGWIN has the 'free' utility
+      _MB_OF_MEMORY := \
+	   $(shell free -m | grep Mem: | awk '{print $$2;}' )
     else
-      _B_OF_MEMORY := \
-         $(shell expr 1048576 '+' $(_B_OF_EXT_MEMORY) 2> $(DEV_NULL))
+      # Windows 2000 has the mem utility, but two memory areas
+      #    extended memory is what is beyond 1024M
+      _B_OF_EXT_MEMORY := \
+	   $(shell mem 2> $(DEV_NULL) | \
+		   grep 'total contiguous extended memory' | awk '{print $$1;}')
+      ifeq ($(_B_OF_EXT_MEMORY),)
+          _B_OF_MEMORY := \
+	   $(shell mem 2> $(DEV_NULL) | \
+		   grep 'total conventional memory' | awk '{print $$1;}')
+      else
+        _B_OF_MEMORY := \
+           $(shell expr 1048576 '+' $(_B_OF_EXT_MEMORY) 2> $(DEV_NULL))
+      endif
+      ifeq ($(_B_OF_MEMORY),)
+        # Windows 2003 has the systeminfo utility use it if mem doesn't work
+        _MB_OF_MEMORY := \
+	    $(shell systeminfo 2> $(DEV_NULL) | \
+		    grep 'Total Physical Memory:' | \
+		    awk '{print $$4;}' | sed -e 's@,@@')
+      else
+        _MB_OF_MEMORY := $(shell expr $(_B_OF_MEMORY) '/' 1024 2> $(DEV_NULL))
+      endif
     endif
-    ifeq ($(_B_OF_MEMORY),)
-      # Windows 2003 has the systeminfo utility use it if mem doesn't work
-      _MB_OF_MEMORY := \
-	  $(shell systeminfo 2> $(DEV_NULL) | grep 'Total Physical Memory:' | awk '{print $$4;}' | sed -e 's@,@@')
+    ifeq ($(shell expr $(_MB_OF_MEMORY) '+' 0 2> $(DEV_NULL)), $(_MB_OF_MEMORY))
+      MB_OF_MEMORY := $(_MB_OF_MEMORY)
     else
-      _MB_OF_MEMORY := $(shell expr $(_B_OF_MEMORY) '/' 1024 2> $(DEV_NULL))
+      MB_OF_MEMORY := 512
     endif
   endif
-  ifeq ($(shell expr $(_MB_OF_MEMORY) '+' 0 2> $(DEV_NULL)), $(_MB_OF_MEMORY))
-    MB_OF_MEMORY := $(_MB_OF_MEMORY)
-  else
-    MB_OF_MEMORY := 512
-  endif
 endif
 
 REQUIRED_ZIP_VER = 2.2
@@ -447,30 +452,38 @@
 #    system swapping during the build.
 #    If we don't know, assume 512. Subtract 128 from MB for VM MAX.
 #    Don't set VM max over 1024-128=896.
-ifneq ($(MB_OF_MEMORY),)
-  LOW_MEMORY_MACHINE := $(shell \
-    if [ $(MB_OF_MEMORY) -le 512 ] ; then \
-      echo "true"; \
-    else \
-      echo "false"; \
-    fi)
-  MAX_VM_MEMORY := $(shell \
-    if [ $(MB_OF_MEMORY) -le 1024 ] ; then \
-      expr $(MB_OF_MEMORY) '-' 128 2> $(DEV_NULL) ; \
-    else \
-      echo "896"; \
-    fi)
-  MIN_VM_MEMORY := $(shell \
-    if [ $(MAX_VM_MEMORY) -le 128 ] ; then \
-      expr $(MAX_VM_MEMORY) '-' 8 2> $(DEV_NULL) ; \
-    else \
-      echo "128"; \
-    fi)
-else
-  MB_OF_MEMORY       := unknown
-  LOW_MEMORY_MACHINE := true
-  MAX_VM_MEMORY      := 384
-  MIN_VM_MEMORY      := 128
+ifeq ($(JDK_HAS_MEM_INFO),)
+  JDK_HAS_MEM_INFO=true
+  export JDK_HAS_MEM_INFO
+  ifneq ($(MB_OF_MEMORY),)
+    LOW_MEMORY_MACHINE := $(shell \
+      if [ $(MB_OF_MEMORY) -le 512 ] ; then \
+        echo "true"; \
+      else \
+        echo "false"; \
+      fi)
+    MAX_VM_MEMORY := $(shell \
+      if [ $(MB_OF_MEMORY) -le 1024 ] ; then \
+        expr $(MB_OF_MEMORY) '-' 128 2> $(DEV_NULL) ; \
+      else \
+        echo "896"; \
+      fi)
+    MIN_VM_MEMORY := $(shell \
+      if [ $(MAX_VM_MEMORY) -le 128 ] ; then \
+        expr $(MAX_VM_MEMORY) '-' 8 2> $(DEV_NULL) ; \
+      else \
+        echo "128"; \
+      fi)
+  else
+    MB_OF_MEMORY       := unknown
+    LOW_MEMORY_MACHINE := true
+    MAX_VM_MEMORY      := 384
+    MIN_VM_MEMORY      := 128
+  endif
+  export MB_OF_MEMORY
+  export LOW_MEMORY_MACHINE
+  export MAX_VM_MEMORY
+  export MIN_VM_MEMORY
 endif
 
 # If blanks in the username, use the first 4 words and pack them together
--- a/make/common/shared/Sanity.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/common/shared/Sanity.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -82,15 +82,16 @@
 endif
 
 ifeq ($(PLATFORM), windows)
-  WINVER=$(JDK_TOPDIR)/make/tools/winver/bin/winver.exe
   FREE_SPACE := $(shell $(DF) -kP $(OUTPUTDIR) | $(TAIL) -1 | $(NAWK) '{print $$4;}')
   TEMP_FREE_SPACE := $(shell $(DF) -kP $(TEMP_DISK) | $(TAIL) -1 | $(NAWK) '{print $$4;}')
-  WINDOWS_VERSION := $(shell \
-      if [ -x $(WINVER) ]; then \
-	$(WINVER) ; \
-      else \
-	$(ECHO) "Unknown Windows Version"; \
-      fi)
+  # Localized systeminfo has localized labels, but not localized values.
+  _WINDOWS_VERSION := \
+    $(shell systeminfo 2> $(DEV_NULL) | grep 'Microsoft' | grep 'Windows' | \
+	 cut -d':' -f2)
+  ifeq ($(_WINDOWS_VERSION),)
+    _WINDOWS_VERSION := Windows 2000 or Unknown (no systeminfo utility)
+  endif
+  WINDOWS_VERSION := $(strip $(_WINDOWS_VERSION))
   DXSDK_VER := $(shell $(EGREP) DIRECT3D_VERSION $(DXSDK_INCLUDE_PATH)/d3d9.h 2>&1 | \
     $(EGREP) "\#define" | $(NAWK) '{print $$3}')
 endif
@@ -264,9 +265,9 @@
 	    "" >> $(WARNING_FILE) ; \
 	fi
   ifeq ($(PLATFORM), windows)
-	@if [ "$(WINDOWS_VERSION)" != "$(REQUIRED_WINDOWS_VERSION)" ]; then \
-	    $(ECHO) "WARNING: $(YOU_ARE_USING) an unsupported version of $(REQUIRED_WINDOWS_NAME). \n" \
-	      "        The supported version is $(REQUIRED_WINDOWS_NAME) $(REQUIRED_WINDOWS_VERSION). \n" \
+	@if [ "$(findstring $(REQUIRED_WINDOWS_VERSION),$(WINDOWS_VERSION))" = "" ]; then \
+	    $(ECHO) "WARNING: $(YOU_ARE_USING) an unknown version of Windows. \n" \
+	      "        The required version is $(REQUIRED_WINDOWS_VERSION). \n" \
 	      "        $(YOU_ARE_USING) $(WINDOWS_VERSION) \n" \
 	      "" >> $(WARNING_FILE) ; \
 	fi
--- a/make/docs/CORE_PKGS.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/docs/CORE_PKGS.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2001-2006 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2001-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/docs/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/docs/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/docs/NON_CORE_PKGS.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/docs/NON_CORE_PKGS.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2002-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/java/awt/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/awt/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1995-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1995-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/java/fdlibm/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/fdlibm/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -46,8 +46,6 @@
   _OPT = $(CC_NO_OPT)
   OTHER_CFLAGS =
   CPPFLAGS_DBG += -DLOGGING
-  # Files built here do not compile with warning level 3 if warnings are fatal
-  COMPILER_WARNINGS_FATAL=false
 endif
 
 #
--- a/make/java/hpi/windows/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/hpi/windows/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -37,8 +37,6 @@
 # windows compiler flags
 ifeq ($(PLATFORM),windows)
   CPPFLAGS_DBG += -DLOGGING
-  # Files built here do not compile with warning level 3 if warnings are fatal
-  COMPILER_WARNINGS_FATAL=false
 endif
 
 FILES_c = \
--- a/make/java/java/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/java/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # 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,8 +37,6 @@
 # windows compiler flags
 ifeq ($(PLATFORM),windows)
   OTHER_CFLAGS =
-  # Files built here do not compile with warning level 3 if warnings are fatal
-  COMPILER_WARNINGS_FATAL=false
   # build directly into BINDIR...
   LIB_LOCATION = $(BINDIR)
   # Exported functions
--- a/make/java/java/genlocales.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/java/genlocales.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/java/java/localegen.sh	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/java/localegen.sh	Thu Aug 07 22:24:26 2008 -0700
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 #
-# Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/java/java/mapfile-vers	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/java/mapfile-vers	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/java/java_crw_demo/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/java_crw_demo/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -48,11 +48,6 @@
 OTHER_INCLUDES = -I$(SRCDIR)
 
 #
-# This removes all asserts in the optimized version
-#
-CPPFLAGS_OPT += -DNDEBUG
-
-#
 # Library to compile.
 #
 include $(BUILDDIR)/common/Library.gmk
--- a/make/java/java_hprof_demo/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/java_hprof_demo/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -92,11 +92,6 @@
 INIT += $(LIBDIR)/jvm.hprof.txt
 
 #
-# This removes all asserts in the optimized version
-#
-CPPFLAGS_OPT += -DNDEBUG
-
-#
 # This puts logging code in
 #
 CPPFLAGS_DBG += -DHPROF_LOGGING
--- a/make/java/jli/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/jli/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -115,9 +115,6 @@
 		     -export:JLI_ManifestIterate \
 		     -export:JLI_SetTraceLauncher
 
-	# Files from zlib built here do not compile with warning level 3
-	# if warnings are fatal
-	COMPILER_WARNINGS_FATAL=false
 endif
 
 OTHER_INCLUDES += -I$(LAUNCHER_SHARE_SRC)
--- a/make/java/main/java/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/main/java/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1996-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/java/main/javaw/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/main/javaw/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/java/net/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/net/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -94,8 +94,6 @@
 
 ifeq ($(PLATFORM), windows)
   OTHER_LDLIBS = ws2_32.lib $(JVMLIB)
-  # Will not compile at warning level 3 if warnings are fatal
-  COMPILER_WARNINGS_FATAL=false
 else
   OTHER_LDLIBS = $(LIBSOCKET) -lnsl -ldl $(JVMLIB)
 endif
--- a/make/java/nio/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/nio/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -134,7 +134,6 @@
      $(OBJDIR)/../../../java.lang/java/$(OBJDIRNAME)/FileDescriptor_md.obj
 endif
 ifeq ($(PLATFORM), linux)
-COMPILER_WARNINGS_FATAL=true
 OTHER_LDLIBS += -L$(LIBDIR)/$(LIBARCH) -ljava -lnet -lpthread -ldl
 endif
 ifeq ($(PLATFORM), solaris)
--- a/make/java/nio/genCharsetProvider.sh	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/nio/genCharsetProvider.sh	Thu Aug 07 22:24:26 2008 -0700
@@ -1,7 +1,7 @@
 #! /bin/sh
 
 #
-# Copyright 2004-2005 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2004-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/java/nio/genExceptions.sh	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/nio/genExceptions.sh	Thu Aug 07 22:24:26 2008 -0700
@@ -1,6 +1,6 @@
 #! /bin/sh
 #
-# Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/java/npt/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/npt/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -53,11 +53,6 @@
 OTHER_INCLUDES = -I$(SRCDIR) -I$(PSRCDIR)
 
 #
-# This removes all asserts in the optimized version
-#
-CPPFLAGS_OPT += -DNDEBUG
-
-#
 # Library to compile.
 #
 include $(BUILDDIR)/common/Library.gmk
--- a/make/java/sun_nio/FILES_java.gmk	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/sun_nio/FILES_java.gmk	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/java/verify/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/verify/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -43,8 +43,6 @@
   #
   JAVALIB = 
   EXTRA_LIBS = 
-  # Files built here do not compile with warning level 3 if warnings are fatal
-  COMPILER_WARNINGS_FATAL=false
 endif
 
 #
--- a/make/java/zip/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/java/zip/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -49,9 +49,6 @@
 
 ifneq ($(PLATFORM), windows)
 OTHER_CFLAGS += -DUSE_MMAP
-else
-  # Files built here do not compile with warning level 3 if warnings are fatal
-  COMPILER_WARNINGS_FATAL=false
 endif
 
 #
--- a/make/javax/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/javax/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1998-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/javax/others/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/javax/others/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1998-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/jdk_generic_profile.sh	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/jdk_generic_profile.sh	Thu Aug 07 22:24:26 2008 -0700
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # 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 @@
   # System place where JDK installed images are stored?
   jdk_instances=/usr/jdk/instances
 
-  # Get the SS11 compilers (and latest patches for them too)
+  # Get the Sun Studio compilers (and latest patches for them too)
   if [ "${ALT_COMPILER_PATH}" = "" ] ; then
     ALT_COMPILER_PATH=/opt/SUNWspro/bin
     export ALT_COMPILER_PATH
--- a/make/jpda/back/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/jpda/back/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -53,11 +53,6 @@
 endif # PLATFORM
 
 #
-# This turns off all assert() checking in the optimized library
-#
-CPPFLAGS_OPT += -DNDEBUG
-
-#
 # This controls the ability to do logging in the library.
 #
 CPPFLAGS_DBG += -DJDWP_LOGGING
--- a/make/jpda/transport/shmem/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/jpda/transport/shmem/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -36,13 +36,6 @@
 
 include $(BUILDDIR)/common/Defs.gmk
 
-# 64-bit windows does not build at -W3 if warnings are fatal
-ifeq ($(PLATFORM), windows)
-  ifeq ($(ARCH_DATA_MODEL), 64)
-    COMPILER_WARNINGS_FATAL=false
-  endif
-endif
-
 FILES_c = \
         SharedMemoryTransport.c \
         SharedMemoryConnection.c \
--- a/make/jpda/transport/socket/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/jpda/transport/socket/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -36,11 +36,6 @@
 
 include $(BUILDDIR)/common/Defs.gmk
 
-ifeq ($(PLATFORM), windows)
-  # Files built here do not compile with warning level 3 if warnings are fatal
-  COMPILER_WARNINGS_FATAL=false
-endif
-
 ifeq ($(PLATFORM), linux)
   OTHER_LDLIBS += -lnsl $(LIBSOCKET) -lpthread
 endif
--- a/make/jprt.config	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/jprt.config	Thu Aug 07 22:24:26 2008 -0700
@@ -1,7 +1,7 @@
 #!echo "This is not a shell script"
 #############################################################################
 #
-# Copyright 2006-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2006-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -133,9 +133,15 @@
 	solaris_arch=i386
     fi
 
-    # Get the SS11 compilers into path (make sure it matches ALT setting)
-    compiler_path=${jdk_devtools}/${solaris_arch}/SUNWspro/SS11/bin
-    compiler_name=SS11
+    # Get the compilers into path (make sure it matches ALT setting)
+    if [ "${JPRT_SOLARIS_COMPILER_NAME}" != "" ] ; then
+        compiler_name=${JPRT_SOLARIS_COMPILER_NAME}
+    else
+        # FIXUP: Change to SS12 when validated
+	#compiler_name=SS12
+	compiler_name=SS11
+    fi
+    compiler_path=${jdk_devtools}/${solaris_arch}/SUNWspro/${compiler_name}/bin
     ALT_COMPILER_PATH="${compiler_path}"
     export ALT_COMPILER_PATH
     dirMustExist "${compiler_path}" ALT_COMPILER_PATH
--- a/make/sun/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/sun/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1995-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1995-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/sun/cmm/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/sun/cmm/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2006-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2006-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/sun/cmm/kcms/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/sun/cmm/kcms/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -47,8 +47,6 @@
 ifeq ($(PLATFORM), windows)
   # Override the default version info with our own resource file (see 5043594)
   VERSIONINFO_RESOURCE = $(CLOSED_SRC)/share/native/sun/java2d/cmm/kcms/cmm.rc
-  # Files built here do not compile with warning level 3 if warnings are fatal
-  COMPILER_WARNINGS_FATAL=false
 endif
 
 # Rules
--- a/make/sun/font/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/sun/font/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -77,9 +77,6 @@
 
 ifeq ($(PLATFORM), windows)
 
-  # Files built here do not compile with warning level 3 if warnings are fatal
-  COMPILER_WARNINGS_FATAL=false
-
   LDLIBS += user32.lib gdi32.lib $(OBJDIR)/../../../sun.awt/awt/$(OBJDIRNAME)/awt.lib  
 
   OTHER_CFLAGS += -DCC_NOEX
--- a/make/sun/font/t2k/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/sun/font/t2k/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -64,9 +64,6 @@
 
 ifeq ($(PLATFORM), windows)
 
-  # Files built here do not compile with warning level 3 if warnings are fatal
-  COMPILER_WARNINGS_FATAL=false
-
   # t2k imports several shared methods from fontmanager.dll
   LDLIBS += user32.lib $(OBJDIR)/../../../sun.font/fontmanager/$(OBJDIRNAME)/fontmanager.lib
 
--- a/make/sun/jawt/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/sun/jawt/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # 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,6 @@
 # Other extra flags needed for compiling.
 #
 CPPFLAGS += -I$(OPENWIN_HOME)/include \
-	    -I$(MOTIF_DIR)/include \
 	    -I$(SHARE_SRC)/native/$(PKGDIR)/debug \
             -I$(SHARE_SRC)/native/$(PKGDIR)/image \
 	    -I$(SHARE_SRC)/native/$(PKGDIR)/image/cvutils \
--- a/make/sun/jdbc/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/sun/jdbc/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -69,11 +69,6 @@
   INIT += $(ODBC_FAKE_LIBRARIES)
 endif
 
-ifeq ($(PLATFORM),windows)
-  # Files built here do not compile with warning level 3 if warnings are fatal
-  COMPILER_WARNINGS_FATAL=false
-endif
-
 #
 # Rules
 #
--- a/make/sun/jpeg/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/sun/jpeg/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -73,10 +73,5 @@
 #
 vpath %.c   $(SHARE_SRC)/native/$(PKGDIR)/image/jpeg
 
-ifeq ($(PLATFORM), windows)
-  # Files built here do not compile with warning level 3 if warnings are fatal
-  COMPILER_WARNINGS_FATAL=false
-endif # PLATFORM
-
 CLASSES.export += java.io.InputStream
 
--- a/make/sun/splashscreen/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/sun/splashscreen/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/tools/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/tools/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 1998-2005 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -51,7 +51,6 @@
   jdwpgen                   \
   makeclasslist             \
   strip_properties          \
-  winver                    \
   CharsetMapping
 
 all build clean clobber::
--- a/make/tools/freetypecheck/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/tools/freetypecheck/Makefile	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
--- a/make/tools/freetypecheck/freetypecheck.c	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/tools/freetypecheck/freetypecheck.c	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/make/tools/src/build/tools/jdwpgen/CommandNode.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/tools/src/build/tools/jdwpgen/CommandNode.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2001 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/make/tools/src/build/tools/jdwpgen/ConstantSetNode.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/tools/src/build/tools/jdwpgen/ConstantSetNode.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2004 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/make/tools/src/build/tools/jdwpgen/RepeatNode.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/make/tools/src/build/tools/jdwpgen/RepeatNode.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-1999 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/make/tools/winver/Makefile	Thu Aug 07 11:19:06 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-#
-# Copyright 1998-2005 Sun Microsystems, Inc.  All Rights Reserved.
-# 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.  Sun designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
-# CA 95054 USA or visit www.sun.com if you need additional information or
-# have any questions.
-#
-
-#
-# Makefile for building the winver tool
-#
-
-BUILDDIR = ../..
-PRODUCT = tools
-PROGRAM = winver
-include $(BUILDDIR)/common/Defs.gmk
-
-build: permissions
-
-permissions:
-ifeq ($(PLATFORM),windows)
-	$(CHMOD) a+x bin/winver.exe
-endif
-
-#
-# Rules.
-#
-include $(BUILDDIR)/common/Rules.gmk
-
-.PHONY: permissions
-
Binary file make/tools/winver/bin/winver.exe has changed
--- a/make/tools/winver/src/StdAfx.cpp	Thu Aug 07 11:19:06 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright 2001 Sun Microsystems, Inc.  All Rights Reserved.
- * 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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-// stdafx.cpp : source file that includes just the standard includes
-//      getver.pch will be the pre-compiled header
-//      stdafx.obj will contain the pre-compiled type information
-
-#include "stdafx.h"
-
-// TODO: reference any additional headers you need in STDAFX.H
-// and not in this file
--- a/make/tools/winver/src/StdAfx.h	Thu Aug 07 11:19:06 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright 2001 Sun Microsystems, Inc.  All Rights Reserved.
- * 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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-// stdafx.h : include file for standard system include files,
-//  or project specific include files that are used frequently, but
-//      are changed infrequently
-//
-
-#if !defined(AFX_STDAFX_H__C592D6C3_027D_11D5_8DFB_080020C19238__INCLUDED_)
-#define AFX_STDAFX_H__C592D6C3_027D_11D5_8DFB_080020C19238__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
-
-#include <stdio.h>
-
-// TODO: reference additional headers your program requires here
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_STDAFX_H__C592D6C3_027D_11D5_8DFB_080020C19238__INCLUDED_)
--- a/make/tools/winver/src/winver.cpp	Thu Aug 07 11:19:06 2008 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright 2001 Sun Microsystems, Inc.  All Rights Reserved.
- * 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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-// getver.cpp : Defines the entry point for the console application.
-//
-
-#include "stdafx.h"
-#include <windows.h>
-
-int main(int argc, char* argv[])
-{
-        OSVERSIONINFO verInfo;
-
-        memset(&verInfo,0,sizeof(verInfo));
-        verInfo.dwOSVersionInfoSize = sizeof(verInfo);
-
-        if (GetVersionEx(&verInfo))
-        {
-                printf("%d %d %s",verInfo.dwMajorVersion,verInfo.dwMinorVersion,verInfo.szCSDVersion);
-        }
-        else
-        {
-                printf("No version info available");
-        }
-
-        return 0;
-}
--- a/src/share/back/eventFilter.c	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/back/eventFilter.c	Thu Aug 07 22:24:26 2008 -0700
@@ -492,14 +492,17 @@
                   char *sourceName = 0;
                   jvmtiError error = JVMTI_FUNC_PTR(gdata->jvmti,GetSourceFileName)
                                             (gdata->jvmti, clazz, &sourceName);
-                  if (error == JVMTI_ERROR_NONE) {
-                      if (sourceName == 0 || !patternStringMatch(sourceName, desiredNamePattern)) {
-                        /* We have no match */
-                        jvmtiDeallocate(sourceName);
-                        return JNI_FALSE;
-                      }
+                  if (error == JVMTI_ERROR_NONE &&
+                      sourceName != 0 &&
+                      patternStringMatch(sourceName, desiredNamePattern)) {
+                          // got a hit - report the event
+                          jvmtiDeallocate(sourceName);
+                          break;
                   }
+                  // We have no match, we have no source file name,
+                  // or we got a JVM TI error. Don't report the event.
                   jvmtiDeallocate(sourceName);
+                  return JNI_FALSE;
               }
               break;
           }
--- a/src/share/bin/java.h	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/bin/java.h	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/bin/main.c	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/bin/main.c	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1995-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/classes/com/sun/java/swing/plaf/gtk/GTKColorChooserPanel.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/java/swing/plaf/gtk/GTKColorChooserPanel.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2004 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifGraphicsUtils.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifGraphicsUtils.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameTitlePane.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameTitlePane.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2004 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1222,9 +1222,7 @@
             "FileChooser.enterFileNameLabelMnemonic", new Integer (KeyEvent.VK_N), // 'n'
             "FileChooser.ancestorInputMap",
                new UIDefaults.LazyInputMap(new Object[] {
-                     "ESCAPE", "cancelSelection",
-                     "ENTER", "approveSelection",
-                "ctrl ENTER", "approveSelection"
+                     "ESCAPE", "cancelSelection"
                  }),
 
 
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -825,9 +825,7 @@
                      "ESCAPE", "cancelSelection",
                      "F2", "editFileName",
                      "F5", "refresh",
-                     "BACK_SPACE", "Go Up",
-                     "ENTER", "approveSelection",
-                "ctrl ENTER", "approveSelection"
+                     "BACK_SPACE", "Go Up"
                  }),
 
             "FileView.directoryIcon", SwingUtilities2.makeIcon(getClass(),
--- a/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -84,8 +84,13 @@
 import com.sun.jmx.mbeanserver.Repository;
 import com.sun.jmx.mbeanserver.NamedObject;
 import com.sun.jmx.mbeanserver.Introspector;
+import com.sun.jmx.mbeanserver.MBeanInjector;
+import com.sun.jmx.mbeanserver.NotifySupport;
+import com.sun.jmx.mbeanserver.Repository.RegistrationContext;
 import com.sun.jmx.mbeanserver.Util;
 import com.sun.jmx.remote.util.EnvHelp;
+import javax.management.DynamicWrapperMBean;
+import javax.management.NotificationBroadcasterSupport;
 
 /**
  * This is the default class for MBean manipulation on the agent side. It
@@ -433,36 +438,26 @@
         if (instance instanceof MBeanRegistration)
             preDeregisterInvoke((MBeanRegistration) instance);
 
-        repository.remove(name);
-            // may throw InstanceNotFoundException
+        final Object resource = getResource(instance);
 
-        /**
-         * Checks if the unregistered MBean is a ClassLoader
-         * If so, it removes the  MBean from the default loader repository.
-         */
+        // Unregisters the MBean from the repository.
+        // Returns the resource context that was used.
+        // The returned context does nothing for regular MBeans.
+        // For ClassLoader MBeans and JMXNamespace (and JMXDomain)
+        // MBeans - the context makes it possible to unregister these
+        // objects from the appropriate framework artifacts, such as
+        // the CLR or the dispatcher, from within the repository lock.
+        // In case of success, we also need to call context.done() at the
+        // end of this method.
+        //
+        final ResourceContext context =
+                unregisterFromRepository(resource, instance, name);
 
-        Object resource = getResource(instance);
-        if (resource instanceof ClassLoader
-            && resource != server.getClass().getClassLoader()) {
-            final ModifiableClassLoaderRepository clr =
-                instantiator.getClassLoaderRepository();
-            if (clr != null) clr.removeClassLoader(name);
-        }
-
-        // ---------------------
-        // Send deletion event
-        // ---------------------
-        if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
-            MBEANSERVER_LOGGER.logp(Level.FINER,
-                    DefaultMBeanServerInterceptor.class.getName(),
-                    "unregisterMBean", "Send delete notification of object " +
-                    name.getCanonicalName());
-        }
-        sendNotification(MBeanServerNotification.UNREGISTRATION_NOTIFICATION,
-                         name);
 
         if (instance instanceof MBeanRegistration)
             postDeregisterInvoke((MBeanRegistration) instance);
+
+        context.done();
     }
 
     public ObjectInstance getObjectInstance(ObjectName name)
@@ -939,15 +934,22 @@
         }
 
         ObjectName logicalName = name;
+        logicalName = preRegister(mbean, server, name);
 
-        if (mbean instanceof MBeanRegistration) {
-            MBeanRegistration reg = (MBeanRegistration) mbean;
-            logicalName = preRegisterInvoke(reg, name, server);
+        // preRegister returned successfully, so from this point on we
+        // must call postRegister(false) if there is any problem.
+        boolean registered = false;
+        boolean registerFailed = false;
+        ResourceContext context = null;
+
+        try {
+            mbean = injectResources(mbean, server, logicalName);
+
             if (mbean instanceof DynamicMBean2) {
                 try {
                     ((DynamicMBean2) mbean).preRegister2(server, logicalName);
+                    registerFailed = true;  // until we succeed
                 } catch (Exception e) {
-                    postRegisterInvoke(reg, false, false);
                     if (e instanceof RuntimeException)
                         throw (RuntimeException) e;
                     if (e instanceof InstanceAlreadyExistsException)
@@ -960,86 +962,102 @@
                 logicalName =
                     ObjectName.getInstance(nonDefaultDomain(logicalName));
             }
+
+            checkMBeanPermission(classname, null, logicalName, "registerMBean");
+
+            if (logicalName == null) {
+                final RuntimeException wrapped =
+                        new IllegalArgumentException("No object name specified");
+                throw new RuntimeOperationsException(wrapped,
+                                                     "Exception occurred trying to register the MBean");
+            }
+
+            final Object resource = getResource(mbean);
+
+            // Register the MBean with the repository.
+            // Returns the resource context that was used.
+            // The returned context does nothing for regular MBeans.
+            // For ClassLoader MBeans and JMXNamespace (and JMXDomain)
+            // MBeans - the context makes it possible to register these
+            // objects with the appropriate framework artifacts, such as
+            // the CLR or the dispatcher, from within the repository lock.
+            // In case of success, we also need to call context.done() at the
+            // end of this method.
+            //
+            context = registerWithRepository(resource, mbean, logicalName);
+
+            registerFailed = false;
+            registered = true;
+        } finally {
+            postRegister(mbean, registered, registerFailed);
         }
 
-        checkMBeanPermission(classname, null, logicalName, "registerMBean");
-
-        final ObjectInstance result;
-        if (logicalName!=null) {
-            result = new ObjectInstance(logicalName, classname);
-            internal_addObject(mbean, logicalName);
-        } else {
-            if (mbean instanceof MBeanRegistration)
-                postRegisterInvoke((MBeanRegistration) mbean, false, true);
-            final RuntimeException wrapped =
-                new IllegalArgumentException("No object name specified");
-            throw new RuntimeOperationsException(wrapped,
-                        "Exception occurred trying to register the MBean");
-        }
-
-        if (mbean instanceof MBeanRegistration)
-            postRegisterInvoke((MBeanRegistration) mbean, true, false);
-
-        /**
-         * Checks if the newly registered MBean is a ClassLoader
-         * If so, tell the ClassLoaderRepository (CLR) about it.  We do
-         * this even if the object is a PrivateClassLoader.  In that
-         * case, the CLR remembers the loader for use when it is
-         * explicitly named (e.g. as the loader in createMBean) but
-         * does not add it to the list that is consulted by
-         * ClassLoaderRepository.loadClass.
-         */
-        final Object resource = getResource(mbean);
-        if (resource instanceof ClassLoader) {
-            final ModifiableClassLoaderRepository clr =
-                instantiator.getClassLoaderRepository();
-            if (clr == null) {
-                final RuntimeException wrapped =
-                    new IllegalArgumentException(
-                     "Dynamic addition of class loaders is not supported");
-                throw new RuntimeOperationsException(wrapped,
-           "Exception occurred trying to register the MBean as a class loader");
-            }
-            clr.addClassLoader(logicalName, (ClassLoader) resource);
-        }
-
-        return result;
+        context.done();
+        return new ObjectInstance(logicalName, classname);
     }
 
-    private static ObjectName preRegisterInvoke(MBeanRegistration moi,
-                                                ObjectName name,
-                                                MBeanServer mbs)
-            throws InstanceAlreadyExistsException, MBeanRegistrationException {
-
-        final ObjectName newName;
-
+    private static void throwMBeanRegistrationException(Throwable t, String where)
+    throws MBeanRegistrationException {
         try {
-            newName = moi.preRegister(mbs, name);
+            throw t;
         } catch (RuntimeException e) {
-                throw new RuntimeMBeanException(e,
-                           "RuntimeException thrown in preRegister method");
+                throw new RuntimeMBeanException(
+                        e, "RuntimeException thrown " + where);
         } catch (Error er) {
-                throw new RuntimeErrorException(er,
-                           "Error thrown in preRegister method");
+                throw new RuntimeErrorException(er, "Error thrown " + where);
         } catch (MBeanRegistrationException r) {
             throw r;
         } catch (Exception ex) {
-            throw new MBeanRegistrationException(ex,
-                          "Exception thrown in preRegister method");
+            throw new MBeanRegistrationException(ex, "Exception thrown " + where);
+        } catch (Throwable t1) {
+            throw new RuntimeException(t);  // neither Error nor Exception??
+        }
+    }
+
+    private static ObjectName preRegister(
+            DynamicMBean mbean, MBeanServer mbs, ObjectName name)
+            throws InstanceAlreadyExistsException, MBeanRegistrationException {
+
+        ObjectName newName = null;
+
+        try {
+            if (mbean instanceof MBeanRegistration)
+                newName = ((MBeanRegistration) mbean).preRegister(mbs, name);
+        } catch (Throwable t) {
+            throwMBeanRegistrationException(t, "in preRegister method");
         }
 
         if (newName != null) return newName;
         else return name;
     }
 
-    private static void postRegisterInvoke(MBeanRegistration moi,
-                                           boolean registrationDone,
-                                           boolean registerFailed) {
+    private static DynamicMBean injectResources(
+            DynamicMBean mbean, MBeanServer mbs, ObjectName name)
+    throws MBeanRegistrationException {
+        try {
+            Object resource = getResource(mbean);
+            MBeanInjector.inject(resource, mbs, name);
+            if (MBeanInjector.injectsSendNotification(resource)) {
+                NotificationBroadcasterSupport nbs =
+                        new NotificationBroadcasterSupport();
+                MBeanInjector.injectSendNotification(resource, nbs);
+                mbean = NotifySupport.wrap(mbean, nbs);
+            }
+            return mbean;
+        } catch (Throwable t) {
+            throwMBeanRegistrationException(t, "injecting @Resources");
+            return null;  // not reached
+        }
+    }
 
-        if (registerFailed && moi instanceof DynamicMBean2)
-            ((DynamicMBean2) moi).registerFailed();
+    private static void postRegister(
+            DynamicMBean mbean, boolean registrationDone, boolean registerFailed) {
+
+        if (registerFailed && mbean instanceof DynamicMBean2)
+            ((DynamicMBean2) mbean).registerFailed();
         try {
-            moi.postRegister(registrationDone);
+            if (mbean instanceof MBeanRegistration)
+                ((MBeanRegistration) mbean).postRegister(registrationDone);
         } catch (RuntimeException e) {
             throw new RuntimeMBeanException(e,
                       "RuntimeException thrown in postRegister method");
@@ -1053,17 +1071,8 @@
             throws MBeanRegistrationException {
         try {
             moi.preDeregister();
-        } catch (RuntimeException e) {
-            throw new RuntimeMBeanException(e,
-                         "RuntimeException thrown in preDeregister method");
-        } catch (Error er) {
-            throw new RuntimeErrorException(er,
-                         "Error thrown in preDeregister method");
-        } catch (MBeanRegistrationException t) {
-            throw t;
-        } catch (Exception ex) {
-            throw new MBeanRegistrationException(ex,
-                         "Exception thrown in preDeregister method");
+        } catch (Throwable t) {
+            throwMBeanRegistrationException(t, "in preDeregister method");
         }
     }
 
@@ -1104,12 +1113,19 @@
     }
 
     private static Object getResource(DynamicMBean mbean) {
-        if (mbean instanceof DynamicMBean2)
-            return ((DynamicMBean2) mbean).getResource();
+        if (mbean instanceof DynamicWrapperMBean)
+            return ((DynamicWrapperMBean) mbean).getWrappedObject();
         else
             return mbean;
     }
 
+    private static ClassLoader getResourceLoader(DynamicMBean mbean) {
+        if (mbean instanceof DynamicWrapperMBean)
+            return ((DynamicWrapperMBean) mbean).getWrappedClassLoader();
+        else
+            return mbean.getClass().getClassLoader();
+    }
+
     private ObjectName nonDefaultDomain(ObjectName name) {
         if (name == null || name.getDomain().length() > 0)
             return name;
@@ -1123,14 +1139,7 @@
            if one is supplied where it shouldn't be).  */
         final String completeName = domain + name;
 
-        try {
-            return new ObjectName(completeName);
-        } catch (MalformedObjectNameException e) {
-            final String msg =
-                "Unexpected default domain problem: " + completeName + ": " +
-                e;
-            throw EnvHelp.initCause(new IllegalArgumentException(msg), e);
-        }
+        return Util.newObjectName(completeName);
     }
 
     public String getDefaultDomain()  {
@@ -1211,7 +1220,7 @@
         }
 
         NotificationListener listenerWrapper =
-            getListenerWrapper(listener, name, broadcaster, true);
+            getListenerWrapper(listener, name, instance, true);
         broadcaster.addNotificationListener(listenerWrapper, filter, handback);
     }
 
@@ -1335,7 +1344,6 @@
         DynamicMBean instance = getMBean(name);
         checkMBeanPermission(instance, null, name,
                              "removeNotificationListener");
-        Object resource = getResource(instance);
 
         /* We could simplify the code by assigning broadcaster after
            assigning listenerWrapper, but that would change the error
@@ -1348,7 +1356,7 @@
             getNotificationBroadcaster(name, instance, reqClass);
 
         NotificationListener listenerWrapper =
-            getListenerWrapper(listener, name, resource, false);
+            getListenerWrapper(listener, name, instance, false);
 
         if (listenerWrapper == null)
             throw new ListenerNotFoundException("Unknown listener");
@@ -1366,8 +1374,10 @@
     private static <T extends NotificationBroadcaster>
             T getNotificationBroadcaster(ObjectName name, Object instance,
                                          Class<T> reqClass) {
-        if (instance instanceof DynamicMBean2)
-            instance = ((DynamicMBean2) instance).getResource();
+        if (reqClass.isInstance(instance))
+            return reqClass.cast(instance);
+        if (instance instanceof DynamicWrapperMBean)
+            instance = ((DynamicWrapperMBean) instance).getWrappedObject();
         if (reqClass.isInstance(instance))
             return reqClass.cast(instance);
         final RuntimeException exc =
@@ -1415,24 +1425,31 @@
         checkMBeanPermission(instance, null, name, "isInstanceOf");
 
         try {
-            if (instance instanceof DynamicMBean2) {
-                Object resource = ((DynamicMBean2) instance).getResource();
-                ClassLoader loader = resource.getClass().getClassLoader();
-                Class<?> c = Class.forName(className, false, loader);
-                return c.isInstance(resource);
-            }
+            Object resource = getResource(instance);
 
-            final String cn = getClassName(instance);
-            if (cn.equals(className))
+            final String resourceClassName =
+                    (resource instanceof DynamicMBean) ?
+                        getClassName((DynamicMBean) resource) :
+                        resource.getClass().getName();
+
+            if (resourceClassName.equals(className))
                 return true;
-            final ClassLoader cl = instance.getClass().getClassLoader();
+            final ClassLoader cl = getResourceLoader(instance);
 
             final Class<?> classNameClass = Class.forName(className, false, cl);
-            if (classNameClass.isInstance(instance))
+            if (classNameClass.isInstance(resource))
                 return true;
 
-            final Class<?> instanceClass = Class.forName(cn, false, cl);
-            return classNameClass.isAssignableFrom(instanceClass);
+            // Ensure that isInstanceOf(NotificationEmitter) is true when
+            // the MBean is a NotificationEmitter by virtue of a @Resource
+            // annotation specifying a SendNotification resource.
+            // This is a hack.
+            if (instance instanceof NotificationBroadcaster &&
+                    classNameClass.isAssignableFrom(NotificationEmitter.class))
+                return true;
+
+            final Class<?> resourceClass = Class.forName(resourceClassName, false, cl);
+            return classNameClass.isAssignableFrom(resourceClass);
         } catch (Exception x) {
             /* Could be SecurityException or ClassNotFoundException */
             if (MBEANSERVER_LOGGER.isLoggable(Level.FINEST)) {
@@ -1457,7 +1474,7 @@
 
         DynamicMBean instance = getMBean(mbeanName);
         checkMBeanPermission(instance, null, mbeanName, "getClassLoaderFor");
-        return getResource(instance).getClass().getClassLoader();
+        return getResourceLoader(instance);
     }
 
     /**
@@ -1489,40 +1506,6 @@
     }
 
     /**
-     * Adds a MBean in the repository
-     */
-    private void internal_addObject(DynamicMBean object, ObjectName logicalName)
-        throws InstanceAlreadyExistsException {
-
-        // ------------------------------
-        // ------------------------------
-
-        // Let the repository do the work.
-
-        try {
-           repository.addMBean(object, logicalName);
-        }  catch (InstanceAlreadyExistsException e) {
-            if (object instanceof MBeanRegistration) {
-                postRegisterInvoke((MBeanRegistration) object, false, true);
-            }
-            throw e;
-        }
-
-        // ---------------------
-        // Send create event
-        // ---------------------
-        if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
-            MBEANSERVER_LOGGER.logp(Level.FINER,
-                    DefaultMBeanServerInterceptor.class.getName(),
-                    "addObject", "Send create notification of object " +
-                    logicalName.getCanonicalName());
-        }
-
-        sendNotification(MBeanServerNotification.REGISTRATION_NOTIFICATION,
-                         logicalName ) ;
-    }
-
-    /**
      * Sends an MBeanServerNotifications with the specified type for the
      * MBean with the specified ObjectName
      */
@@ -1712,9 +1695,10 @@
      */
     private NotificationListener getListenerWrapper(NotificationListener l,
                                                     ObjectName name,
-                                                    Object mbean,
+                                                    DynamicMBean mbean,
                                                     boolean create) {
-        ListenerWrapper wrapper = new ListenerWrapper(l, name, mbean);
+        Object resource = getResource(mbean);
+        ListenerWrapper wrapper = new ListenerWrapper(l, name, resource);
         synchronized (listenerWrappers) {
             WeakReference<ListenerWrapper> ref = listenerWrappers.get(wrapper);
             if (ref != null) {
@@ -1758,6 +1742,7 @@
             listener.handleNotification(notification, handback);
         }
 
+        @Override
         public boolean equals(Object o) {
             if (!(o instanceof ListenerWrapper))
                 return false;
@@ -1774,6 +1759,7 @@
              */
         }
 
+        @Override
         public int hashCode() {
             return (System.identityHashCode(listener) ^
                     System.identityHashCode(mbean));
@@ -1851,4 +1837,213 @@
         }
     }
 
+    // ------------------------------------------------------------------
+    //
+    // Dealing with registration of special MBeans in the repository.
+    //
+    // ------------------------------------------------------------------
+
+    /**
+     * A RegistrationContext that makes it possible to perform additional
+     * post registration actions (or post unregistration actions) outside
+     * of the repository lock, once postRegister (or postDeregister) has
+     * been called.
+     * The method {@code done()} will be called in registerMBean or
+     * unregisterMBean, at the end.
+     */
+    private static interface ResourceContext extends RegistrationContext {
+        public void done();
+        /** An empty ResourceContext which does nothing **/
+        public static final ResourceContext NONE = new ResourceContext() {
+            public void done() {}
+            public void registering() {}
+            public void unregistered() {}
+        };
+    }
+
+    /**
+     * Adds a MBean in the repository,
+     * sends MBeanServerNotification.REGISTRATION_NOTIFICATION,
+     * returns ResourceContext for special resources such as ClassLoaders
+     * or JMXNamespaces. For regular MBean this method returns
+     * ResourceContext.NONE.
+     * @return a ResourceContext for special resources such as ClassLoaders
+     *         or JMXNamespaces.
+     */
+    private ResourceContext registerWithRepository(
+            final Object resource,
+            final DynamicMBean object,
+            final ObjectName logicalName)
+            throws InstanceAlreadyExistsException,
+            MBeanRegistrationException {
+
+        // Creates a registration context, if needed.
+        //
+        final ResourceContext context =
+                makeResourceContextFor(resource, logicalName);
+
+
+        repository.addMBean(object, logicalName, context);
+        // May throw InstanceAlreadyExistsException
+
+        // ---------------------
+        // Send create event
+        // ---------------------
+        if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
+            MBEANSERVER_LOGGER.logp(Level.FINER,
+                    DefaultMBeanServerInterceptor.class.getName(),
+                    "addObject", "Send create notification of object " +
+                    logicalName.getCanonicalName());
+        }
+
+        sendNotification(
+                MBeanServerNotification.REGISTRATION_NOTIFICATION,
+                logicalName);
+
+        return context;
+    }
+
+    /**
+     * Removes a MBean in the repository,
+     * sends MBeanServerNotification.UNREGISTRATION_NOTIFICATION,
+     * returns ResourceContext for special resources such as ClassLoaders
+     * or JMXNamespaces, or null. For regular MBean this method returns
+     * ResourceContext.NONE.
+     *
+     * @return a ResourceContext for special resources such as ClassLoaders
+     *         or JMXNamespaces.
+     */
+    private ResourceContext unregisterFromRepository(
+            final Object resource,
+            final DynamicMBean object,
+            final ObjectName logicalName)
+            throws InstanceNotFoundException {
+
+        // Creates a registration context, if needed.
+        //
+        final ResourceContext context =
+                makeResourceContextFor(resource, logicalName);
+
+
+        repository.remove(logicalName, context);
+
+        // ---------------------
+        // Send deletion event
+        // ---------------------
+        if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
+            MBEANSERVER_LOGGER.logp(Level.FINER,
+                    DefaultMBeanServerInterceptor.class.getName(),
+                    "unregisterMBean", "Send delete notification of object " +
+                    logicalName.getCanonicalName());
+        }
+
+        sendNotification(MBeanServerNotification.UNREGISTRATION_NOTIFICATION,
+                logicalName);
+        return context;
+    }
+
+    /**
+     * Registers a ClassLoader with the CLR.
+     * This method is called by the ResourceContext from within the
+     * repository lock.
+     * @param loader       The ClassLoader.
+     * @param logicalName  The ClassLoader MBean ObjectName.
+     */
+    private void addClassLoader(ClassLoader loader,
+            final ObjectName logicalName) {
+        /**
+         * Called when the newly registered MBean is a ClassLoader
+         * If so, tell the ClassLoaderRepository (CLR) about it.  We do
+         * this even if the loader is a PrivateClassLoader.  In that
+         * case, the CLR remembers the loader for use when it is
+         * explicitly named (e.g. as the loader in createMBean) but
+         * does not add it to the list that is consulted by
+         * ClassLoaderRepository.loadClass.
+         */
+        final ModifiableClassLoaderRepository clr =
+                instantiator.getClassLoaderRepository();
+        if (clr == null) {
+            final RuntimeException wrapped =
+                    new IllegalArgumentException(
+                    "Dynamic addition of class loaders" +
+                    " is not supported");
+            throw new RuntimeOperationsException(wrapped,
+                    "Exception occurred trying to register" +
+                    " the MBean as a class loader");
+        }
+        clr.addClassLoader(logicalName, loader);
+    }
+
+    /**
+     * Unregisters a ClassLoader from the CLR.
+     * This method is called by the ResourceContext from within the
+     * repository lock.
+     * @param loader       The ClassLoader.
+     * @param logicalName  The ClassLoader MBean ObjectName.
+     */
+    private void removeClassLoader(ClassLoader loader,
+            final ObjectName logicalName) {
+        /**
+         * Removes the  MBean from the default loader repository.
+         */
+        if (loader != server.getClass().getClassLoader()) {
+            final ModifiableClassLoaderRepository clr =
+                    instantiator.getClassLoaderRepository();
+            if (clr != null) {
+                clr.removeClassLoader(logicalName);
+            }
+        }
+    }
+
+    /**
+     * Creates a ResourceContext for a ClassLoader MBean.
+     * The resource context makes it possible to add the ClassLoader to
+     * (ResourceContext.registering) or resp. remove the ClassLoader from
+     * (ResourceContext.unregistered) the CLR
+     * when the associated MBean is added to or resp. removed from the
+     * repository.
+     *
+     * @param loader       The ClassLoader MBean being registered or
+     *                     unregistered.
+     * @param logicalName  The name of the ClassLoader MBean.
+     * @return a ResourceContext that takes in charge the addition or removal
+     *         of the loader to or from the CLR.
+     */
+    private ResourceContext createClassLoaderContext(
+            final ClassLoader loader,
+            final ObjectName logicalName) {
+        return new ResourceContext() {
+
+            public void registering() {
+                addClassLoader(loader, logicalName);
+            }
+
+            public void unregistered() {
+                removeClassLoader(loader, logicalName);
+            }
+
+            public void done() {
+            }
+        };
+    }
+
+    /**
+     * Creates a ResourceContext for the given resource.
+     * If the resource does not need a ResourceContext, returns
+     * ResourceContext.NONE.
+     * At this time, only JMXNamespaces and ClassLoaders need a
+     * ResourceContext.
+     *
+     * @param resource     The resource being registered or unregistered.
+     * @param logicalName  The name of the associated MBean.
+     * @return
+     */
+    private ResourceContext makeResourceContextFor(Object resource,
+            ObjectName logicalName) {
+        if (resource instanceof ClassLoader) {
+            return createClassLoaderContext((ClassLoader) resource,
+                    logicalName);
+        }
+        return ResourceContext.NONE;
+    }
 }
--- a/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,13 +31,15 @@
 
 import javax.management.Descriptor;
 import javax.management.MBeanException;
+import javax.management.openmbean.MXBeanMapping;
+import javax.management.openmbean.MXBeanMappingFactory;
 import javax.management.openmbean.OpenDataException;
 import javax.management.openmbean.OpenType;
 
 final class ConvertingMethod {
-    static ConvertingMethod from(Method m) {
+    static ConvertingMethod from(Method m, MXBeanMappingFactory mappingFactory) {
         try {
-            return new ConvertingMethod(m);
+            return new ConvertingMethod(m, mappingFactory);
         } catch (OpenDataException ode) {
             final String msg = "Method " + m.getDeclaringClass().getName() +
                 "." + m.getName() + " has parameter or return type that " +
@@ -67,13 +69,13 @@
     }
 
     OpenType getOpenReturnType() {
-        return returnConverter.getOpenType();
+        return returnMapping.getOpenType();
     }
 
     OpenType[] getOpenParameterTypes() {
-        final OpenType[] types = new OpenType[paramConverters.length];
-        for (int i = 0; i < paramConverters.length; i++)
-            types[i] = paramConverters[i].getOpenType();
+        final OpenType[] types = new OpenType[paramMappings.length];
+        for (int i = 0; i < paramMappings.length; i++)
+            types[i] = paramMappings[i].getOpenType();
         return types;
     }
 
@@ -85,9 +87,9 @@
      * value will be converted to an Open Type, so if it is convertible
      * at all there is no further check needed.
      */
-    void checkCallFromOpen() throws IllegalArgumentException {
+    void checkCallFromOpen() {
         try {
-            for (OpenConverter paramConverter : paramConverters)
+            for (MXBeanMapping paramConverter : paramMappings)
                 paramConverter.checkReconstructible();
         } catch (InvalidObjectException e) {
             throw new IllegalArgumentException(e);
@@ -102,32 +104,32 @@
      * open types, so if it is convertible at all there is no further
      * check needed.
      */
-    void checkCallToOpen() throws IllegalArgumentException {
+    void checkCallToOpen() {
         try {
-            returnConverter.checkReconstructible();
+            returnMapping.checkReconstructible();
         } catch (InvalidObjectException e) {
             throw new IllegalArgumentException(e);
         }
     }
 
     String[] getOpenSignature() {
-        if (paramConverters.length == 0)
+        if (paramMappings.length == 0)
             return noStrings;
 
-        String[] sig = new String[paramConverters.length];
-        for (int i = 0; i < paramConverters.length; i++)
-            sig[i] = paramConverters[i].getOpenClass().getName();
+        String[] sig = new String[paramMappings.length];
+        for (int i = 0; i < paramMappings.length; i++)
+            sig[i] = paramMappings[i].getOpenClass().getName();
         return sig;
     }
 
     final Object toOpenReturnValue(MXBeanLookup lookup, Object ret)
             throws OpenDataException {
-        return returnConverter.toOpenValue(lookup, ret);
+        return returnMapping.toOpenValue(ret);
     }
 
     final Object fromOpenReturnValue(MXBeanLookup lookup, Object ret)
             throws InvalidObjectException {
-        return returnConverter.fromOpenValue(lookup, ret);
+        return returnMapping.fromOpenValue(ret);
     }
 
     final Object[] toOpenParameters(MXBeanLookup lookup, Object[] params)
@@ -136,17 +138,17 @@
             return params;
         final Object[] oparams = new Object[params.length];
         for (int i = 0; i < params.length; i++)
-            oparams[i] = paramConverters[i].toOpenValue(lookup, params[i]);
+            oparams[i] = paramMappings[i].toOpenValue(params[i]);
         return oparams;
     }
 
-    final Object[] fromOpenParameters(MXBeanLookup lookup, Object[] params)
+    final Object[] fromOpenParameters(Object[] params)
             throws InvalidObjectException {
         if (paramConversionIsIdentity || params == null)
             return params;
         final Object[] jparams = new Object[params.length];
         for (int i = 0; i < params.length; i++)
-            jparams[i] = paramConverters[i].fromOpenValue(lookup, params[i]);
+            jparams[i] = paramMappings[i].fromOpenValue(params[i]);
         return jparams;
     }
 
@@ -154,23 +156,35 @@
                                  Object param,
                                  int paramNo)
         throws OpenDataException {
-        return paramConverters[paramNo].toOpenValue(lookup, param);
+        return paramMappings[paramNo].toOpenValue(param);
     }
 
     final Object fromOpenParameter(MXBeanLookup lookup,
                                    Object param,
                                    int paramNo)
         throws InvalidObjectException {
-        return paramConverters[paramNo].fromOpenValue(lookup, param);
+        return paramMappings[paramNo].fromOpenValue(param);
     }
 
     Object invokeWithOpenReturn(MXBeanLookup lookup,
                                 Object obj, Object[] params)
             throws MBeanException, IllegalAccessException,
                    InvocationTargetException {
+        MXBeanLookup old = MXBeanLookup.getLookup();
+        try {
+            MXBeanLookup.setLookup(lookup);
+            return invokeWithOpenReturn(obj, params);
+        } finally {
+            MXBeanLookup.setLookup(old);
+        }
+    }
+
+    private Object invokeWithOpenReturn(Object obj, Object[] params)
+            throws MBeanException, IllegalAccessException,
+                   InvocationTargetException {
         final Object[] javaParams;
         try {
-            javaParams = fromOpenParameters(lookup, params);
+            javaParams = fromOpenParameters(params);
         } catch (InvalidObjectException e) {
             // probably can't happen
             final String msg = methodName() + ": cannot convert parameters " +
@@ -179,7 +193,7 @@
         }
         final Object javaReturn = method.invoke(obj, javaParams);
         try {
-            return returnConverter.toOpenValue(lookup, javaReturn);
+            return returnMapping.toOpenValue(javaReturn);
         } catch (OpenDataException e) {
             // probably can't happen
             final String msg = methodName() + ": cannot convert return " +
@@ -192,15 +206,17 @@
         return method.getDeclaringClass() + "." + method.getName();
     }
 
-    private ConvertingMethod(Method m) throws OpenDataException {
+    private ConvertingMethod(Method m, MXBeanMappingFactory mappingFactory)
+    throws OpenDataException {
         this.method = m;
-        returnConverter = OpenConverter.toConverter(m.getGenericReturnType());
+        returnMapping =
+                mappingFactory.mappingForType(m.getGenericReturnType(), mappingFactory);
         Type[] params = m.getGenericParameterTypes();
-        paramConverters = new OpenConverter[params.length];
+        paramMappings = new MXBeanMapping[params.length];
         boolean identity = true;
         for (int i = 0; i < params.length; i++) {
-            paramConverters[i] = OpenConverter.toConverter(params[i]);
-            identity &= paramConverters[i].isIdentity();
+            paramMappings[i] = mappingFactory.mappingForType(params[i], mappingFactory);
+            identity &= DefaultMXBeanMappingFactory.isIdentity(paramMappings[i]);
         }
         paramConversionIsIdentity = identity;
     }
@@ -208,7 +224,7 @@
     private static final String[] noStrings = new String[0];
 
     private final Method method;
-    private final OpenConverter returnConverter;
-    private final OpenConverter[] paramConverters;
+    private final MXBeanMapping returnMapping;
+    private final MXBeanMapping[] paramMappings;
     private final boolean paramConversionIsIdentity;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java	Thu Aug 07 22:24:26 2008 -0700
@@ -0,0 +1,1519 @@
+/*
+ * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.mbeanserver;
+
+import static com.sun.jmx.mbeanserver.Util.*;
+import java.lang.annotation.ElementType;
+import javax.management.openmbean.MXBeanMappingClass;
+
+import static javax.management.openmbean.SimpleType.*;
+
+import com.sun.jmx.remote.util.EnvHelp;
+
+import java.beans.ConstructorProperties;
+import java.io.InvalidObjectException;
+import java.lang.annotation.ElementType;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.WeakHashMap;
+
+import javax.management.JMX;
+import javax.management.ObjectName;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataInvocationHandler;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeDataView;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.MXBeanMapping;
+import javax.management.openmbean.MXBeanMappingFactory;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+/**
+ *   <p>A converter between Java types and the limited set of classes
+ *   defined by Open MBeans.</p>
+ *
+ *   <p>A Java type is an instance of java.lang.reflect.Type.  For our
+ *   purposes, it is either a Class, such as String.class or int.class;
+ *   or a ParameterizedType, such as List<String> or Map<Integer,
+ *   String[]>.  On J2SE 1.4 and earlier, it can only be a Class.</p>
+ *
+ *   <p>Each Type is associated with an DefaultMXBeanMappingFactory.  The
+ *   DefaultMXBeanMappingFactory defines an OpenType corresponding to the Type, plus a
+ *   Java class corresponding to the OpenType.  For example:</p>
+ *
+ *   <pre>
+ *   Type                     Open class     OpenType
+ *   ----                     ----------     --------
+ *   Integer                Integer        SimpleType.INTEGER
+ *   int                            int            SimpleType.INTEGER
+ *   Integer[]              Integer[]      ArrayType(1, SimpleType.INTEGER)
+ *   int[]                  Integer[]      ArrayType(SimpleType.INTEGER, true)
+ *   String[][]             String[][]     ArrayType(2, SimpleType.STRING)
+ *   List<String>                   String[]       ArrayType(1, SimpleType.STRING)
+ *   ThreadState (an Enum)    String         SimpleType.STRING
+ *   Map<Integer, String[]>   TabularData          TabularType(
+ *                                           CompositeType(
+ *                                             {"key", SimpleType.INTEGER},
+ *                                             {"value",
+ *                                               ArrayType(1,
+ *                                                SimpleType.STRING)}),
+ *                                           indexNames={"key"})
+ *   </pre>
+ *
+ *   <p>Apart from simple types, arrays, and collections, Java types are
+ *   converted through introspection into CompositeType.  The Java type
+ *   must have at least one getter (method such as "int getSize()" or
+ *   "boolean isBig()"), and we must be able to deduce how to
+ *   reconstruct an instance of the Java class from the values of the
+ *   getters using one of various heuristics.</p>
+ *
+ * @since 1.6
+ */
+public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
+    static abstract class NonNullMXBeanMapping extends MXBeanMapping {
+        NonNullMXBeanMapping(Type javaType, OpenType openType) {
+            super(javaType, openType);
+        }
+
+        @Override
+        public final Object fromOpenValue(Object openValue)
+        throws InvalidObjectException {
+            if (openValue == null)
+                return null;
+            else
+                return fromNonNullOpenValue(openValue);
+        }
+
+        @Override
+        public final Object toOpenValue(Object javaValue) throws OpenDataException {
+            if (javaValue == null)
+                return null;
+            else
+                return toNonNullOpenValue(javaValue);
+        }
+
+        abstract Object fromNonNullOpenValue(Object openValue)
+        throws InvalidObjectException;
+
+        abstract Object toNonNullOpenValue(Object javaValue)
+        throws OpenDataException;
+
+        /**
+         * <p>True if and only if this MXBeanMapping's toOpenValue and
+         * fromOpenValue methods are the identity function.</p>
+         */
+        boolean isIdentity() {
+            return false;
+        }
+    }
+
+    static boolean isIdentity(MXBeanMapping mapping) {
+        return (mapping instanceof NonNullMXBeanMapping &&
+                ((NonNullMXBeanMapping) mapping).isIdentity());
+    }
+
+    private static final class Mappings
+        extends WeakHashMap<Type, WeakReference<MXBeanMapping>> {}
+
+    private static final Map<MXBeanMappingFactory, Mappings> factoryMappings =
+            new WeakHashMap<MXBeanMappingFactory, Mappings>();
+
+    private static final Map<Type, MXBeanMapping> permanentMappings = newMap();
+
+    private static synchronized MXBeanMapping getMapping(
+            Type type, MXBeanMappingFactory factory) {
+        Mappings mappings = factoryMappings.get(factory);
+        if (mappings == null) {
+            mappings = new Mappings();
+            factoryMappings.put(factory, mappings);
+        }
+        WeakReference<MXBeanMapping> wr = mappings.get(type);
+        return (wr == null) ? null : wr.get();
+    }
+
+    private static synchronized void putMapping(
+            Type type, MXBeanMapping mapping, MXBeanMappingFactory factory) {
+        Mappings mappings = factoryMappings.get(factory);
+        if (mappings == null) {
+            mappings = new Mappings();
+            factoryMappings.put(factory, mappings);
+        }
+        WeakReference<MXBeanMapping> wr =
+            new WeakReference<MXBeanMapping>(mapping);
+        mappings.put(type, wr);
+    }
+
+    static {
+        /* Set up the mappings for Java types that map to SimpleType.  */
+
+        final OpenType[] simpleTypes = {
+            BIGDECIMAL, BIGINTEGER, BOOLEAN, BYTE, CHARACTER, DATE,
+            DOUBLE, FLOAT, INTEGER, LONG, OBJECTNAME, SHORT, STRING,
+            VOID,
+        };
+
+        for (int i = 0; i < simpleTypes.length; i++) {
+            final OpenType t = simpleTypes[i];
+            Class c;
+            try {
+                c = Class.forName(t.getClassName(), false,
+                                  ObjectName.class.getClassLoader());
+            } catch (ClassNotFoundException e) {
+                // the classes that these predefined types declare must exist!
+                throw new Error(e);
+            }
+            final MXBeanMapping mapping = new IdentityMapping(c, t);
+            permanentMappings.put(c, mapping);
+
+            if (c.getName().startsWith("java.lang.")) {
+                try {
+                    final Field typeField = c.getField("TYPE");
+                    final Class<?> primitiveType = (Class<?>) typeField.get(null);
+                    final MXBeanMapping primitiveMapping =
+                        new IdentityMapping(primitiveType, t);
+                    permanentMappings.put(primitiveType, primitiveMapping);
+                    if (primitiveType != void.class) {
+                        final Class<?> primitiveArrayType =
+                            Array.newInstance(primitiveType, 0).getClass();
+                        final OpenType primitiveArrayOpenType =
+                            ArrayType.getPrimitiveArrayType(primitiveArrayType);
+                        final MXBeanMapping primitiveArrayMapping =
+                            new IdentityMapping(primitiveArrayType,
+                                                primitiveArrayOpenType);
+                        permanentMappings.put(primitiveArrayType,
+                                              primitiveArrayMapping);
+                    }
+                } catch (NoSuchFieldException e) {
+                    // OK: must not be a primitive wrapper
+                } catch (IllegalAccessException e) {
+                    // Should not reach here
+                    assert(false);
+                }
+            }
+        }
+    }
+
+    /** Get the converter for the given Java type, creating it if necessary. */
+    @Override
+    public synchronized MXBeanMapping mappingForType(Type objType,
+                                                     MXBeanMappingFactory factory)
+            throws OpenDataException {
+        if (inProgress.containsKey(objType))
+            throw new OpenDataException("Recursive data structure");
+
+        MXBeanMapping mapping;
+
+        mapping = getMapping(objType, null);
+        if (mapping != null)
+            return mapping;
+
+        inProgress.put(objType, objType);
+        try {
+            mapping = makeMapping(objType, factory);
+        } finally {
+            inProgress.remove(objType);
+        }
+
+        putMapping(objType, mapping, factory);
+        return mapping;
+    }
+
+    private MXBeanMapping makeMapping(Type objType, MXBeanMappingFactory factory)
+    throws OpenDataException {
+
+        /* It's not yet worth formalizing these tests by having for example
+           an array of factory classes, each of which says whether it
+           recognizes the Type (Chain of Responsibility pattern).  */
+        MXBeanMapping mapping = permanentMappings.get(objType);
+        if (mapping != null)
+            return mapping;
+        Class<?> erasure = erasure(objType);
+        MXBeanMappingClass mappingClass =
+                erasure.getAnnotation(MXBeanMappingClass.class);
+        if (mappingClass != null)
+            return makeAnnotationMapping(mappingClass, objType, factory);
+        if (objType instanceof GenericArrayType) {
+            Type componentType =
+                ((GenericArrayType) objType).getGenericComponentType();
+            return makeArrayOrCollectionMapping(objType, componentType, factory);
+        } else if (objType instanceof Class) {
+            Class<?> objClass = (Class<?>) objType;
+            if (objClass.isEnum()) {
+                // Huge hack to avoid compiler warnings here.  The ElementType
+                // parameter is ignored but allows us to obtain a type variable
+                // T that matches <T extends Enum<T>>.
+                return makeEnumMapping((Class) objClass, ElementType.class);
+            } else if (objClass.isArray()) {
+                Type componentType = objClass.getComponentType();
+                return makeArrayOrCollectionMapping(objClass, componentType,
+                        factory);
+            } else if (JMX.isMXBeanInterface(objClass)) {
+                return makeMXBeanRefMapping(objClass);
+            } else {
+                return makeCompositeMapping(objClass, factory);
+            }
+        } else if (objType instanceof ParameterizedType) {
+            return makeParameterizedTypeMapping((ParameterizedType) objType,
+                                                factory);
+        } else
+            throw new OpenDataException("Cannot map type: " + objType);
+    }
+
+    private static MXBeanMapping
+            makeAnnotationMapping(MXBeanMappingClass mappingClass,
+                                  Type objType,
+                                  MXBeanMappingFactory factory)
+    throws OpenDataException {
+        Class<? extends MXBeanMapping> c = mappingClass.value();
+        Constructor<? extends MXBeanMapping> cons;
+        try {
+            cons = c.getConstructor(Type.class);
+        } catch (NoSuchMethodException e) {
+            final String msg =
+                    "Annotation @" + MXBeanMappingClass.class.getName() +
+                    " must name a class with a public constructor that has a " +
+                    "single " + Type.class.getName() + " argument";
+            OpenDataException ode = new OpenDataException(msg);
+            ode.initCause(e);
+            throw ode;
+        }
+        try {
+            return cons.newInstance(objType);
+        } catch (Exception e) {
+            final String msg =
+                    "Could not construct a " + c.getName() + " for @" +
+                    MXBeanMappingClass.class.getName();
+            OpenDataException ode = new OpenDataException(msg);
+            ode.initCause(e);
+            throw ode;
+        }
+    }
+
+    private static Class<?> erasure(Type t) {
+        if (t instanceof Class<?>)
+            return (Class<?>) t;
+        if (t instanceof ParameterizedType)
+            return erasure(((ParameterizedType) t).getRawType());
+        /* Other cases: GenericArrayType, TypeVariable, WildcardType.
+         * Returning the erasure of GenericArrayType is not necessary because
+         * anyway we will be recursing on the element type, and we'll erase
+         * then.  Returning the erasure of the other two would mean returning
+         * the type bound (e.g. Foo in <T extends Foo> or <? extends Foo>)
+         * and since we don't treat this as Foo elsewhere we shouldn't here.
+         */
+        return Object.class;
+    }
+
+    private static <T extends Enum<T>> MXBeanMapping
+            makeEnumMapping(Class enumClass, Class<T> fake) {
+        return new EnumMapping<T>(Util.<Class<T>>cast(enumClass));
+    }
+
+    /* Make the converter for an array type, or a collection such as
+     * List<String> or Set<Integer>.  We never see one-dimensional
+     * primitive arrays (e.g. int[]) here because they use the identity
+     * converter and are registered as such in the static initializer.
+     */
+    private MXBeanMapping
+        makeArrayOrCollectionMapping(Type collectionType, Type elementType,
+                                     MXBeanMappingFactory factory)
+            throws OpenDataException {
+
+        final MXBeanMapping elementMapping = factory.mappingForType(elementType, factory);
+        final OpenType<?> elementOpenType = elementMapping.getOpenType();
+        final ArrayType<?> openType = ArrayType.getArrayType(elementOpenType);
+        final Class<?> elementOpenClass = elementMapping.getOpenClass();
+
+        final Class<?> openArrayClass;
+        final String openArrayClassName;
+        if (elementOpenClass.isArray())
+            openArrayClassName = "[" + elementOpenClass.getName();
+        else
+            openArrayClassName = "[L" + elementOpenClass.getName() + ";";
+        try {
+            openArrayClass = Class.forName(openArrayClassName);
+        } catch (ClassNotFoundException e) {
+            throw openDataException("Cannot obtain array class", e);
+        }
+
+        if (collectionType instanceof ParameterizedType) {
+            return new CollectionMapping(collectionType,
+                                         openType, openArrayClass,
+                                         elementMapping);
+        } else {
+            if (isIdentity(elementMapping)) {
+                return new IdentityMapping(collectionType,
+                                           openType);
+            } else {
+                return new ArrayMapping(collectionType,
+                                          openType,
+                                          openArrayClass,
+                                          elementMapping);
+            }
+        }
+    }
+
+    private static final String[] keyArray = {"key"};
+    private static final String[] keyValueArray = {"key", "value"};
+
+    private MXBeanMapping
+        makeTabularMapping(Type objType, boolean sortedMap,
+                           Type keyType, Type valueType,
+                           MXBeanMappingFactory factory)
+            throws OpenDataException {
+
+        final String objTypeName = objType.toString();
+        final MXBeanMapping keyMapping = factory.mappingForType(keyType, factory);
+        final MXBeanMapping valueMapping = factory.mappingForType(valueType, factory);
+        final OpenType keyOpenType = keyMapping.getOpenType();
+        final OpenType valueOpenType = valueMapping.getOpenType();
+        final CompositeType rowType =
+            new CompositeType(objTypeName,
+                              objTypeName,
+                              keyValueArray,
+                              keyValueArray,
+                              new OpenType[] {keyOpenType, valueOpenType});
+        final TabularType tabularType =
+            new TabularType(objTypeName, objTypeName, rowType, keyArray);
+        return new TabularMapping(objType, sortedMap, tabularType,
+                                    keyMapping, valueMapping);
+    }
+
+    /* We know how to translate List<E>, Set<E>, SortedSet<E>,
+       Map<K,V>, SortedMap<K,V>, and that's it.  We don't accept
+       subtypes of those because we wouldn't know how to deserialize
+       them.  We don't accept Queue<E> because it is unlikely people
+       would use that as a parameter or return type in an MBean.  */
+    private MXBeanMapping
+            makeParameterizedTypeMapping(ParameterizedType objType,
+                                         MXBeanMappingFactory factory)
+            throws OpenDataException {
+
+        final Type rawType = objType.getRawType();
+
+        if (rawType instanceof Class) {
+            Class c = (Class<?>) rawType;
+            if (c == List.class || c == Set.class || c == SortedSet.class) {
+                Type[] actuals = objType.getActualTypeArguments();
+                assert(actuals.length == 1);
+                if (c == SortedSet.class)
+                    mustBeComparable(c, actuals[0]);
+                return makeArrayOrCollectionMapping(objType, actuals[0], factory);
+            } else {
+                boolean sortedMap = (c == SortedMap.class);
+                if (c == Map.class || sortedMap) {
+                    Type[] actuals = objType.getActualTypeArguments();
+                    assert(actuals.length == 2);
+                    if (sortedMap)
+                        mustBeComparable(c, actuals[0]);
+                    return makeTabularMapping(objType, sortedMap,
+                            actuals[0], actuals[1], factory);
+                }
+            }
+        }
+        throw new OpenDataException("Cannot convert type: " + objType);
+    }
+
+    private static MXBeanMapping makeMXBeanRefMapping(Type t)
+            throws OpenDataException {
+        return new MXBeanRefMapping(t);
+    }
+
+    private MXBeanMapping makeCompositeMapping(Class c,
+                                               MXBeanMappingFactory factory)
+            throws OpenDataException {
+
+        // For historical reasons GcInfo implements CompositeData but we
+        // shouldn't count its CompositeData.getCompositeType() field as
+        // an item in the computed CompositeType.
+        final boolean gcInfoHack =
+            (c.getName().equals("com.sun.management.GcInfo") &&
+                c.getClassLoader() == null);
+
+        final List<Method> methods =
+                MBeanAnalyzer.eliminateCovariantMethods(Arrays.asList(c.getMethods()));
+        final SortedMap<String,Method> getterMap = newSortedMap();
+
+        /* Select public methods that look like "T getX()" or "boolean
+           isX()", where T is not void and X is not the empty
+           string.  Exclude "Class getClass()" inherited from Object.  */
+        for (Method method : methods) {
+            final String propertyName = propertyName(method);
+
+            if (propertyName == null)
+                continue;
+            if (gcInfoHack && propertyName.equals("CompositeType"))
+                continue;
+
+            Method old =
+                getterMap.put(decapitalize(propertyName),
+                            method);
+            if (old != null) {
+                final String msg =
+                    "Class " + c.getName() + " has method name clash: " +
+                    old.getName() + ", " + method.getName();
+                throw new OpenDataException(msg);
+            }
+        }
+
+        final int nitems = getterMap.size();
+
+        if (nitems == 0) {
+            throw new OpenDataException("Can't map " + c.getName() +
+                                        " to an open data type");
+        }
+
+        final Method[] getters = new Method[nitems];
+        final String[] itemNames = new String[nitems];
+        final OpenType[] openTypes = new OpenType[nitems];
+        int i = 0;
+        for (Map.Entry<String,Method> entry : getterMap.entrySet()) {
+            itemNames[i] = entry.getKey();
+            final Method getter = entry.getValue();
+            getters[i] = getter;
+            final Type retType = getter.getGenericReturnType();
+            openTypes[i] = factory.mappingForType(retType, factory).getOpenType();
+            i++;
+        }
+
+        CompositeType compositeType =
+            new CompositeType(c.getName(),
+                              c.getName(),
+                              itemNames, // field names
+                              itemNames, // field descriptions
+                              openTypes);
+
+        return new CompositeMapping(c,
+                                    compositeType,
+                                    itemNames,
+                                    getters,
+                                    factory);
+    }
+
+    /* Converter for classes where the open data is identical to the
+       original data.  This is true for any of the SimpleType types,
+       and for an any-dimension array of those.  It is also true for
+       primitive types as of JMX 1.3, since an int[]
+       can be directly represented by an ArrayType, and an int needs no mapping
+       because reflection takes care of it.  */
+    private static final class IdentityMapping extends NonNullMXBeanMapping {
+        IdentityMapping(Type targetType, OpenType openType) {
+            super(targetType, openType);
+        }
+
+        boolean isIdentity() {
+            return true;
+        }
+
+        @Override
+        Object fromNonNullOpenValue(Object openValue)
+        throws InvalidObjectException {
+            return openValue;
+        }
+
+        @Override
+        Object toNonNullOpenValue(Object javaValue) throws OpenDataException {
+            return javaValue;
+        }
+    }
+
+    private static final class EnumMapping<T extends Enum<T>>
+            extends NonNullMXBeanMapping {
+
+        EnumMapping(Class<T> enumClass) {
+            super(enumClass, SimpleType.STRING);
+            this.enumClass = enumClass;
+        }
+
+        @Override
+        final Object toNonNullOpenValue(Object value) {
+            return ((Enum) value).name();
+        }
+
+        @Override
+        final T fromNonNullOpenValue(Object value)
+                throws InvalidObjectException {
+            try {
+                return Enum.valueOf(enumClass, (String) value);
+            } catch (Exception e) {
+                throw invalidObjectException("Cannot convert to enum: " +
+                                             value, e);
+            }
+        }
+
+        private final Class<T> enumClass;
+    }
+
+    private static final class ArrayMapping extends NonNullMXBeanMapping {
+        ArrayMapping(Type targetType,
+                     ArrayType openArrayType, Class openArrayClass,
+                     MXBeanMapping elementMapping) {
+            super(targetType, openArrayType);
+            this.elementMapping = elementMapping;
+        }
+
+        @Override
+        final Object toNonNullOpenValue(Object value)
+                throws OpenDataException {
+            Object[] valueArray = (Object[]) value;
+            final int len = valueArray.length;
+            final Object[] openArray = (Object[])
+                Array.newInstance(getOpenClass().getComponentType(), len);
+            for (int i = 0; i < len; i++)
+                openArray[i] = elementMapping.toOpenValue(valueArray[i]);
+            return openArray;
+        }
+
+        @Override
+        final Object fromNonNullOpenValue(Object openValue)
+                throws InvalidObjectException {
+            final Object[] openArray = (Object[]) openValue;
+            final Type javaType = getJavaType();
+            final Object[] valueArray;
+            final Type componentType;
+            if (javaType instanceof GenericArrayType) {
+                componentType =
+                    ((GenericArrayType) javaType).getGenericComponentType();
+            } else if (javaType instanceof Class &&
+                       ((Class<?>) javaType).isArray()) {
+                componentType = ((Class<?>) javaType).getComponentType();
+            } else {
+                throw new IllegalArgumentException("Not an array: " +
+                                                   javaType);
+            }
+            valueArray = (Object[]) Array.newInstance((Class<?>) componentType,
+                                                      openArray.length);
+            for (int i = 0; i < openArray.length; i++)
+                valueArray[i] = elementMapping.fromOpenValue(openArray[i]);
+            return valueArray;
+        }
+
+        public void checkReconstructible() throws InvalidObjectException {
+            elementMapping.checkReconstructible();
+        }
+
+        /**
+         * DefaultMXBeanMappingFactory for the elements of this array.  If this is an
+         *          array of arrays, the converter converts the second-level arrays,
+         *          not the deepest elements.
+         */
+        private final MXBeanMapping elementMapping;
+    }
+
+    private static final class CollectionMapping extends NonNullMXBeanMapping {
+        CollectionMapping(Type targetType,
+                          ArrayType openArrayType,
+                          Class openArrayClass,
+                          MXBeanMapping elementMapping) {
+            super(targetType, openArrayType);
+            this.elementMapping = elementMapping;
+
+            /* Determine the concrete class to be used when converting
+               back to this Java type.  We convert all Lists to ArrayList
+               and all Sets to TreeSet.  (TreeSet because it is a SortedSet,
+               so works for both Set and SortedSet.)  */
+            Type raw = ((ParameterizedType) targetType).getRawType();
+            Class c = (Class<?>) raw;
+            if (c == List.class)
+                collectionClass = ArrayList.class;
+            else if (c == Set.class)
+                collectionClass = HashSet.class;
+            else if (c == SortedSet.class)
+                collectionClass = TreeSet.class;
+            else { // can't happen
+                assert(false);
+                collectionClass = null;
+            }
+        }
+
+        @Override
+        final Object toNonNullOpenValue(Object value)
+                throws OpenDataException {
+            final Collection valueCollection = (Collection) value;
+            if (valueCollection instanceof SortedSet) {
+                Comparator comparator =
+                    ((SortedSet) valueCollection).comparator();
+                if (comparator != null) {
+                    final String msg =
+                        "Cannot convert SortedSet with non-null comparator: " +
+                        comparator;
+                    throw openDataException(msg, new IllegalArgumentException(msg));
+                }
+            }
+            final Object[] openArray = (Object[])
+                Array.newInstance(getOpenClass().getComponentType(),
+                                  valueCollection.size());
+            int i = 0;
+            for (Object o : valueCollection)
+                openArray[i++] = elementMapping.toOpenValue(o);
+            return openArray;
+        }
+
+        @Override
+        final Object fromNonNullOpenValue(Object openValue)
+                throws InvalidObjectException {
+            final Object[] openArray = (Object[]) openValue;
+            final Collection<Object> valueCollection;
+            try {
+                valueCollection = cast(collectionClass.newInstance());
+            } catch (Exception e) {
+                throw invalidObjectException("Cannot create collection", e);
+            }
+            for (Object o : openArray) {
+                Object value = elementMapping.fromOpenValue(o);
+                if (!valueCollection.add(value)) {
+                    final String msg =
+                        "Could not add " + o + " to " +
+                        collectionClass.getName() +
+                        " (duplicate set element?)";
+                    throw new InvalidObjectException(msg);
+                }
+            }
+            return valueCollection;
+        }
+
+        public void checkReconstructible() throws InvalidObjectException {
+            elementMapping.checkReconstructible();
+        }
+
+        private final Class<? extends Collection> collectionClass;
+        private final MXBeanMapping elementMapping;
+    }
+
+    private static final class MXBeanRefMapping extends NonNullMXBeanMapping {
+        MXBeanRefMapping(Type intf) {
+            super(intf, SimpleType.OBJECTNAME);
+        }
+
+        @Override
+        final Object toNonNullOpenValue(Object javaValue)
+                throws OpenDataException {
+            MXBeanLookup lookup = lookupNotNull(OpenDataException.class);
+            ObjectName name = lookup.mxbeanToObjectName(javaValue);
+            if (name == null)
+                throw new OpenDataException("No name for object: " + javaValue);
+            return name;
+        }
+
+        @Override
+        final Object fromNonNullOpenValue(Object openValue)
+                throws InvalidObjectException {
+            MXBeanLookup lookup = lookupNotNull(InvalidObjectException.class);
+            ObjectName name = (ObjectName) openValue;
+            Object mxbean =
+                lookup.objectNameToMXBean(name, (Class<?>) getJavaType());
+            if (mxbean == null) {
+                final String msg =
+                    "No MXBean for name: " + name;
+                throw new InvalidObjectException(msg);
+            }
+            return mxbean;
+        }
+
+        private <T extends Exception> MXBeanLookup
+            lookupNotNull(Class<T> excClass)
+                throws T {
+            MXBeanLookup lookup = MXBeanLookup.getLookup();
+            if (lookup == null) {
+                final String msg =
+                    "Cannot convert MXBean interface in this context";
+                T exc;
+                try {
+                    Constructor<T> con = excClass.getConstructor(String.class);
+                    exc = con.newInstance(msg);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+                throw exc;
+            }
+            return lookup;
+        }
+    }
+
+    private static final class TabularMapping extends NonNullMXBeanMapping {
+        TabularMapping(Type targetType,
+                       boolean sortedMap,
+                       TabularType tabularType,
+                       MXBeanMapping keyConverter,
+                       MXBeanMapping valueConverter) {
+            super(targetType, tabularType);
+            this.sortedMap = sortedMap;
+            this.keyMapping = keyConverter;
+            this.valueMapping = valueConverter;
+        }
+
+        @Override
+        final Object toNonNullOpenValue(Object value) throws OpenDataException {
+            final Map<Object, Object> valueMap = cast(value);
+            if (valueMap instanceof SortedMap) {
+                Comparator comparator = ((SortedMap) valueMap).comparator();
+                if (comparator != null) {
+                    final String msg =
+                        "Cannot convert SortedMap with non-null comparator: " +
+                        comparator;
+                    throw openDataException(msg, new IllegalArgumentException(msg));
+                }
+            }
+            final TabularType tabularType = (TabularType) getOpenType();
+            final TabularData table = new TabularDataSupport(tabularType);
+            final CompositeType rowType = tabularType.getRowType();
+            for (Map.Entry entry : valueMap.entrySet()) {
+                final Object openKey = keyMapping.toOpenValue(entry.getKey());
+                final Object openValue = valueMapping.toOpenValue(entry.getValue());
+                final CompositeData row;
+                row =
+                    new CompositeDataSupport(rowType, keyValueArray,
+                                             new Object[] {openKey,
+                                                           openValue});
+                table.put(row);
+            }
+            return table;
+        }
+
+        @Override
+        final Object fromNonNullOpenValue(Object openValue)
+                throws InvalidObjectException {
+            final TabularData table = (TabularData) openValue;
+            final Collection<CompositeData> rows = cast(table.values());
+            final Map<Object, Object> valueMap =
+                sortedMap ? newSortedMap() : newMap();
+            for (CompositeData row : rows) {
+                final Object key =
+                    keyMapping.fromOpenValue(row.get("key"));
+                final Object value =
+                    valueMapping.fromOpenValue(row.get("value"));
+                if (valueMap.put(key, value) != null) {
+                    final String msg =
+                        "Duplicate entry in TabularData: key=" + key;
+                    throw new InvalidObjectException(msg);
+                }
+            }
+            return valueMap;
+        }
+
+        @Override
+        public void checkReconstructible() throws InvalidObjectException {
+            keyMapping.checkReconstructible();
+            valueMapping.checkReconstructible();
+        }
+
+        private final boolean sortedMap;
+        private final MXBeanMapping keyMapping;
+        private final MXBeanMapping valueMapping;
+    }
+
+    private final class CompositeMapping extends NonNullMXBeanMapping {
+        CompositeMapping(Class targetClass,
+                         CompositeType compositeType,
+                         String[] itemNames,
+                         Method[] getters,
+                         MXBeanMappingFactory factory) throws OpenDataException {
+            super(targetClass, compositeType);
+
+            assert(itemNames.length == getters.length);
+
+            this.itemNames = itemNames;
+            this.getters = getters;
+            this.getterMappings = new MXBeanMapping[getters.length];
+            for (int i = 0; i < getters.length; i++) {
+                Type retType = getters[i].getGenericReturnType();
+                getterMappings[i] = factory.mappingForType(retType, factory);
+            }
+        }
+
+        @Override
+        final Object toNonNullOpenValue(Object value)
+                throws OpenDataException {
+            CompositeType ct = (CompositeType) getOpenType();
+            if (value instanceof CompositeDataView)
+                return ((CompositeDataView) value).toCompositeData(ct);
+            if (value == null)
+                return null;
+
+            Object[] values = new Object[getters.length];
+            for (int i = 0; i < getters.length; i++) {
+                try {
+                    Object got = getters[i].invoke(value, (Object[]) null);
+                    values[i] = getterMappings[i].toOpenValue(got);
+                } catch (Exception e) {
+                    throw openDataException("Error calling getter for " +
+                                            itemNames[i] + ": " + e, e);
+                }
+            }
+            return new CompositeDataSupport(ct, itemNames, values);
+        }
+
+        /** Determine how to convert back from the CompositeData into
+            the original Java type.  For a type that is not reconstructible,
+            this method will fail every time, and will throw the right
+            exception. */
+        private synchronized void makeCompositeBuilder()
+                throws InvalidObjectException {
+            if (compositeBuilder != null)
+                return;
+
+            Class targetClass = (Class<?>) getJavaType();
+            /* In this 2D array, each subarray is a set of builders where
+               there is no point in consulting the ones after the first if
+               the first refuses.  */
+            CompositeBuilder[][] builders = {
+                {
+                    new CompositeBuilderViaFrom(targetClass, itemNames),
+                },
+                {
+                    new CompositeBuilderViaConstructor(targetClass, itemNames),
+                },
+                {
+                    new CompositeBuilderCheckGetters(targetClass, itemNames,
+                                                     getterMappings),
+                    new CompositeBuilderViaSetters(targetClass, itemNames),
+                    new CompositeBuilderViaProxy(targetClass, itemNames),
+                },
+            };
+            CompositeBuilder foundBuilder = null;
+            /* We try to make a meaningful exception message by
+               concatenating each Builder's explanation of why it
+               isn't applicable.  */
+            final StringBuilder whyNots = new StringBuilder();
+        find:
+            for (CompositeBuilder[] relatedBuilders : builders) {
+                for (int i = 0; i < relatedBuilders.length; i++) {
+                    CompositeBuilder builder = relatedBuilders[i];
+                    String whyNot = builder.applicable(getters);
+                    if (whyNot == null) {
+                        foundBuilder = builder;
+                        break find;
+                    }
+                    if (whyNot.length() > 0) {
+                        if (whyNots.length() > 0)
+                            whyNots.append("; ");
+                        whyNots.append(whyNot);
+                        if (i == 0)
+                           break; // skip other builders in this group
+                    }
+                }
+            }
+            if (foundBuilder == null) {
+                final String msg =
+                    "Do not know how to make a " + targetClass.getName() +
+                    " from a CompositeData: " + whyNots;
+                throw new InvalidObjectException(msg);
+            }
+            compositeBuilder = foundBuilder;
+        }
+
+        @Override
+        public void checkReconstructible() throws InvalidObjectException {
+            makeCompositeBuilder();
+        }
+
+        @Override
+        final Object fromNonNullOpenValue(Object value)
+                throws InvalidObjectException {
+            makeCompositeBuilder();
+            return compositeBuilder.fromCompositeData((CompositeData) value,
+                                                      itemNames,
+                                                      getterMappings);
+        }
+
+        private final String[] itemNames;
+        private final Method[] getters;
+        private final MXBeanMapping[] getterMappings;
+        private CompositeBuilder compositeBuilder;
+    }
+
+    /** Converts from a CompositeData to an instance of the targetClass.  */
+    private static abstract class CompositeBuilder {
+        CompositeBuilder(Class targetClass, String[] itemNames) {
+            this.targetClass = targetClass;
+            this.itemNames = itemNames;
+        }
+
+        Class<?> getTargetClass() {
+            return targetClass;
+        }
+
+        String[] getItemNames() {
+            return itemNames;
+        }
+
+        /** If the subclass is appropriate for targetClass, then the
+            method returns null.  If the subclass is not appropriate,
+            then the method returns an explanation of why not.  If the
+            subclass should be appropriate but there is a problem,
+            then the method throws InvalidObjectException.  */
+        abstract String applicable(Method[] getters)
+                throws InvalidObjectException;
+
+        abstract Object fromCompositeData(CompositeData cd,
+                                          String[] itemNames,
+                                          MXBeanMapping[] converters)
+                throws InvalidObjectException;
+
+        private final Class<?> targetClass;
+        private final String[] itemNames;
+    }
+
+    /** Builder for when the target class has a method "public static
+        from(CompositeData)".  */
+    private static final class CompositeBuilderViaFrom
+            extends CompositeBuilder {
+
+        CompositeBuilderViaFrom(Class targetClass, String[] itemNames) {
+            super(targetClass, itemNames);
+        }
+
+        String applicable(Method[] getters) throws InvalidObjectException {
+            // See if it has a method "T from(CompositeData)"
+            // as is conventional for a CompositeDataView
+            Class<?> targetClass = getTargetClass();
+            try {
+                Method fromMethod =
+                    targetClass.getMethod("from",
+                                          new Class[] {CompositeData.class});
+
+                if (!Modifier.isStatic(fromMethod.getModifiers())) {
+                    final String msg =
+                        "Method from(CompositeData) is not static";
+                    throw new InvalidObjectException(msg);
+                }
+
+                if (fromMethod.getReturnType() != getTargetClass()) {
+                    final String msg =
+                        "Method from(CompositeData) returns " +
+                        fromMethod.getReturnType().getName() +
+                        " not " + targetClass.getName();
+                    throw new InvalidObjectException(msg);
+                }
+
+                this.fromMethod = fromMethod;
+                return null; // success!
+            } catch (InvalidObjectException e) {
+                throw e;
+            } catch (Exception e) {
+                // OK: it doesn't have the method
+                return "no method from(CompositeData)";
+            }
+        }
+
+        final Object fromCompositeData(CompositeData cd,
+                                       String[] itemNames,
+                                       MXBeanMapping[] converters)
+                throws InvalidObjectException {
+            try {
+                return fromMethod.invoke(null, cd);
+            } catch (Exception e) {
+                final String msg = "Failed to invoke from(CompositeData)";
+                throw invalidObjectException(msg, e);
+            }
+        }
+
+        private Method fromMethod;
+    }
+
+    /** This builder never actually returns success.  It simply serves
+        to check whether the other builders in the same group have any
+        chance of success.  If any getter in the targetClass returns
+        a type that we don't know how to reconstruct, then we will
+        not be able to make a builder, and there is no point in repeating
+        the error about the problematic getter as many times as there are
+        candidate builders.  Instead, the "applicable" method will return
+        an explanatory string, and the other builders will be skipped.
+        If all the getters are OK, then the "applicable" method will return
+        an empty string and the other builders will be tried.  */
+    private static class CompositeBuilderCheckGetters extends CompositeBuilder {
+        CompositeBuilderCheckGetters(Class targetClass, String[] itemNames,
+                                     MXBeanMapping[] getterConverters) {
+            super(targetClass, itemNames);
+            this.getterConverters = getterConverters;
+        }
+
+        String applicable(Method[] getters) {
+            for (int i = 0; i < getters.length; i++) {
+                try {
+                    getterConverters[i].checkReconstructible();
+                } catch (InvalidObjectException e) {
+                    return "method " + getters[i].getName() + " returns type " +
+                        "that cannot be mapped back from OpenData";
+                }
+            }
+            return "";
+        }
+
+        final Object fromCompositeData(CompositeData cd,
+                                       String[] itemNames,
+                                       MXBeanMapping[] converters) {
+            throw new Error();
+        }
+
+        private final MXBeanMapping[] getterConverters;
+    }
+
+    /** Builder for when the target class has a setter for every getter. */
+    private static class CompositeBuilderViaSetters extends CompositeBuilder {
+
+        CompositeBuilderViaSetters(Class<?> targetClass, String[] itemNames) {
+            super(targetClass, itemNames);
+        }
+
+        String applicable(Method[] getters) {
+            try {
+                Constructor<?> c = getTargetClass().getConstructor();
+            } catch (Exception e) {
+                return "does not have a public no-arg constructor";
+            }
+
+            Method[] setters = new Method[getters.length];
+            for (int i = 0; i < getters.length; i++) {
+                Method getter = getters[i];
+                Class returnType = getter.getReturnType();
+                String name = propertyName(getter);
+                String setterName = "set" + name;
+                Method setter;
+                try {
+                    setter = getTargetClass().getMethod(setterName, returnType);
+                    if (setter.getReturnType() != void.class)
+                        throw new Exception();
+                } catch (Exception e) {
+                    return "not all getters have corresponding setters " +
+                           "(" + getter + ")";
+                }
+                setters[i] = setter;
+            }
+            this.setters = setters;
+            return null;
+        }
+
+        Object fromCompositeData(CompositeData cd,
+                                 String[] itemNames,
+                                 MXBeanMapping[] converters)
+                throws InvalidObjectException {
+            Object o;
+            try {
+                o = getTargetClass().newInstance();
+                for (int i = 0; i < itemNames.length; i++) {
+                    if (cd.containsKey(itemNames[i])) {
+                        Object openItem = cd.get(itemNames[i]);
+                        Object javaItem =
+                            converters[i].fromOpenValue(openItem);
+                        setters[i].invoke(o, javaItem);
+                    }
+                }
+            } catch (Exception e) {
+                throw invalidObjectException(e);
+            }
+            return o;
+        }
+
+        private Method[] setters;
+    }
+
+    /** Builder for when the target class has a constructor that is
+        annotated with @ConstructorProperties so we can see the correspondence
+        to getters.  */
+    private static final class CompositeBuilderViaConstructor
+            extends CompositeBuilder {
+
+        CompositeBuilderViaConstructor(Class targetClass, String[] itemNames) {
+            super(targetClass, itemNames);
+        }
+
+        String applicable(Method[] getters) throws InvalidObjectException {
+
+            final Class<ConstructorProperties> propertyNamesClass = ConstructorProperties.class;
+
+            Class targetClass = getTargetClass();
+            Constructor[] constrs = targetClass.getConstructors();
+
+            // Applicable if and only if there are any annotated constructors
+            List<Constructor> annotatedConstrList = newList();
+            for (Constructor<?> constr : constrs) {
+                if (Modifier.isPublic(constr.getModifiers())
+                        && constr.getAnnotation(propertyNamesClass) != null)
+                    annotatedConstrList.add(constr);
+            }
+
+            if (annotatedConstrList.isEmpty())
+                return "no constructor has @ConstructorProperties annotation";
+
+            annotatedConstructors = newList();
+
+            // Now check that all the annotated constructors are valid
+            // and throw an exception if not.
+
+            // First link the itemNames to their getter indexes.
+            Map<String, Integer> getterMap = newMap();
+            String[] itemNames = getItemNames();
+            for (int i = 0; i < itemNames.length; i++)
+                getterMap.put(itemNames[i], i);
+
+            // Run through the constructors making the checks in the spec.
+            // For each constructor, remember the correspondence between its
+            // parameters and the items.  The int[] for a constructor says
+            // what parameter index should get what item.  For example,
+            // if element 0 is 2 then that means that item 0 in the
+            // CompositeData goes to parameter 2 of the constructor.  If an
+            // element is -1, that item isn't given to the constructor.
+            // Also remember the set of properties in that constructor
+            // so we can test unambiguity.
+            Set<BitSet> getterIndexSets = newSet();
+            for (Constructor constr : annotatedConstrList) {
+                String[] propertyNames =
+                    constr.getAnnotation(propertyNamesClass).value();
+
+                Type[] paramTypes = constr.getGenericParameterTypes();
+                if (paramTypes.length != propertyNames.length) {
+                    final String msg =
+                        "Number of constructor params does not match " +
+                        "@ConstructorProperties annotation: " + constr;
+                    throw new InvalidObjectException(msg);
+                }
+
+                int[] paramIndexes = new int[getters.length];
+                for (int i = 0; i < getters.length; i++)
+                    paramIndexes[i] = -1;
+                BitSet present = new BitSet();
+
+                for (int i = 0; i < propertyNames.length; i++) {
+                    String propertyName = propertyNames[i];
+                    if (!getterMap.containsKey(propertyName)) {
+                        final String msg =
+                            "@ConstructorProperties includes name " + propertyName +
+                            " which does not correspond to a property: " +
+                            constr;
+                        throw new InvalidObjectException(msg);
+                    }
+                    int getterIndex = getterMap.get(propertyName);
+                    paramIndexes[getterIndex] = i;
+                    if (present.get(getterIndex)) {
+                        final String msg =
+                            "@ConstructorProperties contains property " +
+                            propertyName + " more than once: " + constr;
+                        throw new InvalidObjectException(msg);
+                    }
+                    present.set(getterIndex);
+                    Method getter = getters[getterIndex];
+                    Type propertyType = getter.getGenericReturnType();
+                    if (!propertyType.equals(paramTypes[i])) {
+                        final String msg =
+                            "@ConstructorProperties gives property " + propertyName +
+                            " of type " + propertyType + " for parameter " +
+                            " of type " + paramTypes[i] + ": " + constr;
+                        throw new InvalidObjectException(msg);
+                    }
+                }
+
+                if (!getterIndexSets.add(present)) {
+                    final String msg =
+                        "More than one constructor has a @ConstructorProperties " +
+                        "annotation with this set of names: " +
+                        Arrays.toString(propertyNames);
+                    throw new InvalidObjectException(msg);
+                }
+
+                Constr c = new Constr(constr, paramIndexes, present);
+                annotatedConstructors.add(c);
+            }
+
+            /* Check that no possible set of items could lead to an ambiguous
+             * choice of constructor (spec requires this check).  For any
+             * pair of constructors, their union would be the minimal
+             * ambiguous set.  If this set itself corresponds to a constructor,
+             * there is no ambiguity for that pair.  In the usual case, one
+             * of the constructors is a superset of the other so the union is
+             * just the bigger constuctor.
+             *
+             * The algorithm here is quadratic in the number of constructors
+             * with a @ConstructorProperties annotation.  Typically this corresponds
+             * to the number of versions of the class there have been.  Ten
+             * would already be a large number, so although it's probably
+             * possible to have an O(n lg n) algorithm it wouldn't be
+             * worth the complexity.
+             */
+            for (BitSet a : getterIndexSets) {
+                boolean seen = false;
+                for (BitSet b : getterIndexSets) {
+                    if (a == b)
+                        seen = true;
+                    else if (seen) {
+                        BitSet u = new BitSet();
+                        u.or(a); u.or(b);
+                        if (!getterIndexSets.contains(u)) {
+                            Set<String> names = new TreeSet<String>();
+                            for (int i = u.nextSetBit(0); i >= 0;
+                                 i = u.nextSetBit(i+1))
+                                names.add(itemNames[i]);
+                            final String msg =
+                                "Constructors with @ConstructorProperties annotation " +
+                                " would be ambiguous for these items: " +
+                                names;
+                            throw new InvalidObjectException(msg);
+                        }
+                    }
+                }
+            }
+
+            return null; // success!
+        }
+
+        final Object fromCompositeData(CompositeData cd,
+                                       String[] itemNames,
+                                       MXBeanMapping[] mappings)
+                throws InvalidObjectException {
+            // The CompositeData might come from an earlier version where
+            // not all the items were present.  We look for a constructor
+            // that accepts just the items that are present.  Because of
+            // the ambiguity check in applicable(), we know there must be
+            // at most one maximally applicable constructor.
+            CompositeType ct = cd.getCompositeType();
+            BitSet present = new BitSet();
+            for (int i = 0; i < itemNames.length; i++) {
+                if (ct.getType(itemNames[i]) != null)
+                    present.set(i);
+            }
+
+            Constr max = null;
+            for (Constr constr : annotatedConstructors) {
+                if (subset(constr.presentParams, present) &&
+                        (max == null ||
+                         subset(max.presentParams, constr.presentParams)))
+                    max = constr;
+            }
+
+            if (max == null) {
+                final String msg =
+                    "No constructor has a @ConstructorProperties for this set of " +
+                    "items: " + ct.keySet();
+                throw new InvalidObjectException(msg);
+            }
+
+            Object[] params = new Object[max.presentParams.cardinality()];
+            for (int i = 0; i < itemNames.length; i++) {
+                if (!max.presentParams.get(i))
+                    continue;
+                Object openItem = cd.get(itemNames[i]);
+                Object javaItem = mappings[i].fromOpenValue(openItem);
+                int index = max.paramIndexes[i];
+                if (index >= 0)
+                    params[index] = javaItem;
+            }
+
+            try {
+                return max.constructor.newInstance(params);
+            } catch (Exception e) {
+                final String msg =
+                    "Exception constructing " + getTargetClass().getName();
+                throw invalidObjectException(msg, e);
+            }
+        }
+
+        private static boolean subset(BitSet sub, BitSet sup) {
+            BitSet subcopy = (BitSet) sub.clone();
+            subcopy.andNot(sup);
+            return subcopy.isEmpty();
+        }
+
+        private static class Constr {
+            final Constructor constructor;
+            final int[] paramIndexes;
+            final BitSet presentParams;
+            Constr(Constructor constructor, int[] paramIndexes,
+                   BitSet presentParams) {
+                this.constructor = constructor;
+                this.paramIndexes = paramIndexes;
+                this.presentParams = presentParams;
+            }
+        }
+
+        private List<Constr> annotatedConstructors;
+    }
+
+    /** Builder for when the target class is an interface and contains
+        no methods other than getters.  Then we can make an instance
+        using a dynamic proxy that forwards the getters to the source
+        CompositeData.  */
+    private static final class CompositeBuilderViaProxy
+            extends CompositeBuilder {
+
+        CompositeBuilderViaProxy(Class targetClass, String[] itemNames) {
+            super(targetClass, itemNames);
+        }
+
+        String applicable(Method[] getters) {
+            Class targetClass = getTargetClass();
+            if (!targetClass.isInterface())
+                return "not an interface";
+            Set<Method> methods =
+                newSet(Arrays.asList(targetClass.getMethods()));
+            methods.removeAll(Arrays.asList(getters));
+            /* If the interface has any methods left over, they better be
+             * public methods that are already present in java.lang.Object.
+             */
+            String bad = null;
+            for (Method m : methods) {
+                String mname = m.getName();
+                Class[] mparams = m.getParameterTypes();
+                try {
+                    Method om = Object.class.getMethod(mname, mparams);
+                    if (!Modifier.isPublic(om.getModifiers()))
+                        bad = mname;
+                } catch (NoSuchMethodException e) {
+                    bad = mname;
+                }
+                /* We don't catch SecurityException since it shouldn't
+                 * happen for a method in Object and if it does we would
+                 * like to know about it rather than mysteriously complaining.
+                 */
+            }
+            if (bad != null)
+                return "contains methods other than getters (" + bad + ")";
+            return null; // success!
+        }
+
+        final Object fromCompositeData(CompositeData cd,
+                                       String[] itemNames,
+                                       MXBeanMapping[] converters) {
+            final Class targetClass = getTargetClass();
+            return
+                Proxy.newProxyInstance(targetClass.getClassLoader(),
+                                       new Class[] {targetClass},
+                                       new CompositeDataInvocationHandler(cd));
+        }
+    }
+
+    static InvalidObjectException invalidObjectException(String msg,
+                                                         Throwable cause) {
+        return EnvHelp.initCause(new InvalidObjectException(msg), cause);
+    }
+
+    static InvalidObjectException invalidObjectException(Throwable cause) {
+        return invalidObjectException(cause.getMessage(), cause);
+    }
+
+    static OpenDataException openDataException(String msg, Throwable cause) {
+        return EnvHelp.initCause(new OpenDataException(msg), cause);
+    }
+
+    static OpenDataException openDataException(Throwable cause) {
+        return openDataException(cause.getMessage(), cause);
+    }
+
+    static void mustBeComparable(Class collection, Type element)
+            throws OpenDataException {
+        if (!(element instanceof Class)
+            || !Comparable.class.isAssignableFrom((Class<?>) element)) {
+            final String msg =
+                "Parameter class " + element + " of " +
+                collection.getName() + " does not implement " +
+                Comparable.class.getName();
+            throw new OpenDataException(msg);
+        }
+    }
+
+    /**
+     * Utility method to take a string and convert it to normal Java variable
+     * name capitalization.  This normally means converting the first
+     * character from upper case to lower case, but in the (unusual) special
+     * case when there is more than one character and both the first and
+     * second characters are upper case, we leave it alone.
+     * <p>
+     * Thus "FooBah" becomes "fooBah" and "X" becomes "x", but "URL" stays
+     * as "URL".
+     *
+     * @param  name The string to be decapitalized.
+     * @return  The decapitalized version of the string.
+     */
+    public static String decapitalize(String name) {
+        if (name == null || name.length() == 0) {
+            return name;
+        }
+        int offset1 = Character.offsetByCodePoints(name, 0, 1);
+        // Should be name.offsetByCodePoints but 6242664 makes this fail
+        if (offset1 < name.length() &&
+                Character.isUpperCase(name.codePointAt(offset1)))
+            return name;
+        return name.substring(0, offset1).toLowerCase() +
+               name.substring(offset1);
+    }
+
+    /**
+     * Reverse operation for java.beans.Introspector.decapitalize.  For any s,
+     * capitalize(decapitalize(s)).equals(s).  The reverse is not true:
+     * e.g. capitalize("uRL") produces "URL" which is unchanged by
+     * decapitalize.
+     */
+    static String capitalize(String name) {
+        if (name == null || name.length() == 0)
+            return name;
+        int offset1 = name.offsetByCodePoints(0, 1);
+        return name.substring(0, offset1).toUpperCase() +
+               name.substring(offset1);
+    }
+
+    public static String propertyName(Method m) {
+        String rest = null;
+        String name = m.getName();
+        if (name.startsWith("get"))
+            rest = name.substring(3);
+        else if (name.startsWith("is") && m.getReturnType() == boolean.class)
+            rest = name.substring(2);
+        if (rest == null || rest.length() == 0
+            || m.getParameterTypes().length > 0
+            || m.getReturnType() == void.class
+            || name.equals("getClass"))
+            return null;
+        return rest;
+    }
+
+    private final static Map<Type, Type> inProgress = newIdentityHashMap();
+    // really an IdentityHashSet but that doesn't exist
+}
--- a/src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java	Thu Aug 07 22:24:26 2008 -0700
@@ -25,7 +25,7 @@
 
 package com.sun.jmx.mbeanserver;
 
-import javax.management.DynamicMBean;
+import javax.management.DynamicWrapperMBean;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
 
@@ -35,17 +35,7 @@
  *
  * @since 1.6
  */
-public interface DynamicMBean2 extends DynamicMBean {
-    /**
-     * The resource corresponding to this MBean.  This is the object whose
-     * class name should be reflected by the MBean's
-     * getMBeanInfo().getClassName() for example.  For a "plain"
-     * DynamicMBean it will be "this".  For an MBean that wraps another
-     * object, like javax.management.StandardMBean, it will be the wrapped
-     * object.
-     */
-    public Object getResource();
-
+public interface DynamicMBean2 extends DynamicWrapperMBean {
     /**
      * The name of this MBean's class, as used by permission checks.
      * This is typically equal to getResource().getClass().getName().
--- a/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,23 +25,38 @@
 
 package com.sun.jmx.mbeanserver;
 
+import com.sun.jmx.remote.util.EnvHelp;
+import java.beans.BeanInfo;
+import java.beans.PropertyDescriptor;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
 import java.lang.reflect.UndeclaredThrowableException;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.logging.Level;
+import javax.management.AttributeNotFoundException;
+import javax.management.Description;
 
 import javax.management.Descriptor;
+import javax.management.DescriptorFields;
 import javax.management.DescriptorKey;
 import javax.management.DynamicMBean;
 import javax.management.ImmutableDescriptor;
+import javax.management.MBean;
 import javax.management.MBeanInfo;
+import javax.management.MXBean;
 import javax.management.NotCompliantMBeanException;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.MXBeanMappingFactory;
 
+import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
 import com.sun.jmx.mbeanserver.Util;
 import com.sun.jmx.remote.util.EnvHelp;
 import java.beans.BeanInfo;
@@ -50,6 +65,7 @@
 import java.lang.reflect.InvocationTargetException;
 import javax.management.AttributeNotFoundException;
 import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.MXBeanMappingFactory;
 
 /**
  * This class contains the methods for performing all the tests needed to verify
@@ -133,8 +149,12 @@
         }
     }
 
-    public static void checkCompliance(Class mbeanClass)
-        throws NotCompliantMBeanException {
+    public static void checkCompliance(Class<?> mbeanClass)
+    throws NotCompliantMBeanException {
+
+        // Check that @Resource is used correctly (if it used).
+        MBeanInjector.validate(mbeanClass);
+
         // Is DynamicMBean?
         //
         if (DynamicMBean.class.isAssignableFrom(mbeanClass))
@@ -157,38 +177,60 @@
         } catch (NotCompliantMBeanException e) {
             mxbeanException = e;
         }
+        // Is @MBean or @MXBean class?
+        // In fact we find @MBean or @MXBean as a hacky variant of
+        // getStandardMBeanInterface or getMXBeanInterface.  If we get here
+        // then nothing worked.
         final String msg =
             "MBean class " + mbeanClass.getName() + " does not implement " +
-            "DynamicMBean, neither follows the Standard MBean conventions (" +
-            mbeanException.toString() + ") nor the MXBean conventions (" +
-            mxbeanException.toString() + ")";
+            "DynamicMBean; does not follow the Standard MBean conventions (" +
+            mbeanException.toString() + "); does not follow the MXBean conventions (" +
+            mxbeanException.toString() + "); and does not have or inherit the @" +
+            MBean.class.getSimpleName() + " or @" + MXBean.class.getSimpleName() +
+            " annotation";
         throw new NotCompliantMBeanException(msg);
     }
 
-    public static DynamicMBean makeDynamicMBean(Object mbean)
-        throws NotCompliantMBeanException {
+    /**
+     * <p>Make a DynamicMBean out of the existing MBean object.  The object
+     * may already be a DynamicMBean, or it may be a Standard MBean or
+     * MXBean, possibly defined using {@code @MBean} or {@code @MXBean}.</p>
+     * @param mbean the object to convert to a DynamicMBean.
+     * @param <T> a type parameter defined for implementation convenience
+     * (which would have to be removed if this method were part of the public
+     * API).
+     * @return the converted DynamicMBean.
+     * @throws NotCompliantMBeanException if {@code mbean} is not a compliant
+     * MBean object, including the case where it is null.
+     */
+    public static <T> DynamicMBean makeDynamicMBean(T mbean)
+    throws NotCompliantMBeanException {
+        if (mbean == null)
+            throw new NotCompliantMBeanException("Null MBean object");
         if (mbean instanceof DynamicMBean)
             return (DynamicMBean) mbean;
-        final Class mbeanClass = mbean.getClass();
-        Class<?> c = null;
+        final Class<?> mbeanClass = mbean.getClass();
+        Class<? super T> c = null;
         try {
-            c = getStandardMBeanInterface(mbeanClass);
+            c = Util.cast(getStandardMBeanInterface(mbeanClass));
         } catch (NotCompliantMBeanException e) {
             // Ignore exception - we need to check whether
             // mbean is an MXBean first.
         }
         if (c != null)
-            return new StandardMBeanSupport(mbean, Util.<Class<Object>>cast(c));
+            return new StandardMBeanSupport(mbean, c);
 
         try {
-            c = getMXBeanInterface(mbeanClass);
+            c = Util.cast(getMXBeanInterface(mbeanClass));
         } catch (NotCompliantMBeanException e) {
             // Ignore exception - we cannot decide whether mbean was supposed
             // to be an MBean or an MXBean. We will call checkCompliance()
             // to generate the appropriate exception.
         }
-        if (c != null)
-            return new MXBeanSupport(mbean, Util.<Class<Object>>cast(c));
+        if (c != null) {
+            MXBeanMappingFactory factory = MXBeanMappingFactory.forInterface(c);
+            return new MXBeanSupport(mbean, c, factory);
+        }
         checkCompliance(mbeanClass);
         throw new NotCompliantMBeanException("Not compliant"); // not reached
     }
@@ -217,9 +259,10 @@
         return testCompliance(baseClass, null);
     }
 
-    public static void testComplianceMXBeanInterface(Class interfaceClass)
+    public static void testComplianceMXBeanInterface(Class interfaceClass,
+                                                     MXBeanMappingFactory factory)
             throws NotCompliantMBeanException {
-        MXBeanIntrospector.getInstance().getAnalyzer(interfaceClass);
+        MXBeanIntrospector.getInstance(factory).getAnalyzer(interfaceClass);
     }
 
     /**
@@ -265,7 +308,7 @@
      *         Return <code>null</code> if the MBean is a DynamicMBean,
      *         or if no MBean interface is found.
      */
-    public static Class getMBeanInterface(Class baseClass) {
+    public static Class<?> getMBeanInterface(Class<?> baseClass) {
         // Check if the given class implements the MBean interface
         // or the Dynamic MBean interface
         if (isDynamic(baseClass)) return null;
@@ -286,10 +329,12 @@
      * @throws NotCompliantMBeanException The specified class is
      * not a JMX compliant Standard MBean.
      */
-    public static Class getStandardMBeanInterface(Class baseClass)
-        throws NotCompliantMBeanException {
-        Class current = baseClass;
-        Class mbeanInterface = null;
+    public static <T> Class<? super T> getStandardMBeanInterface(Class<T> baseClass)
+    throws NotCompliantMBeanException {
+        if (baseClass.isAnnotationPresent(MBean.class))
+            return baseClass;
+        Class<? super T> current = baseClass;
+        Class<? super T> mbeanInterface = null;
         while (current != null) {
             mbeanInterface =
                 findMBeanInterface(current, current.getName());
@@ -316,8 +361,10 @@
      * @throws NotCompliantMBeanException The specified class is
      * not a JMX compliant MXBean.
      */
-    public static Class getMXBeanInterface(Class baseClass)
+    public static <T> Class<? super T> getMXBeanInterface(Class<T> baseClass)
         throws NotCompliantMBeanException {
+        if (hasMXBeanAnnotation(baseClass))
+            return baseClass;
         try {
             return MXBeanSupport.findMXBeanInterface(baseClass);
         } catch (Exception e) {
@@ -325,25 +372,39 @@
         }
     }
 
+    public static <T> Class<? super T> getStandardOrMXBeanInterface(
+            Class<T> baseClass, boolean mxbean)
+    throws NotCompliantMBeanException {
+        if (mxbean)
+            return getMXBeanInterface(baseClass);
+        else
+            return getStandardMBeanInterface(baseClass);
+    }
+
     /*
      * ------------------------------------------
      *  PRIVATE METHODS
      * ------------------------------------------
      */
 
+    static boolean hasMXBeanAnnotation(Class<?> c) {
+        MXBean m = c.getAnnotation(MXBean.class);
+        return (m != null && m.value());
+    }
 
     /**
      * Try to find the MBean interface corresponding to the class aName
      * - i.e. <i>aName</i>MBean, from within aClass and its superclasses.
      **/
-    private static Class findMBeanInterface(Class aClass, String aName) {
-        Class current = aClass;
+    private static <T> Class<? super T> findMBeanInterface(
+            Class<T> aClass, String aName) {
+        Class<? super T> current = aClass;
         while (current != null) {
-            final Class[] interfaces = current.getInterfaces();
+            final Class<?>[] interfaces = current.getInterfaces();
             final int len = interfaces.length;
             for (int i=0;i<len;i++)  {
-                final Class inter =
-                    implementsMBean(interfaces[i], aName);
+                Class<? super T> inter = Util.cast(interfaces[i]);
+                inter = implementsMBean(inter, aName);
                 if (inter != null) return inter;
             }
             current = current.getSuperclass();
@@ -351,6 +412,48 @@
         return null;
     }
 
+    public static String descriptionForElement(AnnotatedElement elmt) {
+        if (elmt == null)
+            return null;
+        Description d = elmt.getAnnotation(Description.class);
+        if (d == null)
+            return null;
+        return d.value();
+    }
+
+    public static String descriptionForParameter(
+            Annotation[] parameterAnnotations) {
+        for (Annotation a : parameterAnnotations) {
+            if (a instanceof Description)
+                return ((Description) a).value();
+        }
+        return null;
+    }
+
+    public static String nameForParameter(
+            Annotation[] parameterAnnotations) {
+        for (Annotation a : parameterAnnotations) {
+            Class<? extends Annotation> ac = a.annotationType();
+            // You'd really have to go out of your way to have more than
+            // one @Name annotation, so we don't check for that.
+            if (ac.getSimpleName().equals("Name")) {
+                try {
+                    Method value = ac.getMethod("value");
+                    if (value.getReturnType() == String.class &&
+                            value.getParameterTypes().length == 0) {
+                        return (String) value.invoke(a);
+                    }
+                } catch (Exception e) {
+                    MBEANSERVER_LOGGER.log(
+                            Level.WARNING,
+                            "Unexpected exception getting @" + ac.getName(),
+                            e);
+                }
+            }
+        }
+        return null;
+    }
+
     public static Descriptor descriptorForElement(final AnnotatedElement elmt) {
         if (elmt == null)
             return ImmutableDescriptor.EMPTY_DESCRIPTOR;
@@ -358,41 +461,18 @@
         return descriptorForAnnotations(annots);
     }
 
+    public static Descriptor descriptorForAnnotation(Annotation annot) {
+        return descriptorForAnnotations(new Annotation[] {annot});
+    }
+
     public static Descriptor descriptorForAnnotations(Annotation[] annots) {
         if (annots.length == 0)
             return ImmutableDescriptor.EMPTY_DESCRIPTOR;
         Map<String, Object> descriptorMap = new HashMap<String, Object>();
         for (Annotation a : annots) {
-            Class<? extends Annotation> c = a.annotationType();
-            Method[] elements = c.getMethods();
-            for (Method element : elements) {
-                DescriptorKey key = element.getAnnotation(DescriptorKey.class);
-                if (key != null) {
-                    String name = key.value();
-                    Object value;
-                    try {
-                        value = element.invoke(a);
-                    } catch (RuntimeException e) {
-                        // we don't expect this - except for possibly
-                        // security exceptions?
-                        // RuntimeExceptions shouldn't be "UndeclaredThrowable".
-                        // anyway...
-                        //
-                        throw e;
-                    } catch (Exception e) {
-                        // we don't expect this
-                        throw new UndeclaredThrowableException(e);
-                    }
-                    value = annotationToField(value);
-                    Object oldValue = descriptorMap.put(name, value);
-                    if (oldValue != null && !equals(oldValue, value)) {
-                        final String msg =
-                            "Inconsistent values for descriptor field " + name +
-                            " from annotations: " + value + " :: " + oldValue;
-                        throw new IllegalArgumentException(msg);
-                    }
-                }
-            }
+            if (a instanceof DescriptorFields)
+                addDescriptorFieldsToMap(descriptorMap, (DescriptorFields) a);
+            addAnnotationFieldsToMap(descriptorMap, a);
         }
 
         if (descriptorMap.isEmpty())
@@ -401,6 +481,62 @@
             return new ImmutableDescriptor(descriptorMap);
     }
 
+    private static void addDescriptorFieldsToMap(
+            Map<String, Object> descriptorMap, DescriptorFields df) {
+        for (String field : df.value()) {
+            int eq = field.indexOf('=');
+            if (eq < 0) {
+                throw new IllegalArgumentException(
+                        "@DescriptorFields string must contain '=': " +
+                        field);
+            }
+            String name = field.substring(0, eq);
+            String value = field.substring(eq + 1);
+            addToMap(descriptorMap, name, value);
+        }
+    }
+
+    private static void addAnnotationFieldsToMap(
+            Map<String, Object> descriptorMap, Annotation a) {
+        Class<? extends Annotation> c = a.annotationType();
+        Method[] elements = c.getMethods();
+        for (Method element : elements) {
+            DescriptorKey key = element.getAnnotation(DescriptorKey.class);
+            if (key != null) {
+                String name = key.value();
+                Object value;
+                try {
+                    value = element.invoke(a);
+                } catch (RuntimeException e) {
+                    // we don't expect this - except for possibly
+                    // security exceptions?
+                    // RuntimeExceptions shouldn't be "UndeclaredThrowable".
+                    // anyway...
+                    throw e;
+                } catch (Exception e) {
+                    // we don't expect this
+                    throw new UndeclaredThrowableException(e);
+                }
+                if (!key.omitIfDefault() ||
+                        !equals(value, element.getDefaultValue())) {
+                    value = annotationToField(value);
+                    addToMap(descriptorMap, name, value);
+                }
+            }
+        }
+    }
+
+    private static void addToMap(
+            Map<String, Object> descriptorMap, String name, Object value) {
+        Object oldValue = descriptorMap.put(name, value);
+        if (oldValue != null && !equals(oldValue, value)) {
+            final String msg =
+                "Inconsistent values for descriptor field " + name +
+                " from annotations: " + value + " :: " + oldValue;
+            throw new IllegalArgumentException(msg);
+        }
+    }
+
     /**
      * Throws a NotCompliantMBeanException or a SecurityException.
      * @param notCompliant the class which was under examination
@@ -459,8 +595,13 @@
         // The only other possibility is that the value is another
         // annotation, or that the language has evolved since this code
         // was written.  We don't allow for either of those currently.
+        // If it is indeed another annotation, then x will be a proxy
+        // with an unhelpful name like $Proxy2.  So we extract the
+        // proxy's interface to use that in the exception message.
+        if (Proxy.isProxyClass(c))
+            c = c.getInterfaces()[0];  // array "can't be empty"
         throw new IllegalArgumentException("Illegal type for annotation " +
-                "element: " + x.getClass().getName());
+                "element using @DescriptorKey: " + c.getName());
     }
 
     // This must be consistent with the check for duplicate field values in
@@ -476,15 +617,15 @@
      * @param c The interface to be tested
      * @param clName The name of the class implementing this interface
      */
-    private static Class implementsMBean(Class c, String clName) {
+    private static <T> Class<? super T> implementsMBean(Class<T> c, String clName) {
         String clMBeanName = clName + "MBean";
         if (c.getName().equals(clMBeanName)) {
             return c;
         }
-        Class[] interfaces = c.getInterfaces();
+        Class<?>[] interfaces = c.getInterfaces();
         for (int i = 0;i < interfaces.length; i++) {
             if (interfaces[i].getName().equals(clMBeanName))
-                return interfaces[i];
+                return Util.cast(interfaces[i]);
         }
 
         return null;
--- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,13 +29,14 @@
 
 import java.lang.reflect.Method;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Comparator;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
+import javax.management.MBean;
+import javax.management.MXBean;
+import javax.management.ManagedAttribute;
+import javax.management.ManagedOperation;
 import javax.management.NotCompliantMBeanException;
 
 /**
@@ -54,15 +55,15 @@
  */
 class MBeanAnalyzer<M> {
 
-    static interface MBeanVisitor<M> {
+    static interface MBeanVisitor<M, X extends Exception> {
         public void visitAttribute(String attributeName,
                 M getter,
-                M setter);
+                M setter) throws X;
         public void visitOperation(String operationName,
-                M operation);
+                M operation) throws X;
     }
 
-    void visit(MBeanVisitor<M> visitor) {
+    <X extends Exception> void visit(MBeanVisitor<M, X> visitor) throws X {
         // visit attributes
         for (Map.Entry<String, AttrMethods<M>> entry : attrMap.entrySet()) {
             String name = entry.getKey();
@@ -98,21 +99,21 @@
     // cached PerInterface object for an MBean interface means that
     // an analyzer will not be recreated for a second MBean using the
     // same interface.
-    static <M> MBeanAnalyzer<M> analyzer(Class<?> mbeanInterface,
+    static <M> MBeanAnalyzer<M> analyzer(Class<?> mbeanType,
             MBeanIntrospector<M> introspector)
             throws NotCompliantMBeanException {
-        return new MBeanAnalyzer<M>(mbeanInterface, introspector);
+        return new MBeanAnalyzer<M>(mbeanType, introspector);
     }
 
-    private MBeanAnalyzer(Class<?> mbeanInterface,
+    private MBeanAnalyzer(Class<?> mbeanType,
             MBeanIntrospector<M> introspector)
             throws NotCompliantMBeanException {
-        introspector.checkCompliance(mbeanInterface);
+        introspector.checkCompliance(mbeanType);
 
         try {
-            initMaps(mbeanInterface, introspector);
+            initMaps(mbeanType, introspector);
         } catch (Exception x) {
-            throw Introspector.throwException(mbeanInterface,x);
+            throw Introspector.throwException(mbeanType,x);
         }
     }
 
@@ -126,19 +127,28 @@
         /* Run through the methods to detect inconsistencies and to enable
            us to give getter and setter together to visitAttribute. */
         for (Method m : methods) {
-            String name = m.getName();
+            final String name = m.getName();
+            final int nParams = m.getParameterTypes().length;
+            final boolean managedOp = m.isAnnotationPresent(ManagedOperation.class);
+            final boolean managedAttr = m.isAnnotationPresent(ManagedAttribute.class);
+            if (managedOp && managedAttr) {
+                throw new NotCompliantMBeanException("Method " + name +
+                        " has both @ManagedOperation and @ManagedAttribute");
+            }
 
             final M cm = introspector.mFrom(m);
 
             String attrName = "";
-            if (name.startsWith("get"))
-                attrName = name.substring(3);
-            else if (name.startsWith("is")
-            && m.getReturnType() == boolean.class)
-                attrName = name.substring(2);
+            if (!managedOp) {
+                if (name.startsWith("get"))
+                    attrName = name.substring(3);
+                else if (name.startsWith("is")
+                         && m.getReturnType() == boolean.class)
+                    attrName = name.substring(2);
+            }
 
-            if (attrName.length() != 0 && m.getParameterTypes().length == 0
-                    && m.getReturnType() != void.class) {
+            if (attrName.length() != 0 && nParams == 0
+                    && m.getReturnType() != void.class && !managedOp) {
                 // It's a getter
                 // Check we don't have both isX and getX
                 AttrMethods<M> am = attrMap.get(attrName);
@@ -154,8 +164,8 @@
                 am.getter = cm;
                 attrMap.put(attrName, am);
             } else if (name.startsWith("set") && name.length() > 3
-                    && m.getParameterTypes().length == 1 &&
-                    m.getReturnType() == void.class) {
+                    && nParams == 1 &&
+                    m.getReturnType() == void.class && !managedOp) {
                 // It's a setter
                 attrName = name.substring(3);
                 AttrMethods<M> am = attrMap.get(attrName);
@@ -168,6 +178,9 @@
                 }
                 am.setter = cm;
                 attrMap.put(attrName, am);
+            } else if (managedAttr) {
+                throw new NotCompliantMBeanException("Method " + name +
+                        " has @ManagedAttribute but is not a valid getter or setter");
             } else {
                 // It's an operation
                 List<M> cms = opMap.get(name);
@@ -228,7 +241,11 @@
        but only the overriding one is of interest.  We return the methods
        in the same order they arrived in.  This isn't required by the spec
        but existing code may depend on it and users may be used to seeing
-       operations or attributes appear in a particular order.  */
+       operations or attributes appear in a particular order.
+
+       Because of the way this method works, if the same Method appears
+       more than once in the given List then it will be completely deleted!
+       So don't do that.  */
     static List<Method>
             eliminateCovariantMethods(List<Method> startMethods) {
         // We are assuming that you never have very many methods with the
@@ -243,7 +260,7 @@
             final Method m0 = sorted[i-1];
             final Method m1 = sorted[i];
 
-            // Methods that don't have the same name can't override each others
+            // Methods that don't have the same name can't override each other
             if (!m0.getName().equals(m1.getName())) continue;
 
             // Methods that have the same name and same signature override
@@ -251,7 +268,8 @@
             // due to the way we have sorted them in MethodOrder.
             if (Arrays.equals(m0.getParameterTypes(),
                     m1.getParameterTypes())) {
-                overridden.add(m0);
+                if (!overridden.add(m0))
+                    throw new RuntimeException("Internal error: duplicate Method");
             }
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanInjector.java	Thu Aug 07 22:24:26 2008 -0700
@@ -0,0 +1,291 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * 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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.mbeanserver;
+
+import java.lang.ref.WeakReference;
+import java.security.PrivilegedAction;
+import java.util.Map;
+import java.util.WeakHashMap;
+import javax.annotation.Resource;
+import javax.management.MBeanServer;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+
+import static com.sun.jmx.mbeanserver.Util.newMap;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.management.SendNotification;
+
+public class MBeanInjector {
+    private static Class<?>[] injectedClasses = {
+        MBeanServer.class, ObjectName.class, SendNotification.class,
+    };
+
+    public static void inject(Object mbean, MBeanServer mbs, ObjectName name)
+    throws Exception {
+        ClassInjector injector = injectorForClass(mbean.getClass());
+        injector.inject(mbean, MBeanServer.class, mbs);
+        injector.inject(mbean, ObjectName.class, name);
+    }
+
+    public static boolean injectsSendNotification(Object mbean)
+    throws NotCompliantMBeanException {
+        ClassInjector injector = injectorForClass(mbean.getClass());
+        return injector.injects(SendNotification.class);
+    }
+
+    public static void injectSendNotification(Object mbean, SendNotification sn)
+    throws Exception {
+        ClassInjector injector = injectorForClass(mbean.getClass());
+        injector.inject(mbean, SendNotification.class, sn);
+    }
+
+    public static void validate(Class<?> c) throws NotCompliantMBeanException {
+        injectorForClass(c);
+    }
+
+    private static class ClassInjector {
+        private Map<Class<?>, List<Field>> fields;
+        private Map<Class<?>, List<Method>> methods;
+
+        ClassInjector(Class<?> c) throws NotCompliantMBeanException {
+            fields = newMap();
+            methods = newMap();
+
+            Class<?> sup = c.getSuperclass();
+            ClassInjector supInjector;
+            if (sup == null) {
+                supInjector = null;
+            } else {
+                supInjector = injectorForClass(sup);
+                fields.putAll(supInjector.fields);
+                methods.putAll(supInjector.methods);
+            }
+
+            addMembers(c);
+            eliminateOverriddenMethods();
+
+            // If we haven't added any new fields or methods to what we
+            // inherited, then we can share the parent's maps.
+            if (supInjector != null) {
+                if (fields.equals(supInjector.fields))
+                    fields = supInjector.fields;
+                if (methods.equals(supInjector.methods))
+                    methods = supInjector.methods;
+            }
+        }
+
+        boolean injects(Class<?> c) {
+            return (fields.get(c) != null || methods.get(c) != null);
+        }
+
+        <T> void inject(Object instance, Class<T> type, T resource)
+        throws Exception {
+            List<Field> fs = fields.get(type);
+            if (fs != null) {
+                for (Field f : fs)
+                    f.set(instance, resource);
+            }
+            List<Method> ms = methods.get(type);
+            if (ms != null) {
+                for (Method m : ms) {
+                    try {
+                        m.invoke(instance, resource);
+                    } catch (InvocationTargetException e) {
+                        Throwable cause = e.getCause();
+                        if (cause instanceof Error)
+                            throw (Error) cause;
+                        else
+                            throw (Exception) cause;
+                    }
+                }
+            }
+        }
+
+        private void eliminateOverriddenMethods() {
+            /* Covariant overriding is unlikely, but it is possible that the
+             * parent has a @Resource method that we override with another
+             * @Resource method.  We don't want to invoke both methods,
+             * because polymorphism means we would actually invoke the same
+             * method twice.
+             */
+            for (Map.Entry<Class<?>, List<Method>> entry : methods.entrySet()) {
+                List<Method> list = entry.getValue();
+                list = MBeanAnalyzer.eliminateCovariantMethods(list);
+                entry.setValue(list);
+            }
+        }
+
+        /*
+         * Find Fields or Methods within the given Class that we can inject
+         * resource references into.  Suppose we want to know if a Field can get
+         * a reference to an ObjectName.  We'll accept fields like this:
+         *
+         * @Resource
+         * private transient ObjectName name;
+         *
+         * or like this:
+         *
+         * @Resource(type = ObjectName.class)
+         * private transient Object name;
+         *
+         * but not like this:
+         *
+         * @Resource
+         * private transient Object name;
+         *
+         * (Plain @Resource is equivalent to @Resource(type = Object.class).)
+         *
+         * We don't want to inject into everything that might possibly accept
+         * an ObjectName reference, because examples like the last one above
+         * could also accept an MBeanServer reference or any other sort of
+         * reference.
+         *
+         * So we accept a Field if it has a @Resource annotation and either
+         * (a) its type is ObjectName or a subclass and its @Resource type is
+         * compatible with ObjectName (e.g. it is Object); or
+         * (b) its type is compatible with ObjectName and its @Resource type
+         * is exactly ObjectName.  Fields that meet these criteria will not
+         * meet the same criteria with respect to other types such as MBeanServer.
+         *
+         * The same logic applies mutatis mutandis to Methods such as this:
+         *
+         * @Resource
+         * private void setObjectName1(ObjectName name)
+         * @Resource(type = Object.class)
+         * private void setObjectName2(Object name)
+         */
+        private void addMembers(final Class<?> c)
+        throws NotCompliantMBeanException {
+            AccessibleObject[][] memberArrays =
+                AccessController.doPrivileged(
+                    new PrivilegedAction<AccessibleObject[][]>() {
+                        public AccessibleObject[][] run() {
+                            return new AccessibleObject[][] {
+                                c.getDeclaredFields(), c.getDeclaredMethods()
+                            };
+                        }
+                    });
+            for (AccessibleObject[] members : memberArrays) {
+                for (final AccessibleObject member : members) {
+                    Resource res = member.getAnnotation(Resource.class);
+                    if (res == null)
+                        continue;
+
+                    final Field field;
+                    final Method method;
+                    final Class<?> memberType;
+                    final int modifiers;
+                    if (member instanceof Field) {
+                        field = (Field) member;
+                        memberType = field.getType();
+                        modifiers = field.getModifiers();
+                        method = null;
+                    } else {
+                        field = null;
+                        method = (Method) member;
+                        Class<?>[] paramTypes = method.getParameterTypes();
+                        if (paramTypes.length != 1) {
+                            throw new NotCompliantMBeanException(
+                                    "@Resource method must have exactly 1 " +
+                                    "parameter: " + method);
+                        }
+                        if (method.getReturnType() != void.class) {
+                            throw new NotCompliantMBeanException(
+                                    "@Resource method must return void: " +
+                                    method);
+                        }
+                        memberType = paramTypes[0];
+                        modifiers = method.getModifiers();
+                    }
+
+                    if (Modifier.isStatic(modifiers)) {
+                        throw new NotCompliantMBeanException(
+                                "@Resource method or field cannot be static: " +
+                                member);
+                    }
+
+                    for (Class<?> injectedClass : injectedClasses) {
+                        Class<?>[] types = {memberType, res.type()};
+                        boolean accept = false;
+                        for (int i = 0; i < 2; i++) {
+                            if (types[i] == injectedClass &&
+                                    types[1 - i].isAssignableFrom(injectedClass)) {
+                                accept = true;
+                                break;
+                            }
+                        }
+                        if (accept) {
+                            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                                public Void run() {
+                                    member.setAccessible(true);
+                                    return null;
+                                }
+                            });
+                            addToMap(fields, injectedClass, field);
+                            addToMap(methods, injectedClass, method);
+                        }
+                    }
+                }
+            }
+        }
+
+        private static <K, V> void addToMap(Map<K, List<V>> map, K key, V value) {
+            if (value == null)
+                return;
+            List<V> list = map.get(key);
+            if (list == null)
+                list = Collections.singletonList(value);
+            else {
+                if (list.size() == 1)
+                    list = new ArrayList<V>(list);
+                list.add(value);
+            }
+            map.put(key, list);
+        }
+    }
+
+    private static synchronized ClassInjector injectorForClass(Class<?> c)
+    throws NotCompliantMBeanException {
+        WeakReference<ClassInjector> wr = injectorMap.get(c);
+        ClassInjector ci = (wr == null) ? null : wr.get();
+        if (ci == null) {
+            ci = new ClassInjector(c);
+            injectorMap.put(c, new WeakReference<ClassInjector>(ci));
+        }
+        return ci;
+    }
+
+    private static Map<Class<?>, WeakReference<ClassInjector>> injectorMap =
+            new WeakHashMap<Class<?>, WeakReference<ClassInjector>>();
+}
--- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,25 +36,35 @@
 import java.lang.reflect.Type;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 import java.util.WeakHashMap;
+import javax.management.Description;
 
 import javax.management.Descriptor;
 import javax.management.ImmutableDescriptor;
+import javax.management.IntrospectionException;
 import javax.management.InvalidAttributeValueException;
+import javax.management.MBean;
 import javax.management.MBeanAttributeInfo;
 import javax.management.MBeanConstructorInfo;
 import javax.management.MBeanException;
 import javax.management.MBeanInfo;
 import javax.management.MBeanNotificationInfo;
 import javax.management.MBeanOperationInfo;
+import javax.management.MXBean;
+import javax.management.ManagedAttribute;
+import javax.management.ManagedOperation;
 import javax.management.NotCompliantMBeanException;
 import javax.management.NotificationBroadcaster;
+import javax.management.NotificationInfo;
+import javax.management.NotificationInfos;
 import javax.management.ReflectionException;
 
 /**
  * An introspector for MBeans of a certain type.  There is one instance
- * of this class for Standard MBeans and one for MXBeans, characterized
- * by the two concrete subclasses of this abstract class.
+ * of this class for Standard MBeans, and one for every MXBeanMappingFactory;
+ * these two cases correspond to the two concrete subclasses of this abstract
+ * class.
  *
  * @param <M> the representation of methods for this kind of MBean:
  * Method for Standard MBeans, ConvertingMethod for MXBeans.
@@ -119,7 +129,7 @@
      * MXBean interface is not valid if one of its parameters cannot be
      * mapped to an Open Type.
      */
-    abstract void checkMethod(M m) throws IllegalArgumentException;
+    abstract void checkMethod(M m);
 
     /**
      * Invoke the method with the given target and arguments.
@@ -149,7 +159,27 @@
      * may be null.
      */
     abstract MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
-            M getter, M setter);
+            M getter, M setter) throws IntrospectionException;
+
+    final String getAttributeDescription(
+            String attributeName, String defaultDescription,
+            Method getter, Method setter) throws IntrospectionException {
+        String g = Introspector.descriptionForElement(getter);
+        String s = Introspector.descriptionForElement(setter);
+        if (g == null) {
+            if (s == null)
+                return defaultDescription;
+            else
+                return s;
+        } else if (s == null || g.equals(s)) {
+            return g;
+        } else {
+            throw new IntrospectionException(
+                    "Inconsistent @Description on getter and setter for " +
+                    "attribute " + attributeName);
+        }
+    }
+
     /**
      * Construct an MBeanOperationInfo for the given operation based on
      * the M it was derived from.
@@ -170,9 +200,23 @@
      */
     abstract Descriptor getMBeanDescriptor(Class<?> resourceClass);
 
+    /**
+     * Get any additional Descriptor entries for this introspector instance.
+     * If there is a non-default MXBeanMappingFactory, it will appear in
+     * this Descriptor.
+     * @return Additional Descriptor entries, or an empty Descriptor if none.
+     */
+    Descriptor getSpecificMBeanDescriptor() {
+        return ImmutableDescriptor.EMPTY_DESCRIPTOR;
+    }
+
     void checkCompliance(Class<?> mbeanType) throws NotCompliantMBeanException {
-        if (!mbeanType.isInterface()) {
-            throw new NotCompliantMBeanException("Not an interface: " +
+        if (!mbeanType.isInterface() &&
+                !mbeanType.isAnnotationPresent(MBean.class) &&
+                !Introspector.hasMXBeanAnnotation(mbeanType)) {
+            throw new NotCompliantMBeanException("Not an interface and " +
+                    "does not have @" + MBean.class.getSimpleName() +
+                    " or @" + MXBean.class.getSimpleName() + " annotation: " +
                     mbeanType.getName());
         }
     }
@@ -181,7 +225,12 @@
      * Get the methods to be analyzed to build the MBean interface.
      */
     List<Method> getMethods(final Class<?> mbeanType) throws Exception {
-        return Arrays.asList(mbeanType.getMethods());
+        if (mbeanType.isInterface())
+            return Arrays.asList(mbeanType.getMethods());
+
+        final List<Method> methods = newList();
+        getAnnotatedMethods(mbeanType, methods);
+        return methods;
     }
 
     final PerInterface<M> getPerInterface(Class<?> mbeanInterface)
@@ -216,11 +265,14 @@
      * the MBeanInfo's Descriptor.
      */
     private MBeanInfo makeInterfaceMBeanInfo(Class<?> mbeanInterface,
-            MBeanAnalyzer<M> analyzer) {
+            MBeanAnalyzer<M> analyzer) throws IntrospectionException {
         final MBeanInfoMaker maker = new MBeanInfoMaker();
         analyzer.visit(maker);
-        final String description =
+        final String defaultDescription =
                 "Information on the management interface of the MBean";
+        String description = Introspector.descriptionForElement(mbeanInterface);
+        if (description == null)
+            description = defaultDescription;
         return maker.makeMBeanInfo(mbeanInterface, description);
     }
 
@@ -317,11 +369,12 @@
     }
 
     /** A visitor that constructs the per-interface MBeanInfo. */
-    private class MBeanInfoMaker implements MBeanAnalyzer.MBeanVisitor<M> {
+    private class MBeanInfoMaker
+            implements MBeanAnalyzer.MBeanVisitor<M, IntrospectionException> {
 
         public void visitAttribute(String attributeName,
                 M getter,
-                M setter) {
+                M setter) throws IntrospectionException {
             MBeanAttributeInfo mbai =
                     getMBeanAttributeInfo(attributeName, getter, setter);
 
@@ -346,13 +399,14 @@
                     ops.toArray(new MBeanOperationInfo[0]);
             final String interfaceClassName =
                     "interfaceClassName=" + mbeanInterface.getName();
-            final Descriptor interfDescriptor =
+            final Descriptor classNameDescriptor =
                     new ImmutableDescriptor(interfaceClassName);
             final Descriptor mbeanDescriptor = getBasicMBeanDescriptor();
             final Descriptor annotatedDescriptor =
                     Introspector.descriptorForElement(mbeanInterface);
             final Descriptor descriptor =
-                    DescriptorCache.getInstance().union(interfDescriptor,
+                DescriptorCache.getInstance().union(
+                    classNameDescriptor,
                     mbeanDescriptor,
                     annotatedDescriptor);
 
@@ -388,20 +442,32 @@
      * Return the MBeanInfo for the given resource, based on the given
      * per-interface data.
      */
-    final MBeanInfo getMBeanInfo(Object resource, PerInterface<M> perInterface) {
+    final MBeanInfo getMBeanInfo(Object resource, PerInterface<M> perInterface)
+    throws NotCompliantMBeanException {
         MBeanInfo mbi =
                 getClassMBeanInfo(resource.getClass(), perInterface);
-        MBeanNotificationInfo[] notifs = findNotifications(resource);
-        if (notifs == null || notifs.length == 0)
+        MBeanNotificationInfo[] notifs;
+        try {
+            notifs = findNotifications(resource);
+        } catch (RuntimeException e) {
+            NotCompliantMBeanException x =
+                    new NotCompliantMBeanException(e.getMessage());
+            x.initCause(e);
+            throw x;
+        }
+        Descriptor d = getSpecificMBeanDescriptor();
+        boolean anyNotifs = (notifs != null && notifs.length > 0);
+        if (!anyNotifs && ImmutableDescriptor.EMPTY_DESCRIPTOR.equals(d))
             return mbi;
         else {
+            d = ImmutableDescriptor.union(d, mbi.getDescriptor());
             return new MBeanInfo(mbi.getClassName(),
                     mbi.getDescription(),
                     mbi.getAttributes(),
                     mbi.getConstructors(),
                     mbi.getOperations(),
                     notifs,
-                    mbi.getDescriptor());
+                    d);
         }
     }
 
@@ -441,13 +507,43 @@
         }
     }
 
+    /*
+     * Add to "methods" every public method that has the @ManagedAttribute
+     * or @ManagedOperation annotation, in the given class or any of
+     * its superclasses or superinterfaces.
+     *
+     * We always add superclass or superinterface methods first, so that
+     * the stable sort used by eliminateCovariantMethods will put the
+     * method from the most-derived class last.  This means that we will
+     * see the version of the @ManagedAttribute (or ...Operation) annotation
+     * from that method, which might have a different description or whatever.
+     */
+    private static void getAnnotatedMethods(Class<?> c, List<Method> methods)
+    throws Exception {
+        Class<?> sup = c.getSuperclass();
+        if (sup != null)
+            getAnnotatedMethods(sup, methods);
+        Class<?>[] intfs = c.getInterfaces();
+        for (Class<?> intf : intfs)
+            getAnnotatedMethods(intf, methods);
+        for (Method m : c.getMethods()) {
+            // We are careful not to add m if it is inherited from a parent
+            // class or interface, because duplicate methods lead to nasty
+            // behaviour in eliminateCovariantMethods.
+            if (m.getDeclaringClass() == c &&
+                    (m.isAnnotationPresent(ManagedAttribute.class) ||
+                     m.isAnnotationPresent(ManagedOperation.class)))
+                methods.add(m);
+        }
+    }
+
     static MBeanNotificationInfo[] findNotifications(Object moi) {
         if (!(moi instanceof NotificationBroadcaster))
             return null;
         MBeanNotificationInfo[] mbn =
                 ((NotificationBroadcaster) moi).getNotificationInfo();
-        if (mbn == null)
-            return null;
+        if (mbn == null || mbn.length == 0)
+            return findNotificationsFromAnnotations(moi.getClass());
         MBeanNotificationInfo[] result =
                 new MBeanNotificationInfo[mbn.length];
         for (int i = 0; i < mbn.length; i++) {
@@ -459,11 +555,81 @@
         return result;
     }
 
+    private static MBeanNotificationInfo[] findNotificationsFromAnnotations(
+            Class<?> mbeanClass) {
+        Class<?> c = getAnnotatedNotificationInfoClass(mbeanClass);
+        if (c == null)
+            return null;
+        NotificationInfo ni = c.getAnnotation(NotificationInfo.class);
+        NotificationInfos nis = c.getAnnotation(NotificationInfos.class);
+        List<NotificationInfo> list = newList();
+        if (ni != null)
+            list.add(ni);
+        if (nis != null)
+            list.addAll(Arrays.asList(nis.value()));
+        if (list.isEmpty())
+            return null;
+        List<MBeanNotificationInfo> mbnis = newList();
+        for (NotificationInfo x : list) {
+            // The Descriptor includes any fields explicitly specified by
+            // x.descriptorFields(), plus any fields from the contained
+            // @Description annotation.
+            Descriptor d = new ImmutableDescriptor(x.descriptorFields());
+            d = ImmutableDescriptor.union(
+                    d, Introspector.descriptorForAnnotation(x.description()));
+            MBeanNotificationInfo mbni = new MBeanNotificationInfo(
+                    x.types(), x.notificationClass().getName(),
+                    x.description().value(), d);
+            mbnis.add(mbni);
+        }
+        return mbnis.toArray(new MBeanNotificationInfo[mbnis.size()]);
+    }
+
+    private static final Map<Class<?>, WeakReference<Class<?>>>
+            annotatedNotificationInfoClasses = newWeakHashMap();
+
+    private static Class<?> getAnnotatedNotificationInfoClass(Class<?> baseClass) {
+        synchronized (annotatedNotificationInfoClasses) {
+            WeakReference<Class<?>> wr =
+                    annotatedNotificationInfoClasses.get(baseClass);
+            if (wr != null)
+                return wr.get();
+            Class<?> c = null;
+            if (baseClass.isAnnotationPresent(NotificationInfo.class) ||
+                    baseClass.isAnnotationPresent(NotificationInfos.class)) {
+                c = baseClass;
+            } else {
+                Class<?>[] intfs = baseClass.getInterfaces();
+                for (Class<?> intf : intfs) {
+                    Class<?> c1 = getAnnotatedNotificationInfoClass(intf);
+                    if (c1 != null) {
+                        if (c != null) {
+                            throw new IllegalArgumentException(
+                                    "Class " + baseClass.getName() + " inherits " +
+                                    "@NotificationInfo(s) from both " +
+                                    c.getName() + " and " + c1.getName());
+                        }
+                        c = c1;
+                    }
+                }
+            }
+            // Record the result of the search.  If no @NotificationInfo(s)
+            // were found, c is null, and we store a WeakReference(null).
+            // This prevents us from having to search again and fail again.
+            annotatedNotificationInfoClasses.put(baseClass,
+                    new WeakReference<Class<?>>(c));
+            return c;
+        }
+    }
+
     private static MBeanConstructorInfo[] findConstructors(Class<?> c) {
         Constructor[] cons = c.getConstructors();
         MBeanConstructorInfo[] mbc = new MBeanConstructorInfo[cons.length];
         for (int i = 0; i < cons.length; i++) {
-            final String descr = "Public constructor of the MBean";
+            String descr = "Public constructor of the MBean";
+            Description d = cons[i].getAnnotation(Description.class);
+            if (d != null)
+                descr = d.value();
             mbc[i] = new MBeanConstructorInfo(descr, cons[i]);
         }
         return mbc;
--- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,6 +38,7 @@
 import javax.management.NotCompliantMBeanException;
 import javax.management.ObjectName;
 import javax.management.ReflectionException;
+import javax.management.openmbean.MXBeanMappingFactory;
 
 /**
  * Base class for MBeans.  There is one instance of this class for
@@ -121,24 +122,26 @@
 public abstract class MBeanSupport<M>
         implements DynamicMBean2, MBeanRegistration {
 
-    <T> MBeanSupport(T resource, Class<T> mbeanInterface)
+    <T> MBeanSupport(T resource, Class<T> mbeanInterfaceType,
+                     MXBeanMappingFactory mappingFactory)
             throws NotCompliantMBeanException {
-        if (mbeanInterface == null)
+        if (mbeanInterfaceType == null)
             throw new NotCompliantMBeanException("Null MBean interface");
-        if (!mbeanInterface.isInstance(resource)) {
+        if (!mbeanInterfaceType.isInstance(resource)) {
             final String msg =
                 "Resource class " + resource.getClass().getName() +
-                " is not an instance of " + mbeanInterface.getName();
+                " is not an instance of " + mbeanInterfaceType.getName();
             throw new NotCompliantMBeanException(msg);
         }
         this.resource = resource;
-        MBeanIntrospector<M> introspector = getMBeanIntrospector();
-        this.perInterface = introspector.getPerInterface(mbeanInterface);
+        MBeanIntrospector<M> introspector = getMBeanIntrospector(mappingFactory);
+        this.perInterface = introspector.getPerInterface(mbeanInterfaceType);
         this.mbeanInfo = introspector.getMBeanInfo(resource, perInterface);
     }
 
     /** Return the appropriate introspector for this type of MBean. */
-    abstract MBeanIntrospector<M> getMBeanIntrospector();
+    abstract MBeanIntrospector<M>
+            getMBeanIntrospector(MXBeanMappingFactory mappingFactory);
 
     /**
      * Return a cookie for this MBean.  This cookie will be passed to
@@ -162,9 +165,8 @@
     public final ObjectName preRegister(MBeanServer server, ObjectName name)
             throws Exception {
         if (resource instanceof MBeanRegistration)
-            return ((MBeanRegistration) resource).preRegister(server, name);
-        else
-            return name;
+            name = ((MBeanRegistration) resource).preRegister(server, name);
+        return name;
     }
 
     public final void preRegister2(MBeanServer server, ObjectName name)
@@ -261,10 +263,14 @@
         return resource.getClass().getName();
     }
 
-    public final Object getResource() {
+    public final Object getWrappedObject() {
         return resource;
     }
 
+    public final ClassLoader getWrappedClassLoader() {
+        return resource.getClass().getClassLoader();
+    }
+
     public final Class<?> getMBeanInterface() {
         return perInterface.getMBeanInterface();
     }
--- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,18 +25,28 @@
 
 package com.sun.jmx.mbeanserver;
 
+import com.sun.jmx.mbeanserver.MBeanIntrospector.MBeanInfoMap;
+import com.sun.jmx.mbeanserver.MBeanIntrospector.PerInterfaceMap;
 import java.lang.annotation.Annotation;
+import java.lang.ref.WeakReference;
 import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
+import java.util.Map;
+import java.util.WeakHashMap;
+import javax.management.Description;
 import javax.management.Descriptor;
 import javax.management.ImmutableDescriptor;
+import javax.management.IntrospectionException;
+import javax.management.JMX;
 import javax.management.MBeanAttributeInfo;
 import javax.management.MBeanException;
 import javax.management.MBeanOperationInfo;
 import javax.management.MBeanParameterInfo;
+import javax.management.ManagedOperation;
 import javax.management.NotCompliantMBeanException;
+import javax.management.openmbean.MXBeanMappingFactory;
 import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
 import javax.management.openmbean.OpenMBeanOperationInfoSupport;
 import javax.management.openmbean.OpenMBeanParameterInfo;
@@ -49,10 +59,36 @@
  * @since 1.6
  */
 class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
-    private static final MXBeanIntrospector instance = new MXBeanIntrospector();
+    /* We keep one MXBeanIntrospector per MXBeanMappingFactory, since the results
+     * of the introspection depend on the factory.  The MXBeanIntrospector
+     * has a reference back to the factory, so we wrap it in a WeakReference.
+     * It will be strongly referenced by any MXBeanSupport instances using it;
+     * if there are none then it is OK to gc it.
+     */
+    private static final
+            Map<MXBeanMappingFactory, WeakReference<MXBeanIntrospector>> map =
+            new WeakHashMap<MXBeanMappingFactory, WeakReference<MXBeanIntrospector>>();
 
-    static MXBeanIntrospector getInstance() {
-        return instance;
+    static MXBeanIntrospector getInstance(MXBeanMappingFactory factory) {
+        if (factory == null)
+            factory = MXBeanMappingFactory.DEFAULT;
+        synchronized (map) {
+            MXBeanIntrospector intro;
+            WeakReference<MXBeanIntrospector> wr = map.get(factory);
+            if (wr != null) {
+                intro = wr.get();
+                if (intro != null)
+                    return intro;
+            }
+            intro = new MXBeanIntrospector(factory);
+            wr = new WeakReference<MXBeanIntrospector>(intro);
+            map.put(factory, wr);
+            return intro;
+        }
+    }
+
+    private MXBeanIntrospector(MXBeanMappingFactory factory) {
+        this.mappingFactory = factory;
     }
 
     @Override
@@ -78,7 +114,7 @@
 
     @Override
     ConvertingMethod mFrom(Method m) {
-        return ConvertingMethod.from(m);
+        return ConvertingMethod.from(m, mappingFactory);
     }
 
     @Override
@@ -139,13 +175,17 @@
 
     @Override
     MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
-            ConvertingMethod getter, ConvertingMethod setter) {
+            ConvertingMethod getter, ConvertingMethod setter)
+            throws IntrospectionException {
 
         final boolean isReadable = (getter != null);
         final boolean isWritable = (setter != null);
         final boolean isIs = isReadable && getName(getter).startsWith("is");
 
-        final String description = attributeName;
+        final String description = getAttributeDescription(
+                attributeName, attributeName,
+                getter == null ? null : getter.getMethod(),
+                setter == null ? null : setter.getMethod());
 
         final OpenType<?> openType;
         final Type originalType;
@@ -194,13 +234,17 @@
     MBeanOperationInfo getMBeanOperationInfo(String operationName,
             ConvertingMethod operation) {
         final Method method = operation.getMethod();
-        final String description = operationName;
+        String description = operationName;
         /* Ideally this would be an empty string, but
-           OMBOperationInfo constructor forbids that.  Also, we
-           could consult an annotation to get a useful
-           description.  */
+           OMBOperationInfo constructor forbids that.  */
+        Description d = method.getAnnotation(Description.class);
+        if (d != null)
+            description = d.value();
 
-        final int impact = MBeanOperationInfo.UNKNOWN;
+        int impact = MBeanOperationInfo.UNKNOWN;
+        ManagedOperation annot = method.getAnnotation(ManagedOperation.class);
+        if (annot != null)
+            impact = annot.impact().getCode();
 
         final OpenType<?> returnType = operation.getOpenReturnType();
         final Type originalReturnType = operation.getGenericReturnType();
@@ -212,8 +256,15 @@
         boolean openParameterTypes = true;
         Annotation[][] annots = method.getParameterAnnotations();
         for (int i = 0; i < paramTypes.length; i++) {
-            final String paramName = "p" + i;
-            final String paramDescription = paramName;
+            String paramName = Introspector.nameForParameter(annots[i]);
+            if (paramName == null)
+                paramName = "p" + i;
+
+            String paramDescription =
+                    Introspector.descriptionForParameter(annots[i]);
+            if (paramDescription == null)
+                paramDescription = paramName;
+
             final OpenType<?> openType = paramTypes[i];
             final Type originalType = originalParamTypes[i];
             Descriptor descriptor =
@@ -222,14 +273,14 @@
                     Introspector.descriptorForAnnotations(annots[i]));
             final MBeanParameterInfo pi;
             if (canUseOpenInfo(originalType)) {
-                pi = new OpenMBeanParameterInfoSupport("p" + i,
+                pi = new OpenMBeanParameterInfoSupport(paramName,
                                                        paramDescription,
                                                        openType,
                                                        descriptor);
             } else {
                 openParameterTypes = false;
                 pi = new MBeanParameterInfo(
-                    "p" + i,
+                    paramName,
                     originalTypeString(originalType),
                     paramDescription,
                     descriptor);
@@ -291,6 +342,17 @@
         return ImmutableDescriptor.EMPTY_DESCRIPTOR;
     }
 
+    @Override
+    Descriptor getSpecificMBeanDescriptor() {
+        if (mappingFactory == MXBeanMappingFactory.DEFAULT)
+            return ImmutableDescriptor.EMPTY_DESCRIPTOR;
+        else {
+            return new ImmutableDescriptor(
+                    JMX.MXBEAN_MAPPING_FACTORY_CLASS_FIELD + "=" +
+                    mappingFactory.getClass().getName());
+        }
+    }
+
     private static Descriptor typeDescriptor(OpenType openType,
                                              Type originalType) {
         return new ImmutableDescriptor(
@@ -331,8 +393,10 @@
             return type.toString();
     }
 
-    private static final PerInterfaceMap<ConvertingMethod>
+    private final PerInterfaceMap<ConvertingMethod>
         perInterfaceMap = new PerInterfaceMap<ConvertingMethod>();
 
-    private static final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap();
+    private final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap();
+
+    private final MXBeanMappingFactory mappingFactory;
 }
--- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java	Thu Aug 07 11:19:06 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java	Thu Aug 07 22:24:26 2008 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * 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,15 +25,21 @@
 
 package com.sun.jmx.mbeanserver;
 
+import com.sun.jmx.remote.util.EnvHelp;
+import java.io.InvalidObjectException;
 import static com.sun.jmx.mbeanserver.Util.*;
 import java.util.Map;
 import java.lang.ref.WeakReference;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Proxy;
+import java.security.AccessController;
+import javax.management.InstanceAlreadyExistsException;
 import javax.management.JMX;
 import javax.management.MBeanServerConnection;
 import javax.management.MBeanServerInvocationHandler;
+import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
+import javax.management.openmbean.OpenDataException;
 
 /**
  * @since 1.6
@@ -80,71 +86,199 @@
  *
  * From the above, it is clear that the logic for getX on an MXBean is
  * the same as for setX on a proxy, and vice versa.
+ *
+ * The above describes the logic for "plain" MXBeanLookup, represented
+ * by MXBeanLookup.Plain.  When namespaces enter the picture, we see
+ * MXBeanLookup.Prefix.  Here, the idea is that the name of the ModuleMXBean
+ * might be a//m:m=m.  In this case, we don't accept a reference to
+ * an MXBean object, since that would require different namespaces to know
+ * each others' objects.  We only accept proxies.  Suppose you have a proxy
+ * for a//m:m=m, call it moduleProxy, and you call
+ * moduleProxy.setProduct(productProxy).  Then if productProxy is for
+ * a//p:p=p we should convert this to just p:p=p.  If productProxy is for
+ * a//b//p:p=p we should convert it to b//p:p=p.  Conversely, if getProduct
+ * returns an ObjectName like b//p:p=p then we should convert it into a proxy
+ * for a//b//p:p=p.
  */
-public class MXBeanLookup {
+public abstract class MXBeanLookup {
     private MXBeanLookup(MBeanServerConnection mbsc) {
         this.mbsc = mbsc;
     }
 
-    static MXBeanLookup lookupFor(MBeanServerConnection mbsc) {
-        synchronized (mbscToLookup) {
-            WeakReference<MXBeanLookup> weakLookup = mbscToLookup.get(mbsc);
-            MXBeanLookup lookup = (weakLookup == null) ? null : weakLookup.get();
-            if (lookup == null) {
-                lookup = new MXBeanLookup(mbsc);
-                mbscToLookup.put(mbsc, new WeakReference<MXBeanLookup>(lookup));
+    static MXBeanLookup lookupFor(MBeanServerConnection mbsc, String prefix) {
+        if (prefix == null)
+            return Plain.lookupFor(mbsc);
+        else
+            return new Prefix(mbsc, prefix);
+    }
+
+    abstract <T> T objectNameToMXBean(ObjectName name, Class<T> type)
+            throws InvalidObjectException;
+
+    abstract ObjectName mxbeanToObjectName(Object mxbean)
+            throws OpenDataException;
+
+    static class Plain extends MXBeanLookup {
+        Plain(MBeanServerConnection mbsc) {
+            super(mbsc);
+        }
+
+        static Plain lookupFor(MBeanServerConnection mbsc) {
+            synchronized (mbscToLookup) {
+                WeakReference<Plain> weakLookup = mbscToLookup.get(mbsc);
+                Plain lookup = (weakLookup == null) ? null : weakLookup.get();
+                if (lookup == null) {
+                    lookup = new Plain(mbsc);
+                    mbscToLookup.put(mbsc, new WeakReference<Plain>(lookup));
+                }
+                return lookup;
             }
-            return lookup;
+        }
+
+        @Override
+        synchronized <T> T objectNameToMXBean(ObjectName name, Class<T> type) {
+            WeakReference<Object> wr = objectNameToProxy.get(name);
+            if (wr != null) {
+                Object proxy = wr.get();
+                if (type.isInstance(proxy))
+                    return type.cast(proxy);
+            }
+            T proxy = JMX.newMXBeanProxy(mbsc, name, type);
+            objectNameToProxy.put(name, new WeakReference<Object>(proxy));
+            return proxy;
+        }
+
+        @Override
+        synchronized ObjectName mxbeanToObjectName(Object mxbean)
+        throws OpenDataException {
+            String wrong;
+            if (mxbean instanceof Proxy) {
+                InvocationHandler ih = Proxy.getInvocationHandler(mxbean);
+                if (ih instanceof MBeanServerInvocationHandler) {
+                    MBeanServerInvocationHandler mbsih =
+                            (MBeanServerInvocationHandler) ih;
+                    if (mbsih.getMBeanServerConnection().equals(mbsc))
+                        return mbsih.getObjectName();
+                    else
+                        wrong = "proxy for a different MBeanServer";
+                } else
+                    wrong = "not a JMX proxy";
+            } else {
+                ObjectName name = mxbeanToObjectName.get(mxbean);
+                if (name != null)
+                    return name;
+                wrong = "not an MXBean registered in this MBeanServer";
+            }
+            String s = (mxbean == null) ?
+                "null" : "object of type " + mxbean.getClass().getName();
+            throw new OpenDataException(
+                    "Could not convert " + s + " to an ObjectName: " + wrong);
+            // Message will be strange if mxbean is null but it is not
+            // supposed to be.
+        }
+
+        synchronized void addReference(ObjectName name, Object mxbean)
+        throws InstanceAlreadyExistsException {
+            ObjectName existing = mxbeanToObjectName.get(mxbean);
+            if (existing != null) {
+                String multiname = AccessController.doPrivileged(
+                        new GetPropertyAction("jmx.mxbean.multiname"));
+                if (!"true".equalsIgnoreCase(multiname)) {
+                    throw new InstanceAlreadyExistsException(
+                            "MXBean already registered with name " + existing);
+                }
+            }
+            mxbeanToObjectName.put(mxbean, name);
+        }
+
+        synchronized boolean removeReference(ObjectName name, Object mxbean) {
+            if (name.equals(mxbeanToObjectName.get(mxbean))) {
+                mxbeanToObjectName.remove(mxbean);
+                return true;
+            } else
+                return false;