diff options
author | Jung-uk Kim <jkim@FreeBSD.org> | 2013-03-06 00:50:28 +0000 |
---|---|---|
committer | Jung-uk Kim <jkim@FreeBSD.org> | 2013-03-06 00:50:28 +0000 |
commit | 0f7f30e0b6084a2cbd4b8718e0629ee43e430afb (patch) | |
tree | d7cc0e27c2e50cd501beef2b9faad0637d0b5537 /java/openjdk6 | |
parent | 87617c6f9ad856e35e81fa55668b5a4369d303c0 (diff) | |
download | ports-0f7f30e0b6084a2cbd4b8718e0629ee43e430afb.tar.gz ports-0f7f30e0b6084a2cbd4b8718e0629ee43e430afb.zip |
Notes
Diffstat (limited to 'java/openjdk6')
35 files changed, 22744 insertions, 4 deletions
diff --git a/java/openjdk6/Makefile b/java/openjdk6/Makefile index cbb7444f8b41..71ad10ae9922 100644 --- a/java/openjdk6/Makefile +++ b/java/openjdk6/Makefile @@ -3,7 +3,7 @@ PORTNAME= openjdk6 PORTVERSION= b27 -PORTREVISION?= 1 +PORTREVISION?= 2 CATEGORIES= java devel MASTER_SITES= http://download.java.net/openjdk/jdk6/promoted/${PORTVERSION}/ \ http://download.java.net/jaxp/openjdk/jdk6/:jaxp \ @@ -39,6 +39,40 @@ RUN_DEPENDS= javavm:${PORTSDIR}/java/javavmwrapper \ OPENJDK_BUILDDATE= 26_oct_2012 +EXTRA_PATCHES= ${FILESDIR}/icedtea/security/20120830/7182135-impossible_to_use_some_editors_directly.patch \ + ${FILESDIR}/icedtea/security/20130201/7201068.patch \ + ${FILESDIR}/icedtea/security/20130201/6563318.patch \ + ${FILESDIR}/icedtea/security/20130201/6664509.patch \ + ${FILESDIR}/icedtea/security/20130201/6776941.patch \ + ${FILESDIR}/icedtea/security/20130201/7141694.patch \ + ${FILESDIR}/icedtea/security/20130201/7173145.patch \ + ${FILESDIR}/icedtea/security/20130201/7186945.patch \ + ${FILESDIR}/icedtea/security/20130201/7186948.patch \ + ${FILESDIR}/icedtea/security/20130201/7186952.patch \ + ${FILESDIR}/icedtea/security/20130201/7186954.patch \ + ${FILESDIR}/icedtea/security/20130201/7192392.patch \ + ${FILESDIR}/icedtea/security/20130201/7192393.patch \ + ${FILESDIR}/icedtea/security/20130201/7192977.patch \ + ${FILESDIR}/icedtea/security/20130201/7197546.patch \ + ${FILESDIR}/icedtea/security/20130201/7200491.patch \ + ${FILESDIR}/icedtea/security/20130201/7200500.patch \ + ${FILESDIR}/icedtea/security/20130201/7201064.patch \ + ${FILESDIR}/icedtea/security/20130201/7201066.patch \ + ${FILESDIR}/icedtea/security/20130201/7201070.patch \ + ${FILESDIR}/icedtea/security/20130201/7201071.patch \ + ${FILESDIR}/icedtea/security/20130201/8000210.patch \ + ${FILESDIR}/icedtea/security/20130201/8000537.patch \ + ${FILESDIR}/icedtea/security/20130201/8000540.patch \ + ${FILESDIR}/icedtea/security/20130201/8000631.patch \ + ${FILESDIR}/icedtea/security/20130201/8001242.patch \ + ${FILESDIR}/icedtea/security/20130201/8001307.patch \ + ${FILESDIR}/icedtea/security/20130201/8001972.patch \ + ${FILESDIR}/icedtea/security/20130201/8002325.patch \ + ${FILESDIR}/icedtea/security/20130201/8001235.patch \ + ${FILESDIR}/icedtea/security/20130219/8006446.patch \ + ${FILESDIR}/icedtea/security/20130219/8006777.patch \ + ${FILESDIR}/icedtea/security/20130219/8007688.patch + OPTIONS_DEFINE= ICEDTEA IPV6 POLICY SOUND TZUPDATE OPTIONS_DEFAULT=ICEDTEA IPV6 TZUPDATE ICEDTEA_DESC= Apply additional patches from IcedTea diff --git a/java/openjdk6/files/icedtea/security/20120830/7182135-impossible_to_use_some_editors_directly.patch b/java/openjdk6/files/icedtea/security/20120830/7182135-impossible_to_use_some_editors_directly.patch new file mode 100644 index 000000000000..0653b33c02a7 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20120830/7182135-impossible_to_use_some_editors_directly.patch @@ -0,0 +1,519 @@ +diff --git a/make/sun/Makefile b/make/sun/Makefile +--- jdk/make/sun/Makefile ++++ jdk/make/sun/Makefile +@@ -64,7 +64,7 @@ + SUBDIRS = jar security javazic misc net audio $(RENDER_SUBDIR) image \ + awt splashscreen $(XAWT_SUBDIR) $(MOTIF_SUBDIRS) \ + $(HEADLESS_SUBDIR) $(DGA_SUBDIR) \ +- font jpeg cmm applet rmi $(JDBC_SUBDIR) \ ++ font jpeg cmm applet rmi beans $(JDBC_SUBDIR) \ + jawt text nio launcher management $(ORG_SUBDIR) \ + native2ascii serialver tools jconsole + +diff --git a/make/sun/beans/Makefile b/make/sun/beans/Makefile +new file mode 100644 +--- /dev/null ++++ jdk/make/sun/beans/Makefile +@@ -0,0 +1,43 @@ ++# ++# Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. ++# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++# ++# This code is free software; you can redistribute it and/or modify it ++# under the terms of the GNU General Public License version 2 only, as ++# published by the Free Software Foundation. Oracle designates this ++# particular file as subject to the "Classpath" exception as provided ++# by Oracle in the LICENSE file that accompanied this code. ++# ++# This code is distributed in the hope that it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++# version 2 for more details (a copy is included in the LICENSE file that ++# accompanied this code). ++# ++# You should have received a copy of the GNU General Public License version ++# 2 along with this work; if not, write to the Free Software Foundation, ++# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++# ++# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++# or visit www.oracle.com if you need additional information or have any ++# questions. ++# ++ ++# ++# Makefile for building sun.beans.* ++# ++ ++BUILDDIR = ../.. ++PACKAGE = sun.beans ++PRODUCT = sun ++include $(BUILDDIR)/common/Defs.gmk ++ ++# ++# Files ++# ++AUTO_FILES_JAVA_DIRS = sun/beans ++ ++# ++# Rules ++# ++include $(BUILDDIR)/common/Classes.gmk +diff --git a/src/share/classes/com/sun/beans/editors/EnumEditor.java b/src/share/classes/com/sun/beans/editors/EnumEditor.java +--- jdk/src/share/classes/com/sun/beans/editors/EnumEditor.java ++++ jdk/src/share/classes/com/sun/beans/editors/EnumEditor.java +@@ -42,7 +42,7 @@ + * + * @author Sergey A. Malenkov + */ +-public final class EnumEditor implements PropertyEditor { ++public class EnumEditor implements PropertyEditor { + private final List<PropertyChangeListener> listeners = new ArrayList<PropertyChangeListener>(); + + private final Class type; +diff --git a/src/share/classes/sun/beans/editors/BooleanEditor.java b/src/share/classes/sun/beans/editors/BooleanEditor.java +new file mode 100644 +--- /dev/null ++++ jdk/src/share/classes/sun/beans/editors/BooleanEditor.java +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package sun.beans.editors; ++ ++/** ++ * FOR BACKWARD COMPATIBILITY ONLY - DO NOT USE. ++ */ ++public class BooleanEditor extends com.sun.beans.editors.BooleanEditor { ++} +diff --git a/src/share/classes/sun/beans/editors/ByteEditor.java b/src/share/classes/sun/beans/editors/ByteEditor.java +new file mode 100644 +--- /dev/null ++++ jdk/src/share/classes/sun/beans/editors/ByteEditor.java +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package sun.beans.editors; ++ ++/** ++ * FOR BACKWARD COMPATIBILITY ONLY - DO NOT USE. ++ */ ++public class ByteEditor extends com.sun.beans.editors.ByteEditor { ++} +diff --git a/src/share/classes/sun/beans/editors/ColorEditor.java b/src/share/classes/sun/beans/editors/ColorEditor.java +new file mode 100644 +--- /dev/null ++++ jdk/src/share/classes/sun/beans/editors/ColorEditor.java +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package sun.beans.editors; ++ ++/** ++ * FOR BACKWARD COMPATIBILITY ONLY - DO NOT USE. ++ */ ++public class ColorEditor extends com.sun.beans.editors.ColorEditor { ++} +diff --git a/src/share/classes/sun/beans/editors/DoubleEditor.java b/src/share/classes/sun/beans/editors/DoubleEditor.java +new file mode 100644 +--- /dev/null ++++ jdk/src/share/classes/sun/beans/editors/DoubleEditor.java +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package sun.beans.editors; ++ ++/** ++ * FOR BACKWARD COMPATIBILITY ONLY - DO NOT USE. ++ */ ++public class DoubleEditor extends com.sun.beans.editors.DoubleEditor { ++} +diff --git a/src/share/classes/sun/beans/editors/EnumEditor.java b/src/share/classes/sun/beans/editors/EnumEditor.java +new file mode 100644 +--- /dev/null ++++ jdk/src/share/classes/sun/beans/editors/EnumEditor.java +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package sun.beans.editors; ++ ++/** ++ * FOR BACKWARD COMPATIBILITY ONLY - DO NOT USE. ++ */ ++public class EnumEditor extends com.sun.beans.editors.EnumEditor { ++ public EnumEditor(Class type) { ++ super(type); ++ } ++} +diff --git a/src/share/classes/sun/beans/editors/FloatEditor.java b/src/share/classes/sun/beans/editors/FloatEditor.java +new file mode 100644 +--- /dev/null ++++ jdk/src/share/classes/sun/beans/editors/FloatEditor.java +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package sun.beans.editors; ++ ++/** ++ * FOR BACKWARD COMPATIBILITY ONLY - DO NOT USE. ++ */ ++public class FloatEditor extends com.sun.beans.editors.FloatEditor { ++} +diff --git a/src/share/classes/sun/beans/editors/FontEditor.java b/src/share/classes/sun/beans/editors/FontEditor.java +new file mode 100644 +--- /dev/null ++++ jdk/src/share/classes/sun/beans/editors/FontEditor.java +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package sun.beans.editors; ++ ++/** ++ * FOR BACKWARD COMPATIBILITY ONLY - DO NOT USE. ++ */ ++public class FontEditor extends com.sun.beans.editors.FontEditor { ++} +diff --git a/src/share/classes/sun/beans/editors/IntegerEditor.java b/src/share/classes/sun/beans/editors/IntegerEditor.java +new file mode 100644 +--- /dev/null ++++ jdk/src/share/classes/sun/beans/editors/IntegerEditor.java +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package sun.beans.editors; ++ ++/** ++ * FOR BACKWARD COMPATIBILITY ONLY - DO NOT USE. ++ */ ++public class IntegerEditor extends com.sun.beans.editors.IntegerEditor { ++} +diff --git a/src/share/classes/sun/beans/editors/LongEditor.java b/src/share/classes/sun/beans/editors/LongEditor.java +new file mode 100644 +--- /dev/null ++++ jdk/src/share/classes/sun/beans/editors/LongEditor.java +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package sun.beans.editors; ++ ++/** ++ * FOR BACKWARD COMPATIBILITY ONLY - DO NOT USE. ++ */ ++public class LongEditor extends com.sun.beans.editors.LongEditor { ++} +diff --git a/src/share/classes/sun/beans/editors/NumberEditor.java b/src/share/classes/sun/beans/editors/NumberEditor.java +new file mode 100644 +--- /dev/null ++++ jdk/src/share/classes/sun/beans/editors/NumberEditor.java +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package sun.beans.editors; ++ ++/** ++ * FOR BACKWARD COMPATIBILITY ONLY - DO NOT USE. ++ */ ++abstract public class NumberEditor extends com.sun.beans.editors.NumberEditor { ++} +diff --git a/src/share/classes/sun/beans/editors/ShortEditor.java b/src/share/classes/sun/beans/editors/ShortEditor.java +new file mode 100644 +--- /dev/null ++++ jdk/src/share/classes/sun/beans/editors/ShortEditor.java +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package sun.beans.editors; ++ ++/** ++ * FOR BACKWARD COMPATIBILITY ONLY - DO NOT USE. ++ */ ++public class ShortEditor extends com.sun.beans.editors.ShortEditor { ++} +diff --git a/src/share/classes/sun/beans/editors/StringEditor.java b/src/share/classes/sun/beans/editors/StringEditor.java +new file mode 100644 +--- /dev/null ++++ jdk/src/share/classes/sun/beans/editors/StringEditor.java +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package sun.beans.editors; ++ ++/** ++ * FOR BACKWARD COMPATIBILITY ONLY - DO NOT USE. ++ */ ++public class StringEditor extends com.sun.beans.editors.StringEditor { ++} diff --git a/java/openjdk6/files/icedtea/security/20130201/6563318.patch b/java/openjdk6/files/icedtea/security/20130201/6563318.patch new file mode 100644 index 000000000000..8935ed6666c8 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/6563318.patch @@ -0,0 +1,36 @@ +# HG changeset patch +# User coffeys +# Date 1355323250 0 +# Node ID 0da6d4cbcc77b3326756b52e6086b1262d52c214 +# Parent 042882b32f75d0e736c19f93688d37fb98d7d26d +6563318: RMI data sanitization +Reviewed-by: dmocek + +diff --git a/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java b/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java +--- jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java ++++ jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -150,7 +150,7 @@ public final class CGIHandler { + returnServerError(e.getMessage()); + } + else +- returnClientError("invalid command: " + command); ++ returnClientError("Invalid command."); + } catch (Exception e) { + returnServerError("internal error: " + e.getMessage()); + } +@@ -217,7 +217,7 @@ final class CGIForwardCommand implements + try { + port = Integer.parseInt(param); + } catch (NumberFormatException e) { +- throw new CGIClientException("invalid port number: " + param); ++ throw new CGIClientException("invalid port number."); + } + if (port <= 0 || port > 0xFFFF) + throw new CGIClientException("invalid port: " + port); diff --git a/java/openjdk6/files/icedtea/security/20130201/6664509.patch b/java/openjdk6/files/icedtea/security/20130201/6664509.patch new file mode 100644 index 000000000000..8d8f3191d014 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/6664509.patch @@ -0,0 +1,1322 @@ +# HG changeset patch +# User coffeys +# Date 1355432912 0 +# Node ID eed3ef0116a18e006c4e062b3c8d6d5a5e503a43 +# Parent bedb05bba7fc681e34f9c3ce03dc2daa4ec2ce28 +6664509: Add logging context +6664528: Find log level matching its name or value given at construction time +Reviewed-by: mchung + +diff --git a/src/share/classes/java/util/logging/Level.java b/src/share/classes/java/util/logging/Level.java +--- jdk/src/share/classes/java/util/logging/Level.java ++++ jdk/src/share/classes/java/util/logging/Level.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -24,6 +24,10 @@ + */ + + package java.util.logging; ++import java.util.ArrayList; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; + import java.util.ResourceBundle; + + /** +@@ -59,7 +63,6 @@ import java.util.ResourceBundle; + */ + + public class Level implements java.io.Serializable { +- private static java.util.ArrayList<Level> known = new java.util.ArrayList<Level>(); + private static String defaultBundle = "sun.util.logging.resources.logging"; + + /** +@@ -76,6 +79,9 @@ public class Level implements java.io.Se + * @serial The resource bundle name to be used in localizing the level name. + */ + private final String resourceBundleName; ++ ++ // localized level name ++ private String localizedLevelName; + + /** + * OFF is a special level that can be used to turn off logging. +@@ -202,9 +208,8 @@ public class Level implements java.io.Se + this.name = name; + this.value = value; + this.resourceBundleName = resourceBundleName; +- synchronized (Level.class) { +- known.add(this); +- } ++ this.localizedLevelName = resourceBundleName == null ? name : null; ++ KnownLevel.add(this); + } + + /** +@@ -236,12 +241,76 @@ public class Level implements java.io.Se + * @return localized name + */ + public String getLocalizedName() { ++ return getLocalizedLevelName(); ++ } ++ ++ // package-private getLevelName() is used by the implementation ++ // instead of getName() to avoid calling the subclass's version ++ final String getLevelName() { ++ return this.name; ++ } ++ ++ final synchronized String getLocalizedLevelName() { ++ if (localizedLevelName != null) { ++ return localizedLevelName; ++ } ++ + try { + ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName); +- return rb.getString(name); ++ localizedLevelName = rb.getString(name); + } catch (Exception ex) { +- return name; ++ localizedLevelName = name; + } ++ return localizedLevelName; ++ } ++ ++ // Returns a mirrored Level object that matches the given name as ++ // specified in the Level.parse method. Returns null if not found. ++ // ++ // It returns the same Level object as the one returned by Level.parse ++ // method if the given name is a non-localized name or integer. ++ // ++ // If the name is a localized name, findLevel and parse method may ++ // return a different level value if there is a custom Level subclass ++ // that overrides Level.getLocalizedName() to return a different string ++ // than what's returned by the default implementation. ++ // ++ static Level findLevel(String name) { ++ if (name == null) { ++ throw new NullPointerException(); ++ } ++ ++ KnownLevel level; ++ ++ // Look for a known Level with the given non-localized name. ++ level = KnownLevel.findByName(name); ++ if (level != null) { ++ return level.mirroredLevel; ++ } ++ ++ // Now, check if the given name is an integer. If so, ++ // first look for a Level with the given value and then ++ // if necessary create one. ++ try { ++ int x = Integer.parseInt(name); ++ level = KnownLevel.findByValue(x); ++ if (level == null) { ++ // add new Level ++ Level levelObject = new Level(name, x); ++ level = KnownLevel.findByValue(x); ++ } ++ return level.mirroredLevel; ++ } catch (NumberFormatException ex) { ++ // Not an integer. ++ // Drop through. ++ } ++ ++ level = KnownLevel.findByLocalizedLevelName(name); ++ if (level != null) { ++ return level.mirroredLevel; ++ } ++ ++ return null; + } + + /** +@@ -266,21 +335,15 @@ public class Level implements java.io.Se + // Serialization magic to prevent "doppelgangers". + // This is a performance optimization. + private Object readResolve() { +- synchronized (Level.class) { +- for (int i = 0; i < known.size(); i++) { +- Level other = known.get(i); +- if (this.name.equals(other.name) && this.value == other.value +- && (this.resourceBundleName == other.resourceBundleName || +- (this.resourceBundleName != null && +- this.resourceBundleName.equals(other.resourceBundleName)))) { +- return other; +- } +- } +- // Woops. Whoever sent us this object knows +- // about a new log level. Add it to our list. +- known.add(this); +- return this; ++ KnownLevel o = KnownLevel.matches(this); ++ if (o != null) { ++ return o.levelObject; + } ++ ++ // Woops. Whoever sent us this object knows ++ // about a new log level. Add it to our list. ++ Level level = new Level(this.name, this.value, this.resourceBundleName); ++ return level; + } + + /** +@@ -294,6 +357,7 @@ public class Level implements java.io.Se + * <li> "SEVERE" + * <li> "1000" + * </ul> ++ * + * @param name string to be parsed + * @throws NullPointerException if the name is null + * @throws IllegalArgumentException if the value is not valid. +@@ -313,12 +377,12 @@ public class Level implements java.io.Se + // Check that name is not null. + name.length(); + ++ KnownLevel level; ++ + // Look for a known Level with the given non-localized name. +- for (int i = 0; i < known.size(); i++) { +- Level l = known.get(i); +- if (name.equals(l.name)) { +- return l; +- } ++ level = KnownLevel.findByName(name); ++ if (level != null) { ++ return level.levelObject; + } + + // Now, check if the given name is an integer. If so, +@@ -326,27 +390,23 @@ public class Level implements java.io.Se + // if necessary create one. + try { + int x = Integer.parseInt(name); +- for (int i = 0; i < known.size(); i++) { +- Level l = known.get(i); +- if (l.value == x) { +- return l; +- } ++ level = KnownLevel.findByValue(x); ++ if (level == null) { ++ // add new Level ++ Level levelObject = new Level(name, x); ++ level = KnownLevel.findByValue(x); + } +- // Create a new Level. +- return new Level(name, x); ++ return level.levelObject; + } catch (NumberFormatException ex) { + // Not an integer. + // Drop through. + } +- +- // Finally, look for a known level with the given localized name, ++ // Finally, look for a known level with the given localized name, + // in the current default locale. + // This is relatively expensive, but not excessively so. +- for (int i = 0; i < known.size(); i++) { +- Level l = known.get(i); +- if (name.equals(l.getLocalizedName())) { +- return l; +- } ++ level = KnownLevel.findByLocalizedName(name); ++ if (level != null) { ++ return level.levelObject; + } + + // OK, we've tried everything and failed +@@ -373,4 +433,125 @@ public class Level implements java.io.Se + public int hashCode() { + return this.value; + } ++ ++ // KnownLevel class maintains the global list of all known levels. ++ // The API allows multiple custom Level instances of the same name/value ++ // be created. This class provides convenient methods to find a level ++ // by a given name, by a given value, or by a given localized name. ++ // ++ // KnownLevel wraps the following Level objects: ++ // 1. levelObject: standard Level object or custom Level object ++ // 2. mirroredLevel: Level object representing the level specified in the ++ // logging configuration. ++ // ++ // Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods ++ // are non-final but the name and resource bundle name are parameters to ++ // the Level constructor. Use the mirroredLevel object instead of the ++ // levelObject to prevent the logging framework to execute foreign code ++ // implemented by untrusted Level subclass. ++ // ++ // Implementation Notes: ++ // If Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods ++ // were final, the following KnownLevel implementation can be removed. ++ // Future API change should take this into consideration. ++ static final class KnownLevel { ++ private static Map<String, List<KnownLevel>> nameToLevels = ++ new HashMap<String, List<KnownLevel>>(); ++ private static Map<Integer, List<KnownLevel>> intToLevels = ++ new HashMap<Integer, List<KnownLevel>>(); ++ final Level levelObject; // instance of Level class or Level subclass ++ final Level mirroredLevel; // instance of Level class ++ KnownLevel(Level l) { ++ this.levelObject = l; ++ if (l.getClass() == Level.class) { ++ this.mirroredLevel = l; ++ } else { ++ this.mirroredLevel = new Level(l.name, l.value, l.resourceBundleName); ++ } ++ } ++ ++ static synchronized void add(Level l) { ++ // the mirroredLevel object is always added to the list ++ // before the custom Level instance ++ KnownLevel o = new KnownLevel(l); ++ List<KnownLevel> list = nameToLevels.get(l.name); ++ if (list == null) { ++ list = new ArrayList<KnownLevel>(); ++ nameToLevels.put(l.name, list); ++ } ++ list.add(o); ++ ++ list = intToLevels.get(l.value); ++ if (list == null) { ++ list = new ArrayList<KnownLevel>(); ++ intToLevels.put(l.value, list); ++ } ++ list.add(o); ++ } ++ ++ // Returns a KnownLevel with the given non-localized name. ++ static synchronized KnownLevel findByName(String name) { ++ List<KnownLevel> list = nameToLevels.get(name); ++ if (list != null) { ++ return list.get(0); ++ } ++ return null; ++ } ++ ++ // Returns a KnownLevel with the given value. ++ static synchronized KnownLevel findByValue(int value) { ++ List<KnownLevel> list = intToLevels.get(value); ++ if (list != null) { ++ return list.get(0); ++ } ++ return null; ++ } ++ ++ // Returns a KnownLevel with the given localized name matching ++ // by calling the Level.getLocalizedLevelName() method (i.e. found ++ // from the resourceBundle associated with the Level object). ++ // This method does not call Level.getLocalizedName() that may ++ // be overridden in a subclass implementation ++ static synchronized KnownLevel findByLocalizedLevelName(String name) { ++ for (List<KnownLevel> levels : nameToLevels.values()) { ++ for (KnownLevel l : levels) { ++ String lname = l.levelObject.getLocalizedLevelName(); ++ if (name.equals(lname)) { ++ return l; ++ } ++ } ++ } ++ return null; ++ } ++ ++ // Returns a KnownLevel with the given localized name matching ++ // by calling the Level.getLocalizedName() method ++ static synchronized KnownLevel findByLocalizedName(String name) { ++ for (List<KnownLevel> levels : nameToLevels.values()) { ++ for (KnownLevel l : levels) { ++ String lname = l.levelObject.getLocalizedName(); ++ if (name.equals(lname)) { ++ return l; ++ } ++ } ++ } ++ return null; ++ } ++ ++ static synchronized KnownLevel matches(Level l) { ++ List<KnownLevel> list = nameToLevels.get(l.name); ++ if (list != null) { ++ for (KnownLevel level : list) { ++ Level other = level.mirroredLevel; ++ if (l.value == other.value && ++ (l.resourceBundleName == other.resourceBundleName || ++ (l.resourceBundleName != null && ++ l.resourceBundleName.equals(other.resourceBundleName)))) { ++ return level; ++ } ++ } ++ } ++ return null; ++ } ++ } + } +diff --git a/src/share/classes/java/util/logging/LogManager.java b/src/share/classes/java/util/logging/LogManager.java +--- jdk/src/share/classes/java/util/logging/LogManager.java ++++ jdk/src/share/classes/java/util/logging/LogManager.java +@@ -34,6 +34,8 @@ import java.beans.PropertyChangeListener + import java.beans.PropertyChangeListener; + import java.beans.PropertyChangeSupport; + import java.net.URL; ++import sun.misc.JavaAWTAccess; ++import sun.misc.SharedSecrets; + import sun.security.action.GetPropertyAction; + + /** +@@ -155,11 +157,9 @@ public class LogManager { + = new PropertyChangeSupport(LogManager.class); + private final static Level defaultLevel = Level.INFO; + +- // Table of named Loggers that maps names to Loggers. +- private Hashtable<String,LoggerWeakRef> namedLoggers = +- new Hashtable<String,LoggerWeakRef>(); +- // Tree of named Loggers +- private LogNode root = new LogNode(null); ++ // LoggerContext for system loggers and user loggers ++ private final LoggerContext systemContext = new SystemLoggerContext(); ++ private final LoggerContext userContext = new UserLoggerContext(); + private Logger rootLogger; + + // Have we done the primordial reading of the configuration file? +@@ -197,12 +197,13 @@ public class LogManager { + + // Create and retain Logger for the root of the namespace. + manager.rootLogger = manager.new RootLogger(); +- manager.addLogger(manager.rootLogger); ++ manager.systemContext.addLogger(manager.rootLogger); ++ manager.userContext.addLogger(manager.rootLogger); + + // Adding the global Logger. Doing so in the Logger.<clinit> + // would deadlock with the LogManager.<clinit>. + Logger.global.setLogManager(manager); +- manager.addLogger(Logger.global); ++ manager.systemContext.addLogger(Logger.global); + + // We don't call readConfiguration() here, as we may be running + // very early in the JVM startup sequence. Instead readConfiguration +@@ -273,8 +274,8 @@ public class LogManager { + } + readPrimordialConfiguration = true; + try { +- AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { +- public Object run() throws Exception { ++ AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { ++ public Void run() throws Exception { + readConfiguration(); + return null; + } +@@ -326,6 +327,296 @@ public class LogManager { + changes.removePropertyChangeListener(l); + } + ++ // Returns the LoggerContext for the user code (i.e. application or AppContext). ++ // Loggers are isolated from each AppContext. ++ LoggerContext getUserContext() { ++ LoggerContext context = null; ++ ++ SecurityManager sm = System.getSecurityManager(); ++ JavaAWTAccess javaAwtAccess = SharedSecrets.getJavaAWTAccess(); ++ if (sm != null && javaAwtAccess != null) { ++ synchronized (javaAwtAccess) { ++ // AppContext.getAppContext() returns the system AppContext if called ++ // from a system thread but Logger.getLogger might be called from ++ // an applet code. Instead, find the AppContext of the applet code ++ // from the execution stack. ++ Object ecx = javaAwtAccess.getExecutionContext(); ++ if (ecx == null) { ++ // fall back to AppContext.getAppContext() ++ ecx = javaAwtAccess.getContext(); ++ } ++ context = (LoggerContext) javaAwtAccess.get(ecx, LoggerContext.class); ++ if (context == null) { ++ if (javaAwtAccess.isMainAppContext()) { ++ context = userContext; ++ } else { ++ context = new UserLoggerContext(); ++ context.addLogger(manager.rootLogger); ++ } ++ javaAwtAccess.put(ecx, LoggerContext.class, context); ++ } ++ } ++ } else { ++ context = userContext; ++ } ++ return context; ++ } ++ ++ LoggerContext getSystemContext() { ++ return systemContext; ++ } ++ ++ private List<LoggerContext> contexts() { ++ List<LoggerContext> cxs = new ArrayList<LoggerContext>(); ++ cxs.add(systemContext); ++ cxs.add(getUserContext()); ++ return cxs; ++ } ++ ++ static class LoggerContext { ++ // Table of named Loggers that maps names to Loggers. ++ ++ private final Hashtable<String, LoggerWeakRef> namedLoggers = ++ new Hashtable<String, LoggerWeakRef>(); ++ // Tree of named Loggers ++ private final LogNode root; ++ ++ private LoggerContext() { ++ this.root = new LogNode(null, this); ++ } ++ ++ synchronized Logger findLogger(String name) { ++ LoggerWeakRef ref = namedLoggers.get(name); ++ if (ref == null) { ++ return null; ++ } ++ Logger logger = ref.get(); ++ if (logger == null) { ++ // Hashtable holds stale weak reference ++ // to a logger which has been GC-ed. ++ removeLogger(name); ++ } ++ return logger; ++ } ++ ++ synchronized boolean addLogger(Logger logger) { ++ final String name = logger.getName(); ++ if (name == null) { ++ throw new NullPointerException(); ++ } ++ ++ // cleanup some Loggers that have been GC'ed ++ manager.drainLoggerRefQueueBounded(); ++ ++ LoggerWeakRef ref = namedLoggers.get(name); ++ if (ref != null) { ++ if (ref.get() == null) { ++ // It's possible that the Logger was GC'ed after the ++ // drainLoggerRefQueueBounded() call above so allow ++ // a new one to be registered. ++ removeLogger(name); ++ } else { ++ // We already have a registered logger with the given name. ++ return false; ++ } ++ } ++ ++ // We're adding a new logger. ++ // Note that we are creating a weak reference here. ++ ref = manager.new LoggerWeakRef(logger); ++ namedLoggers.put(name, ref); ++ ++ // Apply any initial level defined for the new logger. ++ Level level = manager.getLevelProperty(name + ".level", null); ++ if (level != null) { ++ doSetLevel(logger, level); ++ } ++ ++ // Do we have a per logger handler too? ++ // Note: this will add a 200ms penalty ++ manager.loadLoggerHandlers(logger, name, name + ".handlers"); ++ processParentHandlers(logger, name); ++ ++ // Find the new node and its parent. ++ LogNode node = getNode(name); ++ node.loggerRef = ref; ++ Logger parent = null; ++ LogNode nodep = node.parent; ++ while (nodep != null) { ++ LoggerWeakRef nodeRef = nodep.loggerRef; ++ if (nodeRef != null) { ++ parent = nodeRef.get(); ++ if (parent != null) { ++ break; ++ } ++ } ++ nodep = nodep.parent; ++ } ++ ++ if (parent != null) { ++ doSetParent(logger, parent); ++ } ++ // Walk over the children and tell them we are their new parent. ++ node.walkAndSetParent(logger); ++ // new LogNode is ready so tell the LoggerWeakRef about it ++ ref.setNode(node); ++ return true; ++ } ++ ++ void removeLogger(String name) { ++ namedLoggers.remove(name); ++ } ++ ++ synchronized Enumeration<String> getLoggerNames() { ++ return namedLoggers.keys(); ++ } ++ ++ Logger demandLogger(String name) { ++ return demandLogger(name, null); ++ } ++ ++ // Find or create a specified logger instance. If a logger has ++ // already been created with the given name it is returned. ++ // Otherwise a new logger instance is created and registered ++ // in the LogManager global namespace. ++ // This method will always return a non-null Logger object. ++ // Synchronization is not required here. All synchronization for ++ // adding a new Logger object is handled by addLogger(). ++ Logger demandLogger(String name, String resourceBundleName) { ++ Logger result = findLogger(name); ++ if (result == null) { ++ // only allocate the new logger once ++ Logger newLogger = new Logger(name, resourceBundleName); ++ do { ++ if (addLogger(newLogger)) { ++ // We successfully added the new Logger that we ++ // created above so return it without refetching. ++ return newLogger; ++ } ++ ++ // We didn't add the new Logger that we created above ++ // because another thread added a Logger with the same ++ // name after our null check above and before our call ++ // to addLogger(). We have to refetch the Logger because ++ // addLogger() returns a boolean instead of the Logger ++ // reference itself. However, if the thread that created ++ // the other Logger is not holding a strong reference to ++ // the other Logger, then it is possible for the other ++ // Logger to be GC'ed after we saw it in addLogger() and ++ // before we can refetch it. If it has been GC'ed then ++ // we'll just loop around and try again. ++ result = findLogger(name); ++ } while (result == null); ++ } ++ return result; ++ } ++ ++ // If logger.getUseParentHandlers() returns 'true' and any of the logger's ++ // parents have levels or handlers defined, make sure they are instantiated. ++ private void processParentHandlers(Logger logger, String name) { ++ int ix = 1; ++ for (;;) { ++ int ix2 = name.indexOf(".", ix); ++ if (ix2 < 0) { ++ break; ++ } ++ String pname = name.substring(0, ix2); ++ ++ if (manager.getProperty(pname + ".level") != null ++ || manager.getProperty(pname + ".handlers") != null) { ++ // This pname has a level/handlers definition. ++ // Make sure it exists. ++ demandLogger(pname); ++ } ++ ix = ix2 + 1; ++ } ++ } ++ ++ // Gets a node in our tree of logger nodes. ++ // If necessary, create it. ++ LogNode getNode(String name) { ++ if (name == null || name.equals("")) { ++ return root; ++ } ++ LogNode node = root; ++ while (name.length() > 0) { ++ int ix = name.indexOf("."); ++ String head; ++ if (ix > 0) { ++ head = name.substring(0, ix); ++ name = name.substring(ix + 1); ++ } else { ++ head = name; ++ name = ""; ++ } ++ if (node.children == null) { ++ node.children = new HashMap<String, LogNode>(); ++ } ++ LogNode child = node.children.get(head); ++ if (child == null) { ++ child = new LogNode(node, this); ++ node.children.put(head, child); ++ } ++ node = child; ++ } ++ return node; ++ } ++ } ++ ++ static class SystemLoggerContext extends LoggerContext { ++ // Default resource bundle for all system loggers ++ ++ Logger demandLogger(String name) { ++ // default to use the system logger's resource bundle ++ return super.demandLogger(name, Logger.SYSTEM_LOGGER_RB_NAME); ++ } ++ } ++ ++ static class UserLoggerContext extends LoggerContext { ++ ++ /** ++ * Returns a Logger of the given name if there is one registered ++ * in this context. Otherwise, it will return the one registered ++ * in the system context if there is one. The returned Logger ++ * instance may be initialized with a different resourceBundleName. ++ * If no such logger exists, a new Logger instance will be created ++ * and registered in this context. ++ */ ++ Logger demandLogger(String name, String resourceBundleName) { ++ Logger result = findLogger(name); ++ if (result == null) { ++ // use the system logger if exists; or allocate a new logger. ++ // The system logger is added to the app logger context so that ++ // any child logger created in the app logger context can have ++ // a system logger as its parent if already exist. ++ Logger logger = manager.systemContext.findLogger(name); ++ Logger newLogger = ++ logger != null ? logger : new Logger(name, resourceBundleName); ++ do { ++ if (addLogger(newLogger)) { ++ // We successfully added the new Logger that we ++ // created above so return it without refetching. ++ return newLogger; ++ } ++ ++ // We didn't add the new Logger that we created above ++ // because another thread added a Logger with the same ++ // name after our null check above and before our call ++ // to addLogger(). We have to refetch the Logger because ++ // addLogger() returns a boolean instead of the Logger ++ // reference itself. However, if the thread that created ++ // the other Logger is not holding a strong reference to ++ // the other Logger, then it is possible for the other ++ // Logger to be GC'ed after we saw it in addLogger() and ++ // before we can refetch it. If it has been GC'ed then ++ // we'll just loop around and try again. ++ result = findLogger(name); ++ } while (result == null); ++ } ++ return result; ++ } ++ } ++ + // Package-level method. + // Find or create a specified logger instance. If a logger has + // already been created with the given name it is returned. +@@ -339,27 +630,6 @@ public class LogManager { + result = getLogger(name); + } + return result; +- } +- +- // If logger.getUseParentHandlers() returns 'true' and any of the logger's +- // parents have levels or handlers defined, make sure they are instantiated. +- private void processParentHandlers(Logger logger, String name) { +- int ix = 1; +- for (;;) { +- int ix2 = name.indexOf(".", ix); +- if (ix2 < 0) { +- break; +- } +- String pname = name.substring(0,ix2); +- +- if (getProperty(pname+".level") != null || +- getProperty(pname+".handlers") != null) { +- // This pname has a level/handlers definition. +- // Make sure it exists. +- demandLogger(pname); +- } +- ix = ix2+1; +- } + } + + // Add new per logger handlers. +@@ -383,16 +653,17 @@ public class LogManager { + try { + Class clz = ClassLoader.getSystemClassLoader().loadClass(word); + Handler hdl = (Handler) clz.newInstance(); +- try { +- // Check if there is a property defining the +- // this handler's level. +- String levs = getProperty(word + ".level"); +- if (levs != null) { +- hdl.setLevel(Level.parse(levs)); ++ // Check if there is a property defining the ++ // this handler's level. ++ String levs = getProperty(word + ".level"); ++ if (levs != null) { ++ Level l = Level.findLevel(levs); ++ if (l != null) { ++ hdl.setLevel(l); ++ } else { ++ // Probably a bad level. Drop through. ++ System.err.println("Can't set level for " + word); + } +- } catch (Exception ex) { +- System.err.println("Can't set level for " + word); +- // Probably a bad level. Drop through. + } + // Add this Handler to the logger + logger.addHandler(hdl); +@@ -448,7 +719,7 @@ public class LogManager { + if (node != null) { + // if we have a LogNode, then we were a named Logger + // so clear namedLoggers weak ref to us +- manager.namedLoggers.remove(name); ++ node.context.removeLogger(name); + name = null; // clear our ref to the Logger's name + + node.loggerRef = null; // clear LogNode's weak ref to us +@@ -544,67 +815,11 @@ public class LogManager { + if (name == null) { + throw new NullPointerException(); + } +- +- // cleanup some Loggers that have been GC'ed +- drainLoggerRefQueueBounded(); +- +- LoggerWeakRef ref = namedLoggers.get(name); +- if (ref != null) { +- if (ref.get() == null) { +- // It's possible that the Logger was GC'ed after the +- // drainLoggerRefQueueBounded() call above so allow +- // a new one to be registered. +- namedLoggers.remove(name); +- } else { +- // We already have a registered logger with the given name. +- return false; +- } ++ if (systemContext.findLogger(name) != null) { ++ return false; + } +- +- // We're adding a new logger. +- // Note that we are creating a weak reference here. +- ref = new LoggerWeakRef(logger); +- namedLoggers.put(name, ref); +- +- // Apply any initial level defined for the new logger. +- Level level = getLevelProperty(name+".level", null); +- if (level != null) { +- doSetLevel(logger, level); +- } +- +- // Do we have a per logger handler too? +- // Note: this will add a 200ms penalty +- loadLoggerHandlers(logger, name, name+".handlers"); +- processParentHandlers(logger, name); +- +- // Find the new node and its parent. +- LogNode node = findNode(name); +- node.loggerRef = ref; +- Logger parent = null; +- LogNode nodep = node.parent; +- while (nodep != null) { +- LoggerWeakRef nodeRef = nodep.loggerRef; +- if (nodeRef != null) { +- parent = nodeRef.get(); +- if (parent != null) { +- break; +- } +- } +- nodep = nodep.parent; +- } +- +- if (parent != null) { +- doSetParent(logger, parent); +- } +- // Walk over the children and tell them we are their new parent. +- node.walkAndSetParent(logger); +- +- // new LogNode is ready so tell the LoggerWeakRef about it +- ref.setNode(node); +- +- return true; ++ return getUserContext().addLogger(logger); + } +- + + // Private method to set a level on a logger. + // If necessary, we raise privilege before doing the call. +@@ -644,36 +859,6 @@ public class LogManager { + }}); + } + +- // Find a node in our tree of logger nodes. +- // If necessary, create it. +- private LogNode findNode(String name) { +- if (name == null || name.equals("")) { +- return root; +- } +- LogNode node = root; +- while (name.length() > 0) { +- int ix = name.indexOf("."); +- String head; +- if (ix > 0) { +- head = name.substring(0,ix); +- name = name.substring(ix+1); +- } else { +- head = name; +- name = ""; +- } +- if (node.children == null) { +- node.children = new HashMap<String,LogNode>(); +- } +- LogNode child = node.children.get(head); +- if (child == null) { +- child = new LogNode(node); +- node.children.put(head, child); +- } +- node = child; +- } +- return node; +- } +- + /** + * Method to find a named logger. + * <p> +@@ -689,18 +874,16 @@ public class LogManager { + * @param name name of the logger + * @return matching logger or null if none is found + */ +- public synchronized Logger getLogger(String name) { +- LoggerWeakRef ref = namedLoggers.get(name); +- if (ref == null) { +- return null; +- } +- Logger logger = ref.get(); +- if (logger == null) { +- // Hashtable holds stale weak reference +- // to a logger which has been GC-ed. +- namedLoggers.remove(name); +- } +- return logger; ++ public Logger getLogger(String name) { ++ // return the first logger added ++ // ++ // once a system logger is added in the system context, no one can ++ // adds a logger with the same name in the global context ++ // (see LogManager.addLogger). So if there is a logger in the global ++ // context with the same name as one in the system context, it must be ++ // added before the system logger was created. ++ Logger logger = getUserContext().findLogger(name); ++ return logger != null ? logger : systemContext.findLogger(name); + } + + /** +@@ -719,8 +902,12 @@ public class LogManager { + * <p> + * @return enumeration of logger name strings + */ +- public synchronized Enumeration<String> getLoggerNames() { +- return namedLoggers.keys(); ++ public Enumeration<String> getLoggerNames() { ++ // only return unique names ++ Set<String> names = ++ new HashSet<String>(Collections.list(systemContext.getLoggerNames())); ++ names.addAll(Collections.list(getUserContext().getLoggerNames())); ++ return Collections.enumeration(names); + } + + /** +@@ -805,20 +992,20 @@ public class LogManager { + // the global handlers, if they haven't been initialized yet. + initializedGlobalHandlers = true; + } +- Enumeration enum_ = getLoggerNames(); +- while (enum_.hasMoreElements()) { +- String name = (String)enum_.nextElement(); +- resetLogger(name); ++ for (LoggerContext cx : contexts()) { ++ Enumeration<String> enum_ = cx.getLoggerNames(); ++ while (enum_.hasMoreElements()) { ++ String name = enum_.nextElement(); ++ Logger logger = cx.findLogger(name); ++ if (logger != null) { ++ resetLogger(logger); ++ } ++ } + } + } + +- + // Private method to reset an individual target logger. +- private void resetLogger(String name) { +- Logger logger = getLogger(name); +- if (logger == null) { +- return; +- } ++ private void resetLogger(Logger logger) { + // Close all the Logger's handlers. + Handler[] targets = logger.getHandlers(); + for (int i = 0; i < targets.length; i++) { +@@ -830,6 +1017,7 @@ public class LogManager { + // Problems closing a handler? Keep going... + } + } ++ String name = logger.getName(); + if (name != null && name.equals("")) { + // This is the root logger. + logger.setLevel(defaultLevel); +@@ -977,11 +1165,8 @@ public class LogManager { + if (val == null) { + return defaultValue; + } +- try { +- return Level.parse(val.trim()); +- } catch (Exception ex) { +- return defaultValue; +- } ++ Level l = Level.findLevel(val.trim()); ++ return l != null ? l : defaultValue; + } + + // Package private method to get a filter property. +@@ -1072,9 +1257,11 @@ public class LogManager { + HashMap<String,LogNode> children; + LoggerWeakRef loggerRef; + LogNode parent; ++ final LoggerContext context; + +- LogNode(LogNode parent) { ++ LogNode(LogNode parent, LoggerContext context) { + this.parent = parent; ++ this.context = context; + } + + // Recursive method to walk the tree below a node and set +@@ -1133,7 +1320,7 @@ public class LogManager { + // Private method to be called when the configuration has + // changed to apply any level settings to any pre-existing loggers. + synchronized private void setLevelsOnExistingLoggers() { +- Enumeration enum_ = props.propertyNames(); ++ Enumeration<?> enum_ = props.propertyNames(); + while (enum_.hasMoreElements()) { + String key = (String)enum_.nextElement(); + if (!key.endsWith(".level")) { +@@ -1147,11 +1334,13 @@ public class LogManager { + System.err.println("Bad level value for property: " + key); + continue; + } +- Logger l = getLogger(name); +- if (l == null) { +- continue; ++ for (LoggerContext cx : contexts()) { ++ Logger l = cx.findLogger(name); ++ if (l == null) { ++ continue; ++ } ++ l.setLevel(level); + } +- l.setLevel(level); + } + } + +diff --git a/src/share/classes/java/util/logging/Logger.java b/src/share/classes/java/util/logging/Logger.java +--- jdk/src/share/classes/java/util/logging/Logger.java ++++ jdk/src/share/classes/java/util/logging/Logger.java +@@ -29,6 +29,7 @@ import java.util.*; + import java.util.*; + import java.security.*; + import java.lang.ref.WeakReference; ++import java.util.logging.LogManager.LoggerContext; + + /** + * A Logger object is used to log messages for a specific +@@ -276,6 +277,26 @@ public class Logger { + } + } + ++ // Until all JDK code converted to call sun.util.logging.PlatformLogger ++ // (see 7054233), we need to determine if Logger.getLogger is to add ++ // a system logger or user logger. ++ // ++ // As an interim solution, if the immediate caller whose caller loader is ++ // null, we assume it's a system logger and add it to the system context. ++ private static LoggerContext getLoggerContext() { ++ LogManager manager = LogManager.getLogManager(); ++ SecurityManager sm = System.getSecurityManager(); ++ if (sm != null) { ++ // 0: Reflection 1: Logger.getLoggerContext 2: Logger.getLogger 3: caller ++ final int SKIP_FRAMES = 3; ++ Class<?> caller = sun.reflect.Reflection.getCallerClass(SKIP_FRAMES); ++ if (caller.getClassLoader() == null) { ++ return manager.getSystemContext(); ++ } ++ } ++ return manager.getUserContext(); ++ } ++ + /** + * Find or create a logger for a named subsystem. If a logger has + * already been created with the given name it is returned. Otherwise +@@ -304,8 +325,8 @@ public class Logger { + * @throws NullPointerException if the name is null. + */ + public static synchronized Logger getLogger(String name) { +- LogManager manager = LogManager.getLogManager(); +- return manager.demandLogger(name); ++ LoggerContext context = getLoggerContext(); ++ return context.demandLogger(name); + } + + /** +@@ -348,8 +369,8 @@ public class Logger { + * @throws NullPointerException if the name is null. + */ + public static synchronized Logger getLogger(String name, String resourceBundleName) { +- LogManager manager = LogManager.getLogManager(); +- Logger result = manager.demandLogger(name); ++ LoggerContext context = getLoggerContext(); ++ Logger result = context.demandLogger(name, resourceBundleName); + if (result.resourceBundleName == null) { + // Note: we may get a MissingResourceException here. + result.setupResourceInfo(resourceBundleName); +@@ -513,7 +534,7 @@ public class Logger { + private void doLog(LogRecord lr) { + lr.setLoggerName(name); + String ebname = getEffectiveResourceBundleName(); +- if (ebname != null) { ++ if (ebname != null && !ebname.equals(SYSTEM_LOGGER_RB_NAME)) { + lr.setResourceBundleName(ebname); + lr.setResourceBundle(findResourceBundle(ebname)); + } +@@ -1271,6 +1292,22 @@ public class Logger { + // May also return null if we can't find the resource bundle and + // there is no suitable previous cached value. + ++ static final String SYSTEM_LOGGER_RB_NAME = "sun.util.logging.resources.logging"; ++ ++ private static ResourceBundle findSystemResourceBundle(final Locale locale) { ++ // the resource bundle is in a restricted package ++ return AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() { ++ public ResourceBundle run() { ++ try { ++ return ResourceBundle.getBundle(SYSTEM_LOGGER_RB_NAME, ++ locale); ++ } catch (MissingResourceException e) { ++ throw new InternalError(e.toString()); ++ } ++ } ++ }); ++ } ++ + private synchronized ResourceBundle findResourceBundle(String name) { + // Return a null bundle for a null name. + if (name == null) { +@@ -1282,6 +1319,13 @@ public class Logger { + // Normally we should hit on our simple one entry cache. + if (catalog != null && currentLocale == catalogLocale + && name == catalogName) { ++ return catalog; ++ } ++ ++ if (name.equals(SYSTEM_LOGGER_RB_NAME)) { ++ catalog = findSystemResourceBundle(currentLocale); ++ catalogName = name; ++ catalogLocale = currentLocale; + return catalog; + } + +diff --git a/src/share/classes/java/util/logging/Logging.java b/src/share/classes/java/util/logging/Logging.java +--- jdk/src/share/classes/java/util/logging/Logging.java ++++ jdk/src/share/classes/java/util/logging/Logging.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -34,15 +34,15 @@ import java.util.ArrayList; + * + * The <tt>LoggingMXBean</tt> interface provides a standard + * method for management access to the individual +- * java.util.Logger objects available at runtime. ++ * {@code Logger} objects available at runtime. + * + * @author Ron Mann + * @author Mandy Chung + * @since 1.5 + * + * @see javax.management +- * @see java.util.Logger +- * @see java.util.LogManager ++ * @see Logger ++ * @see LogManager + */ + class Logging implements LoggingMXBean { + +@@ -75,7 +75,7 @@ class Logging implements LoggingMXBean { + if (level == null) { + return EMPTY_STRING; + } else { +- return level.getName(); ++ return level.getLevelName(); + } + } + +@@ -94,7 +94,10 @@ class Logging implements LoggingMXBean { + Level level = null; + if (levelName != null) { + // parse will throw IAE if logLevel is invalid +- level = Level.parse(levelName); ++ level = Level.findLevel(levelName); ++ if (level == null) { ++ throw new IllegalArgumentException("Unknown level \"" + levelName + "\""); ++ } + } + + logger.setLevel(level); +diff --git a/src/share/classes/java/util/logging/SimpleFormatter.java b/src/share/classes/java/util/logging/SimpleFormatter.java +--- jdk/src/share/classes/java/util/logging/SimpleFormatter.java ++++ jdk/src/share/classes/java/util/logging/SimpleFormatter.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -83,7 +83,7 @@ public class SimpleFormatter extends For + } + sb.append(lineSeparator); + String message = formatMessage(record); +- sb.append(record.getLevel().getLocalizedName()); ++ sb.append(record.getLevel().getLocalizedLevelName()); + sb.append(": "); + sb.append(message); + sb.append(lineSeparator); +diff --git a/src/share/classes/sun/awt/AppContext.java b/src/share/classes/sun/awt/AppContext.java +--- jdk/src/share/classes/sun/awt/AppContext.java ++++ jdk/src/share/classes/sun/awt/AppContext.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -275,7 +275,7 @@ public final class AppContext { + if ((recent != null) && (recent.thread == currentThread)) { + appContext = recent.appContext; // Cache hit + } else { +- appContext = (AppContext)AccessController.doPrivileged( ++ appContext = (AppContext)AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + // Get the current ThreadGroup, and look for it and its +@@ -319,19 +319,25 @@ public final class AppContext { + // Before we return the main "system" AppContext, check to + // see if there's an AWTSecurityManager installed. If so, + // allow it to choose the AppContext to return. +- SecurityManager securityManager = System.getSecurityManager(); +- if ((securityManager != null) && +- (securityManager instanceof AWTSecurityManager)) { +- AWTSecurityManager awtSecMgr = +- (AWTSecurityManager)securityManager; +- AppContext secAppContext = awtSecMgr.getAppContext(); +- if (secAppContext != null) { +- appContext = secAppContext; // Return what we're told +- } ++ AppContext secAppContext = getExecutionAppContext(); ++ if (secAppContext != null) { ++ appContext = secAppContext; // Return what we're told + } + } + + return appContext; ++ } ++ ++ private final static AppContext getExecutionAppContext() { ++ SecurityManager securityManager = System.getSecurityManager(); ++ if ((securityManager != null) && ++ (securityManager instanceof AWTSecurityManager)) ++ { ++ AWTSecurityManager awtSecMgr = (AWTSecurityManager) securityManager; ++ AppContext secAppContext = awtSecMgr.getAppContext(); ++ return secAppContext; // Return what we're told ++ } ++ return null; + } + + private long DISPOSAL_TIMEOUT = 5000; // Default to 5-second timeout +@@ -786,6 +792,21 @@ public final class AppContext { + public boolean isMainAppContext() { + return (numAppContexts == 1); + } ++ public Object getContext() { ++ return getAppContext(); ++ } ++ public Object getExecutionContext() { ++ return getExecutionAppContext(); ++ } ++ public Object get(Object context, Object key) { ++ return ((AppContext)context).get(key); ++ } ++ public void put(Object context, Object key, Object value) { ++ ((AppContext)context).put(key, value); ++ } ++ public void remove(Object context, Object key) { ++ ((AppContext)context).remove(key); ++ } + }); + } + } +diff --git a/src/share/classes/sun/misc/JavaAWTAccess.java b/src/share/classes/sun/misc/JavaAWTAccess.java +--- jdk/src/share/classes/sun/misc/JavaAWTAccess.java ++++ jdk/src/share/classes/sun/misc/JavaAWTAccess.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -24,6 +24,14 @@ package sun.misc; + package sun.misc; + + public interface JavaAWTAccess { ++ public Object getContext(); ++ public Object getExecutionContext(); ++ ++ public Object get(Object context, Object key); ++ public void put(Object context, Object key, Object value); ++ public void remove(Object context, Object key); ++ ++ // convenience methods whose context is the object returned by getContext() + public Object get(Object key); + public void put(Object key, Object value); + public void remove(Object key); +diff --git a/src/share/lib/security/java.security b/src/share/lib/security/java.security +--- jdk/src/share/lib/security/java.security ++++ jdk/src/share/lib/security/java.security +@@ -129,7 +129,10 @@ system.scope=sun.security.provider.Ident + # been granted. + package.access=sun.,\ + com.sun.xml.internal.,\ +- com.sun.imageio. ++ com.sun.imageio.,\ ++ com.sun.istack.internal.,\ ++ com.sun.jmx.defaults.,\ ++ com.sun.jmx.remote.util. + + # + # List of comma-separated packages that start with or equal this string +@@ -143,7 +146,10 @@ package.access=sun.,\ + # + package.definition=sun.,\ + com.sun.xml.internal.,\ +- com.sun.imageio. ++ com.sun.imageio.,\ ++ com.sun.istack.internal.,\ ++ com.sun.jmx.defaults.,\ ++ com.sun.jmx.remote.util. + + # + # Determines whether this properties file can be appended to diff --git a/java/openjdk6/files/icedtea/security/20130201/6776941.patch b/java/openjdk6/files/icedtea/security/20130201/6776941.patch new file mode 100644 index 000000000000..7604b50b9b22 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/6776941.patch @@ -0,0 +1,272 @@ +# HG changeset patch +# User dholmes +# Date 1350872930 14400 +# Node ID 6088f35106866940de257456c8eee21b130d5ff5 +# Parent 21487ef30163da2a96369eee80a3bf5e94612017 +6776941: Improve thread pool shutdown +Reviewed-by: dl, skoivu + +diff --git a/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java b/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java +--- jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java ++++ jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java +@@ -34,8 +34,10 @@ + */ + + package java.util.concurrent; +-import java.util.concurrent.locks.*; +-import java.util.concurrent.atomic.*; ++import java.util.concurrent.locks.AbstractQueuedSynchronizer; ++import java.util.concurrent.locks.Condition; ++import java.util.concurrent.locks.ReentrantLock; ++import java.util.concurrent.atomic.AtomicInteger; + import java.util.*; + + /** +@@ -491,10 +493,15 @@ public class ThreadPoolExecutor extends + * policy limiting the number of threads. Even though it is not + * treated as an error, failure to create threads may result in + * new tasks being rejected or existing ones remaining stuck in +- * the queue. On the other hand, no special precautions exist to +- * handle OutOfMemoryErrors that might be thrown while trying to +- * create threads, since there is generally no recourse from +- * within this class. ++ * the queue. ++ * ++ * We go further and preserve pool invariants even in the face of ++ * errors such as OutOfMemoryError, that might be thrown while ++ * trying to create threads. Such errors are rather common due to ++ * the need to allocate a native stack in Thread#start, and users ++ * will want to perform clean pool shutdown to clean up. There ++ * will likely be enough memory available for the cleanup code to ++ * complete without encountering yet another OutOfMemoryError. + */ + private volatile ThreadFactory threadFactory; + +@@ -568,9 +575,13 @@ public class ThreadPoolExecutor extends + * task execution. This protects against interrupts that are + * intended to wake up a worker thread waiting for a task from + * instead interrupting a task being run. We implement a simple +- * non-reentrant mutual exclusion lock rather than use ReentrantLock +- * because we do not want worker tasks to be able to reacquire the +- * lock when they invoke pool control methods like setCorePoolSize. ++ * non-reentrant mutual exclusion lock rather than use ++ * ReentrantLock because we do not want worker tasks to be able to ++ * reacquire the lock when they invoke pool control methods like ++ * setCorePoolSize. Additionally, to suppress interrupts until ++ * the thread actually starts running tasks, we initialize lock ++ * state to a negative value, and clear it upon start (in ++ * runWorker). + */ + private final class Worker + extends AbstractQueuedSynchronizer +@@ -594,6 +605,7 @@ public class ThreadPoolExecutor extends + * @param firstTask the first task (null if none) + */ + Worker(Runnable firstTask) { ++ setState(-1); // inhibit interrupts until runWorker + this.firstTask = firstTask; + this.thread = getThreadFactory().newThread(this); + } +@@ -609,7 +621,7 @@ public class ThreadPoolExecutor extends + // The value 1 represents the locked state. + + protected boolean isHeldExclusively() { +- return getState() == 1; ++ return getState() != 0; + } + + protected boolean tryAcquire(int unused) { +@@ -630,6 +642,16 @@ public class ThreadPoolExecutor extends + public boolean tryLock() { return tryAcquire(1); } + public void unlock() { release(1); } + public boolean isLocked() { return isHeldExclusively(); } ++ ++ void interruptIfStarted() { ++ Thread t; ++ if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { ++ try { ++ t.interrupt(); ++ } catch (SecurityException ignore) { ++ } ++ } ++ } + } + + /* +@@ -729,10 +751,7 @@ public class ThreadPoolExecutor extends + mainLock.lock(); + try { + for (Worker w : workers) { +- try { +- w.thread.interrupt(); +- } catch (SecurityException ignore) { +- } ++ w.interruptIfStarted(); + } + } finally { + mainLock.unlock(); +@@ -789,19 +808,6 @@ public class ThreadPoolExecutor extends + } + + private static final boolean ONLY_ONE = true; +- +- /** +- * Ensures that unless the pool is stopping, the current thread +- * does not have its interrupt set. This requires a double-check +- * of state in case the interrupt was cleared concurrently with a +- * shutdownNow -- if so, the interrupt is re-enabled. +- */ +- private void clearInterruptsForTaskRun() { +- if (runStateLessThan(ctl.get(), STOP) && +- Thread.interrupted() && +- runStateAtLeast(ctl.get(), STOP)) +- Thread.currentThread().interrupt(); +- } + + /* + * Misc utilities, most of which are also exported to +@@ -862,12 +868,13 @@ public class ThreadPoolExecutor extends + * Checks if a new worker can be added with respect to current + * pool state and the given bound (either core or maximum). If so, + * the worker count is adjusted accordingly, and, if possible, a +- * new worker is created and started running firstTask as its ++ * new worker is created and started, running firstTask as its + * first task. This method returns false if the pool is stopped or + * eligible to shut down. It also returns false if the thread +- * factory fails to create a thread when asked, which requires a +- * backout of workerCount, and a recheck for termination, in case +- * the existence of this worker was holding up termination. ++ * factory fails to create a thread when asked. If the thread ++ * creation fails, either due to the thread factory returning ++ * null, or due to an exception (typically OutOfMemoryError in ++ * Thread#start), we roll back cleanly. + * + * @param firstTask the task the new thread should run first (or + * null if none). Workers are created with an initial first task +@@ -910,46 +917,65 @@ public class ThreadPoolExecutor extends + } + } + +- Worker w = new Worker(firstTask); +- Thread t = w.thread; ++ boolean workerStarted = false; ++ boolean workerAdded = false; ++ Worker w = null; ++ try { ++ final ReentrantLock mainLock = this.mainLock; ++ w = new Worker(firstTask); ++ final Thread t = w.thread; ++ if (t != null) { ++ mainLock.lock(); ++ try { ++ // Recheck while holding lock. ++ // Back out on ThreadFactory failure or if ++ // shut down before lock acquired. ++ int c = ctl.get(); ++ int rs = runStateOf(c); + ++ if (rs < SHUTDOWN || ++ (rs == SHUTDOWN && firstTask == null)) { ++ if (t.isAlive()) // precheck that t is startable ++ throw new IllegalThreadStateException(); ++ workers.add(w); ++ int s = workers.size(); ++ if (s > largestPoolSize) ++ largestPoolSize = s; ++ workerAdded = true; ++ } ++ } finally { ++ mainLock.unlock(); ++ } ++ if (workerAdded) { ++ t.start(); ++ workerStarted = true; ++ } ++ } ++ } finally { ++ if (! workerStarted) ++ addWorkerFailed(w); ++ } ++ return workerStarted; ++ } ++ ++ /** ++ * Rolls back the worker thread creation. ++ * - removes worker from workers, if present ++ * - decrements worker count ++ * - rechecks for termination, in case the existence of this ++ * worker was holding up termination ++ */ ++ private void addWorkerFailed(Worker w) { + final ReentrantLock mainLock = this.mainLock; + mainLock.lock(); + try { +- // Recheck while holding lock. +- // Back out on ThreadFactory failure or if +- // shut down before lock acquired. +- int c = ctl.get(); +- int rs = runStateOf(c); +- +- if (t == null || +- (rs >= SHUTDOWN && +- ! (rs == SHUTDOWN && +- firstTask == null))) { +- decrementWorkerCount(); +- tryTerminate(); +- return false; +- } +- +- workers.add(w); +- +- int s = workers.size(); +- if (s > largestPoolSize) +- largestPoolSize = s; ++ if (w != null) ++ workers.remove(w); ++ decrementWorkerCount(); ++ tryTerminate(); + } finally { + mainLock.unlock(); + } +- +- t.start(); +- // It is possible (but unlikely) for a thread to have been +- // added to workers, but not yet started, during transition to +- // STOP, which could result in a rare missed interrupt, +- // because Thread.interrupt is not guaranteed to have any effect +- // on a non-yet-started Thread (see Thread#interrupt). +- if (runStateOf(ctl.get()) == STOP && ! t.isInterrupted()) +- t.interrupt(); +- +- return true; + } + + /** +@@ -1096,15 +1122,25 @@ public class ThreadPoolExecutor extends + * @param w the worker + */ + final void runWorker(Worker w) { ++ Thread wt = Thread.currentThread(); + Runnable task = w.firstTask; + w.firstTask = null; ++ w.unlock(); // allow interrupts + boolean completedAbruptly = true; + try { + while (task != null || (task = getTask()) != null) { + w.lock(); +- clearInterruptsForTaskRun(); ++ // If pool is stopping, ensure thread is interrupted; ++ // if not, ensure thread is not interrupted. This ++ // requires a recheck in second case to deal with ++ // shutdownNow race while clearing interrupt ++ if ((runStateAtLeast(ctl.get(), STOP) || ++ (Thread.interrupted() && ++ runStateAtLeast(ctl.get(), STOP))) && ++ !wt.isInterrupted()) ++ wt.interrupt(); + try { +- beforeExecute(w.thread, task); ++ beforeExecute(wt, task); + Throwable thrown = null; + try { + task.run(); diff --git a/java/openjdk6/files/icedtea/security/20130201/7141694.patch b/java/openjdk6/files/icedtea/security/20130201/7141694.patch new file mode 100644 index 000000000000..66d69a7b69a7 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7141694.patch @@ -0,0 +1,87 @@ +# HG changeset patch +# User mbankal +# Date 1355396891 28800 +# Node ID 7eb471f1efdd127f982e53b290c1fece845a897c +# Parent 58fdb67fcacc67693fc43b5601e88bd7c216f850 +7141694: Improving CORBA internals +Reviewed-by: coffeys, ahgross + +diff --git a/src/share/classes/com/sun/corba/se/spi/orb/ORB.java b/src/share/classes/com/sun/corba/se/spi/orb/ORB.java +--- corba/src/share/classes/com/sun/corba/se/spi/orb/ORB.java ++++ corba/src/share/classes/com/sun/corba/se/spi/orb/ORB.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -98,6 +98,7 @@ import com.sun.corba.se.impl.presentatio + import com.sun.corba.se.impl.presentation.rmi.PresentationManagerImpl ; + + import com.sun.corba.se.impl.orbutil.ORBClassLoader ; ++import sun.awt.AppContext; + + public abstract class ORB extends com.sun.corba.se.org.omg.CORBA.ORB + implements Broker, TypeCodeFactory +@@ -173,14 +174,7 @@ public abstract class ORB extends com.su + + private MonitoringManager monitoringManager; + +- // There is only one instance of the PresentationManager +- // that is shared between all ORBs. This is necessary +- // because RMI-IIOP requires the PresentationManager in +- // places where no ORB is available, so the PresentationManager +- // must be global. It is initialized here as well. +- protected static PresentationManager globalPM = null ; +- +- static { ++ private static PresentationManager setupPresentationManager() { + staticWrapper = ORBUtilSystemException.get( + CORBALogDomains.RPC_PRESENTATION ) ; + +@@ -220,17 +214,26 @@ public abstract class ORB extends com.su + } + ) ; + +- globalPM = new PresentationManagerImpl( useDynamicStub ) ; +- globalPM.setStubFactoryFactory( false, ++ PresentationManager pm = new PresentationManagerImpl( useDynamicStub ) ; ++ pm.setStubFactoryFactory( false, + PresentationDefaults.getStaticStubFactoryFactory() ) ; +- globalPM.setStubFactoryFactory( true, dynamicStubFactoryFactory ) ; ++ pm.setStubFactoryFactory( true, dynamicStubFactoryFactory ) ; ++ return pm; + } + +- /** Get the single instance of the PresentationManager ++ /** ++ * Returns the Presentation Manager for the current thread group, using the ThreadGroup-specific ++ * AppContext to hold it. Creates and records one if needed. + */ +- public static PresentationManager getPresentationManager() ++ public static PresentationManager getPresentationManager() + { +- return globalPM ; ++ AppContext ac = AppContext.getAppContext(); ++ PresentationManager pm = (PresentationManager) ac.get(PresentationManager.class); ++ if (pm == null) { ++ pm = setupPresentationManager(); ++ ac.put(PresentationManager.class, pm); ++ } ++ return pm; + } + + /** Get the appropriate StubFactoryFactory. This +@@ -240,8 +243,9 @@ public abstract class ORB extends com.su + public static PresentationManager.StubFactoryFactory + getStubFactoryFactory() + { +- boolean useDynamicStubs = globalPM.useDynamicStubs() ; +- return globalPM.getStubFactoryFactory( useDynamicStubs ) ; ++ PresentationManager gPM = getPresentationManager(); ++ boolean useDynamicStubs = gPM.useDynamicStubs() ; ++ return gPM.getStubFactoryFactory( useDynamicStubs ) ; + } + + protected ORB() diff --git a/java/openjdk6/files/icedtea/security/20130201/7173145.patch b/java/openjdk6/files/icedtea/security/20130201/7173145.patch new file mode 100644 index 000000000000..b7971618d3d7 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7173145.patch @@ -0,0 +1,22 @@ +# HG changeset patch +# User anthony +# Date 1350043271 -14400 +# Node ID ce11c5c59cb8672eeddf9d5ce49563ccbc387854 +# Parent 9c2a2aae44a46e0b63b913987672d1488fa4e7a5 +7173145: Improve in-memory representation of splashscreens +Reviewed-by: bae, mschoene + +diff --git a/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c b/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c +--- jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c ++++ jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c +@@ -133,6 +133,10 @@ SplashDecodeJpeg(Splash * splash, struct + ImageFormat srcFormat; + + jpeg_read_header(cinfo, TRUE); ++ ++ // SplashScreen jpeg converter expects data in RGB format only ++ cinfo->out_color_space = JCS_RGB; ++ + jpeg_start_decompress(cinfo); + + SplashCleanup(splash); diff --git a/java/openjdk6/files/icedtea/security/20130201/7186945.patch b/java/openjdk6/files/icedtea/security/20130201/7186945.patch new file mode 100644 index 000000000000..007ff979f1b7 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7186945.patch @@ -0,0 +1,10819 @@ +# HG changeset patch +# User miroslawzn +# Date 1354324090 28800 +# Node ID f3f9b711bb1228f4598ded7eb0380c32eba63521 +# Parent 9bbc6817b00c3e9d4eba05d53a8a20b45947ea03 +7186945: Unpack200 improvement +7186957: Improve Pack200 data validation +7186946: Refine unpacker resource usage +Reviewed-by: ksrini + +diff --git a/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java b/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java +--- jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java ++++ jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -22,7 +22,6 @@ + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +- + package com.sun.java.util.jar.pack; + + import java.io.*; +@@ -62,20 +61,20 @@ class BandStructure implements Constants + + /** Call this exactly once, early, to specify the archive major version. */ + public void initPackageMajver(int packageMajver) throws IOException { +- assert(packageMajver > 0 && packageMajver < 0x10000); +- if (this.packageMajver > 0) { +- throw new IOException( +- "Package majver is already initialized to " + this.packageMajver+ +- "; new setting is " + packageMajver); +- } +- this.packageMajver = packageMajver; +- adjustToMajver(); ++ assert(packageMajver > 0 && packageMajver < 0x10000); ++ if (this.packageMajver > 0) { ++ throw new IOException( ++ "Package majver is already initialized to " + this.packageMajver+ ++ "; new setting is " + packageMajver); ++ } ++ this.packageMajver = packageMajver; ++ adjustToMajver(); + } + public int getPackageMajver() { +- if (packageMajver < 0) { +- throw new RuntimeException("Package majver not yet initialized"); +- } +- return packageMajver; ++ if (packageMajver < 0) { ++ throw new RuntimeException("Package majver not yet initialized"); ++ } ++ return packageMajver; + } + + private final boolean isReader = this instanceof PackageReader; +@@ -103,163 +102,163 @@ class BandStructure implements Constants + final static Coding MDELTA5 = Coding.of(5,64,2).getDeltaCoding(); + + final private static Coding[] basicCodings = { +- // Table of "Canonical BHSD Codings" from Pack200 spec. +- null, // _meta_default ++ // Table of "Canonical BHSD Codings" from Pack200 spec. ++ null, // _meta_default + +- // Fixed-length codings: +- Coding.of(1,256,0), +- Coding.of(1,256,1), +- Coding.of(1,256,0).getDeltaCoding(), +- Coding.of(1,256,1).getDeltaCoding(), +- Coding.of(2,256,0), +- Coding.of(2,256,1), +- Coding.of(2,256,0).getDeltaCoding(), +- Coding.of(2,256,1).getDeltaCoding(), +- Coding.of(3,256,0), +- Coding.of(3,256,1), +- Coding.of(3,256,0).getDeltaCoding(), +- Coding.of(3,256,1).getDeltaCoding(), +- Coding.of(4,256,0), +- Coding.of(4,256,1), +- Coding.of(4,256,0).getDeltaCoding(), +- Coding.of(4,256,1).getDeltaCoding(), ++ // Fixed-length codings: ++ Coding.of(1,256,0), ++ Coding.of(1,256,1), ++ Coding.of(1,256,0).getDeltaCoding(), ++ Coding.of(1,256,1).getDeltaCoding(), ++ Coding.of(2,256,0), ++ Coding.of(2,256,1), ++ Coding.of(2,256,0).getDeltaCoding(), ++ Coding.of(2,256,1).getDeltaCoding(), ++ Coding.of(3,256,0), ++ Coding.of(3,256,1), ++ Coding.of(3,256,0).getDeltaCoding(), ++ Coding.of(3,256,1).getDeltaCoding(), ++ Coding.of(4,256,0), ++ Coding.of(4,256,1), ++ Coding.of(4,256,0).getDeltaCoding(), ++ Coding.of(4,256,1).getDeltaCoding(), + +- // Full-range variable-length codings: +- Coding.of(5, 4,0), +- Coding.of(5, 4,1), +- Coding.of(5, 4,2), +- Coding.of(5, 16,0), +- Coding.of(5, 16,1), +- Coding.of(5, 16,2), +- Coding.of(5, 32,0), +- Coding.of(5, 32,1), +- Coding.of(5, 32,2), +- Coding.of(5, 64,0), +- Coding.of(5, 64,1), +- Coding.of(5, 64,2), +- Coding.of(5,128,0), +- Coding.of(5,128,1), +- Coding.of(5,128,2), ++ // Full-range variable-length codings: ++ Coding.of(5, 4,0), ++ Coding.of(5, 4,1), ++ Coding.of(5, 4,2), ++ Coding.of(5, 16,0), ++ Coding.of(5, 16,1), ++ Coding.of(5, 16,2), ++ Coding.of(5, 32,0), ++ Coding.of(5, 32,1), ++ Coding.of(5, 32,2), ++ Coding.of(5, 64,0), ++ Coding.of(5, 64,1), ++ Coding.of(5, 64,2), ++ Coding.of(5,128,0), ++ Coding.of(5,128,1), ++ Coding.of(5,128,2), + +- Coding.of(5, 4,0).getDeltaCoding(), +- Coding.of(5, 4,1).getDeltaCoding(), +- Coding.of(5, 4,2).getDeltaCoding(), +- Coding.of(5, 16,0).getDeltaCoding(), +- Coding.of(5, 16,1).getDeltaCoding(), +- Coding.of(5, 16,2).getDeltaCoding(), +- Coding.of(5, 32,0).getDeltaCoding(), +- Coding.of(5, 32,1).getDeltaCoding(), +- Coding.of(5, 32,2).getDeltaCoding(), +- Coding.of(5, 64,0).getDeltaCoding(), +- Coding.of(5, 64,1).getDeltaCoding(), +- Coding.of(5, 64,2).getDeltaCoding(), +- Coding.of(5,128,0).getDeltaCoding(), +- Coding.of(5,128,1).getDeltaCoding(), +- Coding.of(5,128,2).getDeltaCoding(), ++ Coding.of(5, 4,0).getDeltaCoding(), ++ Coding.of(5, 4,1).getDeltaCoding(), ++ Coding.of(5, 4,2).getDeltaCoding(), ++ Coding.of(5, 16,0).getDeltaCoding(), ++ Coding.of(5, 16,1).getDeltaCoding(), ++ Coding.of(5, 16,2).getDeltaCoding(), ++ Coding.of(5, 32,0).getDeltaCoding(), ++ Coding.of(5, 32,1).getDeltaCoding(), ++ Coding.of(5, 32,2).getDeltaCoding(), ++ Coding.of(5, 64,0).getDeltaCoding(), ++ Coding.of(5, 64,1).getDeltaCoding(), ++ Coding.of(5, 64,2).getDeltaCoding(), ++ Coding.of(5,128,0).getDeltaCoding(), ++ Coding.of(5,128,1).getDeltaCoding(), ++ Coding.of(5,128,2).getDeltaCoding(), + +- // Variable length subrange codings: +- Coding.of(2,192,0), +- Coding.of(2,224,0), +- Coding.of(2,240,0), +- Coding.of(2,248,0), +- Coding.of(2,252,0), ++ // Variable length subrange codings: ++ Coding.of(2,192,0), ++ Coding.of(2,224,0), ++ Coding.of(2,240,0), ++ Coding.of(2,248,0), ++ Coding.of(2,252,0), + +- Coding.of(2, 8,0).getDeltaCoding(), +- Coding.of(2, 8,1).getDeltaCoding(), +- Coding.of(2, 16,0).getDeltaCoding(), +- Coding.of(2, 16,1).getDeltaCoding(), +- Coding.of(2, 32,0).getDeltaCoding(), +- Coding.of(2, 32,1).getDeltaCoding(), +- Coding.of(2, 64,0).getDeltaCoding(), +- Coding.of(2, 64,1).getDeltaCoding(), +- Coding.of(2,128,0).getDeltaCoding(), +- Coding.of(2,128,1).getDeltaCoding(), +- Coding.of(2,192,0).getDeltaCoding(), +- Coding.of(2,192,1).getDeltaCoding(), +- Coding.of(2,224,0).getDeltaCoding(), +- Coding.of(2,224,1).getDeltaCoding(), +- Coding.of(2,240,0).getDeltaCoding(), +- Coding.of(2,240,1).getDeltaCoding(), +- Coding.of(2,248,0).getDeltaCoding(), +- Coding.of(2,248,1).getDeltaCoding(), ++ Coding.of(2, 8,0).getDeltaCoding(), ++ Coding.of(2, 8,1).getDeltaCoding(), ++ Coding.of(2, 16,0).getDeltaCoding(), ++ Coding.of(2, 16,1).getDeltaCoding(), ++ Coding.of(2, 32,0).getDeltaCoding(), ++ Coding.of(2, 32,1).getDeltaCoding(), ++ Coding.of(2, 64,0).getDeltaCoding(), ++ Coding.of(2, 64,1).getDeltaCoding(), ++ Coding.of(2,128,0).getDeltaCoding(), ++ Coding.of(2,128,1).getDeltaCoding(), ++ Coding.of(2,192,0).getDeltaCoding(), ++ Coding.of(2,192,1).getDeltaCoding(), ++ Coding.of(2,224,0).getDeltaCoding(), ++ Coding.of(2,224,1).getDeltaCoding(), ++ Coding.of(2,240,0).getDeltaCoding(), ++ Coding.of(2,240,1).getDeltaCoding(), ++ Coding.of(2,248,0).getDeltaCoding(), ++ Coding.of(2,248,1).getDeltaCoding(), + +- Coding.of(3,192,0), +- Coding.of(3,224,0), +- Coding.of(3,240,0), +- Coding.of(3,248,0), +- Coding.of(3,252,0), ++ Coding.of(3,192,0), ++ Coding.of(3,224,0), ++ Coding.of(3,240,0), ++ Coding.of(3,248,0), ++ Coding.of(3,252,0), + +- Coding.of(3, 8,0).getDeltaCoding(), +- Coding.of(3, 8,1).getDeltaCoding(), +- Coding.of(3, 16,0).getDeltaCoding(), +- Coding.of(3, 16,1).getDeltaCoding(), +- Coding.of(3, 32,0).getDeltaCoding(), +- Coding.of(3, 32,1).getDeltaCoding(), +- Coding.of(3, 64,0).getDeltaCoding(), +- Coding.of(3, 64,1).getDeltaCoding(), +- Coding.of(3,128,0).getDeltaCoding(), +- Coding.of(3,128,1).getDeltaCoding(), +- Coding.of(3,192,0).getDeltaCoding(), +- Coding.of(3,192,1).getDeltaCoding(), +- Coding.of(3,224,0).getDeltaCoding(), +- Coding.of(3,224,1).getDeltaCoding(), +- Coding.of(3,240,0).getDeltaCoding(), +- Coding.of(3,240,1).getDeltaCoding(), +- Coding.of(3,248,0).getDeltaCoding(), +- Coding.of(3,248,1).getDeltaCoding(), ++ Coding.of(3, 8,0).getDeltaCoding(), ++ Coding.of(3, 8,1).getDeltaCoding(), ++ Coding.of(3, 16,0).getDeltaCoding(), ++ Coding.of(3, 16,1).getDeltaCoding(), ++ Coding.of(3, 32,0).getDeltaCoding(), ++ Coding.of(3, 32,1).getDeltaCoding(), ++ Coding.of(3, 64,0).getDeltaCoding(), ++ Coding.of(3, 64,1).getDeltaCoding(), ++ Coding.of(3,128,0).getDeltaCoding(), ++ Coding.of(3,128,1).getDeltaCoding(), ++ Coding.of(3,192,0).getDeltaCoding(), ++ Coding.of(3,192,1).getDeltaCoding(), ++ Coding.of(3,224,0).getDeltaCoding(), ++ Coding.of(3,224,1).getDeltaCoding(), ++ Coding.of(3,240,0).getDeltaCoding(), ++ Coding.of(3,240,1).getDeltaCoding(), ++ Coding.of(3,248,0).getDeltaCoding(), ++ Coding.of(3,248,1).getDeltaCoding(), + +- Coding.of(4,192,0), +- Coding.of(4,224,0), +- Coding.of(4,240,0), +- Coding.of(4,248,0), +- Coding.of(4,252,0), ++ Coding.of(4,192,0), ++ Coding.of(4,224,0), ++ Coding.of(4,240,0), ++ Coding.of(4,248,0), ++ Coding.of(4,252,0), + +- Coding.of(4, 8,0).getDeltaCoding(), +- Coding.of(4, 8,1).getDeltaCoding(), +- Coding.of(4, 16,0).getDeltaCoding(), +- Coding.of(4, 16,1).getDeltaCoding(), +- Coding.of(4, 32,0).getDeltaCoding(), +- Coding.of(4, 32,1).getDeltaCoding(), +- Coding.of(4, 64,0).getDeltaCoding(), +- Coding.of(4, 64,1).getDeltaCoding(), +- Coding.of(4,128,0).getDeltaCoding(), +- Coding.of(4,128,1).getDeltaCoding(), +- Coding.of(4,192,0).getDeltaCoding(), +- Coding.of(4,192,1).getDeltaCoding(), +- Coding.of(4,224,0).getDeltaCoding(), +- Coding.of(4,224,1).getDeltaCoding(), +- Coding.of(4,240,0).getDeltaCoding(), +- Coding.of(4,240,1).getDeltaCoding(), +- Coding.of(4,248,0).getDeltaCoding(), +- Coding.of(4,248,1).getDeltaCoding(), ++ Coding.of(4, 8,0).getDeltaCoding(), ++ Coding.of(4, 8,1).getDeltaCoding(), ++ Coding.of(4, 16,0).getDeltaCoding(), ++ Coding.of(4, 16,1).getDeltaCoding(), ++ Coding.of(4, 32,0).getDeltaCoding(), ++ Coding.of(4, 32,1).getDeltaCoding(), ++ Coding.of(4, 64,0).getDeltaCoding(), ++ Coding.of(4, 64,1).getDeltaCoding(), ++ Coding.of(4,128,0).getDeltaCoding(), ++ Coding.of(4,128,1).getDeltaCoding(), ++ Coding.of(4,192,0).getDeltaCoding(), ++ Coding.of(4,192,1).getDeltaCoding(), ++ Coding.of(4,224,0).getDeltaCoding(), ++ Coding.of(4,224,1).getDeltaCoding(), ++ Coding.of(4,240,0).getDeltaCoding(), ++ Coding.of(4,240,1).getDeltaCoding(), ++ Coding.of(4,248,0).getDeltaCoding(), ++ Coding.of(4,248,1).getDeltaCoding(), + +- null ++ null + }; + final private static HashMap basicCodingIndexes; + static { +- assert(basicCodings[_meta_default] == null); +- assert(basicCodings[_meta_canon_min] != null); +- assert(basicCodings[_meta_canon_max] != null); +- HashMap map = new HashMap(); +- for (int i = 0; i < basicCodings.length; i++) { +- Coding c = basicCodings[i]; +- if (c == null) continue; +- assert(i >= _meta_canon_min); +- assert(i <= _meta_canon_max); +- map.put(c, new Integer(i)); +- } +- basicCodingIndexes = map; ++ assert(basicCodings[_meta_default] == null); ++ assert(basicCodings[_meta_canon_min] != null); ++ assert(basicCodings[_meta_canon_max] != null); ++ HashMap map = new HashMap(); ++ for (int i = 0; i < basicCodings.length; i++) { ++ Coding c = basicCodings[i]; ++ if (c == null) continue; ++ assert(i >= _meta_canon_min); ++ assert(i <= _meta_canon_max); ++ map.put(c, new Integer(i)); ++ } ++ basicCodingIndexes = map; + } + public static Coding codingForIndex(int i) { +- return i < basicCodings.length ? basicCodings[i] : null; ++ return i < basicCodings.length ? basicCodings[i] : null; + } + public static int indexOf(Coding c) { +- Integer i = (Integer) basicCodingIndexes.get(c); +- if (i == null) return 0; +- return i.intValue(); ++ Integer i = (Integer) basicCodingIndexes.get(c); ++ if (i == null) return 0; ++ return i.intValue(); + } + public static Coding[] getBasicCodings() { +- return (Coding[]) basicCodings.clone(); ++ return (Coding[]) basicCodings.clone(); + } + + protected byte[] bandHeaderBytes; // used for input only +@@ -267,31 +266,31 @@ class BandStructure implements Constants + protected int bandHeaderBytePos0; // for debug + + protected CodingMethod getBandHeader(int XB, Coding regularCoding) { +- CodingMethod[] res = {null}; +- // push back XB onto the band header bytes +- bandHeaderBytes[--bandHeaderBytePos] = (byte) XB; +- bandHeaderBytePos0 = bandHeaderBytePos; +- // scan forward through XB and any additional band header bytes +- bandHeaderBytePos = parseMetaCoding(bandHeaderBytes, +- bandHeaderBytePos, +- regularCoding, +- res); +- return res[0]; ++ CodingMethod[] res = {null}; ++ // push back XB onto the band header bytes ++ bandHeaderBytes[--bandHeaderBytePos] = (byte) XB; ++ bandHeaderBytePos0 = bandHeaderBytePos; ++ // scan forward through XB and any additional band header bytes ++ bandHeaderBytePos = parseMetaCoding(bandHeaderBytes, ++ bandHeaderBytePos, ++ regularCoding, ++ res); ++ return res[0]; + } + + public static int parseMetaCoding(byte[] bytes, int pos, Coding dflt, CodingMethod[] res) { +- if ((bytes[pos] & 0xFF) == _meta_default) { +- res[0] = dflt; +- return pos+1; +- } +- int pos2; +- pos2 = Coding.parseMetaCoding(bytes, pos, dflt, res); +- if (pos2 > pos) return pos2; +- pos2 = PopulationCoding.parseMetaCoding(bytes, pos, dflt, res); +- if (pos2 > pos) return pos2; +- pos2 = AdaptiveCoding.parseMetaCoding(bytes, pos, dflt, res); +- if (pos2 > pos) return pos2; +- throw new RuntimeException("Bad meta-coding op "+(bytes[pos]&0xFF)); ++ if ((bytes[pos] & 0xFF) == _meta_default) { ++ res[0] = dflt; ++ return pos+1; ++ } ++ int pos2; ++ pos2 = Coding.parseMetaCoding(bytes, pos, dflt, res); ++ if (pos2 > pos) return pos2; ++ pos2 = PopulationCoding.parseMetaCoding(bytes, pos, dflt, res); ++ if (pos2 > pos) return pos2; ++ pos2 = AdaptiveCoding.parseMetaCoding(bytes, pos, dflt, res); ++ if (pos2 > pos) return pos2; ++ throw new RuntimeException("Bad meta-coding op "+(bytes[pos]&0xFF)); + } + + static final int SHORT_BAND_HEURISTIC = 100; +@@ -311,11 +310,11 @@ class BandStructure implements Constants + public static final int DONE_PHASE = 8; // done writing or reading + + static boolean phaseIsRead(int p) { +- return (p % 2) == 0; ++ return (p % 2) == 0; + } + static int phaseCmp(int p0, int p1) { +- assert((p0 % 2) == (p1 % 2) || (p0 % 8) == 0 || (p1 % 8) == 0); +- return p0 - p1; ++ assert((p0 % 2) == (p1 % 2) || (p0 % 8) == 0 || (p1 % 8) == 0); ++ return p0 - p1; + } + + /** The packed file is divided up into a number of segments. +@@ -332,7 +331,7 @@ class BandStructure implements Constants + * + * The three phases for reading a packed file are EXPECT, READ, + * and DISBURSE. +- * 1. For each band, the expected number of integers is determined. ++ * 1. For each band, the expected number of integers is determined. + * 2. The data is actually read from the file into the band. + * 3. The band pays out its values as requested, in an ad hoc order. + * +@@ -340,696 +339,695 @@ class BandStructure implements Constants + * Clearly, these phases must be properly ordered WRT each other. + */ + abstract class Band { +- private int phase = NO_PHASE; +- private final String name; ++ private int phase = NO_PHASE; ++ private final String name; + +- private int valuesExpected; ++ private int valuesExpected; + +- protected long outputSize = -1; // cache ++ protected long outputSize = -1; // cache + +- final public Coding regularCoding; ++ final public Coding regularCoding; + +- final public int seqForDebug; +- public int elementCountForDebug; ++ final public int seqForDebug; ++ public int elementCountForDebug; + + +- protected Band(String name, Coding regularCoding) { +- this.name = name; +- this.regularCoding = regularCoding; +- this.seqForDebug = ++nextSeqForDebug; +- if (verbose > 2) +- Utils.log.fine("Band "+seqForDebug+" is "+name); +- // caller must call init +- } ++ protected Band(String name, Coding regularCoding) { ++ this.name = name; ++ this.regularCoding = regularCoding; ++ this.seqForDebug = ++nextSeqForDebug; ++ if (verbose > 2) ++ Utils.log.fine("Band "+seqForDebug+" is "+name); ++ // caller must call init ++ } + +- public Band init() { +- // Cannot due this from the constructor, because constructor +- // may wish to initialize some subclass variables. +- // Set initial phase for reading or writing: +- if (isReader) +- readyToExpect(); +- else +- readyToCollect(); +- return this; +- } ++ public Band init() { ++ // Cannot due this from the constructor, because constructor ++ // may wish to initialize some subclass variables. ++ // Set initial phase for reading or writing: ++ if (isReader) ++ readyToExpect(); ++ else ++ readyToCollect(); ++ return this; ++ } + +- // common operations +- boolean isReader() { return isReader; } +- int phase() { return phase; } +- String name() { return name; } ++ // common operations ++ boolean isReader() { return isReader; } ++ int phase() { return phase; } ++ String name() { return name; } + +- /** Return -1 if data buffer not allocated, else max length. */ +- public abstract int capacity(); ++ /** Return -1 if data buffer not allocated, else max length. */ ++ public abstract int capacity(); + +- /** Allocate data buffer to specified length. */ +- protected abstract void setCapacity(int cap); ++ /** Allocate data buffer to specified length. */ ++ protected abstract void setCapacity(int cap); + +- /** Return current number of values in buffer, which must exist. */ +- public abstract int length(); ++ /** Return current number of values in buffer, which must exist. */ ++ public abstract int length(); + +- protected abstract int valuesRemainingForDebug(); ++ protected abstract int valuesRemainingForDebug(); + +- public final int valuesExpected() { +- return valuesExpected; +- } ++ public final int valuesExpected() { ++ return valuesExpected; ++ } + +- /** Write out bytes, encoding the values. */ +- public final void writeTo(OutputStream out) throws IOException { +- assert(assertReadyToWriteTo(this, out)); +- setPhase(WRITE_PHASE); +- // subclasses continue by writing their contents to output +- writeDataTo(out); +- doneWriting(); +- } ++ /** Write out bytes, encoding the values. */ ++ public final void writeTo(OutputStream out) throws IOException { ++ assert(assertReadyToWriteTo(this, out)); ++ setPhase(WRITE_PHASE); ++ // subclasses continue by writing their contents to output ++ writeDataTo(out); ++ doneWriting(); ++ } + +- abstract void chooseBandCodings() throws IOException; ++ abstract void chooseBandCodings() throws IOException; + +- public final long outputSize() { +- if (outputSize >= 0) { +- long size = outputSize; +- assert(size == computeOutputSize()); +- return size; +- } +- return computeOutputSize(); +- } ++ public final long outputSize() { ++ if (outputSize >= 0) { ++ long size = outputSize; ++ assert(size == computeOutputSize()); ++ return size; ++ } ++ return computeOutputSize(); ++ } + +- protected abstract long computeOutputSize(); ++ protected abstract long computeOutputSize(); + +- abstract protected void writeDataTo(OutputStream out) throws IOException; ++ abstract protected void writeDataTo(OutputStream out) throws IOException; + +- /** Expect a certain number of values. */ +- void expectLength(int l) { +- assert(assertPhase(this, EXPECT_PHASE)); +- assert(valuesExpected == 0); // all at once +- assert(l >= 0); +- valuesExpected = l; +- } +- /** Expect more values. (Multiple calls accumulate.) */ +- void expectMoreLength(int l) { +- assert(assertPhase(this, EXPECT_PHASE)); +- valuesExpected += l; +- } ++ /** Expect a certain number of values. */ ++ void expectLength(int l) { ++ assert(assertPhase(this, EXPECT_PHASE)); ++ assert(valuesExpected == 0); // all at once ++ assert(l >= 0); ++ valuesExpected = l; ++ } ++ /** Expect more values. (Multiple calls accumulate.) */ ++ void expectMoreLength(int l) { ++ assert(assertPhase(this, EXPECT_PHASE)); ++ valuesExpected += l; ++ } + + +- /// Phase change markers. ++ /// Phase change markers. + +- private void readyToCollect() { // called implicitly by constructor +- setCapacity(1); +- setPhase(COLLECT_PHASE); +- } +- protected void doneWriting() { +- assert(assertPhase(this, WRITE_PHASE)); +- setPhase(DONE_PHASE); +- } +- private void readyToExpect() { // called implicitly by constructor +- setPhase(EXPECT_PHASE); +- } +- /** Read in bytes, decoding the values. */ +- public final void readFrom(InputStream in) throws IOException { +- assert(assertReadyToReadFrom(this, in)); +- setCapacity(valuesExpected()); +- setPhase(READ_PHASE); +- // subclasses continue by reading their contents from input: +- readDataFrom(in); +- readyToDisburse(); +- } +- abstract protected void readDataFrom(InputStream in) throws IOException; +- protected void readyToDisburse() { +- if (verbose > 1) Utils.log.fine("readyToDisburse "+this); +- setPhase(DISBURSE_PHASE); +- } +- public void doneDisbursing() { +- assert(assertPhase(this, DISBURSE_PHASE)); +- setPhase(DONE_PHASE); +- } +- public final void doneWithUnusedBand() { +- if (isReader) { +- assert(assertPhase(this, EXPECT_PHASE)); +- assert(valuesExpected() == 0); +- // Fast forward: +- setPhase(READ_PHASE); +- setPhase(DISBURSE_PHASE); +- setPhase(DONE_PHASE); +- } else { +- setPhase(FROZEN_PHASE); +- } +- } ++ private void readyToCollect() { // called implicitly by constructor ++ setCapacity(1); ++ setPhase(COLLECT_PHASE); ++ } ++ protected void doneWriting() { ++ assert(assertPhase(this, WRITE_PHASE)); ++ setPhase(DONE_PHASE); ++ } ++ private void readyToExpect() { // called implicitly by constructor ++ setPhase(EXPECT_PHASE); ++ } ++ /** Read in bytes, decoding the values. */ ++ public final void readFrom(InputStream in) throws IOException { ++ assert(assertReadyToReadFrom(this, in)); ++ setCapacity(valuesExpected()); ++ setPhase(READ_PHASE); ++ // subclasses continue by reading their contents from input: ++ readDataFrom(in); ++ readyToDisburse(); ++ } ++ abstract protected void readDataFrom(InputStream in) throws IOException; ++ protected void readyToDisburse() { ++ if (verbose > 1) Utils.log.fine("readyToDisburse "+this); ++ setPhase(DISBURSE_PHASE); ++ } ++ public void doneDisbursing() { ++ assert(assertPhase(this, DISBURSE_PHASE)); ++ setPhase(DONE_PHASE); ++ } ++ public final void doneWithUnusedBand() { ++ if (isReader) { ++ assert(assertPhase(this, EXPECT_PHASE)); ++ assert(valuesExpected() == 0); ++ // Fast forward: ++ setPhase(READ_PHASE); ++ setPhase(DISBURSE_PHASE); ++ setPhase(DONE_PHASE); ++ } else { ++ setPhase(FROZEN_PHASE); ++ } ++ } + +- protected void setPhase(int newPhase) { +- assert(assertPhaseChangeOK(this, phase, newPhase)); +- this.phase = newPhase; +- } ++ protected void setPhase(int newPhase) { ++ assert(assertPhaseChangeOK(this, phase, newPhase)); ++ this.phase = newPhase; ++ } + +- protected int lengthForDebug = -1; // DEBUG ONLY +- public String toString() { // DEBUG ONLY +- int length = (lengthForDebug != -1 ? lengthForDebug : length()); +- String str = name; +- if (length != 0) +- str += "[" + length + "]"; +- if (elementCountForDebug != 0) +- str += "(" + elementCountForDebug + ")"; +- return str; +- } ++ protected int lengthForDebug = -1; // DEBUG ONLY ++ public String toString() { // DEBUG ONLY ++ int length = (lengthForDebug != -1 ? lengthForDebug : length()); ++ String str = name; ++ if (length != 0) ++ str += "[" + length + "]"; ++ if (elementCountForDebug != 0) ++ str += "(" + elementCountForDebug + ")"; ++ return str; ++ } + } + + class ValueBand extends Band { +- private int[] values; // must be null in EXPECT phase +- private int length; +- private int valuesDisbursed; ++ private int[] values; // must be null in EXPECT phase ++ private int length; ++ private int valuesDisbursed; + +- private CodingMethod bandCoding; +- private byte[] metaCoding; ++ private CodingMethod bandCoding; ++ private byte[] metaCoding; + +- protected ValueBand(String name, Coding regularCoding) { +- super(name, regularCoding); +- } ++ protected ValueBand(String name, Coding regularCoding) { ++ super(name, regularCoding); ++ } + +- public int capacity() { +- return values == null ? -1 : values.length; +- } ++ public int capacity() { ++ return values == null ? -1 : values.length; ++ } + +- /** Declare predicted or needed capacity. */ +- protected void setCapacity(int cap) { +- assert(length <= cap); +- if (cap == -1) { values = null; return; } +- values = realloc(values, cap); +- } ++ /** Declare predicted or needed capacity. */ ++ protected void setCapacity(int cap) { ++ assert(length <= cap); ++ if (cap == -1) { values = null; return; } ++ values = realloc(values, cap); ++ } + +- public int length() { +- return length; +- } +- protected int valuesRemainingForDebug() { +- return length - valuesDisbursed; +- } +- protected int valueAtForDebug(int i) { +- return values[i]; +- } ++ public int length() { ++ return length; ++ } ++ protected int valuesRemainingForDebug() { ++ return length - valuesDisbursed; ++ } ++ protected int valueAtForDebug(int i) { ++ return values[i]; ++ } + +- void patchValue(int i, int value) { +- // Only one use for this. +- assert(this == archive_header_S); +- assert(i == AH_ARCHIVE_SIZE_HI || i == AH_ARCHIVE_SIZE_LO); +- assert(i < length); // must have already output a dummy +- values[i] = value; +- outputSize = -1; // decache +- } ++ void patchValue(int i, int value) { ++ // Only one use for this. ++ assert(this == archive_header_S); ++ assert(i == AH_ARCHIVE_SIZE_HI || i == AH_ARCHIVE_SIZE_LO); ++ assert(i < length); // must have already output a dummy ++ values[i] = value; ++ outputSize = -1; // decache ++ } + +- protected void initializeValues(int[] values) { +- assert(assertCanChangeLength(this)); +- assert(length == 0); +- this.values = values; +- this.length = values.length; +- } ++ protected void initializeValues(int[] values) { ++ assert(assertCanChangeLength(this)); ++ assert(length == 0); ++ this.values = values; ++ this.length = values.length; ++ } + +- /** Collect one value, or store one decoded value. */ +- protected void addValue(int x) { +- assert(assertCanChangeLength(this)); +- if (length == values.length) +- setCapacity(length < 1000 ? length * 10 : length * 2); +- values[length++] = x; +- } ++ /** Collect one value, or store one decoded value. */ ++ protected void addValue(int x) { ++ assert(assertCanChangeLength(this)); ++ if (length == values.length) ++ setCapacity(length < 1000 ? length * 10 : length * 2); ++ values[length++] = x; ++ } + +- private boolean canVaryCoding() { +- if (!optVaryCodings) return false; +- if (length == 0) return false; +- // Can't read band_headers w/o the archive header: +- if (this == archive_header_0) return false; +- if (this == archive_header_S) return false; +- if (this == archive_header_1) return false; +- // BYTE1 bands can't vary codings, but the others can. +- // All that's needed for the initial escape is at least +- // 256 negative values or more than 256 non-negative values +- return (regularCoding.min() <= -256 || regularCoding.max() >= 256); +- } ++ private boolean canVaryCoding() { ++ if (!optVaryCodings) return false; ++ if (length == 0) return false; ++ // Can't read band_headers w/o the archive header: ++ if (this == archive_header_0) return false; ++ if (this == archive_header_S) return false; ++ if (this == archive_header_1) return false; ++ // BYTE1 bands can't vary codings, but the others can. ++ // All that's needed for the initial escape is at least ++ // 256 negative values or more than 256 non-negative values ++ return (regularCoding.min() <= -256 || regularCoding.max() >= 256); ++ } + +- private boolean shouldVaryCoding() { +- assert(canVaryCoding()); +- if (effort < MAX_EFFORT && length < SHORT_BAND_HEURISTIC) +- return false; +- return true; +- } ++ private boolean shouldVaryCoding() { ++ assert(canVaryCoding()); ++ if (effort < MAX_EFFORT && length < SHORT_BAND_HEURISTIC) ++ return false; ++ return true; ++ } + +- protected void chooseBandCodings() throws IOException { +- boolean canVary = canVaryCoding(); +- if (!canVary || !shouldVaryCoding()) { +- if (regularCoding.canRepresent(values, 0, length)) { +- bandCoding = regularCoding; +- } else { +- assert(canVary); +- if (verbose > 1) +- Utils.log.fine("regular coding fails in band "+name()); +- bandCoding = UNSIGNED5; +- } +- outputSize = -1; +- } else { +- int[] sizes = {0,0}; +- bandCoding = chooseCoding(values, 0, length, +- regularCoding, name(), +- sizes); +- outputSize = sizes[CodingChooser.BYTE_SIZE]; +- if (outputSize == 0) // CodingChooser failed to size it. +- outputSize = -1; +- } ++ protected void chooseBandCodings() throws IOException { ++ boolean canVary = canVaryCoding(); ++ if (!canVary || !shouldVaryCoding()) { ++ if (regularCoding.canRepresent(values, 0, length)) { ++ bandCoding = regularCoding; ++ } else { ++ assert(canVary); ++ if (verbose > 1) ++ Utils.log.fine("regular coding fails in band "+name()); ++ bandCoding = UNSIGNED5; ++ } ++ outputSize = -1; ++ } else { ++ int[] sizes = {0,0}; ++ bandCoding = chooseCoding(values, 0, length, ++ regularCoding, name(), ++ sizes); ++ outputSize = sizes[CodingChooser.BYTE_SIZE]; ++ if (outputSize == 0) // CodingChooser failed to size it. ++ outputSize = -1; ++ } + +- // Compute and save the meta-coding bytes also. +- if (bandCoding != regularCoding) { +- metaCoding = bandCoding.getMetaCoding(regularCoding); +- if (verbose > 1) { +- Utils.log.fine("alternate coding "+this+" "+bandCoding); +- } +- } else if (canVary && +- decodeEscapeValue(values[0], regularCoding) >= 0) { +- // Need an explicit default. +- metaCoding = defaultMetaCoding; +- } else { +- // Common case: Zero bytes of meta coding. +- metaCoding = noMetaCoding; +- } +- if (metaCoding.length > 0 +- && (verbose > 2 || verbose > 1 && metaCoding.length > 1)) { +- StringBuffer sb = new StringBuffer(); +- for (int i = 0; i < metaCoding.length; i++) { +- if (i == 1) sb.append(" /"); +- sb.append(" ").append(metaCoding[i] & 0xFF); +- } +- Utils.log.fine(" meta-coding "+sb); +- } ++ // Compute and save the meta-coding bytes also. ++ if (bandCoding != regularCoding) { ++ metaCoding = bandCoding.getMetaCoding(regularCoding); ++ if (verbose > 1) { ++ Utils.log.fine("alternate coding "+this+" "+bandCoding); ++ } ++ } else if (canVary && ++ decodeEscapeValue(values[0], regularCoding) >= 0) { ++ // Need an explicit default. ++ metaCoding = defaultMetaCoding; ++ } else { ++ // Common case: Zero bytes of meta coding. ++ metaCoding = noMetaCoding; ++ } ++ if (metaCoding.length > 0 ++ && (verbose > 2 || verbose > 1 && metaCoding.length > 1)) { ++ StringBuffer sb = new StringBuffer(); ++ for (int i = 0; i < metaCoding.length; i++) { ++ if (i == 1) sb.append(" /"); ++ sb.append(" ").append(metaCoding[i] & 0xFF); ++ } ++ Utils.log.fine(" meta-coding "+sb); ++ } + +- assert((outputSize < 0) || +- !(bandCoding instanceof Coding) || +- (outputSize == ((Coding)bandCoding) +- .getLength(values, 0, length))) +- : (bandCoding+" : "+ +- outputSize+" != "+ +- ((Coding)bandCoding).getLength(values, 0, length) +- +" ?= "+getCodingChooser().computeByteSize(bandCoding,values,0,length) +- ); ++ assert((outputSize < 0) || ++ !(bandCoding instanceof Coding) || ++ (outputSize == ((Coding)bandCoding) ++ .getLength(values, 0, length))) ++ : (bandCoding+" : "+ ++ outputSize+" != "+ ++ ((Coding)bandCoding).getLength(values, 0, length) ++ +" ?= "+getCodingChooser().computeByteSize(bandCoding,values,0,length) ++ ); + +- // Compute outputSize of the escape value X, if any. +- if (metaCoding.length > 0) { +- // First byte XB of meta-coding is treated specially, +- // but any other bytes go into the band headers band. +- // This must be done before any other output happens. +- if (outputSize >= 0) +- outputSize += computeEscapeSize(); // good cache +- // Other bytes go into band_headers. +- for (int i = 1; i < metaCoding.length; i++) { +- band_headers.putByte(metaCoding[i] & 0xFF); +- } +- } +- } ++ // Compute outputSize of the escape value X, if any. ++ if (metaCoding.length > 0) { ++ // First byte XB of meta-coding is treated specially, ++ // but any other bytes go into the band headers band. ++ // This must be done before any other output happens. ++ if (outputSize >= 0) ++ outputSize += computeEscapeSize(); // good cache ++ // Other bytes go into band_headers. ++ for (int i = 1; i < metaCoding.length; i++) { ++ band_headers.putByte(metaCoding[i] & 0xFF); ++ } ++ } ++ } + +- protected long computeOutputSize() { +- outputSize = getCodingChooser().computeByteSize(bandCoding, +- values, 0, length); +- assert(outputSize < Integer.MAX_VALUE); +- outputSize += computeEscapeSize(); +- return outputSize; +- } ++ protected long computeOutputSize() { ++ outputSize = getCodingChooser().computeByteSize(bandCoding, ++ values, 0, length); ++ assert(outputSize < Integer.MAX_VALUE); ++ outputSize += computeEscapeSize(); ++ return outputSize; ++ } + +- protected int computeEscapeSize() { +- if (metaCoding.length == 0) return 0; +- int XB = metaCoding[0] & 0xFF; +- int X = encodeEscapeValue(XB, regularCoding); +- return regularCoding.setD(0).getLength(X); +- } ++ protected int computeEscapeSize() { ++ if (metaCoding.length == 0) return 0; ++ int XB = metaCoding[0] & 0xFF; ++ int X = encodeEscapeValue(XB, regularCoding); ++ return regularCoding.setD(0).getLength(X); ++ } + +- protected void writeDataTo(OutputStream out) throws IOException { +- if (length == 0) return; // nothing to write +- long len0 = 0; +- if (out == outputCounter) { +- len0 = outputCounter.getCount(); +- } +- if (metaCoding.length > 0) { +- int XB = metaCoding[0] & 0xFF; +- // We need an explicit band header, either because +- // there is a non-default coding method, or because +- // the first value would be parsed as an escape value. +- int X = encodeEscapeValue(XB, regularCoding); +- //System.out.println("X="+X+" XB="+XB+" in "+this); +- regularCoding.setD(0).writeTo(out, X); +- } +- bandCoding.writeArrayTo(out, values, 0, length); +- if (out == outputCounter) { +- long len1 = outputCounter.getCount(); +- assert(outputSize == outputCounter.getCount() - len0) +- : (outputSize+" != "+outputCounter.getCount()+"-"+len0); +- } +- if (optDumpBands) dumpBand(); +- } ++ protected void writeDataTo(OutputStream out) throws IOException { ++ if (length == 0) return; // nothing to write ++ long len0 = 0; ++ if (out == outputCounter) { ++ len0 = outputCounter.getCount(); ++ } ++ if (metaCoding.length > 0) { ++ int XB = metaCoding[0] & 0xFF; ++ // We need an explicit band header, either because ++ // there is a non-default coding method, or because ++ // the first value would be parsed as an escape value. ++ int X = encodeEscapeValue(XB, regularCoding); ++ //System.out.println("X="+X+" XB="+XB+" in "+this); ++ regularCoding.setD(0).writeTo(out, X); ++ } ++ bandCoding.writeArrayTo(out, values, 0, length); ++ if (out == outputCounter) { ++ long len1 = outputCounter.getCount(); ++ assert(outputSize == outputCounter.getCount() - len0) ++ : (outputSize+" != "+outputCounter.getCount()+"-"+len0); ++ } ++ if (optDumpBands) dumpBand(); ++ } + +- protected void readDataFrom(InputStream in) throws IOException { +- length = valuesExpected(); +- if (length == 0) return; // nothing to read +- if (verbose > 1) +- Utils.log.fine("Reading band "+this); +- if (!canVaryCoding()) { +- bandCoding = regularCoding; +- metaCoding = noMetaCoding; +- } else { +- assert(in.markSupported()); // input must be buffered +- in.mark(Coding.B_MAX); +- int X = regularCoding.setD(0).readFrom(in); +- int XB = decodeEscapeValue(X, regularCoding); +- if (XB < 0) { +- // Do not consume this value. No alternate coding. +- in.reset(); +- XB = _meta_default; +- bandCoding = regularCoding; +- metaCoding = noMetaCoding; +- } else if (XB == _meta_default) { +- bandCoding = regularCoding; +- metaCoding = defaultMetaCoding; +- } else { +- if (verbose > 2) +- Utils.log.fine("found X="+X+" => XB="+XB); +- bandCoding = getBandHeader(XB, regularCoding); +- // This is really used only by dumpBands. +- int p0 = bandHeaderBytePos0; +- int p1 = bandHeaderBytePos; +- metaCoding = new byte[p1-p0]; +- System.arraycopy(bandHeaderBytes, p0, +- metaCoding, 0, metaCoding.length); +- } +- } +- if (bandCoding != regularCoding) { +- if (verbose > 1) +- Utils.log.fine(name()+": irregular coding "+bandCoding); +- } +- bandCoding.readArrayFrom(in, values, 0, length); +- if (optDumpBands) dumpBand(); +- } ++ protected void readDataFrom(InputStream in) throws IOException { ++ length = valuesExpected(); ++ if (length == 0) return; // nothing to read ++ if (verbose > 1) ++ Utils.log.fine("Reading band "+this); ++ if (!canVaryCoding()) { ++ bandCoding = regularCoding; ++ metaCoding = noMetaCoding; ++ } else { ++ assert(in.markSupported()); // input must be buffered ++ in.mark(Coding.B_MAX); ++ int X = regularCoding.setD(0).readFrom(in); ++ int XB = decodeEscapeValue(X, regularCoding); ++ if (XB < 0) { ++ // Do not consume this value. No alternate coding. ++ in.reset(); ++ XB = _meta_default; ++ bandCoding = regularCoding; ++ metaCoding = noMetaCoding; ++ } else if (XB == _meta_default) { ++ bandCoding = regularCoding; ++ metaCoding = defaultMetaCoding; ++ } else { ++ if (verbose > 2) ++ Utils.log.fine("found X="+X+" => XB="+XB); ++ bandCoding = getBandHeader(XB, regularCoding); ++ // This is really used only by dumpBands. ++ int p0 = bandHeaderBytePos0; ++ int p1 = bandHeaderBytePos; ++ metaCoding = new byte[p1-p0]; ++ System.arraycopy(bandHeaderBytes, p0, ++ metaCoding, 0, metaCoding.length); ++ } ++ } ++ if (bandCoding != regularCoding) { ++ if (verbose > 1) ++ Utils.log.fine(name()+": irregular coding "+bandCoding); ++ } ++ bandCoding.readArrayFrom(in, values, 0, length); ++ if (optDumpBands) dumpBand(); ++ } + +- public void doneDisbursing() { +- super.doneDisbursing(); +- values = null; // for GC +- } ++ public void doneDisbursing() { ++ super.doneDisbursing(); ++ values = null; // for GC ++ } + +- private void dumpBand() throws IOException { +- assert(optDumpBands); +- PrintStream ps = new PrintStream(getDumpStream(this, ".txt")); +- String irr = (bandCoding == regularCoding) ? "" : " irregular"; +- ps.print("# length="+length+ +- " size="+outputSize()+ +- irr+" coding="+bandCoding); +- if (metaCoding != noMetaCoding) { +- StringBuffer sb = new StringBuffer(); +- for (int i = 0; i < metaCoding.length; i++) { +- if (i == 1) sb.append(" /"); +- sb.append(" ").append(metaCoding[i] & 0xFF); +- } +- ps.print(" //header: "+sb); +- } +- printArrayTo(ps, values, 0, length); +- ps.close(); +- OutputStream ds = getDumpStream(this, ".bnd"); +- bandCoding.writeArrayTo(ds, values, 0, length); +- ds.close(); +- } ++ private void dumpBand() throws IOException { ++ assert(optDumpBands); ++ PrintStream ps = new PrintStream(getDumpStream(this, ".txt")); ++ String irr = (bandCoding == regularCoding) ? "" : " irregular"; ++ ps.print("# length="+length+ ++ " size="+outputSize()+ ++ irr+" coding="+bandCoding); ++ if (metaCoding != noMetaCoding) { ++ StringBuffer sb = new StringBuffer(); ++ for (int i = 0; i < metaCoding.length; i++) { ++ if (i == 1) sb.append(" /"); ++ sb.append(" ").append(metaCoding[i] & 0xFF); ++ } ++ ps.print(" //header: "+sb); ++ } ++ printArrayTo(ps, values, 0, length); ++ ps.close(); ++ OutputStream ds = getDumpStream(this, ".bnd"); ++ bandCoding.writeArrayTo(ds, values, 0, length); ++ ds.close(); ++ } + +- /** Disburse one value. */ +- protected int getValue() { +- assert(phase() == DISBURSE_PHASE); +- assert(valuesDisbursed < length); +- return values[valuesDisbursed++]; +- } ++ /** Disburse one value. */ ++ protected int getValue() { ++ assert(phase() == DISBURSE_PHASE); ++ assert(valuesDisbursed < length); ++ return values[valuesDisbursed++]; ++ } + +- /** Reset for another pass over the same value set. */ +- public void resetForSecondPass() { +- assert(phase() == DISBURSE_PHASE); +- assert(valuesDisbursed == length()); // 1st pass is complete +- valuesDisbursed = 0; +- } ++ /** Reset for another pass over the same value set. */ ++ public void resetForSecondPass() { ++ assert(phase() == DISBURSE_PHASE); ++ assert(valuesDisbursed == length()); // 1st pass is complete ++ valuesDisbursed = 0; ++ } + } + + class ByteBand extends Band { +- private ByteArrayOutputStream bytes; // input buffer +- private ByteArrayOutputStream bytesForDump; +- private InputStream in; ++ private ByteArrayOutputStream bytes; // input buffer ++ private ByteArrayOutputStream bytesForDump; ++ private InputStream in; + +- public ByteBand(String name) { +- super(name, BYTE1); +- } ++ public ByteBand(String name) { ++ super(name, BYTE1); ++ } + +- public int capacity() { +- return bytes == null ? -1 : Integer.MAX_VALUE; +- } +- protected void setCapacity(int cap) { +- assert(bytes == null); // do this just once +- bytes = new ByteArrayOutputStream(cap); +- } +- public void destroy() { +- lengthForDebug = length(); +- bytes = null; +- } ++ public int capacity() { ++ return bytes == null ? -1 : Integer.MAX_VALUE; ++ } ++ protected void setCapacity(int cap) { ++ assert(bytes == null); // do this just once ++ bytes = new ByteArrayOutputStream(cap); ++ } ++ public void destroy() { ++ lengthForDebug = length(); ++ bytes = null; ++ } + +- public int length() { +- return bytes == null ? -1 : bytes.size(); +- } +- public void reset() { +- bytes.reset(); +- } +- protected int valuesRemainingForDebug() { +- return (bytes == null) ? -1 : ((ByteArrayInputStream)in).available(); +- } ++ public int length() { ++ return bytes == null ? -1 : bytes.size(); ++ } ++ public void reset() { ++ bytes.reset(); ++ } ++ protected int valuesRemainingForDebug() { ++ return (bytes == null) ? -1 : ((ByteArrayInputStream)in).available(); ++ } + +- protected void chooseBandCodings() throws IOException { +- // No-op. +- assert(decodeEscapeValue(regularCoding.min(), regularCoding) < 0); +- assert(decodeEscapeValue(regularCoding.max(), regularCoding) < 0); +- } ++ protected void chooseBandCodings() throws IOException { ++ // No-op. ++ assert(decodeEscapeValue(regularCoding.min(), regularCoding) < 0); ++ assert(decodeEscapeValue(regularCoding.max(), regularCoding) < 0); ++ } + +- protected long computeOutputSize() { +- // do not cache +- return bytes.size(); +- } ++ protected long computeOutputSize() { ++ // do not cache ++ return bytes.size(); ++ } + +- public void writeDataTo(OutputStream out) throws IOException { +- if (length() == 0) return; +- bytes.writeTo(out); +- if (optDumpBands) dumpBand(); +- destroy(); // done with the bits! +- } ++ public void writeDataTo(OutputStream out) throws IOException { ++ if (length() == 0) return; ++ bytes.writeTo(out); ++ if (optDumpBands) dumpBand(); ++ destroy(); // done with the bits! ++ } + +- private void dumpBand() throws IOException { +- assert(optDumpBands); +- OutputStream ds = getDumpStream(this, ".bnd"); +- if (bytesForDump != null) +- bytesForDump.writeTo(ds); +- else +- bytes.writeTo(ds); +- ds.close(); +- } ++ private void dumpBand() throws IOException { ++ assert(optDumpBands); ++ OutputStream ds = getDumpStream(this, ".bnd"); ++ if (bytesForDump != null) ++ bytesForDump.writeTo(ds); ++ else ++ bytes.writeTo(ds); ++ ds.close(); ++ } + +- public void readDataFrom(InputStream in) throws IOException { +- int vex = valuesExpected(); +- if (vex == 0) return; +- if (verbose > 1) { +- lengthForDebug = vex; +- Utils.log.fine("Reading band "+this); +- lengthForDebug = -1; +- } +- byte[] buf = new byte[Math.min(vex, 1<<14)]; +- while (vex > 0) { +- int nr = in.read(buf, 0, Math.min(vex, buf.length)); +- if (nr < 0) throw new EOFException(); +- bytes.write(buf, 0, nr); +- vex -= nr; +- } +- if (optDumpBands) dumpBand(); +- } ++ public void readDataFrom(InputStream in) throws IOException { ++ int vex = valuesExpected(); ++ if (vex == 0) return; ++ if (verbose > 1) { ++ lengthForDebug = vex; ++ Utils.log.fine("Reading band "+this); ++ lengthForDebug = -1; ++ } ++ byte[] buf = new byte[Math.min(vex, 1<<14)]; ++ while (vex > 0) { ++ int nr = in.read(buf, 0, Math.min(vex, buf.length)); ++ if (nr < 0) throw new EOFException(); ++ bytes.write(buf, 0, nr); ++ vex -= nr; ++ } ++ if (optDumpBands) dumpBand(); ++ } + +- public void readyToDisburse() { +- in = new ByteArrayInputStream(bytes.toByteArray()); +- super.readyToDisburse(); +- } ++ public void readyToDisburse() { ++ in = new ByteArrayInputStream(bytes.toByteArray()); ++ super.readyToDisburse(); ++ } + +- public void doneDisbursing() { +- super.doneDisbursing(); +- if (optDumpBands +- && bytesForDump != null && bytesForDump.size() > 0) { +- try { +- dumpBand(); +- } catch (IOException ee) { +- throw new RuntimeException(ee); +- } +- } +- in = null; // GC +- bytes = null; // GC +- bytesForDump = null; // GC +- } ++ public void doneDisbursing() { ++ super.doneDisbursing(); ++ if (optDumpBands ++ && bytesForDump != null && bytesForDump.size() > 0) { ++ try { ++ dumpBand(); ++ } catch (IOException ee) { ++ throw new RuntimeException(ee); ++ } ++ } ++ in = null; // GC ++ bytes = null; // GC ++ bytesForDump = null; // GC ++ } + +- // alternative to readFrom: +- public void setInputStreamFrom(InputStream in) throws IOException { +- assert(bytes == null); +- assert(assertReadyToReadFrom(this, in)); +- setPhase(READ_PHASE); +- this.in = in; +- if (optDumpBands) { +- // Tap the stream. +- bytesForDump = new ByteArrayOutputStream(); +- this.in = new FilterInputStream(in) { +- public int read() throws IOException { +- int ch = in.read(); +- if (ch >= 0) bytesForDump.write(ch); +- return ch; +- } +- public int read(byte b[], int off, int len) throws IOException { +- int nr = in.read(b, off, len); +- if (nr >= 0) bytesForDump.write(b, off, nr); +- return nr; +- } +- }; +- } +- super.readyToDisburse(); +- } ++ // alternative to readFrom: ++ public void setInputStreamFrom(InputStream in) throws IOException { ++ assert(bytes == null); ++ assert(assertReadyToReadFrom(this, in)); ++ setPhase(READ_PHASE); ++ this.in = in; ++ if (optDumpBands) { ++ // Tap the stream. ++ bytesForDump = new ByteArrayOutputStream(); ++ this.in = new FilterInputStream(in) { ++ public int read() throws IOException { ++ int ch = in.read(); ++ if (ch >= 0) bytesForDump.write(ch); ++ return ch; ++ } ++ public int read(byte b[], int off, int len) throws IOException { ++ int nr = in.read(b, off, len); ++ if (nr >= 0) bytesForDump.write(b, off, nr); ++ return nr; ++ } ++ }; ++ } ++ super.readyToDisburse(); ++ } + +- public OutputStream collectorStream() { +- assert(phase() == COLLECT_PHASE); +- assert(bytes != null); +- return bytes; +- } ++ public OutputStream collectorStream() { ++ assert(phase() == COLLECT_PHASE); ++ assert(bytes != null); ++ return bytes; ++ } + +- public InputStream getInputStream() { +- assert(phase() == DISBURSE_PHASE); +- assert(in != null); +- return in; +- } +- public int getByte() throws IOException { +- int b = getInputStream().read(); +- if (b < 0) throw new EOFException(); +- return b; +- } +- public void putByte(int b) throws IOException { +- assert(b == (b & 0xFF)); +- collectorStream().write(b); +- } +- public String toString() { +- return "byte "+super.toString(); +- } ++ public InputStream getInputStream() { ++ assert(phase() == DISBURSE_PHASE); ++ assert(in != null); ++ return in; ++ } ++ public int getByte() throws IOException { ++ int b = getInputStream().read(); ++ if (b < 0) throw new EOFException(); ++ return b; ++ } ++ public void putByte(int b) throws IOException { ++ assert(b == (b & 0xFF)); ++ collectorStream().write(b); ++ } ++ public String toString() { ++ return "byte "+super.toString(); ++ } + } + + class IntBand extends ValueBand { +- // The usual coding for bands is 7bit/5byte/delta. +- public IntBand(String name, Coding regularCoding) { +- super(name, regularCoding); +- } ++ // The usual coding for bands is 7bit/5byte/delta. ++ public IntBand(String name, Coding regularCoding) { ++ super(name, regularCoding); ++ } + +- public void putInt(int x) { +- assert(phase() == COLLECT_PHASE); +- addValue(x); +- } ++ public void putInt(int x) { ++ assert(phase() == COLLECT_PHASE); ++ addValue(x); ++ } + +- public int getInt() { +- return getValue(); +- } +- /** Return the sum of all values in this band. */ +- public int getIntTotal() { +- assert(phase() == DISBURSE_PHASE); +- // assert that this is the whole pass; no other reads allowed +- assert(valuesRemainingForDebug() == length()); +- int total = 0; +- for (int k = length(); k > 0; k--) { +- total += getInt(); +- } +- resetForSecondPass(); +- return total; +- } +- /** Return the occurrence count of a specific value in this band. */ +- public int getIntCount(int value) { +- assert(phase() == DISBURSE_PHASE); +- // assert that this is the whole pass; no other reads allowed +- assert(valuesRemainingForDebug() == length()); +- int total = 0; +- for (int k = length(); k > 0; k--) { +- if (getInt() == value) { +- total += 1; +- } +- } +- resetForSecondPass(); +- return total; +- } ++ public int getInt() { ++ return getValue(); ++ } ++ /** Return the sum of all values in this band. */ ++ public int getIntTotal() { ++ assert(phase() == DISBURSE_PHASE); ++ // assert that this is the whole pass; no other reads allowed ++ assert(valuesRemainingForDebug() == length()); ++ int total = 0; ++ for (int k = length(); k > 0; k--) { ++ total += getInt(); ++ } ++ resetForSecondPass(); ++ return total; ++ } ++ /** Return the occurrence count of a specific value in this band. */ ++ public int getIntCount(int value) { ++ assert(phase() == DISBURSE_PHASE); ++ // assert that this is the whole pass; no other reads allowed ++ assert(valuesRemainingForDebug() == length()); ++ int total = 0; ++ for (int k = length(); k > 0; k--) { ++ if (getInt() == value) { ++ total += 1; ++ } ++ } ++ resetForSecondPass(); ++ return total; ++ } + } + + static int getIntTotal(int[] values) { +- int total = 0; +- for (int i = 0; i < values.length; i++) { +- total += values[i]; +- } +- return total; ++ int total = 0; ++ for (int i = 0; i < values.length; i++) { ++ total += values[i]; ++ } ++ return total; + } + + class CPRefBand extends ValueBand { +- Index index; +- boolean nullOK; ++ Index index; ++ boolean nullOK; + +- public CPRefBand(String name, Coding regularCoding, byte cpTag, boolean nullOK) { +- super(name, regularCoding); +- this.nullOK = nullOK; +- if (cpTag != CONSTANT_None) +- setBandIndex(this, cpTag); +- } +- public CPRefBand(String name, Coding regularCoding, byte cpTag) { +- this(name, regularCoding, cpTag, false); +- } +- public CPRefBand(String name, Coding regularCoding, Object undef) { +- this(name, regularCoding, CONSTANT_None, false); +- } ++ public CPRefBand(String name, Coding regularCoding, byte cpTag, boolean nullOK) { ++ super(name, regularCoding); ++ this.nullOK = nullOK; ++ if (cpTag != CONSTANT_None) ++ setBandIndex(this, cpTag); ++ } ++ public CPRefBand(String name, Coding regularCoding, byte cpTag) { ++ this(name, regularCoding, cpTag, false); ++ } ++ public CPRefBand(String name, Coding regularCoding, Object undef) { ++ this(name, regularCoding, CONSTANT_None, false); ++ } + +- public void setIndex(Index index) { +- this.index = index; +- } ++ public void setIndex(Index index) { ++ this.index = index; ++ } + +- protected void readDataFrom(InputStream in) throws IOException { +- super.readDataFrom(in); +- assert(assertValidCPRefs(this)); +- } ++ protected void readDataFrom(InputStream in) throws IOException { ++ super.readDataFrom(in); ++ assert(assertValidCPRefs(this)); ++ } + +- /** Write a constant pool reference. */ +- public void putRef(Entry e) { +- assert(index != null); +- addValue(encodeRefOrNull(e, index)); +- } +- public void putRef(Entry e, Index index) { +- assert(this.index == null); +- addValue(encodeRefOrNull(e, index)); +- } +- public void putRef(Entry e, byte cptag) { +- putRef(e, getCPIndex(cptag)); +- } ++ /** Write a constant pool reference. */ ++ public void putRef(Entry e) { ++ addValue(encodeRefOrNull(e, index)); ++ } ++ public void putRef(Entry e, Index index) { ++ assert(this.index == null); ++ addValue(encodeRefOrNull(e, index)); ++ } ++ public void putRef(Entry e, byte cptag) { ++ putRef(e, getCPIndex(cptag)); ++ } + +- public Entry getRef() { +- if (index == null) Utils.log.warning("No index for "+this); +- assert(index != null); +- return decodeRefOrNull(getValue(), index); +- } +- public Entry getRef(Index index) { +- assert(this.index == null); +- return decodeRefOrNull(getValue(), index); +- } +- public Entry getRef(byte cptag) { +- return getRef(getCPIndex(cptag)); +- } ++ public Entry getRef() { ++ if (index == null) Utils.log.warning("No index for "+this); ++ assert(index != null); ++ return decodeRefOrNull(getValue(), index); ++ } ++ public Entry getRef(Index index) { ++ assert(this.index == null); ++ return decodeRefOrNull(getValue(), index); ++ } ++ public Entry getRef(byte cptag) { ++ return getRef(getCPIndex(cptag)); ++ } + +- private int encodeRefOrNull(Entry e, Index index) { +- int nonNullCode; // NNC is the coding which assumes nulls are rare +- if (e == null) { +- nonNullCode = -1; // negative values are rare +- } else { +- nonNullCode = encodeRef(e, index); +- } +- // If nulls are expected, increment, to make -1 code turn to 0. +- return (nullOK ? 1 : 0) + nonNullCode; +- } +- private Entry decodeRefOrNull(int code, Index index) { +- // Inverse to encodeRefOrNull... +- int nonNullCode = code - (nullOK ? 1 : 0); +- if (nonNullCode == -1) { +- return null; +- } else { +- return decodeRef(nonNullCode, index); +- } +- } ++ private int encodeRefOrNull(Entry e, Index index) { ++ int nonNullCode; // NNC is the coding which assumes nulls are rare ++ if (e == null) { ++ nonNullCode = -1; // negative values are rare ++ } else { ++ nonNullCode = encodeRef(e, index); ++ } ++ // If nulls are expected, increment, to make -1 code turn to 0. ++ return (nullOK ? 1 : 0) + nonNullCode; ++ } ++ private Entry decodeRefOrNull(int code, Index index) { ++ // Inverse to encodeRefOrNull... ++ int nonNullCode = code - (nullOK ? 1 : 0); ++ if (nonNullCode == -1) { ++ return null; ++ } else { ++ return decodeRef(nonNullCode, index); ++ } ++ } + } + + // Bootstrap support for CPRefBands. These are needed to record +@@ -1039,51 +1037,53 @@ class BandStructure implements Constants + + + int encodeRef(Entry e, Index ix) { +- int coding = ix.indexOf(e); +- if (verbose > 2) +- Utils.log.fine("putRef "+coding+" => "+e); +- return coding; ++ if (ix == null) ++ throw new RuntimeException("null index for " + e.stringValue()); ++ int coding = ix.indexOf(e); ++ if (verbose > 2) ++ Utils.log.fine("putRef "+coding+" => "+e); ++ return coding; + } + + Entry decodeRef(int n, Index ix) { +- if (n < 0 || n >= ix.size()) +- Utils.log.warning("decoding bad ref "+n+" in "+ix); +- Entry e = ix.getEntry(n); +- if (verbose > 2) +- Utils.log.fine("getRef "+n+" => "+e); +- return e; ++ if (n < 0 || n >= ix.size()) ++ Utils.log.warning("decoding bad ref "+n+" in "+ix); ++ Entry e = ix.getEntry(n); ++ if (verbose > 2) ++ Utils.log.fine("getRef "+n+" => "+e); ++ return e; + } + + private CodingChooser codingChooser; + protected CodingChooser getCodingChooser() { +- if (codingChooser == null) { +- codingChooser = new CodingChooser(effort, basicCodings); +- if (codingChooser.stress != null +- && this instanceof PackageWriter) { +- // Twist the random state based on my first file. +- // This sends each segment off in a different direction. +- List classes = ((PackageWriter)this).pkg.classes; +- if (!classes.isEmpty()) { +- Package.Class cls = (Package.Class) classes.get(0); +- codingChooser.addStressSeed(cls.getName().hashCode()); +- } +- } +- } +- return codingChooser; ++ if (codingChooser == null) { ++ codingChooser = new CodingChooser(effort, basicCodings); ++ if (codingChooser.stress != null ++ && this instanceof PackageWriter) { ++ // Twist the random state based on my first file. ++ // This sends each segment off in a different direction. ++ List classes = ((PackageWriter)this).pkg.classes; ++ if (!classes.isEmpty()) { ++ Package.Class cls = (Package.Class) classes.get(0); ++ codingChooser.addStressSeed(cls.getName().hashCode()); ++ } ++ } ++ } ++ return codingChooser; + } + + public CodingMethod chooseCoding(int[] values, int start, int end, +- Coding regular, String bandName, +- int[] sizes) { +- assert(optVaryCodings); +- if (effort <= MIN_EFFORT) { +- return regular; +- } +- CodingChooser cc = getCodingChooser(); +- if (verbose > 1 || cc.verbose > 1) { +- Utils.log.fine("--- chooseCoding "+bandName); +- } +- return cc.choose(values, start, end, regular, sizes); ++ Coding regular, String bandName, ++ int[] sizes) { ++ assert(optVaryCodings); ++ if (effort <= MIN_EFFORT) { ++ return regular; ++ } ++ CodingChooser cc = getCodingChooser(); ++ if (verbose > 1 || cc.verbose > 1) { ++ Utils.log.fine("--- chooseCoding "+bandName); ++ } ++ return cc.choose(values, start, end, regular, sizes); + } + + static final byte[] defaultMetaCoding = { _meta_default }; +@@ -1108,201 +1108,201 @@ class BandStructure implements Constants + // Result is in [0..255] if XB was successfully extracted, else -1. + // See section "Coding Specifier Meta-Encoding" in the JSR 200 spec. + protected static int decodeEscapeValue(int X, Coding regularCoding) { +- // The first value in a band is always coded with the default coding D. +- // If this first value X is an escape value, it actually represents the +- // first (and perhaps only) byte of a meta-coding. +- // Result is in [0..255] if XB was successfully extracted, else -1. +- if (regularCoding.B() == 1 || regularCoding.L() == 0) +- return -1; // degenerate regular coding (BYTE1) +- if (regularCoding.S() != 0) { +- if (-256 <= X && X <= -1 && regularCoding.min() <= -256) { +- int XB = -1-X; +- assert(XB >= 0 && XB < 256); +- return XB; +- } +- } else { +- int L = regularCoding.L(); +- if (L <= X && X <= L+255 && regularCoding.max() >= L+255) { +- int XB = X-L; +- assert(XB >= 0 && XB < 256); +- return XB; +- } +- } +- return -1; // negative value for failure ++ // The first value in a band is always coded with the default coding D. ++ // If this first value X is an escape value, it actually represents the ++ // first (and perhaps only) byte of a meta-coding. ++ // Result is in [0..255] if XB was successfully extracted, else -1. ++ if (regularCoding.B() == 1 || regularCoding.L() == 0) ++ return -1; // degenerate regular coding (BYTE1) ++ if (regularCoding.S() != 0) { ++ if (-256 <= X && X <= -1 && regularCoding.min() <= -256) { ++ int XB = -1-X; ++ assert(XB >= 0 && XB < 256); ++ return XB; ++ } ++ } else { ++ int L = regularCoding.L(); ++ if (L <= X && X <= L+255 && regularCoding.max() >= L+255) { ++ int XB = X-L; ++ assert(XB >= 0 && XB < 256); ++ return XB; ++ } ++ } ++ return -1; // negative value for failure + } + // Inverse to decodeEscapeValue(). + protected static int encodeEscapeValue(int XB, Coding regularCoding) { +- assert(XB >= 0 && XB < 256); +- assert(regularCoding.B() > 1 && regularCoding.L() > 0); +- int X; +- if (regularCoding.S() != 0) { +- assert(regularCoding.min() <= -256); +- X = -1-XB; +- } else { +- int L = regularCoding.L(); +- assert(regularCoding.max() >= L+255); +- X = XB+L; +- } +- assert(decodeEscapeValue(X, regularCoding) == XB) +- : (regularCoding+" XB="+XB+" X="+X); +- return X; ++ assert(XB >= 0 && XB < 256); ++ assert(regularCoding.B() > 1 && regularCoding.L() > 0); ++ int X; ++ if (regularCoding.S() != 0) { ++ assert(regularCoding.min() <= -256); ++ X = -1-XB; ++ } else { ++ int L = regularCoding.L(); ++ assert(regularCoding.max() >= L+255); ++ X = XB+L; ++ } ++ assert(decodeEscapeValue(X, regularCoding) == XB) ++ : (regularCoding+" XB="+XB+" X="+X); ++ return X; + } + + static { +- boolean checkXB = false; +- assert(checkXB = true); +- if (checkXB) { +- for (int i = 0; i < basicCodings.length; i++) { +- Coding D = basicCodings[i]; +- if (D == null) continue; +- if (D.B() == 1) continue; +- if (D.L() == 0) continue; +- for (int XB = 0; XB <= 255; XB++) { +- // The following exercises decodeEscapeValue also: +- encodeEscapeValue(XB, D); +- } +- } +- } ++ boolean checkXB = false; ++ assert(checkXB = true); ++ if (checkXB) { ++ for (int i = 0; i < basicCodings.length; i++) { ++ Coding D = basicCodings[i]; ++ if (D == null) continue; ++ if (D.B() == 1) continue; ++ if (D.L() == 0) continue; ++ for (int XB = 0; XB <= 255; XB++) { ++ // The following exercises decodeEscapeValue also: ++ encodeEscapeValue(XB, D); ++ } ++ } ++ } + } + + class MultiBand extends Band { +- MultiBand(String name, Coding regularCoding) { +- super(name, regularCoding); +- } ++ MultiBand(String name, Coding regularCoding) { ++ super(name, regularCoding); ++ } + +- public Band init() { +- super.init(); +- // This is all just to keep the asserts happy: +- setCapacity(0); +- if (phase() == EXPECT_PHASE) { +- // Fast forward: +- setPhase(READ_PHASE); +- setPhase(DISBURSE_PHASE); +- } +- return this; +- } ++ public Band init() { ++ super.init(); ++ // This is all just to keep the asserts happy: ++ setCapacity(0); ++ if (phase() == EXPECT_PHASE) { ++ // Fast forward: ++ setPhase(READ_PHASE); ++ setPhase(DISBURSE_PHASE); ++ } ++ return this; ++ } + +- Band[] bands = new Band[10]; +- int bandCount = 0; ++ Band[] bands = new Band[10]; ++ int bandCount = 0; + +- int size() { +- return bandCount; +- } +- Band get(int i) { +- assert(i < bandCount); +- return bands[i]; +- } +- Band[] toArray() { +- return (Band[]) realloc(bands, bandCount); +- } ++ int size() { ++ return bandCount; ++ } ++ Band get(int i) { ++ assert(i < bandCount); ++ return bands[i]; ++ } ++ Band[] toArray() { ++ return (Band[]) realloc(bands, bandCount); ++ } + +- void add(Band b) { +- assert(bandCount == 0 || notePrevForAssert(b, bands[bandCount-1])); +- if (bandCount == bands.length) { +- bands = (Band[]) realloc(bands); +- } +- bands[bandCount++] = b; +- } ++ void add(Band b) { ++ assert(bandCount == 0 || notePrevForAssert(b, bands[bandCount-1])); ++ if (bandCount == bands.length) { ++ bands = (Band[]) realloc(bands); ++ } ++ bands[bandCount++] = b; ++ } + +- ByteBand newByteBand(String name) { +- ByteBand b = new ByteBand(name); +- b.init(); add(b); +- return b; +- } +- IntBand newIntBand(String name) { +- IntBand b = new IntBand(name, regularCoding); +- b.init(); add(b); +- return b; +- } +- IntBand newIntBand(String name, Coding regularCoding) { +- IntBand b = new IntBand(name, regularCoding); +- b.init(); add(b); +- return b; +- } +- MultiBand newMultiBand(String name, Coding regularCoding) { +- MultiBand b = new MultiBand(name, regularCoding); +- b.init(); add(b); +- return b; +- } +- CPRefBand newCPRefBand(String name, byte cpTag) { +- CPRefBand b = new CPRefBand(name, regularCoding, cpTag); +- b.init(); add(b); +- return b; +- } +- CPRefBand newCPRefBand(String name, Coding regularCoding, +- byte cpTag) { +- CPRefBand b = new CPRefBand(name, regularCoding, cpTag); +- b.init(); add(b); +- return b; +- } +- CPRefBand newCPRefBand(String name, Coding regularCoding, +- byte cpTag, boolean nullOK) { +- CPRefBand b = new CPRefBand(name, regularCoding, cpTag, nullOK); +- b.init(); add(b); +- return b; +- } ++ ByteBand newByteBand(String name) { ++ ByteBand b = new ByteBand(name); ++ b.init(); add(b); ++ return b; ++ } ++ IntBand newIntBand(String name) { ++ IntBand b = new IntBand(name, regularCoding); ++ b.init(); add(b); ++ return b; ++ } ++ IntBand newIntBand(String name, Coding regularCoding) { ++ IntBand b = new IntBand(name, regularCoding); ++ b.init(); add(b); ++ return b; ++ } ++ MultiBand newMultiBand(String name, Coding regularCoding) { ++ MultiBand b = new MultiBand(name, regularCoding); ++ b.init(); add(b); ++ return b; ++ } ++ CPRefBand newCPRefBand(String name, byte cpTag) { ++ CPRefBand b = new CPRefBand(name, regularCoding, cpTag); ++ b.init(); add(b); ++ return b; ++ } ++ CPRefBand newCPRefBand(String name, Coding regularCoding, ++ byte cpTag) { ++ CPRefBand b = new CPRefBand(name, regularCoding, cpTag); ++ b.init(); add(b); ++ return b; ++ } ++ CPRefBand newCPRefBand(String name, Coding regularCoding, ++ byte cpTag, boolean nullOK) { ++ CPRefBand b = new CPRefBand(name, regularCoding, cpTag, nullOK); ++ b.init(); add(b); ++ return b; ++ } + +- int bandCount() { return bandCount; } ++ int bandCount() { return bandCount; } + +- private int cap = -1; +- public int capacity() { return cap; } +- public void setCapacity(int cap) { this.cap = cap; } ++ private int cap = -1; ++ public int capacity() { return cap; } ++ public void setCapacity(int cap) { this.cap = cap; } + +- public int length() { return 0; } +- public int valuesRemainingForDebug() { return 0; } ++ public int length() { return 0; } ++ public int valuesRemainingForDebug() { return 0; } + +- protected void chooseBandCodings() throws IOException { +- // coding decision pass +- for (int i = 0; i < bandCount; i++) { +- Band b = bands[i]; +- b.chooseBandCodings(); +- } +- } ++ protected void chooseBandCodings() throws IOException { ++ // coding decision pass ++ for (int i = 0; i < bandCount; i++) { ++ Band b = bands[i]; ++ b.chooseBandCodings(); ++ } ++ } + +- protected long computeOutputSize() { +- // coding decision pass +- long sum = 0; +- for (int i = 0; i < bandCount; i++) { +- Band b = bands[i]; +- long bsize = b.outputSize(); +- assert(bsize >= 0) : b; +- sum += bsize; +- } +- // do not cache +- return sum; +- } ++ protected long computeOutputSize() { ++ // coding decision pass ++ long sum = 0; ++ for (int i = 0; i < bandCount; i++) { ++ Band b = bands[i]; ++ long bsize = b.outputSize(); ++ assert(bsize >= 0) : b; ++ sum += bsize; ++ } ++ // do not cache ++ return sum; ++ } + +- protected void writeDataTo(OutputStream out) throws IOException { +- long preCount = 0; +- if (outputCounter != null) preCount = outputCounter.getCount(); +- for (int i = 0; i < bandCount; i++) { +- Band b = bands[i]; +- b.writeTo(out); +- if (outputCounter != null) { +- long postCount = outputCounter.getCount(); +- long len = postCount - preCount; +- preCount = postCount; +- if ((verbose > 0 && len > 0) || verbose > 1) { +- Utils.log.info(" ...wrote "+len+" bytes from "+b); +- } +- } +- } +- } ++ protected void writeDataTo(OutputStream out) throws IOException { ++ long preCount = 0; ++ if (outputCounter != null) preCount = outputCounter.getCount(); ++ for (int i = 0; i < bandCount; i++) { ++ Band b = bands[i]; ++ b.writeTo(out); ++ if (outputCounter != null) { ++ long postCount = outputCounter.getCount(); ++ long len = postCount - preCount; ++ preCount = postCount; ++ if ((verbose > 0 && len > 0) || verbose > 1) { ++ Utils.log.info(" ...wrote "+len+" bytes from "+b); ++ } ++ } ++ } ++ } + +- protected void readDataFrom(InputStream in) throws IOException { +- assert(false); // not called? +- for (int i = 0; i < bandCount; i++) { +- Band b = bands[i]; +- b.readFrom(in); +- if ((verbose > 0 && b.length() > 0) || verbose > 1) { +- Utils.log.info(" ...read "+b); +- } +- } +- } ++ protected void readDataFrom(InputStream in) throws IOException { ++ assert(false); // not called? ++ for (int i = 0; i < bandCount; i++) { ++ Band b = bands[i]; ++ b.readFrom(in); ++ if ((verbose > 0 && b.length() > 0) || verbose > 1) { ++ Utils.log.info(" ...read "+b); ++ } ++ } ++ } + +- public String toString() { +- return "{"+bandCount()+" bands: "+super.toString()+"}"; +- } ++ public String toString() { ++ return "{"+bandCount()+" bands: "+super.toString()+"}"; ++ } + } + + /** +@@ -1310,42 +1310,42 @@ class BandStructure implements Constants + */ + private static + class ByteCounter extends FilterOutputStream { +- // (should go public under the name CountingOutputStream?) ++ // (should go public under the name CountingOutputStream?) + +- private long count; ++ private long count; + +- public ByteCounter(OutputStream out) { +- super(out); +- } ++ public ByteCounter(OutputStream out) { ++ super(out); ++ } + +- public long getCount() { return count; } +- public void setCount(long c) { count = c; } ++ public long getCount() { return count; } ++ public void setCount(long c) { count = c; } + +- public void write(int b) throws IOException { +- count++; +- if (out != null) out.write(b); +- } +- public void write(byte b[], int off, int len) throws IOException { +- count += len; +- if (out != null) out.write(b, off, len); +- } +- public String toString() { +- return String.valueOf(getCount()); +- } ++ public void write(int b) throws IOException { ++ count++; ++ if (out != null) out.write(b); ++ } ++ public void write(byte b[], int off, int len) throws IOException { ++ count += len; ++ if (out != null) out.write(b, off, len); ++ } ++ public String toString() { ++ return String.valueOf(getCount()); ++ } + } + ByteCounter outputCounter; + + void writeAllBandsTo(OutputStream out) throws IOException { +- // Wrap a byte-counter around the output stream. +- outputCounter = new ByteCounter(out); +- out = outputCounter; +- all_bands.writeTo(out); +- if (verbose > 0) { +- long nbytes = outputCounter.getCount(); +- Utils.log.info("Wrote total of "+nbytes+" bytes."); +- assert(nbytes == archiveSize0+archiveSize1); +- } +- outputCounter = null; ++ // Wrap a byte-counter around the output stream. ++ outputCounter = new ByteCounter(out); ++ out = outputCounter; ++ all_bands.writeTo(out); ++ if (verbose > 0) { ++ long nbytes = outputCounter.getCount(); ++ Utils.log.info("Wrote total of "+nbytes+" bytes."); ++ assert(nbytes == archiveSize0+archiveSize1); ++ } ++ outputCounter = null; + } + + // random AO_XXX bits, decoded from the archive header +@@ -1366,7 +1366,7 @@ class BandStructure implements Constants + static final int AH_SPECIAL_FORMAT_LEN = 2; // layouts/band-headers + static final int AH_CP_NUMBER_LEN = 4; // int/float/long/double + static final int AH_LENGTH_MIN = AH_LENGTH +- -(AH_SPECIAL_FORMAT_LEN+AH_FILE_HEADER_LEN+AH_CP_NUMBER_LEN); ++ -(AH_SPECIAL_FORMAT_LEN+AH_FILE_HEADER_LEN+AH_CP_NUMBER_LEN); + + // Common structure of attribute band groups: + static final int AB_FLAGS_HI = 0; +@@ -1376,22 +1376,22 @@ class BandStructure implements Constants + static final int AB_ATTR_CALLS = 4; + + static IntBand getAttrBand(MultiBand xxx_attr_bands, int which) { +- IntBand b = (IntBand) xxx_attr_bands.get(which); +- switch (which) { +- case AB_FLAGS_HI: +- assert(b.name().endsWith("_flags_hi")); break; +- case AB_FLAGS_LO: +- assert(b.name().endsWith("_flags_lo")); break; +- case AB_ATTR_COUNT: +- assert(b.name().endsWith("_attr_count")); break; +- case AB_ATTR_INDEXES: +- assert(b.name().endsWith("_attr_indexes")); break; +- case AB_ATTR_CALLS: +- assert(b.name().endsWith("_attr_calls")); break; +- default: +- assert(false); break; +- } +- return b; ++ IntBand b = (IntBand) xxx_attr_bands.get(which); ++ switch (which) { ++ case AB_FLAGS_HI: ++ assert(b.name().endsWith("_flags_hi")); break; ++ case AB_FLAGS_LO: ++ assert(b.name().endsWith("_flags_lo")); break; ++ case AB_ATTR_COUNT: ++ assert(b.name().endsWith("_attr_count")); break; ++ case AB_ATTR_INDEXES: ++ assert(b.name().endsWith("_attr_indexes")); break; ++ case AB_ATTR_CALLS: ++ assert(b.name().endsWith("_attr_calls")); break; ++ default: ++ assert(false); break; ++ } ++ return b; + } + + static private final boolean NULL_IS_OK = true; +@@ -1602,55 +1602,55 @@ class BandStructure implements Constants + + /** Given CP indexes, distribute tag-specific indexes to bands. */ + protected void setBandIndexes() { +- // Handle prior calls to setBandIndex: +- for (Iterator i = needPredefIndex.iterator(); i.hasNext(); ) { +- Object[] need = (Object[]) i.next(); +- CPRefBand b = (CPRefBand) need[0]; +- Byte which = (Byte) need[1]; +- b.setIndex(getCPIndex(which.byteValue())); +- } +- needPredefIndex = null; // no more predefs ++ // Handle prior calls to setBandIndex: ++ for (Iterator i = needPredefIndex.iterator(); i.hasNext(); ) { ++ Object[] need = (Object[]) i.next(); ++ CPRefBand b = (CPRefBand) need[0]; ++ Byte which = (Byte) need[1]; ++ b.setIndex(getCPIndex(which.byteValue())); ++ } ++ needPredefIndex = null; // no more predefs + +- if (verbose > 3) { +- printCDecl(all_bands); +- } ++ if (verbose > 3) { ++ printCDecl(all_bands); ++ } + } + + protected void setBandIndex(CPRefBand b, byte which) { +- Object[] need = { b, new Byte(which) }; +- if (which == CONSTANT_Literal) { +- // I.e., attribute layouts KQ (no null) or KQN (null ok). +- allKQBands.add(b); +- } else if (needPredefIndex != null) { +- needPredefIndex.add(need); +- } else { +- // Not in predefinition mode; getCPIndex now works. +- b.setIndex(getCPIndex(which)); +- } ++ Object[] need = { b, new Byte(which) }; ++ if (which == CONSTANT_Literal) { ++ // I.e., attribute layouts KQ (no null) or KQN (null ok). ++ allKQBands.add(b); ++ } else if (needPredefIndex != null) { ++ needPredefIndex.add(need); ++ } else { ++ // Not in predefinition mode; getCPIndex now works. ++ b.setIndex(getCPIndex(which)); ++ } + } + + protected void setConstantValueIndex(Class.Field f) { +- Index ix = null; +- if (f != null) { +- byte tag = f.getLiteralTag(); +- ix = getCPIndex(tag); +- if (verbose > 2) +- Utils.log.fine("setConstantValueIndex "+f+" "+ConstantPool.tagName(tag)+" => "+ix); +- assert(ix != null); +- } +- // Typically, allKQBands is the singleton of field_ConstantValue_KQ. +- for (Iterator i = allKQBands.iterator(); i.hasNext(); ) { +- CPRefBand xxx_KQ = (CPRefBand) i.next(); +- xxx_KQ.setIndex(ix); +- } ++ Index ix = null; ++ if (f != null) { ++ byte tag = f.getLiteralTag(); ++ ix = getCPIndex(tag); ++ if (verbose > 2) ++ Utils.log.fine("setConstantValueIndex "+f+" "+ConstantPool.tagName(tag)+" => "+ix); ++ assert(ix != null); ++ } ++ // Typically, allKQBands is the singleton of field_ConstantValue_KQ. ++ for (Iterator i = allKQBands.iterator(); i.hasNext(); ) { ++ CPRefBand xxx_KQ = (CPRefBand) i.next(); ++ xxx_KQ.setIndex(ix); ++ } + } + + // Table of bands which contain metadata. + protected MultiBand[] metadataBands = new MultiBand[ATTR_CONTEXT_LIMIT]; + { +- metadataBands[ATTR_CONTEXT_CLASS] = class_metadata_bands; +- metadataBands[ATTR_CONTEXT_FIELD] = field_metadata_bands; +- metadataBands[ATTR_CONTEXT_METHOD] = method_metadata_bands; ++ metadataBands[ATTR_CONTEXT_CLASS] = class_metadata_bands; ++ metadataBands[ATTR_CONTEXT_FIELD] = field_metadata_bands; ++ metadataBands[ATTR_CONTEXT_METHOD] = method_metadata_bands; + } + + // Attribute layouts. +@@ -1686,660 +1686,660 @@ class BandStructure implements Constants + // Mapping from attribute index (<32 are flag bits) to attributes. + protected ArrayList[] attrDefs = new ArrayList[ATTR_CONTEXT_LIMIT]; + { +- for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { +- assert(attrIndexLimit[i] == 0); +- attrIndexLimit[i] = 32; // just for the sake of predefs. +- attrDefs[i] = new ArrayList(Collections.nCopies(attrIndexLimit[i], null)); +- } ++ for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { ++ assert(attrIndexLimit[i] == 0); ++ attrIndexLimit[i] = 32; // just for the sake of predefs. ++ attrDefs[i] = new ArrayList(Collections.nCopies(attrIndexLimit[i], null)); ++ } + +- // Add predefined attribute definitions: +- attrInnerClassesEmpty = +- predefineAttribute(CLASS_ATTR_InnerClasses, ATTR_CONTEXT_CLASS, null, +- "InnerClasses", ""); +- assert(attrInnerClassesEmpty == Package.attrInnerClassesEmpty); +- predefineAttribute(CLASS_ATTR_SourceFile, ATTR_CONTEXT_CLASS, +- new Band[] { class_SourceFile_RUN }, +- "SourceFile", "RUNH"); +- predefineAttribute(CLASS_ATTR_EnclosingMethod, ATTR_CONTEXT_CLASS, +- new Band[] { +- class_EnclosingMethod_RC, +- class_EnclosingMethod_RDN +- }, +- "EnclosingMethod", "RCHRDNH"); +- attrClassFileVersion = +- predefineAttribute(CLASS_ATTR_ClassFile_version, ATTR_CONTEXT_CLASS, +- new Band[] { +- class_ClassFile_version_minor_H, +- class_ClassFile_version_major_H +- }, +- ".ClassFile.version", "HH"); +- predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_CLASS, +- new Band[] { class_Signature_RS }, +- "Signature", "RSH"); +- predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_CLASS, null, +- "Deprecated", ""); +- //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_CLASS, null, +- // "Synthetic", ""); +- predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_CLASS, null, +- ".Overflow", ""); +- attrConstantValue = +- predefineAttribute(FIELD_ATTR_ConstantValue, ATTR_CONTEXT_FIELD, +- new Band[] { field_ConstantValue_KQ }, +- "ConstantValue", "KQH"); +- predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_FIELD, +- new Band[] { field_Signature_RS }, +- "Signature", "RSH"); +- predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_FIELD, null, +- "Deprecated", ""); +- //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_FIELD, null, +- // "Synthetic", ""); +- predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_FIELD, null, +- ".Overflow", ""); +- attrCodeEmpty = +- predefineAttribute(METHOD_ATTR_Code, ATTR_CONTEXT_METHOD, null, +- "Code", ""); +- predefineAttribute(METHOD_ATTR_Exceptions, ATTR_CONTEXT_METHOD, +- new Band[] { +- method_Exceptions_N, +- method_Exceptions_RC +- }, +- "Exceptions", "NH[RCH]"); +- assert(attrCodeEmpty == Package.attrCodeEmpty); +- predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_METHOD, +- new Band[] { method_Signature_RS }, +- "Signature", "RSH"); +- predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_METHOD, null, +- "Deprecated", ""); +- //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_METHOD, null, +- // "Synthetic", ""); +- predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_METHOD, null, +- ".Overflow", ""); ++ // Add predefined attribute definitions: ++ attrInnerClassesEmpty = ++ predefineAttribute(CLASS_ATTR_InnerClasses, ATTR_CONTEXT_CLASS, null, ++ "InnerClasses", ""); ++ assert(attrInnerClassesEmpty == Package.attrInnerClassesEmpty); ++ predefineAttribute(CLASS_ATTR_SourceFile, ATTR_CONTEXT_CLASS, ++ new Band[] { class_SourceFile_RUN }, ++ "SourceFile", "RUNH"); ++ predefineAttribute(CLASS_ATTR_EnclosingMethod, ATTR_CONTEXT_CLASS, ++ new Band[] { ++ class_EnclosingMethod_RC, ++ class_EnclosingMethod_RDN ++ }, ++ "EnclosingMethod", "RCHRDNH"); ++ attrClassFileVersion = ++ predefineAttribute(CLASS_ATTR_ClassFile_version, ATTR_CONTEXT_CLASS, ++ new Band[] { ++ class_ClassFile_version_minor_H, ++ class_ClassFile_version_major_H ++ }, ++ ".ClassFile.version", "HH"); ++ predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_CLASS, ++ new Band[] { class_Signature_RS }, ++ "Signature", "RSH"); ++ predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_CLASS, null, ++ "Deprecated", ""); ++ //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_CLASS, null, ++ // "Synthetic", ""); ++ predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_CLASS, null, ++ ".Overflow", ""); ++ attrConstantValue = ++ predefineAttribute(FIELD_ATTR_ConstantValue, ATTR_CONTEXT_FIELD, ++ new Band[] { field_ConstantValue_KQ }, ++ "ConstantValue", "KQH"); ++ predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_FIELD, ++ new Band[] { field_Signature_RS }, ++ "Signature", "RSH"); ++ predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_FIELD, null, ++ "Deprecated", ""); ++ //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_FIELD, null, ++ // "Synthetic", ""); ++ predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_FIELD, null, ++ ".Overflow", ""); ++ attrCodeEmpty = ++ predefineAttribute(METHOD_ATTR_Code, ATTR_CONTEXT_METHOD, null, ++ "Code", ""); ++ predefineAttribute(METHOD_ATTR_Exceptions, ATTR_CONTEXT_METHOD, ++ new Band[] { ++ method_Exceptions_N, ++ method_Exceptions_RC ++ }, ++ "Exceptions", "NH[RCH]"); ++ assert(attrCodeEmpty == Package.attrCodeEmpty); ++ predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_METHOD, ++ new Band[] { method_Signature_RS }, ++ "Signature", "RSH"); ++ predefineAttribute(X_ATTR_Deprecated, ATTR_CONTEXT_METHOD, null, ++ "Deprecated", ""); ++ //predefineAttribute(X_ATTR_Synthetic, ATTR_CONTEXT_METHOD, null, ++ // "Synthetic", ""); ++ predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_METHOD, null, ++ ".Overflow", ""); + +- for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { +- MultiBand xxx_metadata_bands = metadataBands[ctype]; +- if (xxx_metadata_bands == null) +- continue; // no code attrs ++ for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { ++ MultiBand xxx_metadata_bands = metadataBands[ctype]; ++ if (xxx_metadata_bands == null) ++ continue; // no code attrs + +- // These arguments cause the bands to be built +- // automatically for this complicated layout: +- predefineAttribute(X_ATTR_RuntimeVisibleAnnotations, +- ATTR_CONTEXT_NAME[ctype]+"_RVA_", +- xxx_metadata_bands, +- Attribute.lookup(null, ctype, +- "RuntimeVisibleAnnotations")); +- predefineAttribute(X_ATTR_RuntimeInvisibleAnnotations, +- ATTR_CONTEXT_NAME[ctype]+"_RIA_", +- xxx_metadata_bands, +- Attribute.lookup(null, ctype, +- "RuntimeInvisibleAnnotations")); +- if (ctype != ATTR_CONTEXT_METHOD) +- continue; ++ // These arguments cause the bands to be built ++ // automatically for this complicated layout: ++ predefineAttribute(X_ATTR_RuntimeVisibleAnnotations, ++ ATTR_CONTEXT_NAME[ctype]+"_RVA_", ++ xxx_metadata_bands, ++ Attribute.lookup(null, ctype, ++ "RuntimeVisibleAnnotations")); ++ predefineAttribute(X_ATTR_RuntimeInvisibleAnnotations, ++ ATTR_CONTEXT_NAME[ctype]+"_RIA_", ++ xxx_metadata_bands, ++ Attribute.lookup(null, ctype, ++ "RuntimeInvisibleAnnotations")); ++ if (ctype != ATTR_CONTEXT_METHOD) ++ continue; + +- predefineAttribute(METHOD_ATTR_RuntimeVisibleParameterAnnotations, +- "method_RVPA_", xxx_metadata_bands, +- Attribute.lookup(null, ctype, +- "RuntimeVisibleParameterAnnotations")); +- predefineAttribute(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, +- "method_RIPA_", xxx_metadata_bands, +- Attribute.lookup(null, ctype, +- "RuntimeInvisibleParameterAnnotations")); +- predefineAttribute(METHOD_ATTR_AnnotationDefault, +- "method_AD_", xxx_metadata_bands, +- Attribute.lookup(null, ctype, +- "AnnotationDefault")); +- } ++ predefineAttribute(METHOD_ATTR_RuntimeVisibleParameterAnnotations, ++ "method_RVPA_", xxx_metadata_bands, ++ Attribute.lookup(null, ctype, ++ "RuntimeVisibleParameterAnnotations")); ++ predefineAttribute(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, ++ "method_RIPA_", xxx_metadata_bands, ++ Attribute.lookup(null, ctype, ++ "RuntimeInvisibleParameterAnnotations")); ++ predefineAttribute(METHOD_ATTR_AnnotationDefault, ++ "method_AD_", xxx_metadata_bands, ++ Attribute.lookup(null, ctype, ++ "AnnotationDefault")); ++ } + + +- Attribute.Layout stackMapDef = Attribute.lookup(null, ATTR_CONTEXT_CODE, "StackMapTable").layout(); +- predefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE, +- stackmap_bands.toArray(), +- stackMapDef.name(), stackMapDef.layout()); ++ Attribute.Layout stackMapDef = Attribute.lookup(null, ATTR_CONTEXT_CODE, "StackMapTable").layout(); ++ predefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE, ++ stackmap_bands.toArray(), ++ stackMapDef.name(), stackMapDef.layout()); + +- predefineAttribute(CODE_ATTR_LineNumberTable, ATTR_CONTEXT_CODE, +- new Band[] { +- code_LineNumberTable_N, +- code_LineNumberTable_bci_P, +- code_LineNumberTable_line +- }, +- "LineNumberTable", "NH[PHH]"); +- predefineAttribute(CODE_ATTR_LocalVariableTable, ATTR_CONTEXT_CODE, +- new Band[] { +- code_LocalVariableTable_N, +- code_LocalVariableTable_bci_P, +- code_LocalVariableTable_span_O, +- code_LocalVariableTable_name_RU, +- code_LocalVariableTable_type_RS, +- code_LocalVariableTable_slot +- }, +- "LocalVariableTable", "NH[PHOHRUHRSHH]"); +- predefineAttribute(CODE_ATTR_LocalVariableTypeTable, ATTR_CONTEXT_CODE, +- new Band[] { +- code_LocalVariableTypeTable_N, +- code_LocalVariableTypeTable_bci_P, +- code_LocalVariableTypeTable_span_O, +- code_LocalVariableTypeTable_name_RU, +- code_LocalVariableTypeTable_type_RS, +- code_LocalVariableTypeTable_slot +- }, +- "LocalVariableTypeTable", "NH[PHOHRUHRSHH]"); +- predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_CODE, null, +- ".Overflow", ""); ++ predefineAttribute(CODE_ATTR_LineNumberTable, ATTR_CONTEXT_CODE, ++ new Band[] { ++ code_LineNumberTable_N, ++ code_LineNumberTable_bci_P, ++ code_LineNumberTable_line ++ }, ++ "LineNumberTable", "NH[PHH]"); ++ predefineAttribute(CODE_ATTR_LocalVariableTable, ATTR_CONTEXT_CODE, ++ new Band[] { ++ code_LocalVariableTable_N, ++ code_LocalVariableTable_bci_P, ++ code_LocalVariableTable_span_O, ++ code_LocalVariableTable_name_RU, ++ code_LocalVariableTable_type_RS, ++ code_LocalVariableTable_slot ++ }, ++ "LocalVariableTable", "NH[PHOHRUHRSHH]"); ++ predefineAttribute(CODE_ATTR_LocalVariableTypeTable, ATTR_CONTEXT_CODE, ++ new Band[] { ++ code_LocalVariableTypeTable_N, ++ code_LocalVariableTypeTable_bci_P, ++ code_LocalVariableTypeTable_span_O, ++ code_LocalVariableTypeTable_name_RU, ++ code_LocalVariableTypeTable_type_RS, ++ code_LocalVariableTypeTable_slot ++ }, ++ "LocalVariableTypeTable", "NH[PHOHRUHRSHH]"); ++ predefineAttribute(X_ATTR_OVERFLOW, ATTR_CONTEXT_CODE, null, ++ ".Overflow", ""); + +- // Clear the record of having seen these definitions, +- // so they may be redefined without error. +- for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { +- attrDefSeen[i] = 0; +- } ++ // Clear the record of having seen these definitions, ++ // so they may be redefined without error. ++ for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { ++ attrDefSeen[i] = 0; ++ } + +- // Set up the special masks: +- for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { +- attrOverflowMask[i] = (1<<X_ATTR_OVERFLOW); +- attrIndexLimit[i] = 0; // will make a final decision later +- } +- attrClassFileVersionMask = (1<<CLASS_ATTR_ClassFile_version); ++ // Set up the special masks: ++ for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { ++ attrOverflowMask[i] = (1<<X_ATTR_OVERFLOW); ++ attrIndexLimit[i] = 0; // will make a final decision later ++ } ++ attrClassFileVersionMask = (1<<CLASS_ATTR_ClassFile_version); + } + + private void adjustToMajver() { +- if (getPackageMajver() < JAVA6_PACKAGE_MAJOR_VERSION) { +- if (verbose > 0) Utils.log.fine("Legacy package version"); +- // Revoke definition of pre-1.6 attribute type. +- undefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE); +- } ++ if (getPackageMajver() < JAVA6_PACKAGE_MAJOR_VERSION) { ++ if (verbose > 0) Utils.log.fine("Legacy package version"); ++ // Revoke definition of pre-1.6 attribute type. ++ undefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE); ++ } + } + + protected void initAttrIndexLimit() { +- for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { +- assert(attrIndexLimit[i] == 0); // decide on it now! +- attrIndexLimit[i] = (haveFlagsHi(i)? 63: 32); +- assert(attrDefs[i].size() == 32); // all predef indexes are <32 +- int addMore = attrIndexLimit[i] - attrDefs[i].size(); +- attrDefs[i].addAll(Collections.nCopies(addMore, null)); +- } ++ for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { ++ assert(attrIndexLimit[i] == 0); // decide on it now! ++ attrIndexLimit[i] = (haveFlagsHi(i)? 63: 32); ++ assert(attrDefs[i].size() == 32); // all predef indexes are <32 ++ int addMore = attrIndexLimit[i] - attrDefs[i].size(); ++ attrDefs[i].addAll(Collections.nCopies(addMore, null)); ++ } + } + + protected boolean haveFlagsHi(int ctype) { +- int mask = 1<<(LG_AO_HAVE_XXX_FLAGS_HI+ctype); +- switch (ctype) { +- case ATTR_CONTEXT_CLASS: +- assert(mask == AO_HAVE_CLASS_FLAGS_HI); break; +- case ATTR_CONTEXT_FIELD: +- assert(mask == AO_HAVE_FIELD_FLAGS_HI); break; +- case ATTR_CONTEXT_METHOD: +- assert(mask == AO_HAVE_METHOD_FLAGS_HI); break; +- case ATTR_CONTEXT_CODE: +- assert(mask == AO_HAVE_CODE_FLAGS_HI); break; +- default: +- assert(false); +- } +- return testBit(archiveOptions, mask); ++ int mask = 1<<(LG_AO_HAVE_XXX_FLAGS_HI+ctype); ++ switch (ctype) { ++ case ATTR_CONTEXT_CLASS: ++ assert(mask == AO_HAVE_CLASS_FLAGS_HI); break; ++ case ATTR_CONTEXT_FIELD: ++ assert(mask == AO_HAVE_FIELD_FLAGS_HI); break; ++ case ATTR_CONTEXT_METHOD: ++ assert(mask == AO_HAVE_METHOD_FLAGS_HI); break; ++ case ATTR_CONTEXT_CODE: ++ assert(mask == AO_HAVE_CODE_FLAGS_HI); break; ++ default: ++ assert(false); ++ } ++ return testBit(archiveOptions, mask); + } + + protected ArrayList getPredefinedAttrs(int ctype) { +- assert(attrIndexLimit[ctype] != 0); +- ArrayList res = new ArrayList(attrIndexLimit[ctype]); +- // Remove nulls and non-predefs. +- for (int ai = 0; ai < attrIndexLimit[ctype]; ai++) { +- if (testBit(attrDefSeen[ctype], 1L<<ai)) continue; +- Attribute.Layout def = (Attribute.Layout) attrDefs[ctype].get(ai); +- if (def == null) continue; // unused flag bit +- assert(isPredefinedAttr(ctype, ai)); +- res.add(def); +- } +- return res; ++ assert(attrIndexLimit[ctype] != 0); ++ ArrayList res = new ArrayList(attrIndexLimit[ctype]); ++ // Remove nulls and non-predefs. ++ for (int ai = 0; ai < attrIndexLimit[ctype]; ai++) { ++ if (testBit(attrDefSeen[ctype], 1L<<ai)) continue; ++ Attribute.Layout def = (Attribute.Layout) attrDefs[ctype].get(ai); ++ if (def == null) continue; // unused flag bit ++ assert(isPredefinedAttr(ctype, ai)); ++ res.add(def); ++ } ++ return res; + } + + protected boolean isPredefinedAttr(int ctype, int ai) { +- assert(attrIndexLimit[ctype] != 0); +- // Overflow attrs are never predefined. +- if (ai >= attrIndexLimit[ctype]) return false; +- // If the bit is set, it was explicitly def'd. +- if (testBit(attrDefSeen[ctype], 1L<<ai)) return false; +- return (attrDefs[ctype].get(ai) != null); ++ assert(attrIndexLimit[ctype] != 0); ++ // Overflow attrs are never predefined. ++ if (ai >= attrIndexLimit[ctype]) return false; ++ // If the bit is set, it was explicitly def'd. ++ if (testBit(attrDefSeen[ctype], 1L<<ai)) return false; ++ return (attrDefs[ctype].get(ai) != null); + } + + protected void adjustSpecialAttrMasks() { +- // Clear special masks if new definitions have been seen for them. +- attrClassFileVersionMask &= ~ attrDefSeen[ATTR_CONTEXT_CLASS]; +- // It is possible to clear the overflow mask (bit 16). +- for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { +- attrOverflowMask[i] &= ~ attrDefSeen[i]; +- } ++ // Clear special masks if new definitions have been seen for them. ++ attrClassFileVersionMask &= ~ attrDefSeen[ATTR_CONTEXT_CLASS]; ++ // It is possible to clear the overflow mask (bit 16). ++ for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { ++ attrOverflowMask[i] &= ~ attrDefSeen[i]; ++ } + } + + protected Attribute makeClassFileVersionAttr(int minver, int majver) { +- byte[] bytes = { +- (byte)(minver >> 8), (byte)minver, +- (byte)(majver >> 8), (byte)majver +- }; +- return attrClassFileVersion.addContent(bytes); ++ byte[] bytes = { ++ (byte)(minver >> 8), (byte)minver, ++ (byte)(majver >> 8), (byte)majver ++ }; ++ return attrClassFileVersion.addContent(bytes); + } + + protected short[] parseClassFileVersionAttr(Attribute attr) { +- assert(attr.layout() == attrClassFileVersion); +- assert(attr.size() == 4); +- byte[] bytes = attr.bytes(); +- int minver = ((bytes[0] & 0xFF) << 8) | (bytes[1] & 0xFF); +- int majver = ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF); +- return new short[]{ (short) minver, (short) majver }; ++ assert(attr.layout() == attrClassFileVersion); ++ assert(attr.size() == 4); ++ byte[] bytes = attr.bytes(); ++ int minver = ((bytes[0] & 0xFF) << 8) | (bytes[1] & 0xFF); ++ int majver = ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF); ++ return new short[]{ (short) minver, (short) majver }; + } + + private boolean assertBandOKForElems(Band[] ab, Attribute.Layout.Element[] elems) { +- for (int i = 0; i < elems.length; i++) { +- assert(assertBandOKForElem(ab, elems[i])); +- } +- return true; ++ for (int i = 0; i < elems.length; i++) { ++ assert(assertBandOKForElem(ab, elems[i])); ++ } ++ return true; + } + private boolean assertBandOKForElem(Band[] ab, Attribute.Layout.Element e) { +- Band b = null; +- if (e.bandIndex != Attribute.NO_BAND_INDEX) +- b = ab[e.bandIndex]; +- Coding rc = UNSIGNED5; +- boolean wantIntBand = true; +- switch (e.kind) { +- case Attribute.EK_INT: +- if (e.flagTest(Attribute.EF_SIGN)) { +- rc = SIGNED5; +- } else if (e.len == 1) { +- rc = BYTE1; +- } +- break; +- case Attribute.EK_BCI: +- if (!e.flagTest(Attribute.EF_DELTA)) { +- rc = BCI5; +- } else { +- rc = BRANCH5; +- } +- break; +- case Attribute.EK_BCO: +- rc = BRANCH5; +- break; +- case Attribute.EK_FLAG: +- if (e.len == 1) rc = BYTE1; +- break; +- case Attribute.EK_REPL: +- if (e.len == 1) rc = BYTE1; +- assertBandOKForElems(ab, e.body); +- break; +- case Attribute.EK_UN: +- if (e.flagTest(Attribute.EF_SIGN)) { +- rc = SIGNED5; +- } else if (e.len == 1) { +- rc = BYTE1; +- } +- assertBandOKForElems(ab, e.body); +- break; +- case Attribute.EK_CASE: +- assert(b == null); +- assertBandOKForElems(ab, e.body); +- return true; // no direct band +- case Attribute.EK_CALL: +- assert(b == null); +- return true; // no direct band +- case Attribute.EK_CBLE: +- assert(b == null); +- assertBandOKForElems(ab, e.body); +- return true; // no direct band +- case Attribute.EK_REF: +- wantIntBand = false; +- assert(b instanceof CPRefBand); +- assert(((CPRefBand)b).nullOK == e.flagTest(Attribute.EF_NULL)); +- break; +- default: assert(false); +- } +- assert(b.regularCoding == rc) +- : (e+" // "+b); +- if (wantIntBand) +- assert(b instanceof IntBand); +- return true; ++ Band b = null; ++ if (e.bandIndex != Attribute.NO_BAND_INDEX) ++ b = ab[e.bandIndex]; ++ Coding rc = UNSIGNED5; ++ boolean wantIntBand = true; ++ switch (e.kind) { ++ case Attribute.EK_INT: ++ if (e.flagTest(Attribute.EF_SIGN)) { ++ rc = SIGNED5; ++ } else if (e.len == 1) { ++ rc = BYTE1; ++ } ++ break; ++ case Attribute.EK_BCI: ++ if (!e.flagTest(Attribute.EF_DELTA)) { ++ rc = BCI5; ++ } else { ++ rc = BRANCH5; ++ } ++ break; ++ case Attribute.EK_BCO: ++ rc = BRANCH5; ++ break; ++ case Attribute.EK_FLAG: ++ if (e.len == 1) rc = BYTE1; ++ break; ++ case Attribute.EK_REPL: ++ if (e.len == 1) rc = BYTE1; ++ assertBandOKForElems(ab, e.body); ++ break; ++ case Attribute.EK_UN: ++ if (e.flagTest(Attribute.EF_SIGN)) { ++ rc = SIGNED5; ++ } else if (e.len == 1) { ++ rc = BYTE1; ++ } ++ assertBandOKForElems(ab, e.body); ++ break; ++ case Attribute.EK_CASE: ++ assert(b == null); ++ assertBandOKForElems(ab, e.body); ++ return true; // no direct band ++ case Attribute.EK_CALL: ++ assert(b == null); ++ return true; // no direct band ++ case Attribute.EK_CBLE: ++ assert(b == null); ++ assertBandOKForElems(ab, e.body); ++ return true; // no direct band ++ case Attribute.EK_REF: ++ wantIntBand = false; ++ assert(b instanceof CPRefBand); ++ assert(((CPRefBand)b).nullOK == e.flagTest(Attribute.EF_NULL)); ++ break; ++ default: assert(false); ++ } ++ assert(b.regularCoding == rc) ++ : (e+" // "+b); ++ if (wantIntBand) ++ assert(b instanceof IntBand); ++ return true; + } + + private + Attribute.Layout predefineAttribute(int index, int ctype, Band[] ab, +- String name, String layout) { +- // Use Attribute.find to get uniquification of layouts. +- Attribute.Layout def = Attribute.find(ctype, name, layout).layout(); +- //def.predef = true; +- if (index >= 0) { +- setAttributeLayoutIndex(def, index); +- } +- if (ab == null) { +- ab = new Band[0]; +- } +- assert(attrBandTable.get(def) == null); // no redef +- attrBandTable.put(def, ab); +- assert(def.bandCount == ab.length) +- : (def+" // "+Arrays.asList(ab)); +- // Let's make sure the band types match: +- assert(assertBandOKForElems(ab, def.elems)); +- return def; ++ String name, String layout) { ++ // Use Attribute.find to get uniquification of layouts. ++ Attribute.Layout def = Attribute.find(ctype, name, layout).layout(); ++ //def.predef = true; ++ if (index >= 0) { ++ setAttributeLayoutIndex(def, index); ++ } ++ if (ab == null) { ++ ab = new Band[0]; ++ } ++ assert(attrBandTable.get(def) == null); // no redef ++ attrBandTable.put(def, ab); ++ assert(def.bandCount == ab.length) ++ : (def+" // "+Arrays.asList(ab)); ++ // Let's make sure the band types match: ++ assert(assertBandOKForElems(ab, def.elems)); ++ return def; + } + + // This version takes bandPrefix/addHere instead of prebuilt Band[] ab. + private + Attribute.Layout predefineAttribute(int index, +- String bandPrefix, MultiBand addHere, +- Attribute attr) { +- //Attribute.Layout def = Attribute.find(ctype, name, layout).layout(); +- Attribute.Layout def = attr.layout(); +- int ctype = def.ctype(); +- return predefineAttribute(index, ctype, +- makeNewAttributeBands(bandPrefix, def, +- addHere), +- def.name(), def.layout()); ++ String bandPrefix, MultiBand addHere, ++ Attribute attr) { ++ //Attribute.Layout def = Attribute.find(ctype, name, layout).layout(); ++ Attribute.Layout def = attr.layout(); ++ int ctype = def.ctype(); ++ return predefineAttribute(index, ctype, ++ makeNewAttributeBands(bandPrefix, def, ++ addHere), ++ def.name(), def.layout()); + } + + private + void undefineAttribute(int index, int ctype) { +- if (verbose > 1) { +- System.out.println("Removing predefined "+ATTR_CONTEXT_NAME[ctype]+ +- " attribute on bit "+index); +- } +- List defList = attrDefs[ctype]; +- Attribute.Layout def = (Attribute.Layout) defList.get(index); +- assert(def != null); +- defList.set(index, null); +- attrIndexTable.put(def, null); +- // Clear the def bit. (For predefs, it's already clear.) +- assert(index < 64); +- attrDefSeen[ctype] &= ~(1L<<index); +- attrFlagMask[ctype] &= ~(1L<<index); +- Band[] ab = (Band[]) attrBandTable.get(def); +- for (int j = 0; j < ab.length; j++) { +- ab[j].doneWithUnusedBand(); +- } ++ if (verbose > 1) { ++ System.out.println("Removing predefined "+ATTR_CONTEXT_NAME[ctype]+ ++ " attribute on bit "+index); ++ } ++ List defList = attrDefs[ctype]; ++ Attribute.Layout def = (Attribute.Layout) defList.get(index); ++ assert(def != null); ++ defList.set(index, null); ++ attrIndexTable.put(def, null); ++ // Clear the def bit. (For predefs, it's already clear.) ++ assert(index < 64); ++ attrDefSeen[ctype] &= ~(1L<<index); ++ attrFlagMask[ctype] &= ~(1L<<index); ++ Band[] ab = (Band[]) attrBandTable.get(def); ++ for (int j = 0; j < ab.length; j++) { ++ ab[j].doneWithUnusedBand(); ++ } + } + + // Bands which contain non-predefined attrs. + protected MultiBand[] attrBands = new MultiBand[ATTR_CONTEXT_LIMIT]; + { +- attrBands[ATTR_CONTEXT_CLASS] = class_attr_bands; +- attrBands[ATTR_CONTEXT_FIELD] = field_attr_bands; +- attrBands[ATTR_CONTEXT_METHOD] = method_attr_bands; +- attrBands[ATTR_CONTEXT_CODE] = code_attr_bands; ++ attrBands[ATTR_CONTEXT_CLASS] = class_attr_bands; ++ attrBands[ATTR_CONTEXT_FIELD] = field_attr_bands; ++ attrBands[ATTR_CONTEXT_METHOD] = method_attr_bands; ++ attrBands[ATTR_CONTEXT_CODE] = code_attr_bands; + } + + // Create bands for all non-predefined attrs. + void makeNewAttributeBands() { +- // Retract special flag bit bindings, if they were taken over. +- adjustSpecialAttrMasks(); ++ // Retract special flag bit bindings, if they were taken over. ++ adjustSpecialAttrMasks(); + +- for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { +- String cname = ATTR_CONTEXT_NAME[ctype]; +- MultiBand xxx_attr_bands = attrBands[ctype]; +- long defSeen = attrDefSeen[ctype]; +- // Note: attrDefSeen is always a subset of attrFlagMask. +- assert((defSeen & ~attrFlagMask[ctype]) == 0); +- for (int i = 0; i < attrDefs[ctype].size(); i++) { +- Attribute.Layout def = (Attribute.Layout) +- attrDefs[ctype].get(i); +- if (def == null) continue; // unused flag bit +- if (def.bandCount == 0) continue; // empty attr +- if (i < attrIndexLimit[ctype] && !testBit(defSeen, 1L<<i)) { +- // There are already predefined bands here. +- assert(attrBandTable.get(def) != null); +- continue; +- } +- int base = xxx_attr_bands.size(); +- String pfx = cname+"_"+def.name()+"_"; // debug only +- if (verbose > 1) +- Utils.log.fine("Making new bands for "+def); +- Band[] newAB = makeNewAttributeBands(pfx, def, +- xxx_attr_bands); +- assert(newAB.length == def.bandCount); +- Band[] prevAB = (Band[]) attrBandTable.put(def, newAB); +- if (prevAB != null) { +- // We won't be using these predefined bands. +- for (int j = 0; j < prevAB.length; j++) { +- prevAB[j].doneWithUnusedBand(); +- } +- } +- } +- } +- //System.out.println(prevForAssertMap); ++ for (int ctype = 0; ctype < ATTR_CONTEXT_LIMIT; ctype++) { ++ String cname = ATTR_CONTEXT_NAME[ctype]; ++ MultiBand xxx_attr_bands = attrBands[ctype]; ++ long defSeen = attrDefSeen[ctype]; ++ // Note: attrDefSeen is always a subset of attrFlagMask. ++ assert((defSeen & ~attrFlagMask[ctype]) == 0); ++ for (int i = 0; i < attrDefs[ctype].size(); i++) { ++ Attribute.Layout def = (Attribute.Layout) ++ attrDefs[ctype].get(i); ++ if (def == null) continue; // unused flag bit ++ if (def.bandCount == 0) continue; // empty attr ++ if (i < attrIndexLimit[ctype] && !testBit(defSeen, 1L<<i)) { ++ // There are already predefined bands here. ++ assert(attrBandTable.get(def) != null); ++ continue; ++ } ++ int base = xxx_attr_bands.size(); ++ String pfx = cname+"_"+def.name()+"_"; // debug only ++ if (verbose > 1) ++ Utils.log.fine("Making new bands for "+def); ++ Band[] newAB = makeNewAttributeBands(pfx, def, ++ xxx_attr_bands); ++ assert(newAB.length == def.bandCount); ++ Band[] prevAB = (Band[]) attrBandTable.put(def, newAB); ++ if (prevAB != null) { ++ // We won't be using these predefined bands. ++ for (int j = 0; j < prevAB.length; j++) { ++ prevAB[j].doneWithUnusedBand(); ++ } ++ } ++ } ++ } ++ //System.out.println(prevForAssertMap); + } + private + Band[] makeNewAttributeBands(String pfx, Attribute.Layout def, +- MultiBand addHere) { +- int base = addHere.size(); +- makeNewAttributeBands(pfx, def.elems, addHere); +- int nb = addHere.size() - base; +- Band[] newAB = new Band[nb]; +- for (int i = 0; i < nb; i++) { +- newAB[i] = addHere.get(base+i); +- } +- return newAB; ++ MultiBand addHere) { ++ int base = addHere.size(); ++ makeNewAttributeBands(pfx, def.elems, addHere); ++ int nb = addHere.size() - base; ++ Band[] newAB = new Band[nb]; ++ for (int i = 0; i < nb; i++) { ++ newAB[i] = addHere.get(base+i); ++ } ++ return newAB; + } + // Recursive helper, operates on a "body" or other sequence of elems: + private + void makeNewAttributeBands(String pfx, Attribute.Layout.Element[] elems, +- MultiBand ab) { +- for (int i = 0; i < elems.length; i++) { +- Attribute.Layout.Element e = elems[i]; +- String name = pfx+ab.size()+"_"+e.layout; +- { +- int tem; +- if ((tem = name.indexOf('[')) > 0) +- name = name.substring(0, tem); +- if ((tem = name.indexOf('(')) > 0) +- name = name.substring(0, tem); +- if (name.endsWith("H")) +- name = name.substring(0, name.length()-1); +- } +- Band nb; +- switch (e.kind) { +- case Attribute.EK_INT: +- nb = newElemBand(e, name, ab); +- break; +- case Attribute.EK_BCI: +- if (!e.flagTest(Attribute.EF_DELTA)) { +- // PH: transmit R(bci), store bci +- nb = ab.newIntBand(name, BCI5); +- } else { +- // POH: transmit D(R(bci)), store bci +- nb = ab.newIntBand(name, BRANCH5); +- } +- // Note: No case for BYTE1 here. +- break; +- case Attribute.EK_BCO: +- // OH: transmit D(R(bci)), store D(bci) +- nb = ab.newIntBand(name, BRANCH5); +- // Note: No case for BYTE1 here. +- break; +- case Attribute.EK_FLAG: +- assert(!e.flagTest(Attribute.EF_SIGN)); +- nb = newElemBand(e, name, ab); +- break; +- case Attribute.EK_REPL: +- assert(!e.flagTest(Attribute.EF_SIGN)); +- nb = newElemBand(e, name, ab); +- makeNewAttributeBands(pfx, e.body, ab); +- break; +- case Attribute.EK_UN: +- nb = newElemBand(e, name, ab); +- makeNewAttributeBands(pfx, e.body, ab); +- break; +- case Attribute.EK_CASE: +- if (!e.flagTest(Attribute.EF_BACK)) { +- // If it's not a duplicate body, make the bands. +- makeNewAttributeBands(pfx, e.body, ab); +- } +- continue; // no new band to make +- case Attribute.EK_REF: +- byte refKind = e.refKind; +- boolean nullOK = e.flagTest(Attribute.EF_NULL); +- nb = ab.newCPRefBand(name, UNSIGNED5, refKind, nullOK); +- // Note: No case for BYTE1 here. +- break; +- case Attribute.EK_CALL: +- continue; // no new band to make +- case Attribute.EK_CBLE: +- makeNewAttributeBands(pfx, e.body, ab); +- continue; // no new band to make +- default: assert(false); continue; +- } +- if (verbose > 1) { +- Utils.log.fine("New attribute band "+nb); +- } +- } ++ MultiBand ab) { ++ for (int i = 0; i < elems.length; i++) { ++ Attribute.Layout.Element e = elems[i]; ++ String name = pfx+ab.size()+"_"+e.layout; ++ { ++ int tem; ++ if ((tem = name.indexOf('[')) > 0) ++ name = name.substring(0, tem); ++ if ((tem = name.indexOf('(')) > 0) ++ name = name.substring(0, tem); ++ if (name.endsWith("H")) ++ name = name.substring(0, name.length()-1); ++ } ++ Band nb; ++ switch (e.kind) { ++ case Attribute.EK_INT: ++ nb = newElemBand(e, name, ab); ++ break; ++ case Attribute.EK_BCI: ++ if (!e.flagTest(Attribute.EF_DELTA)) { ++ // PH: transmit R(bci), store bci ++ nb = ab.newIntBand(name, BCI5); ++ } else { ++ // POH: transmit D(R(bci)), store bci ++ nb = ab.newIntBand(name, BRANCH5); ++ } ++ // Note: No case for BYTE1 here. ++ break; ++ case Attribute.EK_BCO: ++ // OH: transmit D(R(bci)), store D(bci) ++ nb = ab.newIntBand(name, BRANCH5); ++ // Note: No case for BYTE1 here. ++ break; ++ case Attribute.EK_FLAG: ++ assert(!e.flagTest(Attribute.EF_SIGN)); ++ nb = newElemBand(e, name, ab); ++ break; ++ case Attribute.EK_REPL: ++ assert(!e.flagTest(Attribute.EF_SIGN)); ++ nb = newElemBand(e, name, ab); ++ makeNewAttributeBands(pfx, e.body, ab); ++ break; ++ case Attribute.EK_UN: ++ nb = newElemBand(e, name, ab); ++ makeNewAttributeBands(pfx, e.body, ab); ++ break; ++ case Attribute.EK_CASE: ++ if (!e.flagTest(Attribute.EF_BACK)) { ++ // If it's not a duplicate body, make the bands. ++ makeNewAttributeBands(pfx, e.body, ab); ++ } ++ continue; // no new band to make ++ case Attribute.EK_REF: ++ byte refKind = e.refKind; ++ boolean nullOK = e.flagTest(Attribute.EF_NULL); ++ nb = ab.newCPRefBand(name, UNSIGNED5, refKind, nullOK); ++ // Note: No case for BYTE1 here. ++ break; ++ case Attribute.EK_CALL: ++ continue; // no new band to make ++ case Attribute.EK_CBLE: ++ makeNewAttributeBands(pfx, e.body, ab); ++ continue; // no new band to make ++ default: assert(false); continue; ++ } ++ if (verbose > 1) { ++ Utils.log.fine("New attribute band "+nb); ++ } ++ } + } + private + Band newElemBand(Attribute.Layout.Element e, String name, MultiBand ab) { +- if (e.flagTest(Attribute.EF_SIGN)) { +- return ab.newIntBand(name, SIGNED5); +- } else if (e.len == 1) { +- return ab.newIntBand(name, BYTE1); // Not ByteBand, please. +- } else { +- return ab.newIntBand(name, UNSIGNED5); +- } ++ if (e.flagTest(Attribute.EF_SIGN)) { ++ return ab.newIntBand(name, SIGNED5); ++ } else if (e.len == 1) { ++ return ab.newIntBand(name, BYTE1); // Not ByteBand, please. ++ } else { ++ return ab.newIntBand(name, UNSIGNED5); ++ } + } + + protected int setAttributeLayoutIndex(Attribute.Layout def, int index) { +- int ctype = def.ctype; +- assert(ATTR_INDEX_OVERFLOW <= index && index < attrIndexLimit[ctype]); +- List defList = attrDefs[ctype]; +- if (index == ATTR_INDEX_OVERFLOW) { +- // Overflow attribute. +- index = defList.size(); +- defList.add(def); +- if (verbose > 0) +- Utils.log.info("Adding new attribute at "+def +": "+index); +- attrIndexTable.put(def, new Integer(index)); +- return index; +- } ++ int ctype = def.ctype; ++ assert(ATTR_INDEX_OVERFLOW <= index && index < attrIndexLimit[ctype]); ++ List defList = attrDefs[ctype]; ++ if (index == ATTR_INDEX_OVERFLOW) { ++ // Overflow attribute. ++ index = defList.size(); ++ defList.add(def); ++ if (verbose > 0) ++ Utils.log.info("Adding new attribute at "+def +": "+index); ++ attrIndexTable.put(def, new Integer(index)); ++ return index; ++ } + +- // Detect redefinitions: +- if (testBit(attrDefSeen[ctype], 1L<<index)) { +- throw new RuntimeException("Multiple explicit definition at "+index+": "+def); +- } +- attrDefSeen[ctype] |= (1L<<index); ++ // Detect redefinitions: ++ if (testBit(attrDefSeen[ctype], 1L<<index)) { ++ throw new RuntimeException("Multiple explicit definition at "+index+": "+def); ++ } ++ attrDefSeen[ctype] |= (1L<<index); + +- // Adding a new fixed attribute. +- assert(0 <= index && index < attrIndexLimit[ctype]); +- if (verbose > (attrClassFileVersionMask == 0? 2:0)) +- Utils.log.fine("Fixing new attribute at "+index +- +": "+def +- +(defList.get(index) == null? "": +- "; replacing "+defList.get(index))); +- attrFlagMask[ctype] |= (1L<<index); +- // Remove index binding of any previous fixed attr. +- attrIndexTable.put(defList.get(index), null); +- defList.set(index, def); +- attrIndexTable.put(def, new Integer(index)); +- return index; ++ // Adding a new fixed attribute. ++ assert(0 <= index && index < attrIndexLimit[ctype]); ++ if (verbose > (attrClassFileVersionMask == 0? 2:0)) ++ Utils.log.fine("Fixing new attribute at "+index ++ +": "+def ++ +(defList.get(index) == null? "": ++ "; replacing "+defList.get(index))); ++ attrFlagMask[ctype] |= (1L<<index); ++ // Remove index binding of any previous fixed attr. ++ attrIndexTable.put(defList.get(index), null); ++ defList.set(index, def); ++ attrIndexTable.put(def, new Integer(index)); ++ return index; + } + + // encodings found in the code_headers band + private static final int[][] shortCodeLimits = { +- { 12, 12 }, // s<12, l<12, e=0 [1..144] +- { 8, 8 }, // s<8, l<8, e=1 [145..208] +- { 7, 7 }, // s<7, l<7, e=2 [209..256] ++ { 12, 12 }, // s<12, l<12, e=0 [1..144] ++ { 8, 8 }, // s<8, l<8, e=1 [145..208] ++ { 7, 7 }, // s<7, l<7, e=2 [209..256] + }; + public final int shortCodeHeader_h_limit = shortCodeLimits.length; + + // return 0 if it won't encode, else a number in [1..255] + static int shortCodeHeader(Code code) { +- int s = code.max_stack; +- int l0 = code.max_locals; +- int h = code.handler_class.length; +- if (h >= shortCodeLimits.length) return LONG_CODE_HEADER; +- int siglen = code.getMethod().getArgumentSize(); +- assert(l0 >= siglen); // enough locals for signature! +- if (l0 < siglen) return LONG_CODE_HEADER; +- int l1 = l0 - siglen; // do not count locals required by the signature +- int lims = shortCodeLimits[h][0]; +- int liml = shortCodeLimits[h][1]; +- if (s >= lims || l1 >= liml) return LONG_CODE_HEADER; +- int sc = shortCodeHeader_h_base(h); +- sc += s + lims*l1; +- if (sc > 255) return LONG_CODE_HEADER; +- assert(shortCodeHeader_max_stack(sc) == s); +- assert(shortCodeHeader_max_na_locals(sc) == l1); +- assert(shortCodeHeader_handler_count(sc) == h); +- return sc; ++ int s = code.max_stack; ++ int l0 = code.max_locals; ++ int h = code.handler_class.length; ++ if (h >= shortCodeLimits.length) return LONG_CODE_HEADER; ++ int siglen = code.getMethod().getArgumentSize(); ++ assert(l0 >= siglen); // enough locals for signature! ++ if (l0 < siglen) return LONG_CODE_HEADER; ++ int l1 = l0 - siglen; // do not count locals required by the signature ++ int lims = shortCodeLimits[h][0]; ++ int liml = shortCodeLimits[h][1]; ++ if (s >= lims || l1 >= liml) return LONG_CODE_HEADER; ++ int sc = shortCodeHeader_h_base(h); ++ sc += s + lims*l1; ++ if (sc > 255) return LONG_CODE_HEADER; ++ assert(shortCodeHeader_max_stack(sc) == s); ++ assert(shortCodeHeader_max_na_locals(sc) == l1); ++ assert(shortCodeHeader_handler_count(sc) == h); ++ return sc; + } + + static final int LONG_CODE_HEADER = 0; + static int shortCodeHeader_handler_count(int sc) { +- assert(sc > 0 && sc <= 255); +- for (int h = 0; ; h++) { +- if (sc < shortCodeHeader_h_base(h+1)) +- return h; +- } ++ assert(sc > 0 && sc <= 255); ++ for (int h = 0; ; h++) { ++ if (sc < shortCodeHeader_h_base(h+1)) ++ return h; ++ } + } + static int shortCodeHeader_max_stack(int sc) { +- int h = shortCodeHeader_handler_count(sc); +- int lims = shortCodeLimits[h][0]; +- return (sc - shortCodeHeader_h_base(h)) % lims; ++ int h = shortCodeHeader_handler_count(sc); ++ int lims = shortCodeLimits[h][0]; ++ return (sc - shortCodeHeader_h_base(h)) % lims; + } + static int shortCodeHeader_max_na_locals(int sc) { +- int h = shortCodeHeader_handler_count(sc); +- int lims = shortCodeLimits[h][0]; +- return (sc - shortCodeHeader_h_base(h)) / lims; ++ int h = shortCodeHeader_handler_count(sc); ++ int lims = shortCodeLimits[h][0]; ++ return (sc - shortCodeHeader_h_base(h)) / lims; + } + + private static int shortCodeHeader_h_base(int h) { +- assert(h <= shortCodeLimits.length); +- int sc = 1; +- for (int h0 = 0; h0 < h; h0++) { +- int lims = shortCodeLimits[h0][0]; +- int liml = shortCodeLimits[h0][1]; +- sc += lims * liml; +- } +- return sc; ++ assert(h <= shortCodeLimits.length); ++ int sc = 1; ++ for (int h0 = 0; h0 < h; h0++) { ++ int lims = shortCodeLimits[h0][0]; ++ int liml = shortCodeLimits[h0][1]; ++ sc += lims * liml; ++ } ++ return sc; + } + + // utilities for accessing the bc_label band: + protected void putLabel(IntBand bc_label, Code c, int pc, int targetPC) { +- bc_label.putInt(c.encodeBCI(targetPC) - c.encodeBCI(pc)); ++ bc_label.putInt(c.encodeBCI(targetPC) - c.encodeBCI(pc)); + } + protected int getLabel(IntBand bc_label, Code c, int pc) { +- return c.decodeBCI(bc_label.getInt() + c.encodeBCI(pc)); ++ return c.decodeBCI(bc_label.getInt() + c.encodeBCI(pc)); + } + + protected CPRefBand getCPRefOpBand(int bc) { +- switch (Instruction.getCPRefOpTag(bc)) { +- case CONSTANT_Class: +- return bc_classref; +- case CONSTANT_Fieldref: +- return bc_fieldref; +- case CONSTANT_Methodref: +- return bc_methodref; +- case CONSTANT_InterfaceMethodref: +- return bc_imethodref; +- case CONSTANT_Literal: +- switch (bc) { +- case _ildc: case _ildc_w: +- return bc_intref; +- case _fldc: case _fldc_w: +- return bc_floatref; +- case _lldc2_w: +- return bc_longref; +- case _dldc2_w: +- return bc_doubleref; +- case _aldc: case _aldc_w: +- return bc_stringref; +- case _cldc: case _cldc_w: +- return bc_classref; +- } +- break; +- } +- assert(false); +- return null; ++ switch (Instruction.getCPRefOpTag(bc)) { ++ case CONSTANT_Class: ++ return bc_classref; ++ case CONSTANT_Fieldref: ++ return bc_fieldref; ++ case CONSTANT_Methodref: ++ return bc_methodref; ++ case CONSTANT_InterfaceMethodref: ++ return bc_imethodref; ++ case CONSTANT_Literal: ++ switch (bc) { ++ case _ildc: case _ildc_w: ++ return bc_intref; ++ case _fldc: case _fldc_w: ++ return bc_floatref; ++ case _lldc2_w: ++ return bc_longref; ++ case _dldc2_w: ++ return bc_doubleref; ++ case _aldc: case _aldc_w: ++ return bc_stringref; ++ case _cldc: case _cldc_w: ++ return bc_classref; ++ } ++ break; ++ } ++ assert(false); ++ return null; + } + + protected CPRefBand selfOpRefBand(int self_bc) { +- assert(Instruction.isSelfLinkerOp(self_bc)); +- int idx = (self_bc - _self_linker_op); +- boolean isSuper = (idx >= _self_linker_super_flag); +- if (isSuper) idx -= _self_linker_super_flag; +- boolean isAload = (idx >= _self_linker_aload_flag); +- if (isAload) idx -= _self_linker_aload_flag; +- int origBC = _first_linker_op + idx; +- boolean isField = Instruction.isFieldOp(origBC); +- if (!isSuper) +- return isField? bc_thisfield: bc_thismethod; +- else +- return isField? bc_superfield: bc_supermethod; ++ assert(Instruction.isSelfLinkerOp(self_bc)); ++ int idx = (self_bc - _self_linker_op); ++ boolean isSuper = (idx >= _self_linker_super_flag); ++ if (isSuper) idx -= _self_linker_super_flag; ++ boolean isAload = (idx >= _self_linker_aload_flag); ++ if (isAload) idx -= _self_linker_aload_flag; ++ int origBC = _first_linker_op + idx; ++ boolean isField = Instruction.isFieldOp(origBC); ++ if (!isSuper) ++ return isField? bc_thisfield: bc_thismethod; ++ else ++ return isField? bc_superfield: bc_supermethod; + } + + //////////////////////////////////////////////////////////////////// +@@ -2347,317 +2347,319 @@ class BandStructure implements Constants + static int nextSeqForDebug; + static File dumpDir; + static OutputStream getDumpStream(Band b, String ext) throws IOException { +- return getDumpStream(b.name, b.seqForDebug, ext, b); ++ return getDumpStream(b.name, b.seqForDebug, ext, b); + } + static OutputStream getDumpStream(Index ix, String ext) throws IOException { +- if (ix.size() == 0) return new ByteArrayOutputStream(); +- int seq = ConstantPool.TAG_ORDER[ix.cpMap[0].tag]; +- return getDumpStream(ix.debugName, seq, ext, ix); ++ if (ix.size() == 0) return new ByteArrayOutputStream(); ++ int seq = ConstantPool.TAG_ORDER[ix.cpMap[0].tag]; ++ return getDumpStream(ix.debugName, seq, ext, ix); + } + static OutputStream getDumpStream(String name, int seq, String ext, Object b) throws IOException { +- if (dumpDir == null) { +- dumpDir = File.createTempFile("BD_", "", new File(".")); +- dumpDir.delete(); +- if (dumpDir.mkdir()) +- Utils.log.info("Dumping bands to "+dumpDir); +- } +- name = name.replace('(', ' ').replace(')', ' '); +- name = name.replace('/', ' '); +- name = name.replace('*', ' '); +- name = name.trim().replace(' ','_'); +- name = ((10000+seq) + "_" + name).substring(1); +- File dumpFile = new File(dumpDir, name+ext); +- Utils.log.info("Dumping "+b+" to "+dumpFile); +- return new BufferedOutputStream(new FileOutputStream(dumpFile)); ++ if (dumpDir == null) { ++ dumpDir = File.createTempFile("BD_", "", new File(".")); ++ dumpDir.delete(); ++ if (dumpDir.mkdir()) ++ Utils.log.info("Dumping bands to "+dumpDir); ++ } ++ name = name.replace('(', ' ').replace(')', ' '); ++ name = name.replace('/', ' '); ++ name = name.replace('*', ' '); ++ name = name.trim().replace(' ','_'); ++ name = ((10000+seq) + "_" + name).substring(1); ++ File dumpFile = new File(dumpDir, name+ext); ++ Utils.log.info("Dumping "+b+" to "+dumpFile); ++ return new BufferedOutputStream(new FileOutputStream(dumpFile)); + } + + // DEBUG ONLY: Validate me at each length change. + static boolean assertCanChangeLength(Band b) { +- switch (b.phase) { +- case COLLECT_PHASE: +- case READ_PHASE: +- return true; +- } +- return false; ++ switch (b.phase) { ++ case COLLECT_PHASE: ++ case READ_PHASE: ++ return true; ++ } ++ return false; + } + + // DEBUG ONLY: Validate a phase. + static boolean assertPhase(Band b, int phaseExpected) { +- if (b.phase() != phaseExpected) { +- Utils.log.warning("phase expected "+phaseExpected+" was "+b.phase()+" in "+b); +- return false; +- } +- return true; ++ if (b.phase() != phaseExpected) { ++ Utils.log.warning("phase expected "+phaseExpected+" was "+b.phase()+" in "+b); ++ return false; ++ } ++ return true; + } + + + // DEBUG ONLY: Tells whether verbosity is turned on. + static int verbose() { +- return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE); ++ return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE); + } + + + // DEBUG ONLY: Validate me at each phase change. + static boolean assertPhaseChangeOK(Band b, int p0, int p1) { +- switch (p0*10+p1) { +- /// Writing phases: +- case NO_PHASE*10+COLLECT_PHASE: +- // Ready to collect data from the input classes. +- assert(!b.isReader()); +- assert(b.capacity() >= 0); +- assert(b.length() == 0); +- return true; +- case COLLECT_PHASE*10+FROZEN_PHASE: +- case FROZEN_PHASE*10+FROZEN_PHASE: +- assert(b.length() == 0); +- return true; +- case COLLECT_PHASE*10+WRITE_PHASE: +- case FROZEN_PHASE*10+WRITE_PHASE: +- // Data is all collected. Ready to write bytes to disk. +- return true; +- case WRITE_PHASE*10+DONE_PHASE: +- // Done writing to disk. Ready to reset, in principle. +- return true; ++ switch (p0*10+p1) { ++ /// Writing phases: ++ case NO_PHASE*10+COLLECT_PHASE: ++ // Ready to collect data from the input classes. ++ assert(!b.isReader()); ++ assert(b.capacity() >= 0); ++ assert(b.length() == 0); ++ return true; ++ case COLLECT_PHASE*10+FROZEN_PHASE: ++ case FROZEN_PHASE*10+FROZEN_PHASE: ++ assert(b.length() == 0); ++ return true; ++ case COLLECT_PHASE*10+WRITE_PHASE: ++ case FROZEN_PHASE*10+WRITE_PHASE: ++ // Data is all collected. Ready to write bytes to disk. ++ return true; ++ case WRITE_PHASE*10+DONE_PHASE: ++ // Done writing to disk. Ready to reset, in principle. ++ return true; + +- /// Reading phases: +- case NO_PHASE*10+EXPECT_PHASE: +- assert(b.isReader()); +- assert(b.capacity() < 0); +- return true; +- case EXPECT_PHASE*10+READ_PHASE: +- // Ready to read values from disk. +- assert(Math.max(0,b.capacity()) >= b.valuesExpected()); +- assert(b.length() <= 0); +- return true; +- case READ_PHASE*10+DISBURSE_PHASE: +- // Ready to disburse values. +- assert(b.valuesRemainingForDebug() == b.length()); +- return true; +- case DISBURSE_PHASE*10+DONE_PHASE: +- // Done disbursing values. Ready to reset, in principle. +- assert(assertDoneDisbursing(b)); +- return true; +- } +- if (p0 == p1) +- Utils.log.warning("Already in phase "+p0); +- else +- Utils.log.warning("Unexpected phase "+p0+" -> "+p1); +- return false; ++ /// Reading phases: ++ case NO_PHASE*10+EXPECT_PHASE: ++ assert(b.isReader()); ++ assert(b.capacity() < 0); ++ return true; ++ case EXPECT_PHASE*10+READ_PHASE: ++ // Ready to read values from disk. ++ assert(Math.max(0,b.capacity()) >= b.valuesExpected()); ++ assert(b.length() <= 0); ++ return true; ++ case READ_PHASE*10+DISBURSE_PHASE: ++ // Ready to disburse values. ++ assert(b.valuesRemainingForDebug() == b.length()); ++ return true; ++ case DISBURSE_PHASE*10+DONE_PHASE: ++ // Done disbursing values. Ready to reset, in principle. ++ assert(assertDoneDisbursing(b)); ++ return true; ++ } ++ if (p0 == p1) ++ Utils.log.warning("Already in phase "+p0); ++ else ++ Utils.log.warning("Unexpected phase "+p0+" -> "+p1); ++ return false; + } + + static private boolean assertDoneDisbursing(Band b) { +- if (b.phase != DISBURSE_PHASE) { +- Utils.log.warning("assertDoneDisbursing: still in phase "+b.phase+": "+b); +- if (verbose() <= 1) return false; // fail now +- } +- int left = b.valuesRemainingForDebug(); +- if (left > 0) { +- Utils.log.warning("assertDoneDisbursing: "+left+" values left in "+b); +- if (verbose() <= 1) return false; // fail now +- } +- if (b instanceof MultiBand) { +- MultiBand mb = (MultiBand) b; +- for (int i = 0; i < mb.bandCount; i++) { +- Band sub = mb.bands[i]; +- if (sub.phase != DONE_PHASE) { +- Utils.log.warning("assertDoneDisbursing: sub-band still in phase "+sub.phase+": "+sub); +- if (verbose() <= 1) return false; // fail now +- } +- } +- } +- return true; ++ if (b.phase != DISBURSE_PHASE) { ++ Utils.log.warning("assertDoneDisbursing: still in phase "+b.phase+": "+b); ++ if (verbose() <= 1) return false; // fail now ++ } ++ int left = b.valuesRemainingForDebug(); ++ if (left > 0) { ++ Utils.log.warning("assertDoneDisbursing: "+left+" values left in "+b); ++ if (verbose() <= 1) return false; // fail now ++ } ++ if (b instanceof MultiBand) { ++ MultiBand mb = (MultiBand) b; ++ for (int i = 0; i < mb.bandCount; i++) { ++ Band sub = mb.bands[i]; ++ if (sub.phase != DONE_PHASE) { ++ Utils.log.warning("assertDoneDisbursing: sub-band still in phase "+sub.phase+": "+sub); ++ if (verbose() <= 1) return false; // fail now ++ } ++ } ++ } ++ return true; + } + + static private void printCDecl(Band b) { +- if (b instanceof MultiBand) { +- MultiBand mb = (MultiBand) b; +- for (int i = 0; i < mb.bandCount; i++) { +- printCDecl(mb.bands[i]); +- } +- return; +- } +- String ixS = "NULL"; +- if (b instanceof CPRefBand) { +- Index ix = ((CPRefBand)b).index; +- if (ix != null) ixS = "INDEX("+ix.debugName+")"; +- } +- Coding[] knownc = { BYTE1, CHAR3, BCI5, BRANCH5, UNSIGNED5, +- UDELTA5, SIGNED5, DELTA5, MDELTA5 }; +- String[] knowns = { "BYTE1", "CHAR3", "BCI5", "BRANCH5", "UNSIGNED5", +- "UDELTA5", "SIGNED5", "DELTA5", "MDELTA5" }; +- Coding rc = b.regularCoding; +- int rci = Arrays.asList(knownc).indexOf(rc); +- String cstr; +- if (rci >= 0) +- cstr = knowns[rci]; +- else +- cstr = "CODING"+rc.keyString(); +- System.out.println(" BAND_INIT(\""+b.name()+"\"" +- +", "+cstr+", "+ixS+"),"); ++ if (b instanceof MultiBand) { ++ MultiBand mb = (MultiBand) b; ++ for (int i = 0; i < mb.bandCount; i++) { ++ printCDecl(mb.bands[i]); ++ } ++ return; ++ } ++ String ixS = "NULL"; ++ if (b instanceof CPRefBand) { ++ Index ix = ((CPRefBand)b).index; ++ if (ix != null) ixS = "INDEX("+ix.debugName+")"; ++ } ++ Coding[] knownc = { BYTE1, CHAR3, BCI5, BRANCH5, UNSIGNED5, ++ UDELTA5, SIGNED5, DELTA5, MDELTA5 }; ++ String[] knowns = { "BYTE1", "CHAR3", "BCI5", "BRANCH5", "UNSIGNED5", ++ "UDELTA5", "SIGNED5", "DELTA5", "MDELTA5" }; ++ Coding rc = b.regularCoding; ++ int rci = Arrays.asList(knownc).indexOf(rc); ++ String cstr; ++ if (rci >= 0) ++ cstr = knowns[rci]; ++ else ++ cstr = "CODING"+rc.keyString(); ++ System.out.println(" BAND_INIT(\""+b.name()+"\"" ++ +", "+cstr+", "+ixS+"),"); + } + + private HashMap prevForAssertMap; + + // DEBUG ONLY: Record something about the band order. + boolean notePrevForAssert(Band b, Band p) { +- if (prevForAssertMap == null) +- prevForAssertMap = new HashMap(); +- prevForAssertMap.put(b, p); +- return true; ++ if (prevForAssertMap == null) ++ prevForAssertMap = new HashMap(); ++ prevForAssertMap.put(b, p); ++ return true; + } + + // DEBUG ONLY: Validate next input band. + private boolean assertReadyToReadFrom(Band b, InputStream in) throws IOException { +- Band p = (Band) prevForAssertMap.get(b); +- // Any previous band must be done reading before this one starts. +- if (p != null && phaseCmp(p.phase(), DISBURSE_PHASE) < 0) { +- Utils.log.warning("Previous band not done reading."); +- Utils.log.info(" Previous band: "+p); +- Utils.log.info(" Next band: "+b); +- Thread.dumpStack(); +- assert(verbose > 0); // die unless verbose is true +- } +- String name = b.name; +- if (optDebugBands && !name.startsWith("(")) { +- // Verify synchronization between reader & writer: +- StringBuffer buf = new StringBuffer(); +- int ch; +- while ((ch = in.read()) > 0) +- buf.append((char)ch); +- String inName = buf.toString(); +- if (!inName.equals(name)) { +- StringBuffer sb = new StringBuffer(); +- sb.append("Expected "+name+" but read: "); +- inName += (char)ch; +- while (inName.length() < 10) +- inName += (char)in.read(); +- for (int i = 0; i < inName.length(); i++) +- sb.append(inName.charAt(i)); +- Utils.log.warning(sb.toString()); +- return false; +- } +- } +- return true; ++ Band p = (Band) prevForAssertMap.get(b); ++ // Any previous band must be done reading before this one starts. ++ if (p != null && phaseCmp(p.phase(), DISBURSE_PHASE) < 0) { ++ Utils.log.warning("Previous band not done reading."); ++ Utils.log.info(" Previous band: "+p); ++ Utils.log.info(" Next band: "+b); ++ Thread.dumpStack(); ++ assert(verbose > 0); // die unless verbose is true ++ } ++ String name = b.name; ++ if (optDebugBands && !name.startsWith("(")) { ++ // Verify synchronization between reader & writer: ++ StringBuffer buf = new StringBuffer(); ++ int ch; ++ while ((ch = in.read()) > 0) ++ buf.append((char)ch); ++ String inName = buf.toString(); ++ if (!inName.equals(name)) { ++ StringBuffer sb = new StringBuffer(); ++ sb.append("Expected "+name+" but read: "); ++ inName += (char)ch; ++ while (inName.length() < 10) ++ inName += (char)in.read(); ++ for (int i = 0; i < inName.length(); i++) ++ sb.append(inName.charAt(i)); ++ Utils.log.warning(sb.toString()); ++ return false; ++ } ++ } ++ return true; + } + + // DEBUG ONLY: Make sure a bunch of cprefs are correct. + private boolean assertValidCPRefs(CPRefBand b) { +- if (b.index == null) return true; +- int limit = b.index.size()+1; +- for (int i = 0; i < b.length(); i++) { +- int v = b.valueAtForDebug(i); +- if (v < 0 || v >= limit) { +- Utils.log.warning("CP ref out of range "+ +- "["+i+"] = "+v+" in "+b); +- return false; +- } +- } +- return true; ++ if (b.index == null) return true; ++ int limit = b.index.size()+1; ++ for (int i = 0; i < b.length(); i++) { ++ int v = b.valueAtForDebug(i); ++ if (v < 0 || v >= limit) { ++ Utils.log.warning("CP ref out of range "+ ++ "["+i+"] = "+v+" in "+b); ++ return false; ++ } ++ } ++ return true; + } + + // DEBUG ONLY: Maybe write a debugging cookie to next output band. + private boolean assertReadyToWriteTo(Band b, OutputStream out) throws IOException { +- Band p = (Band) prevForAssertMap.get(b); +- // Any previous band must be done writing before this one starts. +- if (p != null && phaseCmp(p.phase(), DONE_PHASE) < 0) { +- Utils.log.warning("Previous band not done writing."); +- Utils.log.info(" Previous band: "+p); +- Utils.log.info(" Next band: "+b); +- Thread.dumpStack(); +- assert(verbose > 0); // die unless verbose is true +- } +- String name = b.name; +- if (optDebugBands && !name.startsWith("(")) { +- // Verify synchronization between reader & writer: +- for (int j = 0; j < name.length(); j++) { +- out.write((byte)name.charAt(j)); +- } +- out.write((byte)0); +- } +- return true; ++ Band p = (Band) prevForAssertMap.get(b); ++ // Any previous band must be done writing before this one starts. ++ if (p != null && phaseCmp(p.phase(), DONE_PHASE) < 0) { ++ Utils.log.warning("Previous band not done writing."); ++ Utils.log.info(" Previous band: "+p); ++ Utils.log.info(" Next band: "+b); ++ Thread.dumpStack(); ++ assert(verbose > 0); // die unless verbose is true ++ } ++ String name = b.name; ++ if (optDebugBands && !name.startsWith("(")) { ++ // Verify synchronization between reader & writer: ++ for (int j = 0; j < name.length(); j++) { ++ out.write((byte)name.charAt(j)); ++ } ++ out.write((byte)0); ++ } ++ return true; + } + + protected static boolean testBit(int flags, int bitMask) { +- return (flags & bitMask) != 0; ++ return (flags & bitMask) != 0; + } + protected static int setBit(int flags, int bitMask, boolean z) { +- return z ? (flags | bitMask) : (flags &~ bitMask); ++ return z ? (flags | bitMask) : (flags &~ bitMask); + } + protected static boolean testBit(long flags, long bitMask) { +- return (flags & bitMask) != 0; ++ return (flags & bitMask) != 0; + } + protected static long setBit(long flags, long bitMask, boolean z) { +- return z ? (flags | bitMask) : (flags &~ bitMask); ++ return z ? (flags | bitMask) : (flags &~ bitMask); + } + + + static void printArrayTo(PrintStream ps, int[] values, int start, int end) { +- int len = end-start; +- for (int i = 0; i < len; i++) { +- if (i % 10 == 0) +- ps.println(); +- else +- ps.print(" "); +- ps.print(values[start+i]); +- } +- ps.println(); ++ int len = end-start; ++ for (int i = 0; i < len; i++) { ++ if (i % 10 == 0) ++ ps.println(); ++ else ++ ps.print(" "); ++ ps.print(values[start+i]); ++ } ++ ps.println(); + } + + static void printArrayTo(PrintStream ps, Entry[] cpMap, int start, int end) { +- StringBuffer buf = new StringBuffer(); +- int len = end-start; +- for (int i = 0; i < len; i++) { +- String s = cpMap[start+i].stringValue(); +- buf.setLength(0); +- for (int j = 0; j < s.length(); j++) { +- char ch = s.charAt(j); +- if (!(ch < ' ' || ch > '~' || ch == '\\')) { +- buf.append(ch); +- } else if (ch == '\n') { +- buf.append("\\n"); +- } else if (ch == '\t') { +- buf.append("\\t"); +- } else if (ch == '\r') { +- buf.append("\\r"); +- } else { +- buf.append("\\x"+Integer.toHexString(ch)); +- } +- } +- ps.println(buf); +- } ++ StringBuffer buf = new StringBuffer(); ++ int len = end-start; ++ for (int i = 0; i < len; i++) { ++ String s = cpMap[start+i].stringValue(); ++ buf.setLength(0); ++ for (int j = 0; j < s.length(); j++) { ++ char ch = s.charAt(j); ++ if (!(ch < ' ' || ch > '~' || ch == '\\')) { ++ buf.append(ch); ++ } else if (ch == '\n') { ++ buf.append("\\n"); ++ } else if (ch == '\t') { ++ buf.append("\\t"); ++ } else if (ch == '\r') { ++ buf.append("\\r"); ++ } else { ++ buf.append("\\x"+Integer.toHexString(ch)); ++ } ++ } ++ ps.println(buf); ++ } + } + + + // Utilities for reallocating: + protected static Object[] realloc(Object[] a, int len) { +- java.lang.Class elt = a.getClass().getComponentType(); +- Object[] na = (Object[]) java.lang.reflect.Array.newInstance(elt, len); +- System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); +- return na; ++ java.lang.Class elt = a.getClass().getComponentType(); ++ Object[] na = (Object[]) java.lang.reflect.Array.newInstance(elt, len); ++ System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); ++ return na; + } + protected static Object[] realloc(Object[] a) { +- return realloc(a, Math.max(10, a.length*2)); ++ return realloc(a, Math.max(10, a.length*2)); + } + static private int[] noInts = {}; + protected static int[] realloc(int[] a, int len) { +- if (len == 0) return noInts; +- if (a == null) return new int[len]; +- int[] na = new int[len]; +- System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); +- return na; ++ if (len == 0) return noInts; ++ if (a == null) return new int[len]; ++ int[] na = new int[len]; ++ System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); ++ return na; + } + protected static int[] realloc(int[] a) { +- return realloc(a, Math.max(10, a.length*2)); ++ return realloc(a, Math.max(10, a.length*2)); + } + static private byte[] noBytes = {}; + protected static byte[] realloc(byte[] a, int len) { +- if (len == 0) return noBytes; +- if (a == null) return new byte[len]; +- byte[] na = new byte[len]; +- System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); +- return na; ++ if (len == 0) return noBytes; ++ if (a == null) return new byte[len]; ++ byte[] na = new byte[len]; ++ System.arraycopy(a, 0, na, 0, Math.min(a.length, len)); ++ return na; + } + protected static byte[] realloc(byte[] a) { +- return realloc(a, Math.max(10, a.length*2)); ++ return realloc(a, Math.max(10, a.length*2)); + } + } ++ ++ +diff --git a/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java b/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java +--- jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java ++++ jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -22,7 +22,7 @@ + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +- ++ + package com.sun.java.util.jar.pack; + + import java.io.*; +@@ -37,7 +37,7 @@ class ConstantPool implements Constants + private ConstantPool() {} // do not instantiate + + static int verbose() { +- return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE); ++ return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE); + } + + // Uniquification tables for factory methods: +@@ -53,659 +53,659 @@ class ConstantPool implements Constants + * Also used to back up more complex constant pool entries, like Class. + */ + public static synchronized Utf8Entry getUtf8Entry(String value) { +- Utf8Entry e = (Utf8Entry) utf8Entries.get(value); +- if (e == null) { +- e = new Utf8Entry(value); +- utf8Entries.put(e.stringValue(), e); +- } +- return e; ++ Utf8Entry e = (Utf8Entry) utf8Entries.get(value); ++ if (e == null) { ++ e = new Utf8Entry(value); ++ utf8Entries.put(e.stringValue(), e); ++ } ++ return e; + } + /** Factory for Class constants. */ + public static synchronized ClassEntry getClassEntry(String name) { +- ClassEntry e = (ClassEntry) classEntries.get(name); +- if (e == null) { +- e = (ClassEntry) new ClassEntry(getUtf8Entry(name)); +- assert(name.equals(e.stringValue())); +- classEntries.put(e.stringValue(), e); +- } +- return e; ++ ClassEntry e = (ClassEntry) classEntries.get(name); ++ if (e == null) { ++ e = (ClassEntry) new ClassEntry(getUtf8Entry(name)); ++ assert(name.equals(e.stringValue())); ++ classEntries.put(e.stringValue(), e); ++ } ++ return e; + } + /** Factory for literal constants (String, Integer, etc.). */ + public static synchronized LiteralEntry getLiteralEntry(Comparable value) { +- LiteralEntry e = (LiteralEntry) literalEntries.get(value); +- if (e == null) { +- if (value instanceof String) +- e = new StringEntry(getUtf8Entry((String)value)); +- else +- e = new NumberEntry((Number)value); +- literalEntries.put(value, e); +- } +- return e; ++ LiteralEntry e = (LiteralEntry) literalEntries.get(value); ++ if (e == null) { ++ if (value instanceof String) ++ e = new StringEntry(getUtf8Entry((String)value)); ++ else ++ e = new NumberEntry((Number)value); ++ literalEntries.put(value, e); ++ } ++ return e; + } + /** Factory for literal constants (String, Integer, etc.). */ + public static synchronized StringEntry getStringEntry(String value) { +- return (StringEntry) getLiteralEntry(value); ++ return (StringEntry) getLiteralEntry(value); + } + + /** Factory for signature (type) constants. */ + public static synchronized SignatureEntry getSignatureEntry(String type) { +- SignatureEntry e = (SignatureEntry) signatureEntries.get(type); +- if (e == null) { +- e = new SignatureEntry(type); +- assert(e.stringValue().equals(type)); +- signatureEntries.put(type, e); +- } +- return e; ++ SignatureEntry e = (SignatureEntry) signatureEntries.get(type); ++ if (e == null) { ++ e = new SignatureEntry(type); ++ assert(e.stringValue().equals(type)); ++ signatureEntries.put(type, e); ++ } ++ return e; + } + // Convenience overloading. + public static SignatureEntry getSignatureEntry(Utf8Entry formRef, ClassEntry[] classRefs) { +- return getSignatureEntry(SignatureEntry.stringValueOf(formRef, classRefs)); ++ return getSignatureEntry(SignatureEntry.stringValueOf(formRef, classRefs)); + } + + /** Factory for descriptor (name-and-type) constants. */ + public static synchronized DescriptorEntry getDescriptorEntry(Utf8Entry nameRef, SignatureEntry typeRef) { +- String key = DescriptorEntry.stringValueOf(nameRef, typeRef); +- DescriptorEntry e = (DescriptorEntry) descriptorEntries.get(key); +- if (e == null) { +- e = new DescriptorEntry(nameRef, typeRef); +- assert(e.stringValue().equals(key)) +- : (e.stringValue()+" != "+(key)); +- descriptorEntries.put(key, e); +- } +- return e; ++ String key = DescriptorEntry.stringValueOf(nameRef, typeRef); ++ DescriptorEntry e = (DescriptorEntry) descriptorEntries.get(key); ++ if (e == null) { ++ e = new DescriptorEntry(nameRef, typeRef); ++ assert(e.stringValue().equals(key)) ++ : (e.stringValue()+" != "+(key)); ++ descriptorEntries.put(key, e); ++ } ++ return e; + } + // Convenience overloading. + public static DescriptorEntry getDescriptorEntry(Utf8Entry nameRef, Utf8Entry typeRef) { +- return getDescriptorEntry(nameRef, getSignatureEntry(typeRef.stringValue())); ++ return getDescriptorEntry(nameRef, getSignatureEntry(typeRef.stringValue())); + } + + /** Factory for member reference constants. */ + public static synchronized MemberEntry getMemberEntry(byte tag, ClassEntry classRef, DescriptorEntry descRef) { +- String key = MemberEntry.stringValueOf(tag, classRef, descRef); +- MemberEntry e = (MemberEntry) memberEntries.get(key); +- if (e == null) { +- e = new MemberEntry(tag, classRef, descRef); +- assert(e.stringValue().equals(key)) +- : (e.stringValue()+" != "+(key)); +- memberEntries.put(key, e); +- } +- return e; ++ String key = MemberEntry.stringValueOf(tag, classRef, descRef); ++ MemberEntry e = (MemberEntry) memberEntries.get(key); ++ if (e == null) { ++ e = new MemberEntry(tag, classRef, descRef); ++ assert(e.stringValue().equals(key)) ++ : (e.stringValue()+" != "+(key)); ++ memberEntries.put(key, e); ++ } ++ return e; + } + + + /** Entries in the constant pool. */ + public static abstract + class Entry implements Comparable { +- protected final byte tag; // a CONSTANT_foo code +- protected int valueHash; // cached hashCode ++ protected final byte tag; // a CONSTANT_foo code ++ protected int valueHash; // cached hashCode + +- protected Entry(byte tag) { +- this.tag = tag; +- } ++ protected Entry(byte tag) { ++ this.tag = tag; ++ } + +- public final byte getTag() { +- return tag; +- } ++ public final byte getTag() { ++ return tag; ++ } + +- public Entry getRef(int i) { +- return null; +- } ++ public Entry getRef(int i) { ++ return null; ++ } + +- public boolean sameTagAs(Object o) { +- return (o instanceof Entry) && ((Entry)o).tag == tag; +- } +- public boolean eq(Entry that) { // same reference +- assert(that != null); +- return this == that || this.equals(that); +- } ++ public boolean sameTagAs(Object o) { ++ return (o instanceof Entry) && ((Entry)o).tag == tag; ++ } ++ public boolean eq(Entry that) { // same reference ++ assert(that != null); ++ return this == that || this.equals(that); ++ } + +- // Equality of Entries is value-based. +- public abstract boolean equals(Object o); +- public final int hashCode() { +- if (valueHash == 0) { +- valueHash = computeValueHash(); +- if (valueHash == 0) valueHash = 1; +- } +- return valueHash; +- } +- protected abstract int computeValueHash(); ++ // Equality of Entries is value-based. ++ public abstract boolean equals(Object o); ++ public final int hashCode() { ++ if (valueHash == 0) { ++ valueHash = computeValueHash(); ++ if (valueHash == 0) valueHash = 1; ++ } ++ return valueHash; ++ } ++ protected abstract int computeValueHash(); + +- public abstract int compareTo(Object o); ++ public abstract int compareTo(Object o); + +- protected int superCompareTo(Object o) { +- Entry that = (Entry) o; ++ protected int superCompareTo(Object o) { ++ Entry that = (Entry) o; + +- if (this.tag != that.tag) { +- return TAG_ORDER[this.tag] - TAG_ORDER[that.tag]; +- } ++ if (this.tag != that.tag) { ++ return TAG_ORDER[this.tag] - TAG_ORDER[that.tag]; ++ } + +- return 0; // subclasses must refine this +- } ++ return 0; // subclasses must refine this ++ } + +- public final boolean isDoubleWord() { +- return tag == CONSTANT_Double || tag == CONSTANT_Long; +- } ++ public final boolean isDoubleWord() { ++ return tag == CONSTANT_Double || tag == CONSTANT_Long; ++ } + +- public final boolean tagMatches(int tag) { +- return (this.tag == tag); +- } ++ public final boolean tagMatches(int tag) { ++ return (this.tag == tag); ++ } + +- public String toString() { +- String valuePrint = stringValue(); +- if (verbose() > 4) { +- if (valueHash != 0) +- valuePrint += " hash="+valueHash; +- valuePrint += " id="+System.identityHashCode(this); +- } +- return tagName(tag)+"="+valuePrint; +- } +- public abstract String stringValue(); ++ public String toString() { ++ String valuePrint = stringValue(); ++ if (verbose() > 4) { ++ if (valueHash != 0) ++ valuePrint += " hash="+valueHash; ++ valuePrint += " id="+System.identityHashCode(this); ++ } ++ return tagName(tag)+"="+valuePrint; ++ } ++ public abstract String stringValue(); + } + + public static + class Utf8Entry extends Entry { +- final String value; ++ final String value; + +- Utf8Entry(String value) { +- super(CONSTANT_Utf8); +- this.value = value.intern(); +- hashCode(); // force computation of valueHash +- } +- protected int computeValueHash() { +- return value.hashCode(); +- } +- public boolean equals(Object o) { +- if (!sameTagAs(o)) return false; +- // Use reference equality of interned strings: +- return ((Utf8Entry)o).value == value; +- } +- public int compareTo(Object o) { +- int x = superCompareTo(o); +- if (x == 0) { +- x = value.compareTo(((Utf8Entry)o).value); +- } +- return x; +- } +- public String stringValue() { +- return value; +- } ++ Utf8Entry(String value) { ++ super(CONSTANT_Utf8); ++ this.value = value.intern(); ++ hashCode(); // force computation of valueHash ++ } ++ protected int computeValueHash() { ++ return value.hashCode(); ++ } ++ public boolean equals(Object o) { ++ if (!sameTagAs(o)) return false; ++ // Use reference equality of interned strings: ++ return ((Utf8Entry)o).value == value; ++ } ++ public int compareTo(Object o) { ++ int x = superCompareTo(o); ++ if (x == 0) { ++ x = value.compareTo(((Utf8Entry)o).value); ++ } ++ return x; ++ } ++ public String stringValue() { ++ return value; ++ } + } + + static boolean isMemberTag(byte tag) { +- switch (tag) { +- case CONSTANT_Fieldref: +- case CONSTANT_Methodref: +- case CONSTANT_InterfaceMethodref: +- return true; +- } +- return false; ++ switch (tag) { ++ case CONSTANT_Fieldref: ++ case CONSTANT_Methodref: ++ case CONSTANT_InterfaceMethodref: ++ return true; ++ } ++ return false; + } + + static byte numberTagOf(Number value) { +- if (value instanceof Integer) return CONSTANT_Integer; +- if (value instanceof Float) return CONSTANT_Float; +- if (value instanceof Long) return CONSTANT_Long; +- if (value instanceof Double) return CONSTANT_Double; +- throw new RuntimeException("bad literal value "+value); ++ if (value instanceof Integer) return CONSTANT_Integer; ++ if (value instanceof Float) return CONSTANT_Float; ++ if (value instanceof Long) return CONSTANT_Long; ++ if (value instanceof Double) return CONSTANT_Double; ++ throw new RuntimeException("bad literal value "+value); + } + + public static abstract + class LiteralEntry extends Entry { +- protected LiteralEntry(byte tag) { +- super(tag); +- } ++ protected LiteralEntry(byte tag) { ++ super(tag); ++ } + +- public abstract Comparable literalValue(); ++ public abstract Comparable literalValue(); + } + + public static + class NumberEntry extends LiteralEntry { +- final Number value; +- NumberEntry(Number value) { +- super(numberTagOf(value)); +- this.value = value; +- hashCode(); // force computation of valueHash +- } +- protected int computeValueHash() { +- return value.hashCode(); +- } ++ final Number value; ++ NumberEntry(Number value) { ++ super(numberTagOf(value)); ++ this.value = value; ++ hashCode(); // force computation of valueHash ++ } ++ protected int computeValueHash() { ++ return value.hashCode(); ++ } + +- public boolean equals(Object o) { +- if (!sameTagAs(o)) return false; +- return (((NumberEntry)o).value).equals(value); +- } +- public int compareTo(Object o) { +- int x = superCompareTo(o); +- if (x == 0) { +- x = ((Comparable)value).compareTo(((NumberEntry)o).value); +- } +- return x; +- } +- public Number numberValue() { +- return value; +- } +- public Comparable literalValue() { +- return (Comparable) value; +- } +- public String stringValue() { +- return value.toString(); +- } ++ public boolean equals(Object o) { ++ if (!sameTagAs(o)) return false; ++ return (((NumberEntry)o).value).equals(value); ++ } ++ public int compareTo(Object o) { ++ int x = superCompareTo(o); ++ if (x == 0) { ++ x = ((Comparable)value).compareTo(((NumberEntry)o).value); ++ } ++ return x; ++ } ++ public Number numberValue() { ++ return value; ++ } ++ public Comparable literalValue() { ++ return (Comparable) value; ++ } ++ public String stringValue() { ++ return value.toString(); ++ } + } + + public static + class StringEntry extends LiteralEntry { +- final Utf8Entry ref; +- public Entry getRef(int i) { return i == 0 ? ref : null; } ++ final Utf8Entry ref; ++ public Entry getRef(int i) { return i == 0 ? ref : null; } + +- StringEntry(Entry ref) { +- super(CONSTANT_String); +- this.ref = (Utf8Entry) ref; +- hashCode(); // force computation of valueHash +- } +- protected int computeValueHash() { +- return ref.hashCode() + tag; +- } +- public boolean equals(Object o) { +- if (!sameTagAs(o)) return false; +- return ((StringEntry)o).ref.eq(ref); +- } +- public int compareTo(Object o) { +- int x = superCompareTo(o); +- if (x == 0) { +- x = ref.compareTo(((StringEntry)o).ref); +- } +- return x; +- } +- public Comparable literalValue() { +- return ref.stringValue(); +- } +- public String stringValue() { +- return ref.stringValue(); +- } ++ StringEntry(Entry ref) { ++ super(CONSTANT_String); ++ this.ref = (Utf8Entry) ref; ++ hashCode(); // force computation of valueHash ++ } ++ protected int computeValueHash() { ++ return ref.hashCode() + tag; ++ } ++ public boolean equals(Object o) { ++ if (!sameTagAs(o)) return false; ++ return ((StringEntry)o).ref.eq(ref); ++ } ++ public int compareTo(Object o) { ++ int x = superCompareTo(o); ++ if (x == 0) { ++ x = ref.compareTo(((StringEntry)o).ref); ++ } ++ return x; ++ } ++ public Comparable literalValue() { ++ return ref.stringValue(); ++ } ++ public String stringValue() { ++ return ref.stringValue(); ++ } + } + + public static + class ClassEntry extends Entry { +- final Utf8Entry ref; +- public Entry getRef(int i) { return i == 0 ? ref : null; } ++ final Utf8Entry ref; ++ public Entry getRef(int i) { return i == 0 ? ref : null; } + +- protected int computeValueHash() { +- return ref.hashCode() + tag; +- } +- ClassEntry(Entry ref) { +- super(CONSTANT_Class); +- this.ref = (Utf8Entry) ref; +- hashCode(); // force computation of valueHash +- } +- public boolean equals(Object o) { +- if (!sameTagAs(o)) return false; +- return ((ClassEntry)o).ref.eq(ref); +- } +- public int compareTo(Object o) { +- int x = superCompareTo(o); +- if (x == 0) { +- x = ref.compareTo(((ClassEntry)o).ref); +- } +- return x; +- } +- public String stringValue() { +- return ref.stringValue(); +- } ++ protected int computeValueHash() { ++ return ref.hashCode() + tag; ++ } ++ ClassEntry(Entry ref) { ++ super(CONSTANT_Class); ++ this.ref = (Utf8Entry) ref; ++ hashCode(); // force computation of valueHash ++ } ++ public boolean equals(Object o) { ++ if (!sameTagAs(o)) return false; ++ return ((ClassEntry)o).ref.eq(ref); ++ } ++ public int compareTo(Object o) { ++ int x = superCompareTo(o); ++ if (x == 0) { ++ x = ref.compareTo(((ClassEntry)o).ref); ++ } ++ return x; ++ } ++ public String stringValue() { ++ return ref.stringValue(); ++ } + } + + public static + class DescriptorEntry extends Entry { +- final Utf8Entry nameRef; +- final SignatureEntry typeRef; +- public Entry getRef(int i) { +- if (i == 0) return nameRef; +- if (i == 1) return typeRef; +- return null; +- } +- DescriptorEntry(Entry nameRef, Entry typeRef) { +- super(CONSTANT_NameandType); +- if (typeRef instanceof Utf8Entry) { +- typeRef = getSignatureEntry(typeRef.stringValue()); +- } +- this.nameRef = (Utf8Entry) nameRef; +- this.typeRef = (SignatureEntry) typeRef; +- hashCode(); // force computation of valueHash +- } +- protected int computeValueHash() { +- int hc2 = typeRef.hashCode(); +- return (nameRef.hashCode() + (hc2 << 8)) ^ hc2; +- } +- public boolean equals(Object o) { +- if (!sameTagAs(o)) return false; +- DescriptorEntry that = (DescriptorEntry)o; +- return this.nameRef.eq(that.nameRef) +- && this.typeRef.eq(that.typeRef); +- } +- public int compareTo(Object o) { +- int x = superCompareTo(o); +- if (x == 0) { +- DescriptorEntry that = (DescriptorEntry)o; +- // Primary key is typeRef, not nameRef. +- x = this.typeRef.compareTo(that.typeRef); +- if (x == 0) +- x = this.nameRef.compareTo(that.nameRef); +- } +- return x; +- } +- public String stringValue() { +- return stringValueOf(nameRef, typeRef); +- } +- static +- String stringValueOf(Entry nameRef, Entry typeRef) { +- return typeRef.stringValue()+","+nameRef.stringValue(); +- } ++ final Utf8Entry nameRef; ++ final SignatureEntry typeRef; ++ public Entry getRef(int i) { ++ if (i == 0) return nameRef; ++ if (i == 1) return typeRef; ++ return null; ++ } ++ DescriptorEntry(Entry nameRef, Entry typeRef) { ++ super(CONSTANT_NameandType); ++ if (typeRef instanceof Utf8Entry) { ++ typeRef = getSignatureEntry(typeRef.stringValue()); ++ } ++ this.nameRef = (Utf8Entry) nameRef; ++ this.typeRef = (SignatureEntry) typeRef; ++ hashCode(); // force computation of valueHash ++ } ++ protected int computeValueHash() { ++ int hc2 = typeRef.hashCode(); ++ return (nameRef.hashCode() + (hc2 << 8)) ^ hc2; ++ } ++ public boolean equals(Object o) { ++ if (!sameTagAs(o)) return false; ++ DescriptorEntry that = (DescriptorEntry)o; ++ return this.nameRef.eq(that.nameRef) ++ && this.typeRef.eq(that.typeRef); ++ } ++ public int compareTo(Object o) { ++ int x = superCompareTo(o); ++ if (x == 0) { ++ DescriptorEntry that = (DescriptorEntry)o; ++ // Primary key is typeRef, not nameRef. ++ x = this.typeRef.compareTo(that.typeRef); ++ if (x == 0) ++ x = this.nameRef.compareTo(that.nameRef); ++ } ++ return x; ++ } ++ public String stringValue() { ++ return stringValueOf(nameRef, typeRef); ++ } ++ static ++ String stringValueOf(Entry nameRef, Entry typeRef) { ++ return typeRef.stringValue()+","+nameRef.stringValue(); ++ } + +- public String prettyString() { +- return nameRef.stringValue()+typeRef.prettyString(); +- } ++ public String prettyString() { ++ return nameRef.stringValue()+typeRef.prettyString(); ++ } + +- public boolean isMethod() { +- return typeRef.isMethod(); +- } ++ public boolean isMethod() { ++ return typeRef.isMethod(); ++ } + +- public byte getLiteralTag() { +- return typeRef.getLiteralTag(); +- } ++ public byte getLiteralTag() { ++ return typeRef.getLiteralTag(); ++ } + } + + public static + class MemberEntry extends Entry { +- final ClassEntry classRef; +- final DescriptorEntry descRef; +- public Entry getRef(int i) { +- if (i == 0) return classRef; +- if (i == 1) return descRef; +- return null; +- } +- protected int computeValueHash() { +- int hc2 = descRef.hashCode(); +- return (classRef.hashCode() + (hc2 << 8)) ^ hc2; +- } ++ final ClassEntry classRef; ++ final DescriptorEntry descRef; ++ public Entry getRef(int i) { ++ if (i == 0) return classRef; ++ if (i == 1) return descRef; ++ return null; ++ } ++ protected int computeValueHash() { ++ int hc2 = descRef.hashCode(); ++ return (classRef.hashCode() + (hc2 << 8)) ^ hc2; ++ } + +- MemberEntry(byte tag, ClassEntry classRef, DescriptorEntry descRef) { +- super(tag); +- assert(isMemberTag(tag)); +- this.classRef = classRef; +- this.descRef = descRef; +- hashCode(); // force computation of valueHash +- } +- public boolean equals(Object o) { +- if (!sameTagAs(o)) return false; +- MemberEntry that = (MemberEntry)o; +- return this.classRef.eq(that.classRef) +- && this.descRef.eq(that.descRef); +- } +- public int compareTo(Object o) { +- int x = superCompareTo(o); +- if (x == 0) { +- MemberEntry that = (MemberEntry)o; +- // Primary key is classRef. +- x = this.classRef.compareTo(that.classRef); +- if (x == 0) +- x = this.descRef.compareTo(that.descRef); +- } +- return x; +- } +- public String stringValue() { +- return stringValueOf(tag, classRef, descRef); +- } +- static +- String stringValueOf(byte tag, ClassEntry classRef, DescriptorEntry descRef) { +- assert(isMemberTag(tag)); +- String pfx; +- switch (tag) { +- case CONSTANT_Fieldref: pfx = "Field:"; break; +- case CONSTANT_Methodref: pfx = "Method:"; break; +- case CONSTANT_InterfaceMethodref: pfx = "IMethod:"; break; +- default: pfx = tag+"???"; break; +- } +- return pfx+classRef.stringValue()+","+descRef.stringValue(); +- } ++ MemberEntry(byte tag, ClassEntry classRef, DescriptorEntry descRef) { ++ super(tag); ++ assert(isMemberTag(tag)); ++ this.classRef = classRef; ++ this.descRef = descRef; ++ hashCode(); // force computation of valueHash ++ } ++ public boolean equals(Object o) { ++ if (!sameTagAs(o)) return false; ++ MemberEntry that = (MemberEntry)o; ++ return this.classRef.eq(that.classRef) ++ && this.descRef.eq(that.descRef); ++ } ++ public int compareTo(Object o) { ++ int x = superCompareTo(o); ++ if (x == 0) { ++ MemberEntry that = (MemberEntry)o; ++ // Primary key is classRef. ++ x = this.classRef.compareTo(that.classRef); ++ if (x == 0) ++ x = this.descRef.compareTo(that.descRef); ++ } ++ return x; ++ } ++ public String stringValue() { ++ return stringValueOf(tag, classRef, descRef); ++ } ++ static ++ String stringValueOf(byte tag, ClassEntry classRef, DescriptorEntry descRef) { ++ assert(isMemberTag(tag)); ++ String pfx; ++ switch (tag) { ++ case CONSTANT_Fieldref: pfx = "Field:"; break; ++ case CONSTANT_Methodref: pfx = "Method:"; break; ++ case CONSTANT_InterfaceMethodref: pfx = "IMethod:"; break; ++ default: pfx = tag+"???"; break; ++ } ++ return pfx+classRef.stringValue()+","+descRef.stringValue(); ++ } + +- public boolean isMethod() { +- return descRef.isMethod(); +- } ++ public boolean isMethod() { ++ return descRef.isMethod(); ++ } + } + + public static + class SignatureEntry extends Entry { +- final Utf8Entry formRef; +- final ClassEntry[] classRefs; +- String value; +- Utf8Entry asUtf8Entry; +- public Entry getRef(int i) { +- if (i == 0) return formRef; +- return i-1 < classRefs.length ? classRefs[i-1] : null; +- } +- SignatureEntry(String value) { +- super(CONSTANT_Signature); +- value = value.intern(); // always do this +- this.value = value; +- String[] parts = structureSignature(value); +- formRef = getUtf8Entry(parts[0]); +- classRefs = new ClassEntry[parts.length-1]; +- for (int i = 1; i < parts.length; i++) +- classRefs[i-1] = getClassEntry(parts[i]); +- hashCode(); // force computation of valueHash +- } +- protected int computeValueHash() { +- stringValue(); // force computation of value +- return value.hashCode() + tag; +- } ++ final Utf8Entry formRef; ++ final ClassEntry[] classRefs; ++ String value; ++ Utf8Entry asUtf8Entry; ++ public Entry getRef(int i) { ++ if (i == 0) return formRef; ++ return i-1 < classRefs.length ? classRefs[i-1] : null; ++ } ++ SignatureEntry(String value) { ++ super(CONSTANT_Signature); ++ value = value.intern(); // always do this ++ this.value = value; ++ String[] parts = structureSignature(value); ++ formRef = getUtf8Entry(parts[0]); ++ classRefs = new ClassEntry[parts.length-1]; ++ for (int i = 1; i < parts.length; i++) ++ classRefs[i-1] = getClassEntry(parts[i]); ++ hashCode(); // force computation of valueHash ++ } ++ protected int computeValueHash() { ++ stringValue(); // force computation of value ++ return value.hashCode() + tag; ++ } + +- public Utf8Entry asUtf8Entry() { +- if (asUtf8Entry == null) { +- asUtf8Entry = getUtf8Entry(stringValue()); +- } +- return asUtf8Entry; +- } ++ public Utf8Entry asUtf8Entry() { ++ if (asUtf8Entry == null) { ++ asUtf8Entry = getUtf8Entry(stringValue()); ++ } ++ return asUtf8Entry; ++ } + +- public boolean equals(Object o) { +- if (!sameTagAs(o)) return false; +- return ((SignatureEntry)o).value == value; +- } +- public int compareTo(Object o) { +- int x = superCompareTo(o); +- if (x == 0) { +- SignatureEntry that = (SignatureEntry)o; +- x = compareSignatures(this.value, that.value); +- } +- return x; +- } +- public String stringValue() { +- if (value == null) { +- value = stringValueOf(formRef, classRefs); +- } +- return value; +- } +- static +- String stringValueOf(Utf8Entry formRef, ClassEntry[] classRefs) { +- String[] parts = new String[1+classRefs.length]; +- parts[0] = formRef.stringValue(); +- for (int i = 1; i < parts.length; i++) +- parts[i] = classRefs[i-1].stringValue(); +- return flattenSignature(parts).intern(); +- } ++ public boolean equals(Object o) { ++ if (!sameTagAs(o)) return false; ++ return ((SignatureEntry)o).value == value; ++ } ++ public int compareTo(Object o) { ++ int x = superCompareTo(o); ++ if (x == 0) { ++ SignatureEntry that = (SignatureEntry)o; ++ x = compareSignatures(this.value, that.value); ++ } ++ return x; ++ } ++ public String stringValue() { ++ if (value == null) { ++ value = stringValueOf(formRef, classRefs); ++ } ++ return value; ++ } ++ static ++ String stringValueOf(Utf8Entry formRef, ClassEntry[] classRefs) { ++ String[] parts = new String[1+classRefs.length]; ++ parts[0] = formRef.stringValue(); ++ for (int i = 1; i < parts.length; i++) ++ parts[i] = classRefs[i-1].stringValue(); ++ return flattenSignature(parts).intern(); ++ } + +- public int computeSize(boolean countDoublesTwice) { +- String form = formRef.stringValue(); +- int min = 0; +- int max = 1; +- if (isMethod()) { +- min = 1; +- max = form.indexOf(')'); +- } +- int size = 0; +- for (int i = min; i < max; i++) { +- switch (form.charAt(i)) { +- case 'D': +- case 'J': +- if (countDoublesTwice) size++; +- break; +- case '[': +- // Skip rest of array info. +- while (form.charAt(i) == '[') ++i; +- break; +- case ';': +- continue; +- default: +- assert(0 <= JAVA_SIGNATURE_CHARS.indexOf(form.charAt(i))); +- break; +- } +- size++; +- } +- return size; +- } +- public boolean isMethod() { +- return formRef.stringValue().charAt(0) == '('; +- } +- public byte getLiteralTag() { +- switch (formRef.stringValue().charAt(0)) { +- case 'L': return CONSTANT_String; +- case 'I': return CONSTANT_Integer; +- case 'J': return CONSTANT_Long; +- case 'F': return CONSTANT_Float; +- case 'D': return CONSTANT_Double; +- case 'B': case 'S': case 'C': case 'Z': +- return CONSTANT_Integer; +- } +- assert(false); +- return CONSTANT_None; +- } +- public String prettyString() { +- String s; +- if (isMethod()) { +- s = formRef.stringValue(); +- s = s.substring(0, 1+s.indexOf(')')); +- } else { +- s = "/" + formRef.stringValue(); +- } +- int i; +- while ((i = s.indexOf(';')) >= 0) +- s = s.substring(0,i) + s.substring(i+1); +- return s; +- } ++ public int computeSize(boolean countDoublesTwice) { ++ String form = formRef.stringValue(); ++ int min = 0; ++ int max = 1; ++ if (isMethod()) { ++ min = 1; ++ max = form.indexOf(')'); ++ } ++ int size = 0; ++ for (int i = min; i < max; i++) { ++ switch (form.charAt(i)) { ++ case 'D': ++ case 'J': ++ if (countDoublesTwice) size++; ++ break; ++ case '[': ++ // Skip rest of array info. ++ while (form.charAt(i) == '[') ++i; ++ break; ++ case ';': ++ continue; ++ default: ++ assert(0 <= JAVA_SIGNATURE_CHARS.indexOf(form.charAt(i))); ++ break; ++ } ++ size++; ++ } ++ return size; ++ } ++ public boolean isMethod() { ++ return formRef.stringValue().charAt(0) == '('; ++ } ++ public byte getLiteralTag() { ++ switch (formRef.stringValue().charAt(0)) { ++ case 'L': return CONSTANT_String; ++ case 'I': return CONSTANT_Integer; ++ case 'J': return CONSTANT_Long; ++ case 'F': return CONSTANT_Float; ++ case 'D': return CONSTANT_Double; ++ case 'B': case 'S': case 'C': case 'Z': ++ return CONSTANT_Integer; ++ } ++ assert(false); ++ return CONSTANT_None; ++ } ++ public String prettyString() { ++ String s; ++ if (isMethod()) { ++ s = formRef.stringValue(); ++ s = s.substring(0, 1+s.indexOf(')')); ++ } else { ++ s = "/" + formRef.stringValue(); ++ } ++ int i; ++ while ((i = s.indexOf(';')) >= 0) ++ s = s.substring(0,i) + s.substring(i+1); ++ return s; ++ } + } + + static int compareSignatures(String s1, String s2) { +- return compareSignatures(s1, s2, null, null); ++ return compareSignatures(s1, s2, null, null); + } + static int compareSignatures(String s1, String s2, String[] p1, String[] p2) { +- final int S1_COMES_FIRST = -1; +- final int S2_COMES_FIRST = +1; +- char c1 = s1.charAt(0); +- char c2 = s2.charAt(0); +- // fields before methods (because there are fewer of them) +- if (c1 != '(' && c2 == '(') return S1_COMES_FIRST; +- if (c2 != '(' && c1 == '(') return S2_COMES_FIRST; +- if (p1 == null) p1 = structureSignature(s1); +- if (p2 == null) p2 = structureSignature(s2); +- /* +- // non-classes before classes (because there are fewer of them) +- if (p1.length == 1 && p2.length > 1) return S1_COMES_FIRST; +- if (p2.length == 1 && p1.length > 1) return S2_COMES_FIRST; +- // all else being equal, use the same comparison as for Utf8 strings +- return s1.compareTo(s2); +- */ +- if (p1.length != p2.length) return p1.length - p2.length; +- int length = p1.length; +- for (int i = length; --i >= 0; ) { +- int res = p1[i].compareTo(p2[i]); +- if (res != 0) return res; +- } +- assert(s1.equals(s2)); +- return 0; ++ final int S1_COMES_FIRST = -1; ++ final int S2_COMES_FIRST = +1; ++ char c1 = s1.charAt(0); ++ char c2 = s2.charAt(0); ++ // fields before methods (because there are fewer of them) ++ if (c1 != '(' && c2 == '(') return S1_COMES_FIRST; ++ if (c2 != '(' && c1 == '(') return S2_COMES_FIRST; ++ if (p1 == null) p1 = structureSignature(s1); ++ if (p2 == null) p2 = structureSignature(s2); ++ /* ++ // non-classes before classes (because there are fewer of them) ++ if (p1.length == 1 && p2.length > 1) return S1_COMES_FIRST; ++ if (p2.length == 1 && p1.length > 1) return S2_COMES_FIRST; ++ // all else being equal, use the same comparison as for Utf8 strings ++ return s1.compareTo(s2); ++ */ ++ if (p1.length != p2.length) return p1.length - p2.length; ++ int length = p1.length; ++ for (int i = length; --i >= 0; ) { ++ int res = p1[i].compareTo(p2[i]); ++ if (res != 0) return res; ++ } ++ assert(s1.equals(s2)); ++ return 0; + } + + static int countClassParts(Utf8Entry formRef) { +- int num = 0; +- String s = formRef.stringValue(); +- for (int i = 0; i < s.length(); i++) { +- if (s.charAt(i) == 'L') ++num; +- } +- return num; ++ int num = 0; ++ String s = formRef.stringValue(); ++ for (int i = 0; i < s.length(); i++) { ++ if (s.charAt(i) == 'L') ++num; ++ } ++ return num; + } + + static String flattenSignature(String[] parts) { +- String form = parts[0]; +- if (parts.length == 1) return form; +- int len = form.length(); +- for (int i = 1; i < parts.length; i++) { +- len += parts[i].length(); +- } +- char[] sig = new char[len]; +- int j = 0; +- int k = 1; +- for (int i = 0; i < form.length(); i++) { +- char ch = form.charAt(i); +- sig[j++] = ch; +- if (ch == 'L') { +- String cls = parts[k++]; +- cls.getChars(0, cls.length(), sig, j); +- j += cls.length(); +- //sig[j++] = ';'; +- } +- } +- assert(j == len); +- assert(k == parts.length); +- return new String(sig); ++ String form = parts[0]; ++ if (parts.length == 1) return form; ++ int len = form.length(); ++ for (int i = 1; i < parts.length; i++) { ++ len += parts[i].length(); ++ } ++ char[] sig = new char[len]; ++ int j = 0; ++ int k = 1; ++ for (int i = 0; i < form.length(); i++) { ++ char ch = form.charAt(i); ++ sig[j++] = ch; ++ if (ch == 'L') { ++ String cls = parts[k++]; ++ cls.getChars(0, cls.length(), sig, j); ++ j += cls.length(); ++ //sig[j++] = ';'; ++ } ++ } ++ assert(j == len); ++ assert(k == parts.length); ++ return new String(sig); + } + + static private int skipClassNameChars(String sig, int i) { +- int len = sig.length(); +- for (; i < len; i++) { +- char ch = sig.charAt(i); +- if (ch <= ' ') break; +- if (ch >= ';' && ch <= '@') break; +- } +- return i; ++ int len = sig.length(); ++ for (; i < len; i++) { ++ char ch = sig.charAt(i); ++ if (ch <= ' ') break; ++ if (ch >= ';' && ch <= '@') break; ++ } ++ return i; + } + + static String[] structureSignature(String sig) { +- sig = sig.intern(); ++ sig = sig.intern(); + +- int formLen = 0; +- int nparts = 1; +- for (int i = 0; i < sig.length(); i++) { +- char ch = sig.charAt(i); +- formLen++; +- if (ch == 'L') { +- nparts++; +- int i2 = skipClassNameChars(sig, i+1); +- i = i2-1; // keep the semicolon in the form +- int i3 = sig.indexOf('<', i+1); +- if (i3 > 0 && i3 < i2) +- i = i3-1; +- } +- } +- char[] form = new char[formLen]; +- if (nparts == 1) { +- String[] parts = { sig }; +- return parts; +- } +- String[] parts = new String[nparts]; +- int j = 0; +- int k = 1; +- for (int i = 0; i < sig.length(); i++) { +- char ch = sig.charAt(i); +- form[j++] = ch; +- if (ch == 'L') { +- int i2 = skipClassNameChars(sig, i+1); +- parts[k++] = sig.substring(i+1, i2); +- i = i2; +- --i; // keep the semicolon in the form +- } +- } +- assert(j == formLen); +- assert(k == parts.length); +- parts[0] = new String(form); +- //assert(flattenSignature(parts).equals(sig)); +- return parts; ++ int formLen = 0; ++ int nparts = 1; ++ for (int i = 0; i < sig.length(); i++) { ++ char ch = sig.charAt(i); ++ formLen++; ++ if (ch == 'L') { ++ nparts++; ++ int i2 = skipClassNameChars(sig, i+1); ++ i = i2-1; // keep the semicolon in the form ++ int i3 = sig.indexOf('<', i+1); ++ if (i3 > 0 && i3 < i2) ++ i = i3-1; ++ } ++ } ++ char[] form = new char[formLen]; ++ if (nparts == 1) { ++ String[] parts = { sig }; ++ return parts; ++ } ++ String[] parts = new String[nparts]; ++ int j = 0; ++ int k = 1; ++ for (int i = 0; i < sig.length(); i++) { ++ char ch = sig.charAt(i); ++ form[j++] = ch; ++ if (ch == 'L') { ++ int i2 = skipClassNameChars(sig, i+1); ++ parts[k++] = sig.substring(i+1, i2); ++ i = i2; ++ --i; // keep the semicolon in the form ++ } ++ } ++ assert(j == formLen); ++ assert(k == parts.length); ++ parts[0] = new String(form); ++ //assert(flattenSignature(parts).equals(sig)); ++ return parts; + } + + // Handy constants: +@@ -715,182 +715,182 @@ class ConstantPool implements Constants + /** An Index is a mapping between CP entries and small integers. */ + public static + class Index extends AbstractList { +- protected String debugName; +- protected Entry[] cpMap; +- protected boolean flattenSigs; +- protected Entry[] getMap() { +- return cpMap; +- } +- protected Index(String debugName) { +- this.debugName = debugName; +- } +- protected Index(String debugName, Entry[] cpMap) { +- this(debugName); +- setMap(cpMap); +- } +- protected void setMap(Entry[] cpMap) { +- clearIndex(); +- this.cpMap = cpMap; +- } +- protected Index(String debugName, Collection cpMapList) { +- this(debugName); +- setMap(cpMapList); +- } +- protected void setMap(Collection cpMapList) { +- cpMap = new Entry[cpMapList.size()]; +- cpMapList.toArray(cpMap); +- setMap(cpMap); +- } +- public int size() { +- return cpMap.length; +- } +- public Object get(int i) { +- return cpMap[i]; +- } +- public Entry getEntry(int i) { +- // same as get(), with covariant return type +- return cpMap[i]; +- } ++ protected String debugName; ++ protected Entry[] cpMap; ++ protected boolean flattenSigs; ++ protected Entry[] getMap() { ++ return cpMap; ++ } ++ protected Index(String debugName) { ++ this.debugName = debugName; ++ } ++ protected Index(String debugName, Entry[] cpMap) { ++ this(debugName); ++ setMap(cpMap); ++ } ++ protected void setMap(Entry[] cpMap) { ++ clearIndex(); ++ this.cpMap = cpMap; ++ } ++ protected Index(String debugName, Collection cpMapList) { ++ this(debugName); ++ setMap(cpMapList); ++ } ++ protected void setMap(Collection cpMapList) { ++ cpMap = new Entry[cpMapList.size()]; ++ cpMapList.toArray(cpMap); ++ setMap(cpMap); ++ } ++ public int size() { ++ return cpMap.length; ++ } ++ public Object get(int i) { ++ return cpMap[i]; ++ } ++ public Entry getEntry(int i) { ++ // same as get(), with covariant return type ++ return cpMap[i]; ++ } + +- // Find index of e in cpMap, or return -1 if none. +- // +- // As a special hack, if flattenSigs, signatures are +- // treated as equivalent entries of cpMap. This is wrong +- // fron a Collection point of view, because contains() +- // reports true for signatures, but the iterator() +- // never produces them! +- private int findIndexOf(Entry e) { +- if (indexKey == null) initializeIndex(); +- int probe = findIndexLocation(e); +- if (indexKey[probe] != e) { +- if (flattenSigs && e.tag == CONSTANT_Signature) { +- SignatureEntry se = (SignatureEntry) e; +- return findIndexOf(se.asUtf8Entry()); +- } +- return -1; +- } +- int index = indexValue[probe]; +- assert(e.equals(cpMap[index])); +- return index; +- } +- public boolean contains(Entry e) { +- return findIndexOf(e) >= 0; +- } +- // Find index of e in cpMap. Should not return -1. +- public int indexOf(Entry e) { +- int index = findIndexOf(e); +- if (index < 0 && verbose() > 0) { +- System.out.println("not found: "+e); +- System.out.println(" in: "+this.dumpString()); +- Thread.dumpStack(); +- } +- assert(index >= 0); +- return index; +- } +- public boolean contains(Object e) { +- return findIndexOf((Entry)e) >= 0; +- } +- public int indexOf(Object e) { +- return findIndexOf((Entry)e); +- } +- public int lastIndexOf(Object e) { +- return indexOf(e); +- } ++ // Find index of e in cpMap, or return -1 if none. ++ // ++ // As a special hack, if flattenSigs, signatures are ++ // treated as equivalent entries of cpMap. This is wrong ++ // fron a Collection point of view, because contains() ++ // reports true for signatures, but the iterator() ++ // never produces them! ++ private int findIndexOf(Entry e) { ++ if (indexKey == null) initializeIndex(); ++ int probe = findIndexLocation(e); ++ if (indexKey[probe] != e) { ++ if (flattenSigs && e.tag == CONSTANT_Signature) { ++ SignatureEntry se = (SignatureEntry) e; ++ return findIndexOf(se.asUtf8Entry()); ++ } ++ return -1; ++ } ++ int index = indexValue[probe]; ++ assert(e.equals(cpMap[index])); ++ return index; ++ } ++ public boolean contains(Entry e) { ++ return findIndexOf(e) >= 0; ++ } ++ // Find index of e in cpMap. Should not return -1. ++ public int indexOf(Entry e) { ++ int index = findIndexOf(e); ++ if (index < 0 && verbose() > 0) { ++ System.out.println("not found: "+e); ++ System.out.println(" in: "+this.dumpString()); ++ Thread.dumpStack(); ++ } ++ assert(index >= 0); ++ return index; ++ } ++ public boolean contains(Object e) { ++ return findIndexOf((Entry)e) >= 0; ++ } ++ public int indexOf(Object e) { ++ return findIndexOf((Entry)e); ++ } ++ public int lastIndexOf(Object e) { ++ return indexOf(e); ++ } + +- public boolean assertIsSorted() { +- for (int i = 1; i < cpMap.length; i++) { +- if (cpMap[i-1].compareTo(cpMap[i]) > 0) { +- System.out.println("Not sorted at "+(i-1)+"/"+i+": "+this.dumpString()); +- return false; +- } +- } +- return true; +- } ++ public boolean assertIsSorted() { ++ for (int i = 1; i < cpMap.length; i++) { ++ if (cpMap[i-1].compareTo(cpMap[i]) > 0) { ++ System.out.println("Not sorted at "+(i-1)+"/"+i+": "+this.dumpString()); ++ return false; ++ } ++ } ++ return true; ++ } + +- // internal hash table +- protected Entry[] indexKey; +- protected int[] indexValue; +- protected void clearIndex() { +- indexKey = null; +- indexValue = null; +- } +- private int findIndexLocation(Entry e) { +- int size = indexKey.length; +- int hash = e.hashCode(); +- int probe = hash & (size - 1); +- int stride = ((hash >>> 8) | 1) & (size - 1); +- for (;;) { +- Entry e1 = indexKey[probe]; +- if (e1 == e || e1 == null) +- return probe; +- probe += stride; +- if (probe >= size) probe -= size; +- } +- } +- private void initializeIndex() { +- if (verbose() > 2) +- System.out.println("initialize Index "+debugName+" ["+size()+"]"); +- int hsize0 = (int)((cpMap.length + 10) * 1.5); +- int hsize = 1; +- while (hsize < hsize0) hsize <<= 1; +- indexKey = new Entry[hsize]; +- indexValue = new int[hsize]; +- for (int i = 0; i < cpMap.length; i++) { +- Entry e = cpMap[i]; +- if (e == null) continue; +- int probe = findIndexLocation(e); +- assert(indexKey[probe] == null); // e has unique index +- indexKey[probe] = e; +- indexValue[probe] = i; +- } +- } +- public Object[] toArray(Object[] a) { +- int sz = size(); +- if (a.length < sz) return super.toArray(a); +- System.arraycopy(cpMap, 0, a, 0, sz); +- if (a.length > sz) a[sz] = null; +- return a; +- } +- public Object[] toArray() { +- return toArray(new Entry[size()]); +- } +- public Object clone() { +- return new Index(debugName, (Entry[]) cpMap.clone()); +- } +- public String toString() { +- return "Index "+debugName+" ["+size()+"]"; +- } +- public String dumpString() { +- String s = toString(); +- s += " {\n"; +- for (int i = 0; i < cpMap.length; i++) { +- s += " "+i+": "+cpMap[i]+"\n"; +- } +- s += "}"; +- return s; +- } ++ // internal hash table ++ protected Entry[] indexKey; ++ protected int[] indexValue; ++ protected void clearIndex() { ++ indexKey = null; ++ indexValue = null; ++ } ++ private int findIndexLocation(Entry e) { ++ int size = indexKey.length; ++ int hash = e.hashCode(); ++ int probe = hash & (size - 1); ++ int stride = ((hash >>> 8) | 1) & (size - 1); ++ for (;;) { ++ Entry e1 = indexKey[probe]; ++ if (e1 == e || e1 == null) ++ return probe; ++ probe += stride; ++ if (probe >= size) probe -= size; ++ } ++ } ++ private void initializeIndex() { ++ if (verbose() > 2) ++ System.out.println("initialize Index "+debugName+" ["+size()+"]"); ++ int hsize0 = (int)((cpMap.length + 10) * 1.5); ++ int hsize = 1; ++ while (hsize < hsize0) hsize <<= 1; ++ indexKey = new Entry[hsize]; ++ indexValue = new int[hsize]; ++ for (int i = 0; i < cpMap.length; i++) { ++ Entry e = cpMap[i]; ++ if (e == null) continue; ++ int probe = findIndexLocation(e); ++ assert(indexKey[probe] == null); // e has unique index ++ indexKey[probe] = e; ++ indexValue[probe] = i; ++ } ++ } ++ public Object[] toArray(Object[] a) { ++ int sz = size(); ++ if (a.length < sz) return super.toArray(a); ++ System.arraycopy(cpMap, 0, a, 0, sz); ++ if (a.length > sz) a[sz] = null; ++ return a; ++ } ++ public Object[] toArray() { ++ return toArray(new Entry[size()]); ++ } ++ public Object clone() { ++ return new Index(debugName, (Entry[]) cpMap.clone()); ++ } ++ public String toString() { ++ return "Index "+debugName+" ["+size()+"]"; ++ } ++ public String dumpString() { ++ String s = toString(); ++ s += " {\n"; ++ for (int i = 0; i < cpMap.length; i++) { ++ s += " "+i+": "+cpMap[i]+"\n"; ++ } ++ s += "}"; ++ return s; ++ } + } + + // Index methods. + + public static + Index makeIndex(String debugName, Entry[] cpMap) { +- return new Index(debugName, cpMap); ++ return new Index(debugName, cpMap); + } + + public static + Index makeIndex(String debugName, Collection cpMapList) { +- return new Index(debugName, cpMapList); ++ return new Index(debugName, cpMapList); + } + + /** Sort this index (destructively) into canonical order. */ + public static + void sort(Index ix) { +- // %%% Should move this into class Index. +- ix.clearIndex(); +- Arrays.sort(ix.cpMap); +- if (verbose() > 2) +- System.out.println("sorted "+ix.dumpString()); ++ // %%% Should move this into class Index. ++ ix.clearIndex(); ++ Arrays.sort(ix.cpMap); ++ if (verbose() > 2) ++ System.out.println("sorted "+ix.dumpString()); + } + + /** Return a set of indexes partitioning these entries. +@@ -900,210 +900,212 @@ class ConstantPool implements Constants + */ + public static + Index[] partition(Index ix, int[] keys) { +- // %%% Should move this into class Index. +- ArrayList parts = new ArrayList(); +- Entry[] cpMap = ix.cpMap; +- assert(keys.length == cpMap.length); +- for (int i = 0; i < keys.length; i++) { +- int key = keys[i]; +- if (key < 0) continue; +- while (key >= parts.size()) parts.add(null); +- ArrayList part = (ArrayList) parts.get(key); +- if (part == null) { +- parts.set(key, part = new ArrayList()); +- } +- part.add(cpMap[i]); +- } +- Index[] indexes = new Index[parts.size()]; +- for (int key = 0; key < indexes.length; key++) { +- ArrayList part = (ArrayList) parts.get(key); +- if (part == null) continue; +- indexes[key] = new Index(ix.debugName+"/part#"+key, part); +- assert(indexes[key].indexOf(part.get(0)) == 0); +- } +- return indexes; ++ // %%% Should move this into class Index. ++ ArrayList parts = new ArrayList(); ++ Entry[] cpMap = ix.cpMap; ++ assert(keys.length == cpMap.length); ++ for (int i = 0; i < keys.length; i++) { ++ int key = keys[i]; ++ if (key < 0) continue; ++ while (key >= parts.size()) parts.add(null); ++ ArrayList part = (ArrayList) parts.get(key); ++ if (part == null) { ++ parts.set(key, part = new ArrayList()); ++ } ++ part.add(cpMap[i]); ++ } ++ Index[] indexes = new Index[parts.size()]; ++ for (int key = 0; key < indexes.length; key++) { ++ ArrayList part = (ArrayList) parts.get(key); ++ if (part == null) continue; ++ indexes[key] = new Index(ix.debugName+"/part#"+key, part); ++ assert(indexes[key].indexOf(part.get(0)) == 0); ++ } ++ return indexes; + } + public static + Index[] partitionByTag(Index ix) { +- // Partition by tag. +- Entry[] cpMap = ix.cpMap; +- int[] keys = new int[cpMap.length]; +- for (int i = 0; i < keys.length; i++) { +- Entry e = cpMap[i]; +- keys[i] = (e == null)? -1: e.tag; +- } +- Index[] byTag = partition(ix, keys); +- for (int tag = 0; tag < byTag.length; tag++) { +- if (byTag[tag] == null) continue; +- byTag[tag].debugName = tagName(tag); +- } +- if (byTag.length < CONSTANT_Limit) { +- Index[] longer = new Index[CONSTANT_Limit]; +- System.arraycopy(byTag, 0, longer, 0, byTag.length); +- byTag = longer; +- } +- return byTag; ++ // Partition by tag. ++ Entry[] cpMap = ix.cpMap; ++ int[] keys = new int[cpMap.length]; ++ for (int i = 0; i < keys.length; i++) { ++ Entry e = cpMap[i]; ++ keys[i] = (e == null)? -1: e.tag; ++ } ++ Index[] byTag = partition(ix, keys); ++ for (int tag = 0; tag < byTag.length; tag++) { ++ if (byTag[tag] == null) continue; ++ byTag[tag].debugName = tagName(tag); ++ } ++ if (byTag.length < CONSTANT_Limit) { ++ Index[] longer = new Index[CONSTANT_Limit]; ++ System.arraycopy(byTag, 0, longer, 0, byTag.length); ++ byTag = longer; ++ } ++ return byTag; + } + + /** Coherent group of constant pool indexes. */ + public static + class IndexGroup { +- private Index indexUntyped; +- private Index[] indexByTag = new Index[CONSTANT_Limit]; +- private int[] untypedFirstIndexByTag; +- private int totalSize; +- private Index[][] indexByTagAndClass; ++ private Index indexUntyped; ++ private Index[] indexByTag = new Index[CONSTANT_Limit]; ++ private int[] untypedFirstIndexByTag; ++ private int totalSize; ++ private Index[][] indexByTagAndClass; + +- /** Index of all CP entries of all types, in definition order. */ +- public Index getUntypedIndex() { +- if (indexUntyped == null) { +- untypedIndexOf(null); // warm up untypedFirstIndexByTag +- Entry[] cpMap = new Entry[totalSize]; +- for (int tag = 0; tag < indexByTag.length; tag++) { +- Index ix = indexByTag[tag]; +- if (ix == null) continue; +- int ixLen = ix.cpMap.length; +- if (ixLen == 0) continue; +- int fillp = untypedFirstIndexByTag[tag]; +- assert(cpMap[fillp] == null); +- assert(cpMap[fillp+ixLen-1] == null); +- System.arraycopy(ix.cpMap, 0, cpMap, fillp, ixLen); +- } +- indexUntyped = new Index("untyped", cpMap); +- } +- return indexUntyped; +- } ++ /** Index of all CP entries of all types, in definition order. */ ++ public Index getUntypedIndex() { ++ if (indexUntyped == null) { ++ untypedIndexOf(null); // warm up untypedFirstIndexByTag ++ Entry[] cpMap = new Entry[totalSize]; ++ for (int tag = 0; tag < indexByTag.length; tag++) { ++ Index ix = indexByTag[tag]; ++ if (ix == null) continue; ++ int ixLen = ix.cpMap.length; ++ if (ixLen == 0) continue; ++ int fillp = untypedFirstIndexByTag[tag]; ++ assert(cpMap[fillp] == null); ++ assert(cpMap[fillp+ixLen-1] == null); ++ System.arraycopy(ix.cpMap, 0, cpMap, fillp, ixLen); ++ } ++ indexUntyped = new Index("untyped", cpMap); ++ } ++ return indexUntyped; ++ } + +- public int untypedIndexOf(Entry e) { +- if (untypedFirstIndexByTag == null) { +- untypedFirstIndexByTag = new int[CONSTANT_Limit]; +- int fillp = 0; +- for (int i = 0; i < TAGS_IN_ORDER.length; i++) { +- byte tag = TAGS_IN_ORDER[i]; +- Index ix = indexByTag[tag]; +- if (ix == null) continue; +- int ixLen = ix.cpMap.length; +- untypedFirstIndexByTag[tag] = fillp; +- fillp += ixLen; +- } +- totalSize = fillp; +- } +- if (e == null) return -1; +- int tag = e.tag; +- Index ix = indexByTag[tag]; +- if (ix == null) return -1; +- int idx = ix.findIndexOf(e); +- if (idx >= 0) +- idx += untypedFirstIndexByTag[tag]; +- return idx; +- } ++ public int untypedIndexOf(Entry e) { ++ if (untypedFirstIndexByTag == null) { ++ untypedFirstIndexByTag = new int[CONSTANT_Limit]; ++ int fillp = 0; ++ for (int i = 0; i < TAGS_IN_ORDER.length; i++) { ++ byte tag = TAGS_IN_ORDER[i]; ++ Index ix = indexByTag[tag]; ++ if (ix == null) continue; ++ int ixLen = ix.cpMap.length; ++ untypedFirstIndexByTag[tag] = fillp; ++ fillp += ixLen; ++ } ++ totalSize = fillp; ++ } ++ if (e == null) return -1; ++ int tag = e.tag; ++ Index ix = indexByTag[tag]; ++ if (ix == null) return -1; ++ int idx = ix.findIndexOf(e); ++ if (idx >= 0) ++ idx += untypedFirstIndexByTag[tag]; ++ return idx; ++ } + +- public void initIndexByTag(byte tag, Index ix) { +- assert(indexByTag[tag] == null); // do not init twice +- Entry[] cpMap = ix.cpMap; +- for (int i = 0; i < cpMap.length; i++) { +- // It must be a homogeneous Entry set. +- assert(cpMap[i].tag == tag); +- } +- if (tag == CONSTANT_Utf8) { +- // Special case: First Utf8 must always be empty string. +- assert(cpMap.length == 0 || cpMap[0].stringValue().equals("")); +- } +- indexByTag[tag] = ix; +- // decache indexes derived from this one: +- untypedFirstIndexByTag = null; +- indexUntyped = null; +- if (indexByTagAndClass != null) +- indexByTagAndClass[tag] = null; +- } ++ public void initIndexByTag(byte tag, Index ix) { ++ assert(indexByTag[tag] == null); // do not init twice ++ Entry[] cpMap = ix.cpMap; ++ for (int i = 0; i < cpMap.length; i++) { ++ // It must be a homogeneous Entry set. ++ assert(cpMap[i].tag == tag); ++ } ++ if (tag == CONSTANT_Utf8) { ++ // Special case: First Utf8 must always be empty string. ++ assert(cpMap.length == 0 || cpMap[0].stringValue().equals("")); ++ } ++ indexByTag[tag] = ix; ++ // decache indexes derived from this one: ++ untypedFirstIndexByTag = null; ++ indexUntyped = null; ++ if (indexByTagAndClass != null) ++ indexByTagAndClass[tag] = null; ++ } + +- /** Index of all CP entries of a given tag. */ +- public Index getIndexByTag(byte tag) { +- if (tag == CONSTANT_All) { +- return getUntypedIndex(); +- } +- Index ix = indexByTag[tag]; +- if (ix == null) { +- // Make an empty one by default. +- ix = new Index(tagName(tag), new Entry[0]); +- indexByTag[tag] = ix; +- } +- return ix; +- } ++ /** Index of all CP entries of a given tag. */ ++ public Index getIndexByTag(byte tag) { ++ if (tag == CONSTANT_All) { ++ return getUntypedIndex(); ++ } ++ Index ix = indexByTag[tag]; ++ if (ix == null) { ++ // Make an empty one by default. ++ ix = new Index(tagName(tag), new Entry[0]); ++ indexByTag[tag] = ix; ++ } ++ return ix; ++ } + +- /** Index of all CP entries of a given tag and class. */ +- public Index getMemberIndex(byte tag, ClassEntry classRef) { +- if (indexByTagAndClass == null) +- indexByTagAndClass = new Index[CONSTANT_Limit][]; +- Index allClasses = getIndexByTag(CONSTANT_Class); +- Index[] perClassIndexes = indexByTagAndClass[tag]; +- if (perClassIndexes == null) { +- // Create the partition now. +- // Divide up all entries of the given tag according to their class. +- Index allMembers = getIndexByTag(tag); +- int[] whichClasses = new int[allMembers.size()]; +- for (int i = 0; i < whichClasses.length; i++) { +- MemberEntry e = (MemberEntry) allMembers.get(i); +- int whichClass = allClasses.indexOf(e.classRef); +- whichClasses[i] = whichClass; +- } +- perClassIndexes = partition(allMembers, whichClasses); +- for (int i = 0; i < perClassIndexes.length; i++) +- assert(perClassIndexes[i]==null +- || perClassIndexes[i].assertIsSorted()); +- indexByTagAndClass[tag] = perClassIndexes; +- } +- int whichClass = allClasses.indexOf(classRef); +- return perClassIndexes[whichClass]; +- } ++ /** Index of all CP entries of a given tag and class. */ ++ public Index getMemberIndex(byte tag, ClassEntry classRef) { ++ if (classRef == null) ++ throw new RuntimeException("missing class reference for " + tagName(tag)); ++ if (indexByTagAndClass == null) ++ indexByTagAndClass = new Index[CONSTANT_Limit][]; ++ Index allClasses = getIndexByTag(CONSTANT_Class); ++ Index[] perClassIndexes = indexByTagAndClass[tag]; ++ if (perClassIndexes == null) { ++ // Create the partition now. ++ // Divide up all entries of the given tag according to their class. ++ Index allMembers = getIndexByTag(tag); ++ int[] whichClasses = new int[allMembers.size()]; ++ for (int i = 0; i < whichClasses.length; i++) { ++ MemberEntry e = (MemberEntry) allMembers.get(i); ++ int whichClass = allClasses.indexOf(e.classRef); ++ whichClasses[i] = whichClass; ++ } ++ perClassIndexes = partition(allMembers, whichClasses); ++ for (int i = 0; i < perClassIndexes.length; i++) ++ assert(perClassIndexes[i]==null ++ || perClassIndexes[i].assertIsSorted()); ++ indexByTagAndClass[tag] = perClassIndexes; ++ } ++ int whichClass = allClasses.indexOf(classRef); ++ return perClassIndexes[whichClass]; ++ } + +- // Given the sequence of all methods of the given name and class, +- // produce the ordinal of this particular given overloading. +- public int getOverloadingIndex(MemberEntry methodRef) { +- Index ix = getMemberIndex(methodRef.tag, methodRef.classRef); +- Utf8Entry nameRef = methodRef.descRef.nameRef; +- int ord = 0; +- for (int i = 0; i < ix.cpMap.length; i++) { +- MemberEntry e = (MemberEntry) ix.cpMap[i]; +- if (e.equals(methodRef)) +- return ord; +- if (e.descRef.nameRef.equals(nameRef)) +- // Found a different overloading. Increment the ordinal. +- ord++; +- } +- throw new RuntimeException("should not reach here"); +- } ++ // Given the sequence of all methods of the given name and class, ++ // produce the ordinal of this particular given overloading. ++ public int getOverloadingIndex(MemberEntry methodRef) { ++ Index ix = getMemberIndex(methodRef.tag, methodRef.classRef); ++ Utf8Entry nameRef = methodRef.descRef.nameRef; ++ int ord = 0; ++ for (int i = 0; i < ix.cpMap.length; i++) { ++ MemberEntry e = (MemberEntry) ix.cpMap[i]; ++ if (e.equals(methodRef)) ++ return ord; ++ if (e.descRef.nameRef.equals(nameRef)) ++ // Found a different overloading. Increment the ordinal. ++ ord++; ++ } ++ throw new RuntimeException("should not reach here"); ++ } + +- // Inverse of getOverloadingIndex +- public MemberEntry getOverloadingForIndex(byte tag, ClassEntry classRef, String name, int which) { +- assert(name == name.intern()); +- Index ix = getMemberIndex(tag, classRef); +- int ord = 0; +- for (int i = 0; i < ix.cpMap.length; i++) { +- MemberEntry e = (MemberEntry) ix.cpMap[i]; +- if (e.descRef.nameRef.stringValue() == name) { +- if (ord == which) return e; +- ord++; +- } +- } +- throw new RuntimeException("should not reach here"); +- } ++ // Inverse of getOverloadingIndex ++ public MemberEntry getOverloadingForIndex(byte tag, ClassEntry classRef, String name, int which) { ++ assert(name == name.intern()); ++ Index ix = getMemberIndex(tag, classRef); ++ int ord = 0; ++ for (int i = 0; i < ix.cpMap.length; i++) { ++ MemberEntry e = (MemberEntry) ix.cpMap[i]; ++ if (e.descRef.nameRef.stringValue() == name) { ++ if (ord == which) return e; ++ ord++; ++ } ++ } ++ throw new RuntimeException("should not reach here"); ++ } + +- public boolean haveNumbers() { +- for (byte tag = CONSTANT_Integer; tag <= CONSTANT_Double; tag++) { +- switch (tag) { +- case CONSTANT_Integer: +- case CONSTANT_Float: +- case CONSTANT_Long: +- case CONSTANT_Double: +- break; +- default: +- assert(false); +- } +- if (getIndexByTag(tag).size() > 0) return true; +- } +- return false; +- } ++ public boolean haveNumbers() { ++ for (byte tag = CONSTANT_Integer; tag <= CONSTANT_Double; tag++) { ++ switch (tag) { ++ case CONSTANT_Integer: ++ case CONSTANT_Float: ++ case CONSTANT_Long: ++ case CONSTANT_Double: ++ break; ++ default: ++ assert(false); ++ } ++ if (getIndexByTag(tag).size() > 0) return true; ++ } ++ return false; ++ } + + } + +@@ -1114,84 +1116,84 @@ class ConstantPool implements Constants + */ + public static + void completeReferencesIn(Set cpRefs, boolean flattenSigs) { +- cpRefs.remove(null); +- for (ListIterator work = +- new ArrayList(cpRefs).listIterator(cpRefs.size()); +- work.hasPrevious(); ) { +- Entry e = (Entry) work.previous(); +- work.remove(); // pop stack +- assert(e != null); +- if (flattenSigs && e.tag == CONSTANT_Signature) { +- SignatureEntry se = (SignatureEntry) e; +- Utf8Entry ue = se.asUtf8Entry(); +- // Totally replace e by se. +- cpRefs.remove(se); +- cpRefs.add(ue); +- e = ue; // do not descend into the sig +- } +- // Recursively add the refs of e to cpRefs: +- for (int i = 0; ; i++) { +- Entry re = e.getRef(i); +- if (re == null) +- break; // no more refs in e +- if (cpRefs.add(re)) // output the ref +- work.add(re); // push stack, if a new ref +- } +- } ++ cpRefs.remove(null); ++ for (ListIterator work = ++ new ArrayList(cpRefs).listIterator(cpRefs.size()); ++ work.hasPrevious(); ) { ++ Entry e = (Entry) work.previous(); ++ work.remove(); // pop stack ++ assert(e != null); ++ if (flattenSigs && e.tag == CONSTANT_Signature) { ++ SignatureEntry se = (SignatureEntry) e; ++ Utf8Entry ue = se.asUtf8Entry(); ++ // Totally replace e by se. ++ cpRefs.remove(se); ++ cpRefs.add(ue); ++ e = ue; // do not descend into the sig ++ } ++ // Recursively add the refs of e to cpRefs: ++ for (int i = 0; ; i++) { ++ Entry re = e.getRef(i); ++ if (re == null) ++ break; // no more refs in e ++ if (cpRefs.add(re)) // output the ref ++ work.add(re); // push stack, if a new ref ++ } ++ } + } + + static double percent(int num, int den) { +- return (int)((10000.0*num)/den + 0.5) / 100.0; ++ return (int)((10000.0*num)/den + 0.5) / 100.0; + } + + public static String tagName(int tag) { +- switch (tag) { +- case CONSTANT_Utf8: return "Utf8"; +- case CONSTANT_Integer: return "Integer"; +- case CONSTANT_Float: return "Float"; +- case CONSTANT_Long: return "Long"; +- case CONSTANT_Double: return "Double"; +- case CONSTANT_Class: return "Class"; +- case CONSTANT_String: return "String"; +- case CONSTANT_Fieldref: return "Fieldref"; +- case CONSTANT_Methodref: return "Methodref"; +- case CONSTANT_InterfaceMethodref: return "InterfaceMethodref"; +- case CONSTANT_NameandType: return "NameandType"; ++ switch (tag) { ++ case CONSTANT_Utf8: return "Utf8"; ++ case CONSTANT_Integer: return "Integer"; ++ case CONSTANT_Float: return "Float"; ++ case CONSTANT_Long: return "Long"; ++ case CONSTANT_Double: return "Double"; ++ case CONSTANT_Class: return "Class"; ++ case CONSTANT_String: return "String"; ++ case CONSTANT_Fieldref: return "Fieldref"; ++ case CONSTANT_Methodref: return "Methodref"; ++ case CONSTANT_InterfaceMethodref: return "InterfaceMethodref"; ++ case CONSTANT_NameandType: return "NameandType"; + +- // pseudo-tags: +- case CONSTANT_All: return "*All"; +- case CONSTANT_None: return "*None"; +- case CONSTANT_Signature: return "*Signature"; +- } +- return "tag#"+tag; ++ // pseudo-tags: ++ case CONSTANT_All: return "*All"; ++ case CONSTANT_None: return "*None"; ++ case CONSTANT_Signature: return "*Signature"; ++ } ++ return "tag#"+tag; + } + + // archive constant pool definition order + static final byte TAGS_IN_ORDER[] = { +- CONSTANT_Utf8, +- CONSTANT_Integer, // cp_Int +- CONSTANT_Float, +- CONSTANT_Long, +- CONSTANT_Double, +- CONSTANT_String, +- CONSTANT_Class, +- CONSTANT_Signature, +- CONSTANT_NameandType, // cp_Descr +- CONSTANT_Fieldref, // cp_Field +- CONSTANT_Methodref, // cp_Method +- CONSTANT_InterfaceMethodref // cp_Imethod ++ CONSTANT_Utf8, ++ CONSTANT_Integer, // cp_Int ++ CONSTANT_Float, ++ CONSTANT_Long, ++ CONSTANT_Double, ++ CONSTANT_String, ++ CONSTANT_Class, ++ CONSTANT_Signature, ++ CONSTANT_NameandType, // cp_Descr ++ CONSTANT_Fieldref, // cp_Field ++ CONSTANT_Methodref, // cp_Method ++ CONSTANT_InterfaceMethodref // cp_Imethod + }; + static final byte TAG_ORDER[]; + static { +- TAG_ORDER = new byte[CONSTANT_Limit]; +- for (int i = 0; i < TAGS_IN_ORDER.length; i++) { +- TAG_ORDER[TAGS_IN_ORDER[i]] = (byte)(i+1); +- } +- /* +- System.out.println("TAG_ORDER[] = {"); +- for (int i = 0; i < TAG_ORDER.length; i++) +- System.out.println(" "+TAG_ORDER[i]+","); +- System.out.println("};"); +- */ ++ TAG_ORDER = new byte[CONSTANT_Limit]; ++ for (int i = 0; i < TAGS_IN_ORDER.length; i++) { ++ TAG_ORDER[TAGS_IN_ORDER[i]] = (byte)(i+1); ++ } ++ /* ++ System.out.println("TAG_ORDER[] = {"); ++ for (int i = 0; i < TAG_ORDER.length; i++) ++ System.out.println(" "+TAG_ORDER[i]+","); ++ System.out.println("};"); ++ */ + } + } +diff --git a/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java b/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java +--- jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java ++++ jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -22,7 +22,6 @@ + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +- + + package com.sun.java.util.jar.pack; + +@@ -81,239 +80,246 @@ class NativeUnpack { + private PropMap _props; + + static { +- // If loading from stand alone build uncomment this. +- // System.loadLibrary("unpack"); +- java.security.AccessController.doPrivileged( +- new sun.security.action.LoadLibraryAction("unpack")); +- initIDs(); ++ // If loading from stand alone build uncomment this. ++ // System.loadLibrary("unpack"); ++ java.security.AccessController.doPrivileged( ++ new sun.security.action.LoadLibraryAction("unpack")); ++ initIDs(); + } +- ++ + NativeUnpack(UnpackerImpl p200) { +- super(); +- _p200 = p200; +- _props = p200._props; +- p200._nunp = this; ++ super(); ++ _p200 = p200; ++ _props = p200._props; ++ p200._nunp = this; + } + + // for JNI callbacks + static private Object currentInstance() { +- UnpackerImpl p200 = (UnpackerImpl) Utils.currentInstance.get(); +- return (p200 == null)? null: p200._nunp; ++ UnpackerImpl p200 = (UnpackerImpl) Utils.currentInstance.get(); ++ return (p200 == null)? null: p200._nunp; ++ } ++ ++ private synchronized long getUnpackerPtr() { ++ return unpackerPtr; + } + + // Callback from the unpacker engine to get more data. + private long readInputFn(ByteBuffer pbuf, long minlen) throws IOException { +- if (in == null) return 0; // nothing is readable +- long maxlen = pbuf.capacity() - pbuf.position(); +- assert(minlen <= maxlen); // don't talk nonsense +- long numread = 0; +- int steps = 0; +- while (numread < minlen) { +- steps++; +- // read available input, up to buf.length or maxlen +- int readlen = _buf.length; +- if (readlen > (maxlen - numread)) +- readlen = (int)(maxlen - numread); +- int nr = in.read(_buf, 0, readlen); +- if (nr <= 0) break; +- numread += nr; +- assert(numread <= maxlen); +- // %%% get rid of this extra copy by using nio? +- pbuf.put(_buf, 0, nr); +- } +- if (_verbose > 1) +- Utils.log.fine("readInputFn("+minlen+","+maxlen+") => "+numread+" steps="+steps); +- if (maxlen > 100) { +- _estByteLimit = _byteCount + maxlen; +- } else { +- _estByteLimit = (_byteCount + numread) * 20; +- } +- _byteCount += numread; +- updateProgress(); +- return numread; ++ if (in == null) return 0; // nothing is readable ++ long maxlen = pbuf.capacity() - pbuf.position(); ++ assert(minlen <= maxlen); // don't talk nonsense ++ long numread = 0; ++ int steps = 0; ++ while (numread < minlen) { ++ steps++; ++ // read available input, up to buf.length or maxlen ++ int readlen = _buf.length; ++ if (readlen > (maxlen - numread)) ++ readlen = (int)(maxlen - numread); ++ int nr = in.read(_buf, 0, readlen); ++ if (nr <= 0) break; ++ numread += nr; ++ assert(numread <= maxlen); ++ // %%% get rid of this extra copy by using nio? ++ pbuf.put(_buf, 0, nr); ++ } ++ if (_verbose > 1) ++ Utils.log.fine("readInputFn("+minlen+","+maxlen+") => "+numread+" steps="+steps); ++ if (maxlen > 100) { ++ _estByteLimit = _byteCount + maxlen; ++ } else { ++ _estByteLimit = (_byteCount + numread) * 20; ++ } ++ _byteCount += numread; ++ updateProgress(); ++ return numread; + } + + private void updateProgress() { +- // Progress is a combination of segment reading and file writing. +- final double READ_WT = 0.33; +- final double WRITE_WT = 0.67; +- double readProgress = _segCount; +- if (_estByteLimit > 0 && _byteCount > 0) +- readProgress += (double)_byteCount / _estByteLimit; +- double writeProgress = _fileCount; +- double scaledProgress +- = READ_WT * readProgress / Math.max(_estSegLimit,1) +- + WRITE_WT * writeProgress / Math.max(_estFileLimit,1); +- int percent = (int) Math.round(100*scaledProgress); +- if (percent > 100) percent = 100; +- if (percent > _prevPercent) { +- _prevPercent = percent; +- _props.setInteger(Pack200.Unpacker.PROGRESS, percent); +- if (_verbose > 0) +- Utils.log.info("progress = "+percent); +- } ++ // Progress is a combination of segment reading and file writing. ++ final double READ_WT = 0.33; ++ final double WRITE_WT = 0.67; ++ double readProgress = _segCount; ++ if (_estByteLimit > 0 && _byteCount > 0) ++ readProgress += (double)_byteCount / _estByteLimit; ++ double writeProgress = _fileCount; ++ double scaledProgress ++ = READ_WT * readProgress / Math.max(_estSegLimit,1) ++ + WRITE_WT * writeProgress / Math.max(_estFileLimit,1); ++ int percent = (int) Math.round(100*scaledProgress); ++ if (percent > 100) percent = 100; ++ if (percent > _prevPercent) { ++ _prevPercent = percent; ++ _props.setInteger(Pack200.Unpacker.PROGRESS, percent); ++ if (_verbose > 0) ++ Utils.log.info("progress = "+percent); ++ } + } + + private void copyInOption(String opt) { +- String val = _props.getProperty(opt); +- if (_verbose > 0) +- Utils.log.info("set "+opt+"="+val); +- if (val != null) { +- boolean set = setOption(opt, val); +- if (!set) +- Utils.log.warning("Invalid option "+opt+"="+val); +- } ++ String val = _props.getProperty(opt); ++ if (_verbose > 0) ++ Utils.log.info("set "+opt+"="+val); ++ if (val != null) { ++ boolean set = setOption(opt, val); ++ if (!set) ++ Utils.log.warning("Invalid option "+opt+"="+val); ++ } + } + + void run(InputStream inRaw, JarOutputStream jstream, +- ByteBuffer presetInput) throws IOException { +- BufferedInputStream in = new BufferedInputStream(inRaw); +- this.in = in; // for readInputFn to see +- _verbose = _props.getInteger(Utils.DEBUG_VERBOSE); +- // Fix for BugId: 4902477, -unpack.modification.time = 1059010598000 ++ ByteBuffer presetInput) throws IOException { ++ BufferedInputStream in = new BufferedInputStream(inRaw); ++ this.in = in; // for readInputFn to see ++ _verbose = _props.getInteger(Utils.DEBUG_VERBOSE); ++ // Fix for BugId: 4902477, -unpack.modification.time = 1059010598000 + // TODO eliminate and fix in unpack.cpp ++ ++ final int modtime = Pack200.Packer.KEEP.equals(_props.getProperty(Utils.UNPACK_MODIFICATION_TIME, "0")) ? ++ Constants.NO_MODTIME : _props.getTime(Utils.UNPACK_MODIFICATION_TIME); + +- final int modtime = Pack200.Packer.KEEP.equals(_props.getProperty(Utils.UNPACK_MODIFICATION_TIME, "0")) ? +- Constants.NO_MODTIME : _props.getTime(Utils.UNPACK_MODIFICATION_TIME); ++ copyInOption(Utils.DEBUG_VERBOSE); ++ copyInOption(Pack200.Unpacker.DEFLATE_HINT); ++ if (modtime == Constants.NO_MODTIME) // Dont pass KEEP && NOW ++ copyInOption(Utils.UNPACK_MODIFICATION_TIME); ++ updateProgress(); // reset progress bar ++ for (;;) { ++ // Read the packed bits. ++ long counts = start(presetInput, 0); ++ _byteCount = _estByteLimit = 0; // reset partial scan counts ++ ++_segCount; // just finished scanning a whole segment... ++ int nextSeg = (int)( counts >>> 32 ); ++ int nextFile = (int)( counts >>> 0 ); + +- copyInOption(Utils.DEBUG_VERBOSE); +- copyInOption(Pack200.Unpacker.DEFLATE_HINT); +- if (modtime == Constants.NO_MODTIME) // Dont pass KEEP && NOW +- copyInOption(Utils.UNPACK_MODIFICATION_TIME); +- updateProgress(); // reset progress bar +- for (;;) { +- // Read the packed bits. +- long counts = start(presetInput, 0); +- _byteCount = _estByteLimit = 0; // reset partial scan counts +- ++_segCount; // just finished scanning a whole segment... +- int nextSeg = (int)( counts >>> 32 ); +- int nextFile = (int)( counts >>> 0 ); ++ // Estimate eventual total number of segments and files. ++ _estSegLimit = _segCount + nextSeg; ++ double filesAfterThisSeg = _fileCount + nextFile; ++ _estFileLimit = (int)( (filesAfterThisSeg * ++ _estSegLimit) / _segCount ); + +- // Estimate eventual total number of segments and files. +- _estSegLimit = _segCount + nextSeg; +- double filesAfterThisSeg = _fileCount + nextFile; +- _estFileLimit = (int)( (filesAfterThisSeg * +- _estSegLimit) / _segCount ); ++ // Write the files. ++ int[] intParts = { 0,0, 0, 0 }; ++ // intParts = {size.hi/lo, mod, defl} ++ Object[] parts = { intParts, null, null, null }; ++ // parts = { {intParts}, name, data0/1 } ++ while (getNextFile(parts)) { ++ //BandStructure.printArrayTo(System.out, intParts, 0, parts.length); ++ String name = (String) parts[1]; ++ long size = ( (long)intParts[0] << 32) ++ + (((long)intParts[1] << 32) >>> 32); + +- // Write the files. +- int[] intParts = { 0,0, 0, 0 }; +- // intParts = {size.hi/lo, mod, defl} +- Object[] parts = { intParts, null, null, null }; +- // parts = { {intParts}, name, data0/1 } +- while (getNextFile(parts)) { +- //BandStructure.printArrayTo(System.out, intParts, 0, parts.length); +- String name = (String) parts[1]; +- long size = ( (long)intParts[0] << 32) +- + (((long)intParts[1] << 32) >>> 32); +- +- long mtime = (modtime != Constants.NO_MODTIME ) ? +- modtime : intParts[2] ; +- boolean deflateHint = (intParts[3] != 0); +- ByteBuffer data0 = (ByteBuffer) parts[2]; +- ByteBuffer data1 = (ByteBuffer) parts[3]; +- writeEntry(jstream, name, mtime, size, deflateHint, +- data0, data1); +- ++_fileCount; +- updateProgress(); +- } +- long consumed = finish(); +- if (_verbose > 0) +- Utils.log.info("bytes consumed = "+consumed); +- presetInput = getUnusedInput(); +- if (presetInput == null && +- !Utils.isPackMagic(Utils.readMagic(in))) { +- break; +- } +- if (_verbose > 0 ) { +- if (presetInput != null) +- Utils.log.info("unused input = "+presetInput); +- } +- } ++ long mtime = (modtime != Constants.NO_MODTIME ) ? ++ modtime : intParts[2] ; ++ boolean deflateHint = (intParts[3] != 0); ++ ByteBuffer data0 = (ByteBuffer) parts[2]; ++ ByteBuffer data1 = (ByteBuffer) parts[3]; ++ writeEntry(jstream, name, mtime, size, deflateHint, ++ data0, data1); ++ ++_fileCount; ++ updateProgress(); ++ } ++ long consumed = finish(); ++ if (_verbose > 0) ++ Utils.log.info("bytes consumed = "+consumed); ++ presetInput = getUnusedInput(); ++ if (presetInput == null && ++ !Utils.isPackMagic(Utils.readMagic(in))) { ++ break; ++ } ++ if (_verbose > 0 ) { ++ if (presetInput != null) ++ Utils.log.info("unused input = "+presetInput); ++ } ++ } + } + + void run(InputStream in, JarOutputStream jstream) throws IOException { +- run(in, jstream, null); ++ run(in, jstream, null); + } + + void run(File inFile, JarOutputStream jstream) throws IOException { +- // %%% maybe memory-map the file, and pass it straight into unpacker +- ByteBuffer mappedFile = null; +- FileInputStream fis = new FileInputStream(inFile); +- run(fis, jstream, mappedFile); +- fis.close(); +- // Note: caller is responsible to finish with jstream. ++ // %%% maybe memory-map the file, and pass it straight into unpacker ++ ByteBuffer mappedFile = null; ++ FileInputStream fis = new FileInputStream(inFile); ++ run(fis, jstream, mappedFile); ++ fis.close(); ++ // Note: caller is responsible to finish with jstream. + } ++ ++ private void writeEntry(JarOutputStream j, String name, ++ long mtime, long lsize, boolean deflateHint, ++ ByteBuffer data0, ByteBuffer data1) throws IOException { ++ int size = (int)lsize; ++ if (size != lsize) ++ throw new IOException("file too large: "+lsize); + +- private void writeEntry(JarOutputStream j, String name, +- long mtime, long lsize, boolean deflateHint, +- ByteBuffer data0, ByteBuffer data1) throws IOException { +- int size = (int)lsize; +- if (size != lsize) +- throw new IOException("file too large: "+lsize); ++ CRC32 crc32 = _crc32; + +- CRC32 crc32 = _crc32; ++ if (_verbose > 1) ++ Utils.log.fine("Writing entry: "+name+" size="+size ++ +(deflateHint?" deflated":"")); + +- if (_verbose > 1) +- Utils.log.fine("Writing entry: "+name+" size="+size +- +(deflateHint?" deflated":"")); ++ if (_buf.length < size) { ++ int newSize = size; ++ while (newSize < _buf.length) { ++ newSize <<= 1; ++ if (newSize <= 0) { ++ newSize = size; ++ break; ++ } ++ } ++ _buf = new byte[newSize]; ++ } ++ assert(_buf.length >= size); + +- if (_buf.length < size) { +- int newSize = size; +- while (newSize < _buf.length) { +- newSize <<= 1; +- if (newSize <= 0) { +- newSize = size; +- break; +- } +- } +- _buf = new byte[newSize]; +- } +- assert(_buf.length >= size); ++ int fillp = 0; ++ if (data0 != null) { ++ int size0 = data0.capacity(); ++ data0.get(_buf, fillp, size0); ++ fillp += size0; ++ } ++ if (data1 != null) { ++ int size1 = data1.capacity(); ++ data1.get(_buf, fillp, size1); ++ fillp += size1; ++ } ++ while (fillp < size) { ++ // Fill in rest of data from the stream itself. ++ int nr = in.read(_buf, fillp, size - fillp); ++ if (nr <= 0) throw new IOException("EOF at end of archive"); ++ fillp += nr; ++ } + +- int fillp = 0; +- if (data0 != null) { +- int size0 = data0.capacity(); +- data0.get(_buf, fillp, size0); +- fillp += size0; +- } +- if (data1 != null) { +- int size1 = data1.capacity(); +- data1.get(_buf, fillp, size1); +- fillp += size1; +- } +- while (fillp < size) { +- // Fill in rest of data from the stream itself. +- int nr = in.read(_buf, fillp, size - fillp); +- if (nr <= 0) throw new IOException("EOF at end of archive"); +- fillp += nr; +- } ++ ZipEntry z = new ZipEntry(name); ++ z.setTime( (long)mtime * 1000); ++ ++ if (size == 0) { ++ z.setMethod(ZipOutputStream.STORED); ++ z.setSize(0); ++ z.setCrc(0); ++ z.setCompressedSize(0); ++ } else if (!deflateHint) { ++ z.setMethod(ZipOutputStream.STORED); ++ z.setSize(size); ++ z.setCompressedSize(size); ++ crc32.reset(); ++ crc32.update(_buf, 0, size); ++ z.setCrc(crc32.getValue()); ++ } else { ++ z.setMethod(Deflater.DEFLATED); ++ z.setSize(size); ++ } + +- ZipEntry z = new ZipEntry(name); +- z.setTime( (long)mtime * 1000); ++ j.putNextEntry(z); + +- if (size == 0) { +- z.setMethod(ZipOutputStream.STORED); +- z.setSize(0); +- z.setCrc(0); +- z.setCompressedSize(0); +- } else if (!deflateHint) { +- z.setMethod(ZipOutputStream.STORED); +- z.setSize(size); +- z.setCompressedSize(size); +- crc32.reset(); +- crc32.update(_buf, 0, size); +- z.setCrc(crc32.getValue()); +- } else { +- z.setMethod(Deflater.DEFLATED); +- z.setSize(size); +- } ++ if (size > 0) ++ j.write(_buf, 0, size); + +- j.putNextEntry(z); +- +- if (size > 0) +- j.write(_buf, 0, size); +- +- j.closeEntry(); +- if (_verbose > 0) Utils.log.info("Writing " + Utils.zeString(z)); ++ j.closeEntry(); ++ if (_verbose > 0) Utils.log.info("Writing " + Utils.zeString(z)); + } + } ++ ++ ++ +diff --git a/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java b/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java +--- jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java ++++ jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -22,7 +22,6 @@ + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +- + package com.sun.java.util.jar.pack; + + import java.util.*; +@@ -48,9 +47,9 @@ public class PackerImpl implements Pack2 + * the packer engines. + */ + public PackerImpl() { +- _props = new PropMap(); +- //_props.getProperty() consults defaultProps invisibly. +- //_props.putAll(defaultProps); ++ _props = new PropMap(); ++ //_props.getProperty() consults defaultProps invisibly. ++ //_props.putAll(defaultProps); + } + + +@@ -62,7 +61,7 @@ public class PackerImpl implements Pack2 + * @return A sorted association of option key strings to option values. + */ + public SortedMap properties() { +- return _props; ++ return _props; + } + + +@@ -76,24 +75,24 @@ public class PackerImpl implements Pack2 + * @param out an OutputStream + * @exception IOException if an error is encountered. + */ +- public void pack(JarFile in, OutputStream out) throws IOException { +- assert(Utils.currentInstance.get() == null); +- TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null : +- TimeZone.getDefault(); +- try { +- Utils.currentInstance.set(this); +- if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC")); ++ public synchronized void pack(JarFile in, OutputStream out) throws IOException { ++ assert(Utils.currentInstance.get() == null); ++ TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null : ++ TimeZone.getDefault(); ++ try { ++ Utils.currentInstance.set(this); ++ if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + +- if ("0".equals(_props.getProperty(Pack200.Packer.EFFORT))) { +- Utils.copyJarFile(in, out); +- } else { +- (new DoPack()).run(in, out); +- in.close(); +- } +- } finally { +- Utils.currentInstance.set(null); +- if (tz != null) TimeZone.setDefault(tz); +- } ++ if ("0".equals(_props.getProperty(Pack200.Packer.EFFORT))) { ++ Utils.copyJarFile(in, out); ++ } else { ++ (new DoPack()).run(in, out); ++ in.close(); ++ } ++ } finally { ++ Utils.currentInstance.set(null); ++ if (tz != null) TimeZone.setDefault(tz); ++ } + } + + /** +@@ -110,39 +109,39 @@ public class PackerImpl implements Pack2 + * @param out an OutputStream + * @exception IOException if an error is encountered. + */ +- public void pack(JarInputStream in, OutputStream out) throws IOException { +- assert(Utils.currentInstance.get() == null); +- TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null : +- TimeZone.getDefault(); +- try { +- Utils.currentInstance.set(this); +- if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC")); +- if ("0".equals(_props.getProperty(Pack200.Packer.EFFORT))) { +- Utils.copyJarFile(in, out); +- } else { +- (new DoPack()).run(in, out); +- in.close(); +- } +- } finally { +- Utils.currentInstance.set(null); +- if (tz != null) TimeZone.setDefault(tz); ++ public synchronized void pack(JarInputStream in, OutputStream out) throws IOException { ++ assert(Utils.currentInstance.get() == null); ++ TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null : ++ TimeZone.getDefault(); ++ try { ++ Utils.currentInstance.set(this); ++ if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC")); ++ if ("0".equals(_props.getProperty(Pack200.Packer.EFFORT))) { ++ Utils.copyJarFile(in, out); ++ } else { ++ (new DoPack()).run(in, out); ++ in.close(); ++ } ++ } finally { ++ Utils.currentInstance.set(null); ++ if (tz != null) TimeZone.setDefault(tz); + +- } ++ } + } + /** + * Register a listener for changes to options. +- * @param listener An object to be invoked when a property is changed. ++ * @param listener An object to be invoked when a property is changed. + */ + public void addPropertyChangeListener(PropertyChangeListener listener) { +- _props.addListener(listener); ++ _props.addListener(listener); + } + + /** + * Remove a listener for the PropertyChange event. +- * @param listener The PropertyChange listener to be removed. ++ * @param listener The PropertyChange listener to be removed. + */ + public void removePropertyChangeListener(PropertyChangeListener listener) { +- _props.removeListener(listener); ++ _props.removeListener(listener); + } + + +@@ -151,471 +150,478 @@ public class PackerImpl implements Pack2 + + // The packer worker. + private class DoPack { +- final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE); ++ final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE); + +- { +- _props.setInteger(Pack200.Packer.PROGRESS, 0); +- if (verbose > 0) Utils.log.info(_props.toString()); +- } ++ { ++ _props.setInteger(Pack200.Packer.PROGRESS, 0); ++ if (verbose > 0) Utils.log.info(_props.toString()); ++ } + +- // Here's where the bits are collected before getting packed: +- final Package pkg = new Package(); ++ // Here's where the bits are collected before getting packed: ++ final Package pkg = new Package(); + +- final String unknownAttrCommand; +- { +- String uaMode = _props.getProperty(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS); +- if (!(Pack200.Packer.STRIP.equals(uaMode) || +- Pack200.Packer.PASS.equals(uaMode) || +- Pack200.Packer.ERROR.equals(uaMode))) { +- throw new RuntimeException("Bad option: " + Pack200.Packer.UNKNOWN_ATTRIBUTE + " = " + uaMode); +- } +- unknownAttrCommand = uaMode.intern(); +- } ++ final String unknownAttrCommand; ++ { ++ String uaMode = _props.getProperty(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS); ++ if (!(Pack200.Packer.STRIP.equals(uaMode) || ++ Pack200.Packer.PASS.equals(uaMode) || ++ Pack200.Packer.ERROR.equals(uaMode))) { ++ throw new RuntimeException("Bad option: " + Pack200.Packer.UNKNOWN_ATTRIBUTE + " = " + uaMode); ++ } ++ unknownAttrCommand = uaMode.intern(); ++ } + +- final HashMap attrDefs; +- final HashMap attrCommands; +- { +- HashMap attrDefs = new HashMap(); +- HashMap attrCommands = new HashMap(); +- String[] keys = { +- Pack200.Packer.CLASS_ATTRIBUTE_PFX, +- Pack200.Packer.FIELD_ATTRIBUTE_PFX, +- Pack200.Packer.METHOD_ATTRIBUTE_PFX, +- Pack200.Packer.CODE_ATTRIBUTE_PFX +- }; +- int[] ctypes = { +- Constants.ATTR_CONTEXT_CLASS, +- Constants.ATTR_CONTEXT_FIELD, +- Constants.ATTR_CONTEXT_METHOD, +- Constants.ATTR_CONTEXT_CODE +- }; +- for (int i = 0; i < ctypes.length; i++) { +- String pfx = keys[i]; +- Map map = _props.prefixMap(pfx); +- for (Iterator j = map.keySet().iterator(); j.hasNext(); ) { +- String key = (String) j.next(); +- assert(key.startsWith(pfx)); +- String name = key.substring(pfx.length()); +- String layout = _props.getProperty(key); +- Object lkey = Attribute.keyForLookup(ctypes[i], name); +- if (Pack200.Packer.STRIP.equals(layout) || +- Pack200.Packer.PASS.equals(layout) || +- Pack200.Packer.ERROR.equals(layout)) { +- attrCommands.put(lkey, layout.intern()); +- } else { +- Attribute.define(attrDefs, ctypes[i], name, layout); +- if (verbose > 1) { +- Utils.log.fine("Added layout for "+Constants.ATTR_CONTEXT_NAME[i]+" attribute "+name+" = "+layout); +- } +- assert(attrDefs.containsKey(lkey)); +- } +- } +- } +- if (attrDefs.size() > 0) +- this.attrDefs = attrDefs; +- else +- this.attrDefs = null; +- if (attrCommands.size() > 0) +- this.attrCommands = attrCommands; +- else +- this.attrCommands = null; +- } ++ final HashMap attrDefs; ++ final HashMap attrCommands; ++ { ++ HashMap attrDefs = new HashMap(); ++ HashMap attrCommands = new HashMap(); ++ String[] keys = { ++ Pack200.Packer.CLASS_ATTRIBUTE_PFX, ++ Pack200.Packer.FIELD_ATTRIBUTE_PFX, ++ Pack200.Packer.METHOD_ATTRIBUTE_PFX, ++ Pack200.Packer.CODE_ATTRIBUTE_PFX ++ }; ++ int[] ctypes = { ++ Constants.ATTR_CONTEXT_CLASS, ++ Constants.ATTR_CONTEXT_FIELD, ++ Constants.ATTR_CONTEXT_METHOD, ++ Constants.ATTR_CONTEXT_CODE ++ }; ++ for (int i = 0; i < ctypes.length; i++) { ++ String pfx = keys[i]; ++ Map map = _props.prefixMap(pfx); ++ for (Iterator j = map.keySet().iterator(); j.hasNext(); ) { ++ String key = (String) j.next(); ++ assert(key.startsWith(pfx)); ++ String name = key.substring(pfx.length()); ++ String layout = _props.getProperty(key); ++ Object lkey = Attribute.keyForLookup(ctypes[i], name); ++ if (Pack200.Packer.STRIP.equals(layout) || ++ Pack200.Packer.PASS.equals(layout) || ++ Pack200.Packer.ERROR.equals(layout)) { ++ attrCommands.put(lkey, layout.intern()); ++ } else { ++ Attribute.define(attrDefs, ctypes[i], name, layout); ++ if (verbose > 1) { ++ Utils.log.fine("Added layout for "+Constants.ATTR_CONTEXT_NAME[i]+" attribute "+name+" = "+layout); ++ } ++ assert(attrDefs.containsKey(lkey)); ++ } ++ } ++ } ++ if (attrDefs.size() > 0) ++ this.attrDefs = attrDefs; ++ else ++ this.attrDefs = null; ++ if (attrCommands.size() > 0) ++ this.attrCommands = attrCommands; ++ else ++ this.attrCommands = null; ++ } + +- final boolean keepFileOrder +- = _props.getBoolean(Pack200.Packer.KEEP_FILE_ORDER); +- final boolean keepClassOrder +- = _props.getBoolean(Utils.PACK_KEEP_CLASS_ORDER); ++ final boolean keepFileOrder ++ = _props.getBoolean(Pack200.Packer.KEEP_FILE_ORDER); ++ final boolean keepClassOrder ++ = _props.getBoolean(Utils.PACK_KEEP_CLASS_ORDER); + +- final boolean keepModtime +- = Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Packer.MODIFICATION_TIME)); +- final boolean latestModtime +- = Pack200.Packer.LATEST.equals(_props.getProperty(Pack200.Packer.MODIFICATION_TIME)); +- final boolean keepDeflateHint +- = Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Packer.DEFLATE_HINT)); +- { +- if (!keepModtime && !latestModtime) { +- int modtime = _props.getTime(Pack200.Packer.MODIFICATION_TIME); +- if (modtime != Constants.NO_MODTIME) { +- pkg.default_modtime = modtime; +- } +- } +- if (!keepDeflateHint) { +- boolean deflate_hint = _props.getBoolean(Pack200.Packer.DEFLATE_HINT); +- if (deflate_hint) { +- pkg.default_options |= Constants.AO_DEFLATE_HINT; +- } +- } +- } ++ final boolean keepModtime ++ = Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Packer.MODIFICATION_TIME)); ++ final boolean latestModtime ++ = Pack200.Packer.LATEST.equals(_props.getProperty(Pack200.Packer.MODIFICATION_TIME)); ++ final boolean keepDeflateHint ++ = Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Packer.DEFLATE_HINT)); ++ { ++ if (!keepModtime && !latestModtime) { ++ int modtime = _props.getTime(Pack200.Packer.MODIFICATION_TIME); ++ if (modtime != Constants.NO_MODTIME) { ++ pkg.default_modtime = modtime; ++ } ++ } ++ if (!keepDeflateHint) { ++ boolean deflate_hint = _props.getBoolean(Pack200.Packer.DEFLATE_HINT); ++ if (deflate_hint) { ++ pkg.default_options |= Constants.AO_DEFLATE_HINT; ++ } ++ } ++ } + +- long totalOutputSize = 0; +- int segmentCount = 0; +- long segmentTotalSize = 0; +- long segmentSize = 0; // running counter +- final long segmentLimit; +- { +- long limit; +- if (_props.getProperty(Pack200.Packer.SEGMENT_LIMIT, "").equals("")) +- limit = -1; +- else +- limit = _props.getLong(Pack200.Packer.SEGMENT_LIMIT); +- limit = Math.min(Integer.MAX_VALUE, limit); +- limit = Math.max(-1, limit); +- if (limit == -1) +- limit = Long.MAX_VALUE; +- segmentLimit = limit; +- } ++ long totalOutputSize = 0; ++ int segmentCount = 0; ++ long segmentTotalSize = 0; ++ long segmentSize = 0; // running counter ++ final long segmentLimit; ++ { ++ long limit; ++ if (_props.getProperty(Pack200.Packer.SEGMENT_LIMIT, "").equals("")) ++ limit = -1; ++ else ++ limit = _props.getLong(Pack200.Packer.SEGMENT_LIMIT); ++ limit = Math.min(Integer.MAX_VALUE, limit); ++ limit = Math.max(-1, limit); ++ if (limit == -1) ++ limit = Long.MAX_VALUE; ++ segmentLimit = limit; ++ } + +- final List passFiles; // parsed pack.pass.file options +- { +- // Which class files will be passed through? +- passFiles = _props.getProperties(Pack200.Packer.PASS_FILE_PFX); +- for (ListIterator i = passFiles.listIterator(); i.hasNext(); ) { +- String file = (String) i.next(); +- if (file == null) { i.remove(); continue; } +- file = Utils.getJarEntryName(file); // normalize '\\' to '/' +- if (file.endsWith("/")) +- file = file.substring(0, file.length()-1); +- i.set(file); +- } +- if (verbose > 0) Utils.log.info("passFiles = " + passFiles); +- } ++ final List passFiles; // parsed pack.pass.file options ++ { ++ // Which class files will be passed through? ++ passFiles = _props.getProperties(Pack200.Packer.PASS_FILE_PFX); ++ for (ListIterator i = passFiles.listIterator(); i.hasNext(); ) { ++ String file = (String) i.next(); ++ if (file == null) { i.remove(); continue; } ++ file = Utils.getJarEntryName(file); // normalize '\\' to '/' ++ if (file.endsWith("/")) ++ file = file.substring(0, file.length()-1); ++ i.set(file); ++ } ++ if (verbose > 0) Utils.log.info("passFiles = " + passFiles); ++ } + +- { +- // Fill in permitted range of major/minor version numbers. +- int ver; +- if ((ver = _props.getInteger(Utils.COM_PREFIX+"min.class.majver")) != 0) +- pkg.min_class_majver = (short) ver; +- if ((ver = _props.getInteger(Utils.COM_PREFIX+"min.class.minver")) != 0) +- pkg.min_class_minver = (short) ver; +- if ((ver = _props.getInteger(Utils.COM_PREFIX+"max.class.majver")) != 0) +- pkg.max_class_majver = (short) ver; +- if ((ver = _props.getInteger(Utils.COM_PREFIX+"max.class.minver")) != 0) +- pkg.max_class_minver = (short) ver; +- if ((ver = _props.getInteger(Utils.COM_PREFIX+"package.minver")) != 0) +- pkg.package_minver = (short) ver; +- if ((ver = _props.getInteger(Utils.COM_PREFIX+"package.majver")) != 0) +- pkg.package_majver = (short) ver; +- } ++ { ++ // Fill in permitted range of major/minor version numbers. ++ int ver; ++ if ((ver = _props.getInteger(Utils.COM_PREFIX+"min.class.majver")) != 0) ++ pkg.min_class_majver = (short) ver; ++ if ((ver = _props.getInteger(Utils.COM_PREFIX+"min.class.minver")) != 0) ++ pkg.min_class_minver = (short) ver; ++ if ((ver = _props.getInteger(Utils.COM_PREFIX+"max.class.majver")) != 0) ++ pkg.max_class_majver = (short) ver; ++ if ((ver = _props.getInteger(Utils.COM_PREFIX+"max.class.minver")) != 0) ++ pkg.max_class_minver = (short) ver; ++ if ((ver = _props.getInteger(Utils.COM_PREFIX+"package.minver")) != 0) ++ pkg.package_minver = (short) ver; ++ if ((ver = _props.getInteger(Utils.COM_PREFIX+"package.majver")) != 0) ++ pkg.package_majver = (short) ver; ++ } + +- { +- // Hook for testing: Forces use of special archive modes. +- int opt = _props.getInteger(Utils.COM_PREFIX+"archive.options"); +- if (opt != 0) +- pkg.default_options |= opt; +- } ++ { ++ // Hook for testing: Forces use of special archive modes. ++ int opt = _props.getInteger(Utils.COM_PREFIX+"archive.options"); ++ if (opt != 0) ++ pkg.default_options |= opt; ++ } + +- // (Done collecting options from _props.) ++ // (Done collecting options from _props.) + +- boolean isClassFile(String name) { +- if (!name.endsWith(".class")) return false; +- for (String prefix = name; ; ) { +- if (passFiles.contains(prefix)) return false; +- int chop = prefix.lastIndexOf('/'); +- if (chop < 0) break; +- prefix = prefix.substring(0, chop); +- } +- return true; +- } ++ boolean isClassFile(String name) { ++ if (!name.endsWith(".class")) return false; ++ for (String prefix = name; ; ) { ++ if (passFiles.contains(prefix)) return false; ++ int chop = prefix.lastIndexOf('/'); ++ if (chop < 0) break; ++ prefix = prefix.substring(0, chop); ++ } ++ return true; ++ } + +- boolean isMetaInfFile(String name) { +- return name.startsWith("/" + Utils.METAINF) || +- name.startsWith(Utils.METAINF); +- } ++ boolean isMetaInfFile(String name) { ++ return name.startsWith("/" + Utils.METAINF) || ++ name.startsWith(Utils.METAINF); ++ } + +- // Get a new package, based on the old one. +- private void makeNextPackage() { +- pkg.reset(); +- } ++ // Get a new package, based on the old one. ++ private void makeNextPackage() { ++ pkg.reset(); ++ } + +- class InFile { +- final String name; +- final JarFile jf; +- final JarEntry je; +- final File f; +- int modtime = Constants.NO_MODTIME; +- int options; +- InFile(String name) { +- this.name = Utils.getJarEntryName(name); +- this.f = new File(name); +- this.jf = null; +- this.je = null; +- int timeSecs = getModtime(f.lastModified()); +- if (keepModtime && timeSecs != Constants.NO_MODTIME) { +- this.modtime = timeSecs; +- } else if (latestModtime && timeSecs > pkg.default_modtime) { +- pkg.default_modtime = timeSecs; +- } +- } +- InFile(JarFile jf, JarEntry je) { +- this.name = Utils.getJarEntryName(je.getName()); +- this.f = null; +- this.jf = jf; +- this.je = je; +- int timeSecs = getModtime(je.getTime()); +- if (keepModtime && timeSecs != Constants.NO_MODTIME) { +- this.modtime = timeSecs; +- } else if (latestModtime && timeSecs > pkg.default_modtime) { +- pkg.default_modtime = timeSecs; +- } +- if (keepDeflateHint && je.getMethod() == JarEntry.DEFLATED) { +- options |= Constants.FO_DEFLATE_HINT; +- } +- } +- InFile(JarEntry je) { +- this(null, je); +- } +- long getInputLength() { +- long len = (je != null)? je.getSize(): f.length(); +- assert(len >= 0) : this+".len="+len; +- // Bump size by pathname length and modtime/def-hint bytes. +- return Math.max(0, len) + name.length() + 5; +- } +- int getModtime(long timeMillis) { +- // Convert milliseconds to seconds. +- long seconds = (timeMillis+500) / 1000; +- if ((int)seconds == seconds) { +- return (int)seconds; +- } else { +- Utils.log.warning("overflow in modtime for "+f); +- return Constants.NO_MODTIME; +- } +- } +- void copyTo(Package.File file) { +- if (modtime != Constants.NO_MODTIME) +- file.modtime = modtime; +- file.options |= options; +- } +- InputStream getInputStream() throws IOException { +- if (jf != null) +- return jf.getInputStream(je); +- else +- return new FileInputStream(f); +- } ++ class InFile { ++ final String name; ++ final JarFile jf; ++ final JarEntry je; ++ final File f; ++ int modtime = Constants.NO_MODTIME; ++ int options; ++ InFile(String name) { ++ this.name = Utils.getJarEntryName(name); ++ this.f = new File(name); ++ this.jf = null; ++ this.je = null; ++ int timeSecs = getModtime(f.lastModified()); ++ if (keepModtime && timeSecs != Constants.NO_MODTIME) { ++ this.modtime = timeSecs; ++ } else if (latestModtime && timeSecs > pkg.default_modtime) { ++ pkg.default_modtime = timeSecs; ++ } ++ } ++ InFile(JarFile jf, JarEntry je) { ++ this.name = Utils.getJarEntryName(je.getName()); ++ this.f = null; ++ this.jf = jf; ++ this.je = je; ++ int timeSecs = getModtime(je.getTime()); ++ if (keepModtime && timeSecs != Constants.NO_MODTIME) { ++ this.modtime = timeSecs; ++ } else if (latestModtime && timeSecs > pkg.default_modtime) { ++ pkg.default_modtime = timeSecs; ++ } ++ if (keepDeflateHint && je.getMethod() == JarEntry.DEFLATED) { ++ options |= Constants.FO_DEFLATE_HINT; ++ } ++ } ++ InFile(JarEntry je) { ++ this(null, je); ++ } ++ long getInputLength() { ++ long len = (je != null)? je.getSize(): f.length(); ++ assert(len >= 0) : this+".len="+len; ++ // Bump size by pathname length and modtime/def-hint bytes. ++ return Math.max(0, len) + name.length() + 5; ++ } ++ int getModtime(long timeMillis) { ++ // Convert milliseconds to seconds. ++ long seconds = (timeMillis+500) / 1000; ++ if ((int)seconds == seconds) { ++ return (int)seconds; ++ } else { ++ Utils.log.warning("overflow in modtime for "+f); ++ return Constants.NO_MODTIME; ++ } ++ } ++ void copyTo(Package.File file) { ++ if (modtime != Constants.NO_MODTIME) ++ file.modtime = modtime; ++ file.options |= options; ++ } ++ InputStream getInputStream() throws IOException { ++ if (jf != null) ++ return jf.getInputStream(je); ++ else ++ return new FileInputStream(f); ++ } + +- public String toString() { +- return name; +- } +- } ++ public String toString() { ++ return name; ++ } ++ } + +- private int nread = 0; // used only if (verbose > 0) +- private void noteRead(InFile f) { +- nread++; +- if (verbose > 2) +- Utils.log.fine("...read "+f.name); +- if (verbose > 0 && (nread % 1000) == 0) +- Utils.log.info("Have read "+nread+" files..."); +- } ++ private int nread = 0; // used only if (verbose > 0) ++ private void noteRead(InFile f) { ++ nread++; ++ if (verbose > 2) ++ Utils.log.fine("...read "+f.name); ++ if (verbose > 0 && (nread % 1000) == 0) ++ Utils.log.info("Have read "+nread+" files..."); ++ } + +- void run(JarInputStream in, OutputStream out) throws IOException { +- // First thing we do is get the manifest, as JIS does +- // not provide the Manifest as an entry. +- if (in.getManifest() != null) { +- ByteArrayOutputStream tmp = new ByteArrayOutputStream(); +- in.getManifest().write(tmp); +- InputStream tmpIn = new ByteArrayInputStream(tmp.toByteArray()); +- pkg.addFile(readFile(JarFile.MANIFEST_NAME, tmpIn)); +- } +- for (JarEntry je; (je = in.getNextJarEntry()) != null; ) { +- InFile inFile = new InFile(je); ++ void run(JarInputStream in, OutputStream out) throws IOException { ++ // First thing we do is get the manifest, as JIS does ++ // not provide the Manifest as an entry. ++ if (in.getManifest() != null) { ++ ByteArrayOutputStream tmp = new ByteArrayOutputStream(); ++ in.getManifest().write(tmp); ++ InputStream tmpIn = new ByteArrayInputStream(tmp.toByteArray()); ++ pkg.addFile(readFile(JarFile.MANIFEST_NAME, tmpIn)); ++ } ++ for (JarEntry je; (je = in.getNextJarEntry()) != null; ) { ++ InFile inFile = new InFile(je); + +- String name = inFile.name; +- Package.File bits = readFile(name, in); +- Package.File file = null; +- // (5078608) : discount the resource files in META-INF +- // from segment computation. +- long inflen = (isMetaInfFile(name)) ? 0L : +- inFile.getInputLength(); ++ String name = inFile.name; ++ Package.File bits = readFile(name, in); ++ Package.File file = null; ++ // (5078608) : discount the resource files in META-INF ++ // from segment computation. ++ long inflen = (isMetaInfFile(name)) ? 0L : ++ inFile.getInputLength(); + +- if ((segmentSize += inflen) > segmentLimit) { +- segmentSize -= inflen; +- int nextCount = -1; // don't know; it's a stream +- flushPartial(out, nextCount); +- } +- if (verbose > 1) +- Utils.log.fine("Reading " + name); ++ if ((segmentSize += inflen) > segmentLimit) { ++ segmentSize -= inflen; ++ int nextCount = -1; // don't know; it's a stream ++ flushPartial(out, nextCount); ++ } ++ if (verbose > 1) ++ Utils.log.fine("Reading " + name); + +- assert(je.isDirectory() == name.endsWith("/")); ++ assert(je.isDirectory() == name.endsWith("/")); + +- if (isClassFile(name)) { +- file = readClass(name, bits.getInputStream()); +- } +- if (file == null) { +- file = bits; +- pkg.addFile(file); +- } +- inFile.copyTo(file); +- noteRead(inFile); +- } +- flushAll(out); +- } ++ if (isClassFile(name)) { ++ file = readClass(name, bits.getInputStream()); ++ } ++ if (file == null) { ++ file = bits; ++ pkg.addFile(file); ++ } ++ inFile.copyTo(file); ++ noteRead(inFile); ++ } ++ flushAll(out); ++ } + +- void run(JarFile in, OutputStream out) throws IOException { +- List inFiles = scanJar(in); ++ void run(JarFile in, OutputStream out) throws IOException { ++ List inFiles = scanJar(in); + +- if (verbose > 0) +- Utils.log.info("Reading " + inFiles.size() + " files..."); ++ if (verbose > 0) ++ Utils.log.info("Reading " + inFiles.size() + " files..."); + +- int numDone = 0; +- for (Iterator i = inFiles.iterator(); i.hasNext(); ) { +- InFile inFile = (InFile) i.next(); +- String name = inFile.name; +- // (5078608) : discount the resource files completely from segmenting +- long inflen = (isMetaInfFile(name)) ? 0L : +- inFile.getInputLength() ; +- if ((segmentSize += inflen) > segmentLimit) { +- segmentSize -= inflen; +- // Estimate number of remaining segments: +- float filesDone = numDone+1; +- float segsDone = segmentCount+1; +- float filesToDo = inFiles.size() - filesDone; +- float segsToDo = filesToDo * (segsDone/filesDone); +- if (verbose > 1) +- Utils.log.fine("Estimated segments to do: "+segsToDo); +- flushPartial(out, (int) Math.ceil(segsToDo)); +- } +- InputStream strm = inFile.getInputStream(); +- if (verbose > 1) +- Utils.log.fine("Reading " + name); +- Package.File file = null; +- if (isClassFile(name)) { +- file = readClass(name, strm); +- if (file == null) { +- strm.close(); +- strm = inFile.getInputStream(); +- } +- } +- if (file == null) { +- file = readFile(name, strm); +- pkg.addFile(file); +- } +- inFile.copyTo(file); +- strm.close(); // tidy up +- noteRead(inFile); +- numDone += 1; +- } +- flushAll(out); +- } ++ int numDone = 0; ++ for (Iterator i = inFiles.iterator(); i.hasNext(); ) { ++ InFile inFile = (InFile) i.next(); ++ String name = inFile.name; ++ // (5078608) : discount the resource files completely from segmenting ++ long inflen = (isMetaInfFile(name)) ? 0L : ++ inFile.getInputLength() ; ++ if ((segmentSize += inflen) > segmentLimit) { ++ segmentSize -= inflen; ++ // Estimate number of remaining segments: ++ float filesDone = numDone+1; ++ float segsDone = segmentCount+1; ++ float filesToDo = inFiles.size() - filesDone; ++ float segsToDo = filesToDo * (segsDone/filesDone); ++ if (verbose > 1) ++ Utils.log.fine("Estimated segments to do: "+segsToDo); ++ flushPartial(out, (int) Math.ceil(segsToDo)); ++ } ++ InputStream strm = inFile.getInputStream(); ++ if (verbose > 1) ++ Utils.log.fine("Reading " + name); ++ Package.File file = null; ++ if (isClassFile(name)) { ++ file = readClass(name, strm); ++ if (file == null) { ++ strm.close(); ++ strm = inFile.getInputStream(); ++ } ++ } ++ if (file == null) { ++ file = readFile(name, strm); ++ pkg.addFile(file); ++ } ++ inFile.copyTo(file); ++ strm.close(); // tidy up ++ noteRead(inFile); ++ numDone += 1; ++ } ++ flushAll(out); ++ } + +- Package.File readClass(String fname, InputStream in) throws IOException { +- Package.Class cls = pkg.new Class(fname); +- in = new BufferedInputStream(in); +- ClassReader reader = new ClassReader(cls, in); +- reader.setAttrDefs(attrDefs); +- reader.setAttrCommands(attrCommands); +- reader.unknownAttrCommand = unknownAttrCommand; +- try { +- reader.read(); +- } catch (Attribute.FormatException ee) { +- // He passed up the category to us in layout. +- if (ee.layout.equals(Pack200.Packer.PASS)) { +- Utils.log.warning("Passing class file uncompressed due to unrecognized attribute: "+fname); +- Utils.log.info(ee.toString()); +- return null; +- } +- // Otherwise, it must be an error. +- throw ee; +- } +- pkg.addClass(cls); +- return cls.file; +- } ++ Package.File readClass(String fname, InputStream in) throws IOException { ++ Package.Class cls = pkg.new Class(fname); ++ in = new BufferedInputStream(in); ++ ClassReader reader = new ClassReader(cls, in); ++ reader.setAttrDefs(attrDefs); ++ reader.setAttrCommands(attrCommands); ++ reader.unknownAttrCommand = unknownAttrCommand; ++ try { ++ reader.read(); ++ } catch (Attribute.FormatException ee) { ++ // He passed up the category to us in layout. ++ if (ee.layout.equals(Pack200.Packer.PASS)) { ++ Utils.log.warning("Passing class file uncompressed due to unrecognized attribute: "+fname); ++ Utils.log.info(ee.toString()); ++ return null; ++ } ++ // Otherwise, it must be an error. ++ throw ee; ++ } ++ pkg.addClass(cls); ++ return cls.file; ++ } + +- // Read raw data. +- Package.File readFile(String fname, InputStream in) throws IOException { ++ // Read raw data. ++ Package.File readFile(String fname, InputStream in) throws IOException { + +- Package.File file = pkg.new File(fname); +- file.readFrom(in); +- if (file.isDirectory() && file.getFileLength() != 0) +- throw new IllegalArgumentException("Non-empty directory: "+file.getFileName()); +- return file; +- } ++ Package.File file = pkg.new File(fname); ++ file.readFrom(in); ++ if (file.isDirectory() && file.getFileLength() != 0) ++ throw new IllegalArgumentException("Non-empty directory: "+file.getFileName()); ++ return file; ++ } + +- void flushPartial(OutputStream out, int nextCount) throws IOException { +- if (pkg.files.size() == 0 && pkg.classes.size() == 0) { +- return; // do not flush an empty segment +- } +- flushPackage(out, Math.max(1, nextCount)); +- _props.setInteger(Pack200.Packer.PROGRESS, 25); +- // In case there will be another segment: +- makeNextPackage(); +- segmentCount += 1; +- segmentTotalSize += segmentSize; +- segmentSize = 0; +- } ++ void flushPartial(OutputStream out, int nextCount) throws IOException { ++ if (pkg.files.size() == 0 && pkg.classes.size() == 0) { ++ return; // do not flush an empty segment ++ } ++ flushPackage(out, Math.max(1, nextCount)); ++ _props.setInteger(Pack200.Packer.PROGRESS, 25); ++ // In case there will be another segment: ++ makeNextPackage(); ++ segmentCount += 1; ++ segmentTotalSize += segmentSize; ++ segmentSize = 0; ++ } + +- void flushAll(OutputStream out) throws IOException { +- _props.setInteger(Pack200.Packer.PROGRESS, 50); +- flushPackage(out, 0); +- out.flush(); +- _props.setInteger(Pack200.Packer.PROGRESS, 100); +- segmentCount += 1; +- segmentTotalSize += segmentSize; +- segmentSize = 0; +- if (verbose > 0 && segmentCount > 1) { +- Utils.log.info("Transmitted " +- +segmentTotalSize+" input bytes in " +- +segmentCount+" segments totaling " +- +totalOutputSize+" bytes"); +- } +- } ++ void flushAll(OutputStream out) throws IOException { ++ _props.setInteger(Pack200.Packer.PROGRESS, 50); ++ flushPackage(out, 0); ++ out.flush(); ++ _props.setInteger(Pack200.Packer.PROGRESS, 100); ++ segmentCount += 1; ++ segmentTotalSize += segmentSize; ++ segmentSize = 0; ++ if (verbose > 0 && segmentCount > 1) { ++ Utils.log.info("Transmitted " ++ +segmentTotalSize+" input bytes in " ++ +segmentCount+" segments totaling " ++ +totalOutputSize+" bytes"); ++ } ++ } + + +- /** Write all information in the current package segment +- * to the output stream. +- */ +- void flushPackage(OutputStream out, int nextCount) throws IOException { +- int nfiles = pkg.files.size(); +- if (!keepFileOrder) { +- // Keeping the order of classes costs about 1% +- // Keeping the order of all files costs something more. +- if (verbose > 1) Utils.log.fine("Reordering files."); +- boolean stripDirectories = true; +- pkg.reorderFiles(keepClassOrder, stripDirectories); +- } else { +- // Package builder must have created a stub for each class. +- assert(pkg.files.containsAll(pkg.getClassStubs())); +- // Order of stubs in file list must agree with classes. +- List res = pkg.files; +- assert((res = new ArrayList(pkg.files)) +- .retainAll(pkg.getClassStubs()) || true); +- assert(res.equals(pkg.getClassStubs())); +- } +- pkg.trimStubs(); ++ /** Write all information in the current package segment ++ * to the output stream. ++ */ ++ void flushPackage(OutputStream out, int nextCount) throws IOException { ++ int nfiles = pkg.files.size(); ++ if (!keepFileOrder) { ++ // Keeping the order of classes costs about 1% ++ // Keeping the order of all files costs something more. ++ if (verbose > 1) Utils.log.fine("Reordering files."); ++ boolean stripDirectories = true; ++ pkg.reorderFiles(keepClassOrder, stripDirectories); ++ } else { ++ // Package builder must have created a stub for each class. ++ assert(pkg.files.containsAll(pkg.getClassStubs())); ++ // Order of stubs in file list must agree with classes. ++ List res = pkg.files; ++ assert((res = new ArrayList(pkg.files)) ++ .retainAll(pkg.getClassStubs()) || true); ++ assert(res.equals(pkg.getClassStubs())); ++ } ++ pkg.trimStubs(); + +- // Do some stripping, maybe. +- if (_props.getBoolean(Utils.COM_PREFIX+"strip.debug")) pkg.stripAttributeKind("Debug"); +- if (_props.getBoolean(Utils.COM_PREFIX+"strip.compile")) pkg.stripAttributeKind("Compile"); +- if (_props.getBoolean(Utils.COM_PREFIX+"strip.constants")) pkg.stripAttributeKind("Constant"); +- if (_props.getBoolean(Utils.COM_PREFIX+"strip.exceptions")) pkg.stripAttributeKind("Exceptions"); +- if (_props.getBoolean(Utils.COM_PREFIX+"strip.innerclasses")) pkg.stripAttributeKind("InnerClasses"); ++ // Do some stripping, maybe. ++ if (_props.getBoolean(Utils.COM_PREFIX+"strip.debug")) pkg.stripAttributeKind("Debug"); ++ if (_props.getBoolean(Utils.COM_PREFIX+"strip.compile")) pkg.stripAttributeKind("Compile"); ++ if (_props.getBoolean(Utils.COM_PREFIX+"strip.constants")) pkg.stripAttributeKind("Constant"); ++ if (_props.getBoolean(Utils.COM_PREFIX+"strip.exceptions")) pkg.stripAttributeKind("Exceptions"); ++ if (_props.getBoolean(Utils.COM_PREFIX+"strip.innerclasses")) pkg.stripAttributeKind("InnerClasses"); + +- // Must choose an archive version; PackageWriter does not. +- if (pkg.package_majver <= 0) pkg.choosePackageVersion(); ++ // Must choose an archive version; PackageWriter does not. ++ if (pkg.package_majver <= 0) pkg.choosePackageVersion(); + +- PackageWriter pw = new PackageWriter(pkg, out); +- pw.archiveNextCount = nextCount; +- pw.write(); +- out.flush(); +- if (verbose > 0) { +- long outSize = pw.archiveSize0+pw.archiveSize1; +- totalOutputSize += outSize; +- long inSize = segmentSize; +- Utils.log.info("Transmitted " +- +nfiles+" files of " +- +inSize+" input bytes in a segment of " +- +outSize+" bytes"); +- } +- } ++ PackageWriter pw = new PackageWriter(pkg, out); ++ pw.archiveNextCount = nextCount; ++ pw.write(); ++ out.flush(); ++ if (verbose > 0) { ++ long outSize = pw.archiveSize0+pw.archiveSize1; ++ totalOutputSize += outSize; ++ long inSize = segmentSize; ++ Utils.log.info("Transmitted " ++ +nfiles+" files of " ++ +inSize+" input bytes in a segment of " ++ +outSize+" bytes"); ++ } ++ } + +- List scanJar(JarFile jf) throws IOException { +- // Collect jar entries, preserving order. +- List inFiles = new ArrayList(); +- for (Enumeration e = jf.entries(); e.hasMoreElements(); ) { +- JarEntry je = (JarEntry) e.nextElement(); +- InFile inFile = new InFile(jf, je); +- assert(je.isDirectory() == inFile.name.endsWith("/")); +- inFiles.add(inFile); +- } +- return inFiles; +- } ++ List scanJar(JarFile jf) throws IOException { ++ // Collect jar entries, preserving order. ++ List inFiles = new ArrayList(); ++ for (Enumeration e = jf.entries(); e.hasMoreElements(); ) { ++ JarEntry je = (JarEntry) e.nextElement(); ++ InFile inFile = new InFile(jf, je); ++ assert(je.isDirectory() == inFile.name.endsWith("/")); ++ inFiles.add(inFile); ++ } ++ return inFiles; ++ } + } + } ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java b/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java +--- jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java ++++ jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -41,53 +41,53 @@ import java.beans.PropertyChangeEvent; + + + public class UnpackerImpl implements Pack200.Unpacker { +- +- ++ ++ + /** + * Register a listener for changes to options. + * @param listener An object to be invoked when a property is changed. + */ + public void addPropertyChangeListener(PropertyChangeListener listener) { +- _props.addListener(listener); ++ _props.addListener(listener); + } +- +- ++ ++ + /** + * Remove a listener for the PropertyChange event. + * @param listener The PropertyChange listener to be removed. + */ + public void removePropertyChangeListener(PropertyChangeListener listener) { +- _props.removeListener(listener); ++ _props.removeListener(listener); + } +- ++ + public UnpackerImpl() { +- _props = new PropMap(); +- //_props.getProperty() consults defaultProps invisibly. +- //_props.putAll(defaultProps); ++ _props = new PropMap(); ++ //_props.getProperty() consults defaultProps invisibly. ++ //_props.putAll(defaultProps); + } +- ++ + // Private stuff. + final PropMap _props; + +- ++ + /** + * Get the set of options for the pack and unpack engines. + * @return A sorted association of option key strings to option values. + */ + public SortedMap properties() { +- return _props; ++ return _props; + } +- ++ + // Back-pointer to NativeUnpacker, when active. + Object _nunp; +- +- ++ ++ + public String toString() { +- return Utils.getVersionString(); ++ return Utils.getVersionString(); + } +- ++ + //Driver routines +- ++ + // The unpack worker... + /** + * Takes a packed-stream InputStream, and writes to a JarOutputStream. Internally +@@ -99,36 +99,36 @@ public class UnpackerImpl implements Pac + * @param out a JarOutputStream. + * @exception IOException if an error is encountered. + */ +- public void unpack(InputStream in0, JarOutputStream out) throws IOException { +- assert(Utils.currentInstance.get() == null); +- TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null : +- TimeZone.getDefault(); +- +- try { +- Utils.currentInstance.set(this); +- if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC")); +- final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE); +- BufferedInputStream in = new BufferedInputStream(in0); +- if (Utils.isJarMagic(Utils.readMagic(in))) { +- if (verbose > 0) +- Utils.log.info("Copying unpacked JAR file..."); +- Utils.copyJarFile(new JarInputStream(in), out); +- } else if (_props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) { +- (new DoUnpack()).run(in, out); +- in.close(); +- Utils.markJarFile(out); +- } else { +- (new NativeUnpack(this)).run(in, out); +- in.close(); +- Utils.markJarFile(out); +- } +- } finally { +- _nunp = null; +- Utils.currentInstance.set(null); +- if (tz != null) TimeZone.setDefault(tz); +- } ++ public synchronized void unpack(InputStream in0, JarOutputStream out) throws IOException { ++ assert(Utils.currentInstance.get() == null); ++ TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null : ++ TimeZone.getDefault(); ++ ++ try { ++ Utils.currentInstance.set(this); ++ if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC")); ++ final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE); ++ BufferedInputStream in = new BufferedInputStream(in0); ++ if (Utils.isJarMagic(Utils.readMagic(in))) { ++ if (verbose > 0) ++ Utils.log.info("Copying unpacked JAR file..."); ++ Utils.copyJarFile(new JarInputStream(in), out); ++ } else if (_props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) { ++ (new DoUnpack()).run(in, out); ++ in.close(); ++ Utils.markJarFile(out); ++ } else { ++ (new NativeUnpack(this)).run(in, out); ++ in.close(); ++ Utils.markJarFile(out); ++ } ++ } finally { ++ _nunp = null; ++ Utils.currentInstance.set(null); ++ if (tz != null) TimeZone.setDefault(tz); ++ } + } +- ++ + /** + * Takes an input File containing the pack file, and generates a JarOutputStream. + * <p> +@@ -137,121 +137,121 @@ public class UnpackerImpl implements Pac + * @param out a JarOutputStream. + * @exception IOException if an error is encountered. + */ +- public void unpack(File in, JarOutputStream out) throws IOException { +- // Use the stream-based implementation. +- // %%% Reconsider if native unpacker learns to memory-map the file. +- FileInputStream instr = new FileInputStream(in); +- unpack(instr, out); +- if (_props.getBoolean(Utils.UNPACK_REMOVE_PACKFILE)) { +- in.delete(); +- } ++ public synchronized void unpack(File in, JarOutputStream out) throws IOException { ++ // Use the stream-based implementation. ++ // %%% Reconsider if native unpacker learns to memory-map the file. ++ FileInputStream instr = new FileInputStream(in); ++ unpack(instr, out); ++ if (_props.getBoolean(Utils.UNPACK_REMOVE_PACKFILE)) { ++ in.delete(); ++ } + } +- ++ + private class DoUnpack { +- final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE); +- +- { +- _props.setInteger(Pack200.Unpacker.PROGRESS, 0); +- } +- +- // Here's where the bits are read from disk: +- final Package pkg = new Package(); +- +- final boolean keepModtime +- = Pack200.Packer.KEEP.equals(_props.getProperty(Utils.UNPACK_MODIFICATION_TIME, Pack200.Packer.KEEP)); +- final boolean keepDeflateHint +- = Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Unpacker.DEFLATE_HINT, Pack200.Packer.KEEP)); +- final int modtime; +- final boolean deflateHint; +- { +- if (!keepModtime) { +- modtime = _props.getTime(Utils.UNPACK_MODIFICATION_TIME); +- } else { +- modtime = pkg.default_modtime; +- } +- +- deflateHint = (keepDeflateHint) ? false : +- _props.getBoolean(java.util.jar.Pack200.Unpacker.DEFLATE_HINT); +- } +- +- // Checksum apparatus. +- final CRC32 crc = new CRC32(); +- final ByteArrayOutputStream bufOut = new ByteArrayOutputStream(); +- final OutputStream crcOut = new CheckedOutputStream(bufOut, crc); +- +- public void run(BufferedInputStream in, JarOutputStream out) throws IOException { +- if (verbose > 0) { +- _props.list(System.out); +- } +- for (int seg = 1; ; seg++) { +- unpackSegment(in, out); +- +- // Try to get another segment. +- if (!Utils.isPackMagic(Utils.readMagic(in))) break; +- if (verbose > 0) +- Utils.log.info("Finished segment #"+seg); +- } +- } +- +- private void unpackSegment(InputStream in, JarOutputStream out) throws IOException { +- _props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"0"); +- // Process the output directory or jar output. +- new PackageReader(pkg, in).read(); +- +- if (_props.getBoolean("unpack.strip.debug")) pkg.stripAttributeKind("Debug"); +- if (_props.getBoolean("unpack.strip.compile")) pkg.stripAttributeKind("Compile"); +- _props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"50"); +- pkg.ensureAllClassFiles(); +- // Now write out the files. +- HashSet classesToWrite = new HashSet(pkg.getClasses()); +- for (Iterator i = pkg.getFiles().iterator(); i.hasNext(); ) { +- Package.File file = (Package.File) i.next(); +- String name = file.nameString; +- JarEntry je = new JarEntry(Utils.getJarEntryName(name)); +- boolean deflate; +- +- deflate = (keepDeflateHint) ? (((file.options & Constants.FO_DEFLATE_HINT) != 0) || +- ((pkg.default_options & Constants.AO_DEFLATE_HINT) != 0)) : +- deflateHint; +- +- boolean needCRC = !deflate; // STORE mode requires CRC +- +- if (needCRC) crc.reset(); +- bufOut.reset(); +- if (file.isClassStub()) { +- Package.Class cls = file.getStubClass(); +- assert(cls != null); +- new ClassWriter(cls, needCRC ? crcOut : bufOut).write(); +- classesToWrite.remove(cls); // for an error check +- } else { +- // collect data & maybe CRC +- file.writeTo(needCRC ? crcOut : bufOut); +- } +- je.setMethod(deflate ? JarEntry.DEFLATED : JarEntry.STORED); +- if (needCRC) { +- if (verbose > 0) +- Utils.log.info("stored size="+bufOut.size()+" and crc="+crc.getValue()); +- +- je.setMethod(JarEntry.STORED); +- je.setSize(bufOut.size()); +- je.setCrc(crc.getValue()); +- } +- if (keepModtime) { +- je.setTime(file.modtime); +- // Convert back to milliseconds +- je.setTime((long)file.modtime * 1000); +- } else { +- je.setTime((long)modtime * 1000); +- } +- out.putNextEntry(je); +- bufOut.writeTo(out); +- out.closeEntry(); +- if (verbose > 0) +- Utils.log.info("Writing "+Utils.zeString((ZipEntry)je)); +- } +- assert(classesToWrite.isEmpty()); +- _props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"100"); +- pkg.reset(); // reset for the next segment, if any +- } ++ final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE); ++ ++ { ++ _props.setInteger(Pack200.Unpacker.PROGRESS, 0); ++ } ++ ++ // Here's where the bits are read from disk: ++ final Package pkg = new Package(); ++ ++ final boolean keepModtime ++ = Pack200.Packer.KEEP.equals(_props.getProperty(Utils.UNPACK_MODIFICATION_TIME, Pack200.Packer.KEEP)); ++ final boolean keepDeflateHint ++ = Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Unpacker.DEFLATE_HINT, Pack200.Packer.KEEP)); ++ final int modtime; ++ final boolean deflateHint; ++ { ++ if (!keepModtime) { ++ modtime = _props.getTime(Utils.UNPACK_MODIFICATION_TIME); ++ } else { ++ modtime = pkg.default_modtime; ++ } ++ ++ deflateHint = (keepDeflateHint) ? false : ++ _props.getBoolean(java.util.jar.Pack200.Unpacker.DEFLATE_HINT); ++ } ++ ++ // Checksum apparatus. ++ final CRC32 crc = new CRC32(); ++ final ByteArrayOutputStream bufOut = new ByteArrayOutputStream(); ++ final OutputStream crcOut = new CheckedOutputStream(bufOut, crc); ++ ++ public void run(BufferedInputStream in, JarOutputStream out) throws IOException { ++ if (verbose > 0) { ++ _props.list(System.out); ++ } ++ for (int seg = 1; ; seg++) { ++ unpackSegment(in, out); ++ ++ // Try to get another segment. ++ if (!Utils.isPackMagic(Utils.readMagic(in))) break; ++ if (verbose > 0) ++ Utils.log.info("Finished segment #"+seg); ++ } ++ } ++ ++ private void unpackSegment(InputStream in, JarOutputStream out) throws IOException { ++ _props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"0"); ++ // Process the output directory or jar output. ++ new PackageReader(pkg, in).read(); ++ ++ if (_props.getBoolean("unpack.strip.debug")) pkg.stripAttributeKind("Debug"); ++ if (_props.getBoolean("unpack.strip.compile")) pkg.stripAttributeKind("Compile"); ++ _props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"50"); ++ pkg.ensureAllClassFiles(); ++ // Now write out the files. ++ HashSet classesToWrite = new HashSet(pkg.getClasses()); ++ for (Iterator i = pkg.getFiles().iterator(); i.hasNext(); ) { ++ Package.File file = (Package.File) i.next(); ++ String name = file.nameString; ++ JarEntry je = new JarEntry(Utils.getJarEntryName(name)); ++ boolean deflate; ++ ++ deflate = (keepDeflateHint) ? (((file.options & Constants.FO_DEFLATE_HINT) != 0) || ++ ((pkg.default_options & Constants.AO_DEFLATE_HINT) != 0)) : ++ deflateHint; ++ ++ boolean needCRC = !deflate; // STORE mode requires CRC ++ ++ if (needCRC) crc.reset(); ++ bufOut.reset(); ++ if (file.isClassStub()) { ++ Package.Class cls = file.getStubClass(); ++ assert(cls != null); ++ new ClassWriter(cls, needCRC ? crcOut : bufOut).write(); ++ classesToWrite.remove(cls); // for an error check ++ } else { ++ // collect data & maybe CRC ++ file.writeTo(needCRC ? crcOut : bufOut); ++ } ++ je.setMethod(deflate ? JarEntry.DEFLATED : JarEntry.STORED); ++ if (needCRC) { ++ if (verbose > 0) ++ Utils.log.info("stored size="+bufOut.size()+" and crc="+crc.getValue()); ++ ++ je.setMethod(JarEntry.STORED); ++ je.setSize(bufOut.size()); ++ je.setCrc(crc.getValue()); ++ } ++ if (keepModtime) { ++ je.setTime(file.modtime); ++ // Convert back to milliseconds ++ je.setTime((long)file.modtime * 1000); ++ } else { ++ je.setTime((long)modtime * 1000); ++ } ++ out.putNextEntry(je); ++ bufOut.writeTo(out); ++ out.closeEntry(); ++ if (verbose > 0) ++ Utils.log.info("Writing "+Utils.zeString((ZipEntry)je)); ++ } ++ assert(classesToWrite.isEmpty()); ++ _props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"100"); ++ pkg.reset(); // reset for the next segment, if any ++ } + } + } +diff --git a/src/share/native/com/sun/java/util/jar/pack/bands.cpp b/src/share/native/com/sun/java/util/jar/pack/bands.cpp +--- jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp ++++ jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -81,11 +81,11 @@ void band::readData(int expectedLength) + assert(defc->B() > 1 && defc->L() > 0); + // must have already read from previous band: + assert(bn >= BAND_LIMIT || bn <= 0 +- || bn == e_cp_Utf8_big_chars +- || endsWith(name, "_lo") // preceded by _hi conditional band +- || bn == e_file_options // preceded by conditional band +- || u->rp == u->all_bands[bn-1].maxRP() +- || u->all_bands[bn-1].defc == null); ++ || bn == e_cp_Utf8_big_chars ++ || endsWith(name, "_lo") // preceded by _hi conditional band ++ || bn == e_file_options // preceded by conditional band ++ || u->rp == u->all_bands[bn-1].maxRP() ++ || u->all_bands[bn-1].defc == null); + + value_stream xvs; + coding* valc = defc; +@@ -136,7 +136,7 @@ void band::readData(int expectedLength) + + #ifndef PRODUCT + printcr(3,"readFrom %s at %p [%d values, %d bytes, cp=%d/%d]", +- (name?name:"(band)"), minRP(), length, size(), cp1, cp2); ++ (name?name:"(band)"), minRP(), length, size(), cp1, cp2); + if (u->verbose_bands || u->verbose >= 4) dump(); + + if (ix != null && u->verbose != 0 && length > 0) { +@@ -187,10 +187,14 @@ void band::setIndexByTag(byte tag) { + + entry* band::getRefCommon(cpindex* ix_, bool nullOKwithCaller) { + CHECK_0; ++ if (ix_ == NULL) { ++ abort("no index"); ++ return NULL; ++ } + assert(ix_->ixTag == ixTag +- || (ixTag == CONSTANT_Literal +- && ix_->ixTag >= CONSTANT_Integer +- && ix_->ixTag <= CONSTANT_String)); ++ || (ixTag == CONSTANT_Literal ++ && ix_->ixTag >= CONSTANT_Integer ++ && ix_->ixTag <= CONSTANT_String)); + int n = vs[0].getInt() - nullOK; + // Note: band-local nullOK means null encodes as 0. + // But nullOKwithCaller means caller is willing to tolerate a null. +@@ -245,9 +249,9 @@ int band::getIntCount(int tag) { + hist0 = U_NEW(int, (HIST0_MAX - HIST0_MIN)+1); + CHECK_0; + for (int k = length; k > 0; k--) { +- int x = vs[0].getInt(); +- if (x >= HIST0_MIN && x <= HIST0_MAX) +- hist0[x - HIST0_MIN] += 1; ++ int x = vs[0].getInt(); ++ if (x >= HIST0_MIN && x <= HIST0_MAX) ++ hist0[x - HIST0_MIN] += 1; + } + rewind(); + } +@@ -262,7 +266,7 @@ int band::getIntCount(int tag) { + } + + #define INDEX_INIT(tag, nullOK, subindex) \ +- ((tag) + (subindex)*SUBINDEX_BIT + (nullOK)*256) ++ ((tag) + (subindex)*SUBINDEX_BIT + (nullOK)*256) + + #define INDEX(tag) INDEX_INIT(tag, 0, 0) + #define NULL_OR_INDEX(tag) INDEX_INIT(tag, 1, 0) +@@ -437,13 +441,13 @@ const band_init all_band_inits[] = { + {0} + }; + #define NUM_BAND_INITS \ +- (sizeof(all_band_inits)/sizeof(all_band_inits[0])) ++ (sizeof(all_band_inits)/sizeof(all_band_inits[0])) + + band* band::makeBands(unpacker* u) { + band* all_bands = U_NEW(band, BAND_LIMIT); + for (int i = 0; i < BAND_LIMIT; i++) { + assert((byte*)&all_band_inits[i+1] +- < (byte*)all_band_inits+sizeof(all_band_inits)); ++ < (byte*)all_band_inits+sizeof(all_band_inits)); + const band_init& bi = all_band_inits[i]; + band& b = all_bands[i]; + coding* defc = coding::findBySpec(bi.defc); +@@ -472,3 +476,5 @@ void band::initIndexes(unpacker* u) { + } + } + } ++ ++ +diff --git a/src/share/native/com/sun/java/util/jar/pack/bands.h b/src/share/native/com/sun/java/util/jar/pack/bands.h +--- jdk/src/share/native/com/sun/java/util/jar/pack/bands.h ++++ jdk/src/share/native/com/sun/java/util/jar/pack/bands.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -22,7 +22,7 @@ + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +- ++ + // -*- C++ -*- + struct entry; + struct cpindex; +@@ -50,7 +50,7 @@ struct band { + + // properties for attribute layout elements: + byte le_kind; // EK_XXX +- byte le_bci; // 0,EK_BCI,EK_BCD,EK_BCO ++ byte le_bci; // 0,EK_BCI,EK_BCD,EK_BCO + byte le_back; // ==EF_BACK + byte le_len; // 0,1,2,4 (size in classfile), or call addr + band** le_body; // body of repl, union, call (null-terminated) +@@ -101,8 +101,8 @@ struct band { + + int getByte() { assert(ix == null); return vs[0].getByte(); } + int getInt() { assert(ix == null); return vs[0].getInt(); } +- entry* getRefN() { assert(ix != null); return getRefCommon(ix, true); } +- entry* getRef() { assert(ix != null); return getRefCommon(ix, false); } ++ entry* getRefN() { return getRefCommon(ix, true); } ++ entry* getRef() { return getRefCommon(ix, false); } + entry* getRefUsing(cpindex* ix2) + { assert(ix == null); return getRefCommon(ix2, true); } + entry* getRefCommon(cpindex* ix, bool nullOK); +diff --git a/src/share/native/com/sun/java/util/jar/pack/defines.h b/src/share/native/com/sun/java/util/jar/pack/defines.h +--- jdk/src/share/native/com/sun/java/util/jar/pack/defines.h ++++ jdk/src/share/native/com/sun/java/util/jar/pack/defines.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -22,10 +22,10 @@ + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +- ++ + // random definitions + +-#ifdef _MSC_VER ++#ifdef _MSC_VER + #include <windows.h> + #include <winuser.h> + #else +@@ -94,15 +94,15 @@ typedef unsigned int uLong; // Historica + #else + typedef unsigned long uLong; + #endif +-#ifdef _MSC_VER +-typedef LONGLONG jlong; +-typedef DWORDLONG julong; +-#define MKDIR(dir) mkdir(dir) +-#define getpid() _getpid() +-#define PATH_MAX MAX_PATH +-#define dup2(a,b) _dup2(a,b) ++#ifdef _MSC_VER ++typedef LONGLONG jlong; ++typedef DWORDLONG julong; ++#define MKDIR(dir) mkdir(dir) ++#define getpid() _getpid() ++#define PATH_MAX MAX_PATH ++#define dup2(a,b) _dup2(a,b) + #define strcasecmp(s1, s2) _stricmp(s1,s2) +-#define tempname _tempname ++#define tempname _tempname + #define sleep Sleep + #else + typedef signed char byte; +@@ -123,37 +123,40 @@ enum { false, true }; + + #define null (0) + +-#ifndef __sparc ++#ifndef __sparc + #define intptr_t jlong + #endif + + #define ptrlowbits(x) ((int) (intptr_t)(x)) + ++/* Back and forth from jlong to pointer */ ++#define ptr2jlong(x) ((jlong)(size_t)(void*)(x)) ++#define jlong2ptr(x) ((void*)(size_t)(x)) + + // Keys used by Java: +-#define UNPACK_DEFLATE_HINT "unpack.deflate.hint" ++#define UNPACK_DEFLATE_HINT "unpack.deflate.hint" + +-#define COM_PREFIX "com.sun.java.util.jar.pack." +-#define UNPACK_MODIFICATION_TIME COM_PREFIX"unpack.modification.time" +-#define DEBUG_VERBOSE COM_PREFIX"verbose" ++#define COM_PREFIX "com.sun.java.util.jar.pack." ++#define UNPACK_MODIFICATION_TIME COM_PREFIX"unpack.modification.time" ++#define DEBUG_VERBOSE COM_PREFIX"verbose" + +-#define ZIP_ARCHIVE_MARKER_COMMENT "PACK200" ++#define ZIP_ARCHIVE_MARKER_COMMENT "PACK200" + + // The following are not known to the Java classes: +-#define UNPACK_LOG_FILE COM_PREFIX"unpack.log.file" +-#define UNPACK_REMOVE_PACKFILE COM_PREFIX"unpack.remove.packfile" ++#define UNPACK_LOG_FILE COM_PREFIX"unpack.log.file" ++#define UNPACK_REMOVE_PACKFILE COM_PREFIX"unpack.remove.packfile" + + + // Called from unpacker layers +-#define _CHECK_DO(t,x) { if (t) {x;} } ++#define _CHECK_DO(t,x) { if (t) {x;} } + +-#define CHECK _CHECK_DO(aborting(), return) +-#define CHECK_(y) _CHECK_DO(aborting(), return y) +-#define CHECK_0 _CHECK_DO(aborting(), return 0) ++#define CHECK _CHECK_DO(aborting(), return) ++#define CHECK_(y) _CHECK_DO(aborting(), return y) ++#define CHECK_0 _CHECK_DO(aborting(), return 0) + +-#define CHECK_NULL(p) _CHECK_DO((p)==null, return) +-#define CHECK_NULL_(y,p) _CHECK_DO((p)==null, return y) +-#define CHECK_NULL_0(p) _CHECK_DO((p)==null, return 0) ++#define CHECK_NULL(p) _CHECK_DO((p)==null, return) ++#define CHECK_NULL_(y,p) _CHECK_DO((p)==null, return y) ++#define CHECK_NULL_0(p) _CHECK_DO((p)==null, return 0) + + #define CHECK_COUNT(t) if (t < 0){abort("bad value count");} CHECK + +diff --git a/src/share/native/com/sun/java/util/jar/pack/jni.cpp b/src/share/native/com/sun/java/util/jar/pack/jni.cpp +--- jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp ++++ jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -43,6 +43,9 @@ + #include "bands.h" + #include "constants.h" + #include "zip.h" ++ ++#include "jni_util.h" ++ + #include "unpack.h" + + +@@ -50,17 +53,19 @@ static jmethodID currentInstMID; + static jmethodID currentInstMID; + static jmethodID readInputMID; + static jclass NIclazz; ++static jmethodID getUnpackerPtrMID; + + static char* dbg = null; + + #define THROW_IOE(x) JNU_ThrowIOException(env,x) + + static jlong read_input_via_jni(unpacker* self, +- void* buf, jlong minlen, jlong maxlen); +- ++ void* buf, jlong minlen, jlong maxlen); ++ + static unpacker* get_unpacker(JNIEnv *env, jobject pObj, bool noCreate=false) { +- unpacker* uPtr = (unpacker*) env->GetLongField(pObj, unpackerPtrFID); +- //fprintf(stderr, "get_unpacker(%p) uPtr=%p\n", pObj, uPtr); ++ unpacker* uPtr; ++ jlong p = env->CallLongMethod(pObj, getUnpackerPtrMID); ++ uPtr = (unpacker*)jlong2ptr(p); + if (uPtr == null) { + if (noCreate) return null; + uPtr = new unpacker(); +@@ -89,11 +94,15 @@ static unpacker* get_unpacker() { + if (env == null) + return null; + jobject pObj = env->CallStaticObjectMethod(NIclazz, currentInstMID); +- //fprintf(stderr, "get_unpacker() pObj=%p\n", pObj); +- if (pObj == null) +- return null; +- // Got pObj and env; now do it the easy way. +- return get_unpacker(env, pObj); ++ //fprintf(stderr, "get_unpacker0() pObj=%p\n", pObj); ++ if (pObj != null) { ++ // Got pObj and env; now do it the easy way. ++ return get_unpacker(env, pObj); ++ } ++ // this should really not happen, if it does something is seriously ++ // wrong throw an exception ++ THROW_IOE(ERROR_INTERNAL); ++ return null; + } + + static void free_unpacker(JNIEnv *env, jobject pObj, unpacker* uPtr) { +@@ -113,36 +122,47 @@ unpacker* unpacker::current() { + + // Callback for fetching data, Java style. Calls NativeUnpack.readInputFn(). + static jlong read_input_via_jni(unpacker* self, +- void* buf, jlong minlen, jlong maxlen) { ++ void* buf, jlong minlen, jlong maxlen) { + JNIEnv* env = (JNIEnv*) self->jnienv; + jobject pbuf = env->NewDirectByteBuffer(buf, maxlen); + return env->CallLongMethod((jobject) self->jniobj, readInputMID, +- pbuf, minlen); ++ pbuf, minlen); + } + +-JNIEXPORT void JNICALL ++JNIEXPORT void JNICALL + Java_com_sun_java_util_jar_pack_NativeUnpack_initIDs(JNIEnv *env, jclass clazz) { ++#ifndef PRODUCT + dbg = getenv("DEBUG_ATTACH"); + while( dbg != null) { sleep(10); } ++#endif + NIclazz = (jclass) env->NewGlobalRef(clazz); + unpackerPtrFID = env->GetFieldID(clazz, "unpackerPtr", "J"); + currentInstMID = env->GetStaticMethodID(clazz, "currentInstance", +- "()Ljava/lang/Object;"); ++ "()Ljava/lang/Object;"); + readInputMID = env->GetMethodID(clazz, "readInputFn", +- "(Ljava/nio/ByteBuffer;J)J"); ++ "(Ljava/nio/ByteBuffer;J)J"); ++ ++ getUnpackerPtrMID = env->GetMethodID(clazz, "getUnpackerPtr", "()J"); ++ + if (unpackerPtrFID == null || + currentInstMID == null || + readInputMID == null || +- NIclazz == null) { ++ NIclazz == null || ++ getUnpackerPtrMID == null) { + THROW_IOE("cannot init class members"); + } + } + +-JNIEXPORT jlong JNICALL ++JNIEXPORT jlong JNICALL + Java_com_sun_java_util_jar_pack_NativeUnpack_start(JNIEnv *env, jobject pObj, +- jobject pBuf, jlong offset) { +- unpacker* uPtr = get_unpacker(env, pObj); +- ++ jobject pBuf, jlong offset) { ++ // try to get the unpacker pointer the hard way first, we do this to ensure ++ // valid object pointers and env is intact, if not now is good time to bail. ++ unpacker* uPtr = get_unpacker(); ++ //fprintf(stderr, "start(%p) uPtr=%p initializing\n", pObj, uPtr); ++ if (uPtr == null) { ++ return -1; ++ } + // redirect our io to the default log file or whatever. + uPtr->redirect_stdio(); + +@@ -158,6 +178,13 @@ Java_com_sun_java_util_jar_pack_NativeUn + else + { buf = (char*)buf + (size_t)offset; buflen -= (size_t)offset; } + } ++ ++ // before we start off we make sure there is no other error by the time we ++ // get here ++ if (uPtr->aborting()) { ++ THROW_IOE(uPtr->get_abort_message()); ++ return 0; ++ } + + uPtr->start(buf, buflen); + if (uPtr->aborting()) { +@@ -166,13 +193,13 @@ Java_com_sun_java_util_jar_pack_NativeUn + } + + return ((jlong) +- uPtr->get_segments_remaining() << 32) ++ uPtr->get_segments_remaining() << 32) + + uPtr->get_files_remaining(); + } + +-JNIEXPORT jboolean JNICALL +-Java_com_sun_java_util_jar_pack_NativeUnpack_getNextFile(JNIEnv *env, jobject pObj, +- jobjectArray pParts) { ++JNIEXPORT jboolean JNICALL ++Java_com_sun_java_util_jar_pack_NativeUnpack_getNextFile(JNIEnv *env, jobject pObj, ++ jobjectArray pParts) { + + unpacker* uPtr = get_unpacker(env, pObj); + unpacker::file* filep = uPtr->get_next_file(); +@@ -201,19 +228,19 @@ Java_com_sun_java_util_jar_pack_NativeUn + jobject pDataBuf = null; + if (filep->data[0].len > 0) + pDataBuf = env->NewDirectByteBuffer(filep->data[0].ptr, +- filep->data[0].len); ++ filep->data[0].len); + env->SetObjectArrayElement(pParts, pidx++, pDataBuf); + pDataBuf = null; + if (filep->data[1].len > 0) + pDataBuf = env->NewDirectByteBuffer(filep->data[1].ptr, +- filep->data[1].len); ++ filep->data[1].len); + env->SetObjectArrayElement(pParts, pidx++, pDataBuf); + + return true; + } + + +-JNIEXPORT jobject JNICALL ++JNIEXPORT jobject JNICALL + Java_com_sun_java_util_jar_pack_NativeUnpack_getUnusedInput(JNIEnv *env, jobject pObj) { + unpacker* uPtr = get_unpacker(env, pObj); + unpacker::file* filep = &uPtr->cur_file; +@@ -225,14 +252,18 @@ Java_com_sun_java_util_jar_pack_NativeUn + + // We have fetched all the files. + // Now swallow up any remaining input. +- if (uPtr->input_remaining() == 0) ++ if (uPtr->input_remaining() == 0) { + return null; +- else +- return env->NewDirectByteBuffer(uPtr->input_scan(), +- uPtr->input_remaining()); ++ } ++ else { ++ bytes remaining_bytes; ++ remaining_bytes.malloc(uPtr->input_remaining()); ++ remaining_bytes.copyFrom(uPtr->input_scan(), uPtr->input_remaining()); ++ return env->NewDirectByteBuffer(remaining_bytes.ptr, remaining_bytes.len); ++ } + } + +-JNIEXPORT jlong JNICALL ++JNIEXPORT jlong JNICALL + Java_com_sun_java_util_jar_pack_NativeUnpack_finish(JNIEnv *env, jobject pObj) { + unpacker* uPtr = get_unpacker(env, pObj, false); + if (uPtr == null) return 0; +@@ -241,9 +272,9 @@ Java_com_sun_java_util_jar_pack_NativeUn + return consumed; + } + +-JNIEXPORT jboolean JNICALL +-Java_com_sun_java_util_jar_pack_NativeUnpack_setOption(JNIEnv *env, jobject pObj, +- jstring pProp, jstring pValue) { ++JNIEXPORT jboolean JNICALL ++Java_com_sun_java_util_jar_pack_NativeUnpack_setOption(JNIEnv *env, jobject pObj, ++ jstring pProp, jstring pValue) { + unpacker* uPtr = get_unpacker(env, pObj); + const char* prop = env->GetStringUTFChars(pProp, JNI_FALSE); + const char* value = env->GetStringUTFChars(pValue, JNI_FALSE); +@@ -253,9 +284,9 @@ Java_com_sun_java_util_jar_pack_NativeUn + return retval; + } + +-JNIEXPORT jstring JNICALL +-Java_com_sun_java_util_jar_pack_NativeUnpack_getOption(JNIEnv *env, jobject pObj, +- jstring pProp) { ++JNIEXPORT jstring JNICALL ++Java_com_sun_java_util_jar_pack_NativeUnpack_getOption(JNIEnv *env, jobject pObj, ++ jstring pProp) { + + unpacker* uPtr = get_unpacker(env, pObj); + const char* prop = env->GetStringUTFChars(pProp, JNI_FALSE); +diff --git a/src/share/native/com/sun/java/util/jar/pack/unpack.cpp b/src/share/native/com/sun/java/util/jar/pack/unpack.cpp +--- jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp ++++ jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -38,7 +38,7 @@ + #include <time.h> + + +- ++ + + #include "defines.h" + #include "bytes.h" +@@ -185,9 +185,9 @@ struct entry { + || (tag2 == CONSTANT_Utf8 && tag == CONSTANT_Signature) + #ifndef PRODUCT + || (tag2 == CONSTANT_Literal +- && tag >= CONSTANT_Integer && tag <= CONSTANT_String && tag != CONSTANT_Class) ++ && tag >= CONSTANT_Integer && tag <= CONSTANT_String && tag != CONSTANT_Class) + || (tag2 == CONSTANT_Member +- && tag >= CONSTANT_Fieldref && tag <= CONSTANT_InterfaceMethodref) ++ && tag >= CONSTANT_Fieldref && tag <= CONSTANT_InterfaceMethodref) + #endif + ; + } +@@ -238,9 +238,9 @@ int entry::typeSize() { + // else fall through + case 'L': + sigp = strchr(sigp, ';'); +- if (sigp == null) { +- unpack_abort("bad data"); +- return 0; ++ if (sigp == null) { ++ unpack_abort("bad data"); ++ return 0; + } + sigp += 1; + break; +@@ -252,11 +252,13 @@ int entry::typeSize() { + } + + inline cpindex* cpool::getFieldIndex(entry* classRef) { ++ if (classRef == NULL) { abort("missing class reference"); return NULL; } + assert(classRef->tagMatches(CONSTANT_Class)); + assert((uint)classRef->inord < tag_count[CONSTANT_Class]); + return &member_indexes[classRef->inord*2+0]; + } + inline cpindex* cpool::getMethodIndex(entry* classRef) { ++ if (classRef == NULL) { abort("missing class reference"); return NULL; } + assert(classRef->tagMatches(CONSTANT_Class)); + assert((uint)classRef->inord < tag_count[CONSTANT_Class]); + return &member_indexes[classRef->inord*2+1]; +@@ -512,11 +514,10 @@ void unpacker::read_file_header() { + AH_CP_NUMBER_LEN = 4, // int/float/long/double + AH_SPECIAL_FORMAT_LEN = 2, // layouts/band-headers + AH_LENGTH_MIN = AH_LENGTH +- -(AH_FILE_HEADER_LEN+AH_SPECIAL_FORMAT_LEN+AH_CP_NUMBER_LEN), +- ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - (AH_LENGTH_0 + AH_ARCHIVE_SIZE_LEN), ++ -(AH_FILE_HEADER_LEN+AH_SPECIAL_FORMAT_LEN+AH_CP_NUMBER_LEN), ++ ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - (AH_LENGTH_0 + AH_ARCHIVE_SIZE_LEN), + FIRST_READ = MAGIC_BYTES + AH_LENGTH_MIN + }; +- + + assert(AH_LENGTH_MIN == 15); // # of UNSIGNED5 fields required after archive_magic + assert(ARCHIVE_SIZE_MIN == 10); // # of UNSIGNED5 fields required after archive_size +@@ -580,15 +581,15 @@ void unpacker::read_file_header() { + for (;;) { + jarout->write_data(rp, input_remaining()); + if (foreign_buf) +- break; // one-time use of a passed in buffer ++ break; // one-time use of a passed in buffer + if (input.size() < CHUNK) { +- // Get some breathing room. +- input.set(U_NEW(byte, (size_t) CHUNK + C_SLOP), (size_t) CHUNK); +- CHECK; ++ // Get some breathing room. ++ input.set(U_NEW(byte, (size_t) CHUNK + C_SLOP), (size_t) CHUNK); ++ CHECK; + } + rp = rplimit = input.base(); + if (!ensure_input(1)) +- break; ++ break; + } + jarout->closeJarFile(false); + #endif +@@ -612,16 +613,16 @@ void unpacker::read_file_header() { + hdrVals += 2; + + if (magic != JAVA_PACKAGE_MAGIC || +- (majver != JAVA5_PACKAGE_MAJOR_VERSION && +- majver != JAVA6_PACKAGE_MAJOR_VERSION) || +- (minver != JAVA5_PACKAGE_MINOR_VERSION && ++ (majver != JAVA5_PACKAGE_MAJOR_VERSION && ++ majver != JAVA6_PACKAGE_MAJOR_VERSION) || ++ (minver != JAVA5_PACKAGE_MINOR_VERSION && + minver != JAVA6_PACKAGE_MINOR_VERSION)) { + char message[200]; + sprintf(message, "@" ERROR_FORMAT ": magic/ver = " +- "%08X/%d.%d should be %08X/%d.%d OR %08X/%d.%d\n", +- magic, majver, minver, +- JAVA_PACKAGE_MAGIC, JAVA5_PACKAGE_MAJOR_VERSION, JAVA5_PACKAGE_MINOR_VERSION, +- JAVA_PACKAGE_MAGIC, JAVA6_PACKAGE_MAJOR_VERSION, JAVA6_PACKAGE_MINOR_VERSION); ++ "%08X/%d.%d should be %08X/%d.%d OR %08X/%d.%d\n", ++ magic, majver, minver, ++ JAVA_PACKAGE_MAGIC, JAVA5_PACKAGE_MAJOR_VERSION, JAVA5_PACKAGE_MINOR_VERSION, ++ JAVA_PACKAGE_MAGIC, JAVA6_PACKAGE_MAJOR_VERSION, JAVA6_PACKAGE_MINOR_VERSION); + abort(message); + } + CHECK; +@@ -635,7 +636,7 @@ void unpacker::read_file_header() { + #undef ORBIT + if ((archive_options & ~OPTION_LIMIT) != 0) { + fprintf(errstrm, "Warning: Illegal archive options 0x%x\n", +- archive_options); ++ archive_options); + abort("illegal archive options"); + return; + } +@@ -675,7 +676,7 @@ void unpacker::read_file_header() { + if (archive_size < header_size_1) { + abort("too much read-ahead"); // somehow we pre-fetched too much? + return; +- } ++ } + input.set(U_NEW(byte, add_size(header_size_0, archive_size, C_SLOP)), + (size_t) header_size_0 + archive_size); + CHECK; +@@ -756,9 +757,9 @@ void unpacker::read_file_header() { + case CONSTANT_Float: + case CONSTANT_Long: + case CONSTANT_Double: +- cp_counts[k] = 0; +- hdrValsSkipped += 1; +- continue; ++ cp_counts[k] = 0; ++ hdrValsSkipped += 1; ++ continue; + } + } + cp_counts[k] = hdr.getInt(); +@@ -813,7 +814,7 @@ void unpacker::read_file_header() { + bytes band_headers; + // The "1+" allows an initial byte to be pushed on the front. + band_headers.set(1+U_NEW(byte, 1+band_headers_size+C_SLOP), +- band_headers_size); ++ band_headers_size); + CHECK; + // Start scanning band headers here: + band_headers.copyFrom(rp, band_headers.len); +@@ -874,7 +875,7 @@ void cpool::init(unpacker* u_, int count + IMPLICIT_ENTRY_COUNT = 1 // empty Utf8 string + }; + if (len >= (1<<29) || len < 0 +- || next_entry >= CP_SIZE_LIMIT+IMPLICIT_ENTRY_COUNT) { ++ || next_entry >= CP_SIZE_LIMIT+IMPLICIT_ENTRY_COUNT) { + abort("archive too large: constant pool limit exceeded"); + return; + } +@@ -935,9 +936,9 @@ static byte* skip_Utf8_chars(byte* cp, i + int ch = *cp & 0xFF; + if ((ch & 0xC0) != 0x80) { + if (len-- == 0) +- return cp; ++ return cp; + if (ch < 0x80 && len == 0) +- return cp+1; ++ return cp+1; + } + } + } +@@ -963,9 +964,9 @@ static int compare_Utf8_chars(bytes& b1, + if (c1 == 0xC0 && (p1[i+1] & 0xFF) == 0x80) c1 = 0; + if (c2 == 0xC0 && (p2[i+1] & 0xFF) == 0x80) c2 = 0; + if (c0 == 0xC0) { +- assert(((c1|c2) & 0xC0) == 0x80); // c1 & c2 are extension chars +- if (c1 == 0x80) c1 = 0; // will sort below c2 +- if (c2 == 0x80) c2 = 0; // will sort below c1 ++ assert(((c1|c2) & 0xC0) == 0x80); // c1 & c2 are extension chars ++ if (c1 == 0x80) c1 = 0; // will sort below c2 ++ if (c2 == 0x80) c2 = 0; // will sort below c1 + } + return c1 - c2; + } +@@ -1024,9 +1025,9 @@ void unpacker::read_Utf8_values(entry* c + chars.malloc(size3); + } else { + if (!charbuf.canAppend(size3+1)) { +- assert(charbuf.allocated == 0 || tmallocs.contains(charbuf.base())); +- charbuf.init(CHUNK); // Reset to new buffer. +- tmallocs.add(charbuf.base()); ++ assert(charbuf.allocated == 0 || tmallocs.contains(charbuf.base())); ++ charbuf.init(CHUNK); // Reset to new buffer. ++ tmallocs.add(charbuf.base()); + } + chars.set(charbuf.grow(size3+1), size3); + } +@@ -1191,9 +1192,9 @@ void unpacker::read_single_refs(band& cp + // Maintain cross-reference: + entry* &htref = cp.hashTabRef(indexTag, e.value.b); + if (htref == null) { +- // Note that if two identical classes are transmitted, +- // the first is taken to be the canonical one. +- htref = &e; ++ // Note that if two identical classes are transmitted, ++ // the first is taken to be the canonical one. ++ htref = &e; + } + } + } +@@ -1202,7 +1203,7 @@ void unpacker::read_single_refs(band& cp + + maybe_inline + void unpacker::read_double_refs(band& cp_band, byte ref1Tag, byte ref2Tag, +- entry* cpMap, int len) { ++ entry* cpMap, int len) { + band& cp_band1 = cp_band; + band& cp_band2 = cp_band.nextBand(); + cp_band1.setIndexByTag(ref1Tag); +@@ -1214,6 +1215,7 @@ void unpacker::read_double_refs(band& cp + entry& e = cpMap[i]; + e.refs = U_NEW(entry*, e.nrefs = 2); + e.refs[0] = cp_band1.getRef(); ++ CHECK; + e.refs[1] = cp_band2.getRef(); + CHECK; + } +@@ -1302,23 +1304,23 @@ void unpacker::read_cp() { + break; + case CONSTANT_NameandType: + read_double_refs(cp_Descr_name /*& cp_Descr_type*/, +- CONSTANT_Utf8, CONSTANT_Signature, +- cpMap, len); ++ CONSTANT_Utf8, CONSTANT_Signature, ++ cpMap, len); + break; + case CONSTANT_Fieldref: + read_double_refs(cp_Field_class /*& cp_Field_desc*/, +- CONSTANT_Class, CONSTANT_NameandType, +- cpMap, len); ++ CONSTANT_Class, CONSTANT_NameandType, ++ cpMap, len); + break; + case CONSTANT_Methodref: + read_double_refs(cp_Method_class /*& cp_Method_desc*/, +- CONSTANT_Class, CONSTANT_NameandType, +- cpMap, len); ++ CONSTANT_Class, CONSTANT_NameandType, ++ cpMap, len); + break; + case CONSTANT_InterfaceMethodref: + read_double_refs(cp_Imethod_class /*& cp_Imethod_desc*/, +- CONSTANT_Class, CONSTANT_NameandType, +- cpMap, len); ++ CONSTANT_Class, CONSTANT_NameandType, ++ cpMap, len); + break; + default: + assert(false); +@@ -1384,8 +1386,8 @@ inline + inline + unpacker::layout_definition* + unpacker::attr_definitions::defineLayout(int idx, +- entry* nameEntry, +- const char* layout) { ++ entry* nameEntry, ++ const char* layout) { + const char* name = nameEntry->value.b.strval(); + layout_definition* lo = defineLayout(idx, name, layout); + CHECK_0; +@@ -1395,8 +1397,8 @@ unpacker::attr_definitions::defineLayout + + unpacker::layout_definition* + unpacker::attr_definitions::defineLayout(int idx, +- const char* name, +- const char* layout) { ++ const char* name, ++ const char* layout) { + assert(flag_limit != 0); // must be set up already + if (idx >= 0) { + // Fixed attr. +@@ -1419,12 +1421,12 @@ unpacker::attr_definitions::defineLayout + } + CHECK_0; + layouts.get(idx) = lo; +- return lo; ++ return lo; + } + + band** + unpacker::attr_definitions::buildBands(unpacker::layout_definition* lo) { +- int i; ++ int i; + if (lo->elems != null) + return lo->bands(); + if (lo->layout[0] == '\0') { +@@ -1448,11 +1450,11 @@ unpacker::attr_definitions::buildBands(u + int num_callables = 0; + if (hasCallables) { + while (bands[num_callables] != null) { +- if (bands[num_callables]->le_kind != EK_CBLE) { +- abort("garbage mixed with callables"); +- break; +- } +- num_callables += 1; ++ if (bands[num_callables]->le_kind != EK_CBLE) { ++ abort("garbage mixed with callables"); ++ break; ++ } ++ num_callables += 1; + } + } + for (i = 0; i < calls_to_link.length(); i++) { +@@ -1461,8 +1463,8 @@ unpacker::attr_definitions::buildBands(u + // Determine the callee. + int call_num = call.le_len; + if (call_num < 0 || call_num >= num_callables) { +- abort("bad call in layout"); +- break; ++ abort("bad call in layout"); ++ break; + } + band& cble = *bands[call_num]; + // Link the call to it. +@@ -1540,7 +1542,7 @@ unpacker::attr_definitions::buildBands(u + + const char* + unpacker::attr_definitions::parseIntLayout(const char* lp, band* &res, +- byte le_kind, bool can_be_signed) { ++ byte le_kind, bool can_be_signed) { + const char* lp0 = lp; + band* b = U_NEW(band, 1); + CHECK_(lp); +@@ -1619,7 +1621,7 @@ unpacker::attr_definitions::popBody(int + + const char* + unpacker::attr_definitions::parseLayout(const char* lp, band** &res, +- int curCble) { ++ int curCble) { + const char* lp0 = lp; + int bs_base = band_stack.length(); + bool top_level = (bs_base == 0); +@@ -1636,18 +1638,18 @@ unpacker::attr_definitions::parseLayout( + break; + case 'P': + { +- int le_bci = EK_BCI; +- if (*lp == 'O') { +- ++lp; +- le_bci = EK_BCID; +- } +- assert(*lp != 'S'); // no PSH, etc. +- lp = parseIntLayout(lp, b, EK_INT); +- b->le_bci = le_bci; +- if (le_bci == EK_BCI) +- b->defc = coding::findBySpec(BCI5_spec); +- else +- b->defc = coding::findBySpec(BRANCH5_spec); ++ int le_bci = EK_BCI; ++ if (*lp == 'O') { ++ ++lp; ++ le_bci = EK_BCID; ++ } ++ assert(*lp != 'S'); // no PSH, etc. ++ lp = parseIntLayout(lp, b, EK_INT); ++ b->le_bci = le_bci; ++ if (le_bci == EK_BCI) ++ b->defc = coding::findBySpec(BCI5_spec); ++ else ++ b->defc = coding::findBySpec(BRANCH5_spec); + } + break; + case 'O': +@@ -1665,25 +1667,25 @@ unpacker::attr_definitions::parseLayout( + case 'T': // union: 'T' any_int union_case* '(' ')' '[' body ']' + lp = parseIntLayout(lp, b, EK_UN, can_be_signed); + { +- int union_base = band_stack.length(); +- for (;;) { // for each case +- band& k_case = *U_NEW(band, 1); +- CHECK_(lp); +- band_stack.add(&k_case); +- k_case.le_kind = EK_CASE; +- k_case.bn = bands_made++; +- if (*lp++ != '(') { +- abort("bad union case"); +- return ""; +- } +- if (*lp++ != ')') { +- --lp; // reparse +- // Read some case values. (Use band_stack for temp. storage.) +- int case_base = band_stack.length(); +- for (;;) { +- int caseval = 0; +- lp = parseNumeral(lp, caseval); +- band_stack.add((void*)caseval); ++ int union_base = band_stack.length(); ++ for (;;) { // for each case ++ band& k_case = *U_NEW(band, 1); ++ CHECK_(lp); ++ band_stack.add(&k_case); ++ k_case.le_kind = EK_CASE; ++ k_case.bn = bands_made++; ++ if (*lp++ != '(') { ++ abort("bad union case"); ++ return ""; ++ } ++ if (*lp++ != ')') { ++ --lp; // reparse ++ // Read some case values. (Use band_stack for temp. storage.) ++ int case_base = band_stack.length(); ++ for (;;) { ++ int caseval = 0; ++ lp = parseNumeral(lp, caseval); ++ band_stack.add((void*)caseval); + if (*lp == '-') { + // new in version 160, allow (1-5) for (1,2,3,4,5) + if (u->majver < JAVA6_PACKAGE_MAJOR_VERSION) { +@@ -1706,111 +1708,111 @@ unpacker::attr_definitions::parseLayout( + if (caseval == caselimit) break; + } + } +- if (*lp != ',') break; +- lp++; +- } +- if (*lp++ != ')') { +- abort("bad case label"); +- return ""; +- } +- // save away the case labels +- int ntags = band_stack.length() - case_base; +- int* tags = U_NEW(int, add_size(ntags, 1)); +- CHECK_(lp); +- k_case.le_casetags = tags; +- *tags++ = ntags; +- for (int i = 0; i < ntags; i++) { +- *tags++ = ptrlowbits(band_stack.get(case_base+i)); +- } +- band_stack.popTo(case_base); +- CHECK_(lp); +- } +- // Got le_casetags. Now grab the body. +- assert(*lp == '['); +- ++lp; +- lp = parseLayout(lp, k_case.le_body, curCble); +- CHECK_(lp); +- if (k_case.le_casetags == null) break; // done +- } +- b->le_body = popBody(union_base); ++ if (*lp != ',') break; ++ lp++; ++ } ++ if (*lp++ != ')') { ++ abort("bad case label"); ++ return ""; ++ } ++ // save away the case labels ++ int ntags = band_stack.length() - case_base; ++ int* tags = U_NEW(int, add_size(ntags, 1)); ++ CHECK_(lp); ++ k_case.le_casetags = tags; ++ *tags++ = ntags; ++ for (int i = 0; i < ntags; i++) { ++ *tags++ = ptrlowbits(band_stack.get(case_base+i)); ++ } ++ band_stack.popTo(case_base); ++ CHECK_(lp); ++ } ++ // Got le_casetags. Now grab the body. ++ assert(*lp == '['); ++ ++lp; ++ lp = parseLayout(lp, k_case.le_body, curCble); ++ CHECK_(lp); ++ if (k_case.le_casetags == null) break; // done ++ } ++ b->le_body = popBody(union_base); + } + break; + case '(': // call: '(' -?NN* ')' + { +- band& call = *U_NEW(band, 1); +- CHECK_(lp); +- band_stack.add(&call); +- call.le_kind = EK_CALL; +- call.bn = bands_made++; +- call.le_body = U_NEW(band*, 2); // fill in later +- int call_num = 0; +- lp = parseNumeral(lp, call_num); +- call.le_back = (call_num <= 0); +- call_num += curCble; // numeral is self-relative offset +- call.le_len = call_num; //use le_len as scratch +- calls_to_link.add(&call); +- CHECK_(lp); +- if (*lp++ != ')') { +- abort("bad call label"); +- return ""; ++ band& call = *U_NEW(band, 1); ++ CHECK_(lp); ++ band_stack.add(&call); ++ call.le_kind = EK_CALL; ++ call.bn = bands_made++; ++ call.le_body = U_NEW(band*, 2); // fill in later ++ int call_num = 0; ++ lp = parseNumeral(lp, call_num); ++ call.le_back = (call_num <= 0); ++ call_num += curCble; // numeral is self-relative offset ++ call.le_len = call_num; //use le_len as scratch ++ calls_to_link.add(&call); ++ CHECK_(lp); ++ if (*lp++ != ')') { ++ abort("bad call label"); ++ return ""; + } + } + break; + case 'K': // reference_type: constant_ref + case 'R': // reference_type: schema_ref + { +- int ixTag = CONSTANT_None; +- if (lp[-1] == 'K') { +- switch (*lp++) { +- case 'I': ixTag = CONSTANT_Integer; break; +- case 'J': ixTag = CONSTANT_Long; break; +- case 'F': ixTag = CONSTANT_Float; break; +- case 'D': ixTag = CONSTANT_Double; break; +- case 'S': ixTag = CONSTANT_String; break; +- case 'Q': ixTag = CONSTANT_Literal; break; +- } +- } else { +- switch (*lp++) { +- case 'C': ixTag = CONSTANT_Class; break; +- case 'S': ixTag = CONSTANT_Signature; break; +- case 'D': ixTag = CONSTANT_NameandType; break; +- case 'F': ixTag = CONSTANT_Fieldref; break; +- case 'M': ixTag = CONSTANT_Methodref; break; +- case 'I': ixTag = CONSTANT_InterfaceMethodref; break; +- case 'U': ixTag = CONSTANT_Utf8; break; //utf8_ref +- case 'Q': ixTag = CONSTANT_All; break; //untyped_ref +- } +- } +- if (ixTag == CONSTANT_None) { +- abort("bad reference layout"); +- break; +- } +- bool nullOK = false; +- if (*lp == 'N') { +- nullOK = true; +- lp++; +- } +- lp = parseIntLayout(lp, b, EK_REF); +- b->defc = coding::findBySpec(UNSIGNED5_spec); +- b->initRef(ixTag, nullOK); ++ int ixTag = CONSTANT_None; ++ if (lp[-1] == 'K') { ++ switch (*lp++) { ++ case 'I': ixTag = CONSTANT_Integer; break; ++ case 'J': ixTag = CONSTANT_Long; break; ++ case 'F': ixTag = CONSTANT_Float; break; ++ case 'D': ixTag = CONSTANT_Double; break; ++ case 'S': ixTag = CONSTANT_String; break; ++ case 'Q': ixTag = CONSTANT_Literal; break; ++ } ++ } else { ++ switch (*lp++) { ++ case 'C': ixTag = CONSTANT_Class; break; ++ case 'S': ixTag = CONSTANT_Signature; break; ++ case 'D': ixTag = CONSTANT_NameandType; break; ++ case 'F': ixTag = CONSTANT_Fieldref; break; ++ case 'M': ixTag = CONSTANT_Methodref; break; ++ case 'I': ixTag = CONSTANT_InterfaceMethodref; break; ++ case 'U': ixTag = CONSTANT_Utf8; break; //utf8_ref ++ case 'Q': ixTag = CONSTANT_All; break; //untyped_ref ++ } ++ } ++ if (ixTag == CONSTANT_None) { ++ abort("bad reference layout"); ++ break; ++ } ++ bool nullOK = false; ++ if (*lp == 'N') { ++ nullOK = true; ++ lp++; ++ } ++ lp = parseIntLayout(lp, b, EK_REF); ++ b->defc = coding::findBySpec(UNSIGNED5_spec); ++ b->initRef(ixTag, nullOK); + } + break; + case '[': + { +- // [callable1][callable2]... +- if (!top_level) { +- abort("bad nested callable"); +- break; +- } +- curCble += 1; +- NOT_PRODUCT(int call_num = band_stack.length() - bs_base); +- band& cble = *U_NEW(band, 1); +- CHECK_(lp); +- band_stack.add(&cble); +- cble.le_kind = EK_CBLE; +- NOT_PRODUCT(cble.le_len = call_num); +- cble.bn = bands_made++; +- lp = parseLayout(lp, cble.le_body, curCble); ++ // [callable1][callable2]... ++ if (!top_level) { ++ abort("bad nested callable"); ++ break; ++ } ++ curCble += 1; ++ NOT_PRODUCT(int call_num = band_stack.length() - bs_base); ++ band& cble = *U_NEW(band, 1); ++ CHECK_(lp); ++ band_stack.add(&cble); ++ cble.le_kind = EK_CBLE; ++ NOT_PRODUCT(cble.le_len = call_num); ++ cble.bn = bands_made++; ++ lp = parseLayout(lp, cble.le_body, curCble); + } + break; + case ']': +@@ -1880,10 +1882,10 @@ void unpacker::read_attr_defs() { + "(115)[RUH]" + "(91)[NH[(0)]]" + "(64)[" +- // nested annotation: +- "RSH" +- "NH[RUH(0)]" +- "]" ++ // nested annotation: ++ "RSH" ++ "NH[RUH(0)]" ++ "]" + "()[]" + "]" + ); +@@ -1897,16 +1899,16 @@ void unpacker::read_attr_defs() { + for (i = 0; i < ATTR_CONTEXT_LIMIT; i++) { + attr_definitions& ad = attr_defs[i]; + ad.defineLayout(X_ATTR_RuntimeVisibleAnnotations, +- "RuntimeVisibleAnnotations", md_layout_A); ++ "RuntimeVisibleAnnotations", md_layout_A); + ad.defineLayout(X_ATTR_RuntimeInvisibleAnnotations, +- "RuntimeInvisibleAnnotations", md_layout_A); ++ "RuntimeInvisibleAnnotations", md_layout_A); + if (i != ATTR_CONTEXT_METHOD) continue; + ad.defineLayout(METHOD_ATTR_RuntimeVisibleParameterAnnotations, +- "RuntimeVisibleParameterAnnotations", md_layout_P); ++ "RuntimeVisibleParameterAnnotations", md_layout_P); + ad.defineLayout(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, +- "RuntimeInvisibleParameterAnnotations", md_layout_P); ++ "RuntimeInvisibleParameterAnnotations", md_layout_P); + ad.defineLayout(METHOD_ATTR_AnnotationDefault, +- "AnnotationDefault", md_layout_V); ++ "AnnotationDefault", md_layout_V); + } + + attr_definition_headers.readData(attr_definition_count); +@@ -1939,6 +1941,7 @@ void unpacker::read_attr_defs() { + int attrc = ADH_BYTE_CONTEXT(header); + int idx = ADH_BYTE_INDEX(header); + entry* name = attr_definition_name.getRef(); ++ CHECK; + entry* layout = attr_definition_layout.getRef(); + CHECK; + attr_defs[attrc].defineLayout(idx, name, layout->value.b.strval()); +@@ -2043,7 +2046,9 @@ void unpacker::read_ics() { + if (ics[i].name == NO_ENTRY_YET) { + // Long form. + ics[i].outer = ic_outer_class.getRefN(); ++ CHECK; + ics[i].name = ic_name.getRefN(); ++ CHECK; + } else { + // Fill in outer and name based on inner. + bytes& n = ics[i].inner->value.b; +@@ -2058,48 +2063,48 @@ void unpacker::read_ics() { + int pkglen = lastIndexOf(SLASH_MIN, SLASH_MAX, n, nlen) + 1; + dollar2 = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, n, nlen); + if (dollar2 < 0) { +- abort(); +- return; ++ abort(); ++ return; + } + assert(dollar2 >= pkglen); + if (isDigitString(n, dollar2+1, nlen)) { +- // n = (<pkg>/)*<outer>$<number> +- number = n.slice(dollar2+1, nlen); +- name.set(null,0); +- dollar1 = dollar2; ++ // n = (<pkg>/)*<outer>$<number> ++ number = n.slice(dollar2+1, nlen); ++ name.set(null,0); ++ dollar1 = dollar2; + } else if (pkglen < (dollar1 +- = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, n, dollar2-1)) +- && isDigitString(n, dollar1+1, dollar2)) { +- // n = (<pkg>/)*<outer>$<number>$<name> +- number = n.slice(dollar1+1, dollar2); +- name = n.slice(dollar2+1, nlen); ++ = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, n, dollar2-1)) ++ && isDigitString(n, dollar1+1, dollar2)) { ++ // n = (<pkg>/)*<outer>$<number>$<name> ++ number = n.slice(dollar1+1, dollar2); ++ name = n.slice(dollar2+1, nlen); + } else { +- // n = (<pkg>/)*<outer>$<name> +- dollar1 = dollar2; +- number.set(null,0); +- name = n.slice(dollar2+1, nlen); ++ // n = (<pkg>/)*<outer>$<name> ++ dollar1 = dollar2; ++ number.set(null,0); ++ name = n.slice(dollar2+1, nlen); + } + if (number.ptr == null) +- pkgOuter = n.slice(0, dollar1); ++ pkgOuter = n.slice(0, dollar1); + else +- pkgOuter.set(null,0); ++ pkgOuter.set(null,0); + printcr(5,"=> %s$ 0%s $%s", +- pkgOuter.string(), number.string(), name.string()); ++ pkgOuter.string(), number.string(), name.string()); + + if (pkgOuter.ptr != null) +- ics[i].outer = cp.ensureClass(pkgOuter); ++ ics[i].outer = cp.ensureClass(pkgOuter); + + if (name.ptr != null) +- ics[i].name = cp.ensureUtf8(name); ++ ics[i].name = cp.ensureUtf8(name); + } + + // update child/sibling list + if (ics[i].outer != null) { + uint outord = ics[i].outer->inord; + if (outord != NO_INORD) { +- assert(outord < cp.tag_count[CONSTANT_Class]); +- ics[i].next_sibling = ic_child_index[outord]; +- ic_child_index[outord] = &ics[i]; ++ assert(outord < cp.tag_count[CONSTANT_Class]); ++ ics[i].next_sibling = ic_child_index[outord]; ++ ic_child_index[outord] = &ics[i]; + } + } + } +@@ -2149,7 +2154,7 @@ void unpacker::read_classes() { + read_code_headers(); + + printcr(1,"scanned %d classes, %d fields, %d methods, %d code headers", +- class_count, field_count, method_count, code_count); ++ class_count, field_count, method_count, code_count); + } + + maybe_inline +@@ -2226,11 +2231,11 @@ void unpacker::read_attrs(int attrc, int + band** bands = ad.buildBands(lo); + CHECK; + if (lo->hasCallables()) { +- for (i = 0; bands[i] != null; i++) { +- if (bands[i]->le_back) { +- assert(bands[i]->le_kind == EK_CBLE); +- backwardCounts += 1; +- } ++ for (i = 0; bands[i] != null; i++) { ++ if (bands[i]->le_back) { ++ assert(bands[i]->le_kind == EK_CBLE); ++ backwardCounts += 1; ++ } + } + } + } +@@ -2427,7 +2432,7 @@ void unpacker::attr_definitions::readBan + layout_definition* lo = getLayout(idx); + if (lo != null) { + printcr(1, "counted %d [redefined = %d predefined = %d] attributes of type %s.%s", +- count, isRedefined(idx), isPredefined(idx), ++ count, isRedefined(idx), isPredefined(idx), + ATTR_CONTEXT_NAME[attrc], lo->name); + } + bool hasCallables = lo->hasCallables(); +@@ -2444,10 +2449,10 @@ void unpacker::attr_definitions::readBan + band& j_cble = *bands[j]; + assert(j_cble.le_kind == EK_CBLE); + if (j_cble.le_back) { +- // Add in the predicted effects of backward calls, too. +- int back_calls = xxx_attr_calls().getInt(); +- j_cble.expectMoreLength(back_calls); +- // In a moment, more forward calls may increment j_cble.length. ++ // Add in the predicted effects of backward calls, too. ++ int back_calls = xxx_attr_calls().getInt(); ++ j_cble.expectMoreLength(back_calls); ++ // In a moment, more forward calls may increment j_cble.length. + } + } + // Now consult whichever callables have non-zero entry counts. +@@ -2467,38 +2472,38 @@ void unpacker::attr_definitions::readBan + switch (b.le_kind) { + case EK_REPL: + { +- int reps = b.getIntTotal(); +- readBandData(b.le_body, reps); ++ int reps = b.getIntTotal(); ++ readBandData(b.le_body, reps); + } + break; + case EK_UN: + { +- int remaining = count; +- for (k = 0; b.le_body[k] != null; k++) { +- band& k_case = *b.le_body[k]; +- int k_count = 0; +- if (k_case.le_casetags == null) { +- k_count = remaining; // last (empty) case +- } else { +- int* tags = k_case.le_casetags; +- int ntags = *tags++; // 1st element is length (why not?) +- while (ntags-- > 0) { +- int tag = *tags++; +- k_count += b.getIntCount(tag); +- } +- } +- readBandData(k_case.le_body, k_count); +- remaining -= k_count; +- } +- assert(remaining == 0); ++ int remaining = count; ++ for (k = 0; b.le_body[k] != null; k++) { ++ band& k_case = *b.le_body[k]; ++ int k_count = 0; ++ if (k_case.le_casetags == null) { ++ k_count = remaining; // last (empty) case ++ } else { ++ int* tags = k_case.le_casetags; ++ int ntags = *tags++; // 1st element is length (why not?) ++ while (ntags-- > 0) { ++ int tag = *tags++; ++ k_count += b.getIntCount(tag); ++ } ++ } ++ readBandData(k_case.le_body, k_count); ++ remaining -= k_count; ++ } ++ assert(remaining == 0); + } + break; + case EK_CALL: + // Push the count forward, if it is not a backward call. + if (!b.le_back) { +- band& cble = *b.le_body[0]; +- assert(cble.le_kind == EK_CBLE); +- cble.expectMoreLength(count); ++ band& cble = *b.le_body[0]; ++ assert(cble.le_kind == EK_CBLE); ++ cble.expectMoreLength(count); + } + break; + case EK_CBLE: +@@ -2522,12 +2527,12 @@ band** findMatchingCase(int matchTag, ba + int* tags = k_case.le_casetags; + int ntags = *tags++; // 1st element is length + for (; ntags > 0; ntags--) { +- int tag = *tags++; +- if (tag == matchTag) +- break; ++ int tag = *tags++; ++ if (tag == matchTag) ++ break; + } + if (ntags == 0) +- continue; // does not match ++ continue; // does not match + } + return k_case.le_body; + } +@@ -2549,46 +2554,47 @@ void unpacker::putlayout(band** body) { + if (b.defc != null) { + // It has data, so unparse an element. + if (b.ixTag != CONSTANT_None) { +- assert(le_kind == EK_REF); +- if (b.ixTag == CONSTANT_Literal) +- e = b.getRefUsing(cp.getKQIndex()); +- else +- e = b.getRefN(); +- switch (b.le_len) { +- case 0: break; +- case 1: putu1ref(e); break; +- case 2: putref(e); break; +- case 4: putu2(0); putref(e); break; +- default: assert(false); +- } ++ assert(le_kind == EK_REF); ++ if (b.ixTag == CONSTANT_Literal) ++ e = b.getRefUsing(cp.getKQIndex()); ++ else ++ e = b.getRefN(); ++ CHECK; ++ switch (b.le_len) { ++ case 0: break; ++ case 1: putu1ref(e); break; ++ case 2: putref(e); break; ++ case 4: putu2(0); putref(e); break; ++ default: assert(false); ++ } + } else { +- assert(le_kind == EK_INT || le_kind == EK_REPL || le_kind == EK_UN); +- x = b.getInt(); +- +- assert(!b.le_bci || prevBCI == to_bci(prevBII)); +- switch (b.le_bci) { +- case EK_BCI: // PH: transmit R(bci), store bci +- x = to_bci(prevBII = x); +- prevBCI = x; +- break; +- case EK_BCID: // POH: transmit D(R(bci)), store bci +- x = to_bci(prevBII += x); +- prevBCI = x; +- break; +- case EK_BCO: // OH: transmit D(R(bci)), store D(bci) +- x = to_bci(prevBII += x) - prevBCI; +- prevBCI += x; +- break; +- } +- assert(!b.le_bci || prevBCI == to_bci(prevBII)); +- +- switch (b.le_len) { +- case 0: break; +- case 1: putu1(x); break; +- case 2: putu2(x); break; +- case 4: putu4(x); break; +- default: assert(false); +- } ++ assert(le_kind == EK_INT || le_kind == EK_REPL || le_kind == EK_UN); ++ x = b.getInt(); ++ ++ assert(!b.le_bci || prevBCI == to_bci(prevBII)); ++ switch (b.le_bci) { ++ case EK_BCI: // PH: transmit R(bci), store bci ++ x = to_bci(prevBII = x); ++ prevBCI = x; ++ break; ++ case EK_BCID: // POH: transmit D(R(bci)), store bci ++ x = to_bci(prevBII += x); ++ prevBCI = x; ++ break; ++ case EK_BCO: // OH: transmit D(R(bci)), store D(bci) ++ x = to_bci(prevBII += x) - prevBCI; ++ prevBCI += x; ++ break; ++ } ++ assert(!b.le_bci || prevBCI == to_bci(prevBII)); ++ ++ switch (b.le_len) { ++ case 0: break; ++ case 1: putu1(x); break; ++ case 2: putu2(x); break; ++ case 4: putu4(x); break; ++ default: assert(false); ++ } + } + } + +@@ -2597,7 +2603,7 @@ void unpacker::putlayout(band** body) { + case EK_REPL: + // x is the repeat count + while (x-- > 0) { +- putlayout(b.le_body); ++ putlayout(b.le_body); + } + break; + case EK_UN: +@@ -2606,10 +2612,10 @@ void unpacker::putlayout(band** body) { + break; + case EK_CALL: + { +- band& cble = *b.le_body[0]; +- assert(cble.le_kind == EK_CBLE); +- assert(cble.le_len == b.le_len); +- putlayout(cble.le_body); ++ band& cble = *b.le_body[0]; ++ assert(cble.le_kind == EK_CBLE); ++ assert(cble.le_len == b.le_len); ++ putlayout(cble.le_body); + } + break; + +@@ -2635,7 +2641,7 @@ void unpacker::read_files() { + // FO_IS_CLASS_STUB might be set, causing overlap between classes and files + for (int i = 0; i < file_count; i++) { + if ((file_options.getInt() & FO_IS_CLASS_STUB) != 0) { +- allFiles -= 1; // this one counts as both class and file ++ allFiles -= 1; // this one counts as both class and file + } + } + file_options.rewind(); +@@ -2646,9 +2652,9 @@ void unpacker::read_files() { + + maybe_inline + void unpacker::get_code_header(int& max_stack, +- int& max_na_locals, +- int& handler_count, +- int& cflags) { ++ int& max_na_locals, ++ int& handler_count, ++ int& cflags) { + int sc = code_headers.getByte(); + if (sc == 0) { + max_stack = max_na_locals = handler_count = cflags = -1; +@@ -2801,7 +2807,7 @@ inline // called exactly once => inline + inline // called exactly once => inline + void unpacker::read_bcs() { + printcr(3, "reading compressed bytecodes and operands for %d codes...", +- code_count); ++ code_count); + + // read from bc_codes and bc_case_count + fillbytes all_switch_ops; +@@ -2822,80 +2828,80 @@ void unpacker::read_bcs() { + // Scan one method: + for (;;) { + if (opptr+2 > oplimit) { +- rp = opptr; +- ensure_input(2); +- oplimit = rplimit; +- rp = rp0; // back up ++ rp = opptr; ++ ensure_input(2); ++ oplimit = rplimit; ++ rp = rp0; // back up + } + if (opptr == oplimit) { abort(); break; } + int bc = *opptr++ & 0xFF; + bool isWide = false; + if (bc == bc_wide) { +- if (opptr == oplimit) { abort(); break; } +- bc = *opptr++ & 0xFF; +- isWide = true; ++ if (opptr == oplimit) { abort(); break; } ++ bc = *opptr++ & 0xFF; ++ isWide = true; + } + // Adjust expectations of various band sizes. + switch (bc) { + case bc_tableswitch: + case bc_lookupswitch: +- all_switch_ops.addByte(bc); +- break; ++ all_switch_ops.addByte(bc); ++ break; + case bc_iinc: +- bc_local.expectMoreLength(1); +- bc_which = isWide ? &bc_short : &bc_byte; +- bc_which->expectMoreLength(1); +- break; ++ bc_local.expectMoreLength(1); ++ bc_which = isWide ? &bc_short : &bc_byte; ++ bc_which->expectMoreLength(1); ++ break; + case bc_sipush: +- bc_short.expectMoreLength(1); +- break; ++ bc_short.expectMoreLength(1); ++ break; + case bc_bipush: +- bc_byte.expectMoreLength(1); +- break; ++ bc_byte.expectMoreLength(1); ++ break; + case bc_newarray: +- bc_byte.expectMoreLength(1); +- break; ++ bc_byte.expectMoreLength(1); ++ break; + case bc_multianewarray: +- assert(ref_band_for_op(bc) == &bc_classref); +- bc_classref.expectMoreLength(1); +- bc_byte.expectMoreLength(1); +- break; ++ assert(ref_band_for_op(bc) == &bc_classref); ++ bc_classref.expectMoreLength(1); ++ bc_byte.expectMoreLength(1); ++ break; + case bc_ref_escape: +- bc_escrefsize.expectMoreLength(1); +- bc_escref.expectMoreLength(1); +- break; ++ bc_escrefsize.expectMoreLength(1); ++ bc_escref.expectMoreLength(1); ++ break; + case bc_byte_escape: +- bc_escsize.expectMoreLength(1); +- // bc_escbyte will have to be counted too +- break; ++ bc_escsize.expectMoreLength(1); ++ // bc_escbyte will have to be counted too ++ break; + default: +- if (is_invoke_init_op(bc)) { +- bc_initref.expectMoreLength(1); +- break; +- } +- bc_which = ref_band_for_self_op(bc, isAload, junkBC); +- if (bc_which != null) { +- bc_which->expectMoreLength(1); +- break; +- } +- if (is_branch_op(bc)) { +- bc_label.expectMoreLength(1); +- break; +- } +- bc_which = ref_band_for_op(bc); +- if (bc_which != null) { +- bc_which->expectMoreLength(1); +- assert(bc != bc_multianewarray); // handled elsewhere +- break; +- } +- if (is_local_slot_op(bc)) { +- bc_local.expectMoreLength(1); +- break; +- } +- break; ++ if (is_invoke_init_op(bc)) { ++ bc_initref.expectMoreLength(1); ++ break; ++ } ++ bc_which = ref_band_for_self_op(bc, isAload, junkBC); ++ if (bc_which != null) { ++ bc_which->expectMoreLength(1); ++ break; ++ } ++ if (is_branch_op(bc)) { ++ bc_label.expectMoreLength(1); ++ break; ++ } ++ bc_which = ref_band_for_op(bc); ++ if (bc_which != null) { ++ bc_which->expectMoreLength(1); ++ assert(bc != bc_multianewarray); // handled elsewhere ++ break; ++ } ++ if (is_local_slot_op(bc)) { ++ bc_local.expectMoreLength(1); ++ break; ++ } ++ break; + case bc_end_marker: +- // Increment k and test against code_count. +- goto doneScanningMethod; ++ // Increment k and test against code_count. ++ goto doneScanningMethod; + } + } + doneScanningMethod:{} +@@ -2929,15 +2935,15 @@ void unpacker::read_bcs() { + bc_escbyte.readData(bc_escsize.getIntTotal()); + + printcr(3, "scanned %d opcode and %d operand bytes for %d codes...", +- (int)(bc_codes.size()), +- (int)(bc_escsize.maxRP() - bc_case_value.minRP()), +- code_count); ++ (int)(bc_codes.size()), ++ (int)(bc_escsize.maxRP() - bc_case_value.minRP()), ++ code_count); + } + + void unpacker::read_bands() { + byte* rp0 = rp; + int i; +- ++ CHECK; + read_file_header(); + CHECK; + +@@ -3063,8 +3069,8 @@ void cpool::expandSignatures() { + int c = form.ptr[j]; + buf.addByte(c); + if (c == 'L') { +- entry* cls = e.refs[refnum++]; +- buf.append(cls->className()->asUtf8()); ++ entry* cls = e.refs[refnum++]; ++ buf.append(cls->className()->asUtf8()); + } + } + assert(refnum == e.nrefs); +@@ -3099,7 +3105,7 @@ void cpool::expandSignatures() { + for (int j = 0; j < e.nrefs; j++) { + entry*& e2 = e.refs[j]; + if (e2 != null && e2->tag == CONSTANT_Signature) +- e2 = e2->refs[0]; ++ e2 = e2->refs[0]; + } + } + } +@@ -3141,14 +3147,14 @@ void cpool::initMemberIndexes() { + int fc = field_counts[i]; + int mc = method_counts[i]; + all_indexes[i*2+0].init(fc, field_ix+fbase, +- CONSTANT_Fieldref + SUBINDEX_BIT); ++ CONSTANT_Fieldref + SUBINDEX_BIT); + all_indexes[i*2+1].init(mc, method_ix+mbase, +- CONSTANT_Methodref + SUBINDEX_BIT); ++ CONSTANT_Methodref + SUBINDEX_BIT); + // reuse field_counts and member_counts as fill pointers: + field_counts[i] = fbase; + method_counts[i] = mbase; + printcr(3, "class %d fields @%d[%d] methods @%d[%d]", +- i, fbase, fc, mbase, mc); ++ i, fbase, fc, mbase, mc); + fbase += fc+1; + mbase += mc+1; + // (the +1 leaves a space between every subarray) +@@ -3178,7 +3184,7 @@ void cpool::initMemberIndexes() { + cpindex* fix = getFieldIndex(cls); + cpindex* mix = getMethodIndex(cls); + printcr(2, "field and method index for %s [%d] [%d]", +- cls->string(), mix->len, fix->len); ++ cls->string(), mix->len, fix->len); + prevord = -1; + for (j = 0, len = fix->len; j < len; j++) { + entry* f = fix->get(j); +@@ -3204,7 +3210,7 @@ void cpool::initMemberIndexes() { + } + assert(fvisited == nfields); + assert(mvisited == nmethods); +-#endif ++#endif + + // Free intermediate buffers. + u->free_temps(); +@@ -3438,8 +3444,8 @@ bool unpacker::set_option(const char* pr + bool unpacker::set_option(const char* prop, const char* value) { + if (prop == NULL) return false; + if (strcmp(prop, UNPACK_DEFLATE_HINT) == 0) { +- deflate_hint_or_zero = ( (value == null || strcmp(value, "keep") == 0) +- ? 0: BOOL_TF(value) ? +1: -1); ++ deflate_hint_or_zero = ( (value == null || strcmp(value, "keep") == 0) ++ ? 0: BOOL_TF(value) ? +1: -1); + #ifdef HAVE_STRIP + } else if (strcmp(prop, UNPACK_STRIP_COMPILE) == 0) { + strip_compile = STR_TF(value); +@@ -3466,7 +3472,7 @@ bool unpacker::set_option(const char* pr + } else { + modification_time_or_zero = atoi(value); + if (modification_time_or_zero == 0) +- modification_time_or_zero = 1; // make non-zero ++ modification_time_or_zero = 1; // make non-zero + } + } else if (strcmp(prop, UNPACK_LOG_FILE) == 0) { + log_file = (value == null)? value: saveStr(value); +@@ -3597,14 +3603,16 @@ void unpacker::dump_options() { + + + // Usage: unpack a byte buffer +-// packptr is a reference to byte buffer containing a ++// packptr is a reference to byte buffer containing a + // packed file and len is the length of the buffer. + // If null, the callback is used to fill an internal buffer. + void unpacker::start(void* packptr, size_t len) { ++ CHECK; + NOT_PRODUCT(debug_u = this); + if (packptr != null && len != 0) { + inbytes.set((byte*) packptr, len); + } ++ CHECK; + read_bands(); + } + +@@ -3735,6 +3743,7 @@ void unpacker::write_bc_ops() { + NOT_PRODUCT(bc_superfield.setIndex(null)); + NOT_PRODUCT(bc_supermethod.setIndex(null)); + } ++ CHECK; + + for (int curIP = 0; ; curIP++) { + int curPC = wpoffset() - codeBase; +@@ -3760,196 +3769,197 @@ void unpacker::write_bc_ops() { + case bc_tableswitch: // apc: (df, lo, hi, (hi-lo+1)*(label)) + case bc_lookupswitch: // apc: (df, nc, nc*(case, label)) + { +- int caseCount = bc_case_count.getInt(); +- while (((wpoffset() - codeBase) % 4) != 0) putu1_fast(0); +- ensure_put_space(30 + caseCount*8); +- put_label(curIP, 4); //int df = bc_label.getInt(); +- if (bc == bc_tableswitch) { +- int lo = bc_case_value.getInt(); +- int hi = lo + caseCount-1; +- putu4(lo); +- putu4(hi); +- for (int j = 0; j < caseCount; j++) { +- put_label(curIP, 4); //int lVal = bc_label.getInt(); +- //int cVal = lo + j; +- } +- } else { +- putu4(caseCount); +- for (int j = 0; j < caseCount; j++) { +- int cVal = bc_case_value.getInt(); +- putu4(cVal); +- put_label(curIP, 4); //int lVal = bc_label.getInt(); +- } +- } +- assert(to_bci(curIP) == curPC); +- continue; ++ int caseCount = bc_case_count.getInt(); ++ while (((wpoffset() - codeBase) % 4) != 0) putu1_fast(0); ++ ensure_put_space(30 + caseCount*8); ++ put_label(curIP, 4); //int df = bc_label.getInt(); ++ if (bc == bc_tableswitch) { ++ int lo = bc_case_value.getInt(); ++ int hi = lo + caseCount-1; ++ putu4(lo); ++ putu4(hi); ++ for (int j = 0; j < caseCount; j++) { ++ put_label(curIP, 4); //int lVal = bc_label.getInt(); ++ //int cVal = lo + j; ++ } ++ } else { ++ putu4(caseCount); ++ for (int j = 0; j < caseCount; j++) { ++ int cVal = bc_case_value.getInt(); ++ putu4(cVal); ++ put_label(curIP, 4); //int lVal = bc_label.getInt(); ++ } ++ } ++ assert(to_bci(curIP) == curPC); ++ continue; + } + case bc_iinc: + { +- int local = bc_local.getInt(); +- int delta = (isWide ? bc_short : bc_byte).getInt(); +- if (isWide) { +- putu2(local); +- putu2(delta); +- } else { +- putu1_fast(local); +- putu1_fast(delta); +- } +- continue; ++ int local = bc_local.getInt(); ++ int delta = (isWide ? bc_short : bc_byte).getInt(); ++ if (isWide) { ++ putu2(local); ++ putu2(delta); ++ } else { ++ putu1_fast(local); ++ putu1_fast(delta); ++ } ++ continue; + } + case bc_sipush: + { +- int val = bc_short.getInt(); +- putu2(val); +- continue; ++ int val = bc_short.getInt(); ++ putu2(val); ++ continue; + } + case bc_bipush: + case bc_newarray: + { +- int val = bc_byte.getByte(); +- putu1_fast(val); +- continue; ++ int val = bc_byte.getByte(); ++ putu1_fast(val); ++ continue; + } + case bc_ref_escape: + { +- // Note that insnMap has one entry for this. ++ // Note that insnMap has one entry for this. + --wp; // not really part of the code +- int size = bc_escrefsize.getInt(); +- entry* ref = bc_escref.getRefN(); +- CHECK; +- switch (size) { +- case 1: putu1ref(ref); break; +- case 2: putref(ref); break; +- default: assert(false); +- } +- continue; ++ int size = bc_escrefsize.getInt(); ++ entry* ref = bc_escref.getRefN(); ++ CHECK; ++ switch (size) { ++ case 1: putu1ref(ref); break; ++ case 2: putref(ref); break; ++ default: assert(false); ++ } ++ continue; + } + case bc_byte_escape: + { +- // Note that insnMap has one entry for all these bytes. ++ // Note that insnMap has one entry for all these bytes. + --wp; // not really part of the code +- int size = bc_escsize.getInt(); +- ensure_put_space(size); +- for (int j = 0; j < size; j++) +- putu1_fast(bc_escbyte.getByte()); +- continue; ++ int size = bc_escsize.getInt(); ++ ensure_put_space(size); ++ for (int j = 0; j < size; j++) ++ putu1_fast(bc_escbyte.getByte()); ++ continue; + } + default: + if (is_invoke_init_op(bc)) { +- origBC = bc_invokespecial; +- entry* classRef; +- switch (bc - _invokeinit_op) { +- case _invokeinit_self_option: classRef = thisClass; break; +- case _invokeinit_super_option: classRef = superClass; break; +- default: assert(bc == _invokeinit_op+_invokeinit_new_option); +- case _invokeinit_new_option: classRef = newClass; break; +- } +- wp[-1] = origBC; // overwrite with origBC +- int coding = bc_initref.getInt(); +- // Find the nth overloading of <init> in classRef. +- entry* ref = null; +- cpindex* ix = (classRef == null)? null: cp.getMethodIndex(classRef); +- for (int j = 0, which_init = 0; ; j++) { +- ref = (ix == null)? null: ix->get(j); +- if (ref == null) break; // oops, bad input +- assert(ref->tag == CONSTANT_Methodref); +- if (ref->memberDescr()->descrName() == cp.sym[cpool::s_lt_init_gt]) { +- if (which_init++ == coding) break; +- } +- } +- putref(ref); +- continue; ++ origBC = bc_invokespecial; ++ entry* classRef; ++ switch (bc - _invokeinit_op) { ++ case _invokeinit_self_option: classRef = thisClass; break; ++ case _invokeinit_super_option: classRef = superClass; break; ++ default: assert(bc == _invokeinit_op+_invokeinit_new_option); ++ case _invokeinit_new_option: classRef = newClass; break; ++ } ++ wp[-1] = origBC; // overwrite with origBC ++ int coding = bc_initref.getInt(); ++ // Find the nth overloading of <init> in classRef. ++ entry* ref = null; ++ cpindex* ix = cp.getMethodIndex(classRef); ++ CHECK; ++ for (int j = 0, which_init = 0; ; j++) { ++ ref = (ix == null)? null: ix->get(j); ++ if (ref == null) break; // oops, bad input ++ assert(ref->tag == CONSTANT_Methodref); ++ if (ref->memberDescr()->descrName() == cp.sym[cpool::s_lt_init_gt]) { ++ if (which_init++ == coding) break; ++ } ++ } ++ putref(ref); ++ continue; + } + bc_which = ref_band_for_self_op(bc, isAload, origBC); + if (bc_which != null) { +- if (!isAload) { +- wp[-1] = origBC; // overwrite with origBC +- } else { +- wp[-1] = bc_aload_0; // overwrite with _aload_0 +- // Note: insnMap keeps the _aload_0 separate. +- bcimap.add(++curPC); +- ++curIP; +- putu1_fast(origBC); +- } +- entry* ref = bc_which->getRef(); +- CHECK; +- putref(ref); +- continue; ++ if (!isAload) { ++ wp[-1] = origBC; // overwrite with origBC ++ } else { ++ wp[-1] = bc_aload_0; // overwrite with _aload_0 ++ // Note: insnMap keeps the _aload_0 separate. ++ bcimap.add(++curPC); ++ ++curIP; ++ putu1_fast(origBC); ++ } ++ entry* ref = bc_which->getRef(); ++ CHECK; ++ putref(ref); ++ continue; + } + if (is_branch_op(bc)) { +- //int lVal = bc_label.getInt(); +- if (bc < bc_goto_w) { +- put_label(curIP, 2); //putu2(lVal & 0xFFFF); +- } else { +- assert(bc <= bc_jsr_w); +- put_label(curIP, 4); //putu4(lVal); +- } +- assert(to_bci(curIP) == curPC); +- continue; ++ //int lVal = bc_label.getInt(); ++ if (bc < bc_goto_w) { ++ put_label(curIP, 2); //putu2(lVal & 0xFFFF); ++ } else { ++ assert(bc <= bc_jsr_w); ++ put_label(curIP, 4); //putu4(lVal); ++ } ++ assert(to_bci(curIP) == curPC); ++ continue; + } + bc_which = ref_band_for_op(bc); + if (bc_which != null) { +- entry* ref = bc_which->getRefCommon(bc_which->ix, bc_which->nullOK); +- CHECK; +- if (ref == null && bc_which == &bc_classref) { +- // Shorthand for class self-references. +- ref = thisClass; +- } +- origBC = bc; +- switch (bc) { +- case bc_ildc: +- case bc_cldc: +- case bc_fldc: +- case bc_aldc: +- origBC = bc_ldc; +- break; +- case bc_ildc_w: +- case bc_cldc_w: +- case bc_fldc_w: +- case bc_aldc_w: +- origBC = bc_ldc_w; +- break; +- case bc_lldc2_w: +- case bc_dldc2_w: +- origBC = bc_ldc2_w; +- break; +- case bc_new: +- newClass = ref; +- break; +- } +- wp[-1] = origBC; // overwrite with origBC +- if (origBC == bc_ldc) { +- putu1ref(ref); +- } else { +- putref(ref); +- } +- if (origBC == bc_multianewarray) { +- // Copy the trailing byte also. +- int val = bc_byte.getByte(); +- putu1_fast(val); +- } else if (origBC == bc_invokeinterface) { +- int argSize = ref->memberDescr()->descrType()->typeSize(); +- putu1_fast(1 + argSize); +- putu1_fast(0); +- } +- continue; ++ entry* ref = bc_which->getRefCommon(bc_which->ix, bc_which->nullOK); ++ CHECK; ++ if (ref == null && bc_which == &bc_classref) { ++ // Shorthand for class self-references. ++ ref = thisClass; ++ } ++ origBC = bc; ++ switch (bc) { ++ case bc_ildc: ++ case bc_cldc: ++ case bc_fldc: ++ case bc_aldc: ++ origBC = bc_ldc; ++ break; ++ case bc_ildc_w: ++ case bc_cldc_w: ++ case bc_fldc_w: ++ case bc_aldc_w: ++ origBC = bc_ldc_w; ++ break; ++ case bc_lldc2_w: ++ case bc_dldc2_w: ++ origBC = bc_ldc2_w; ++ break; ++ case bc_new: ++ newClass = ref; ++ break; ++ } ++ wp[-1] = origBC; // overwrite with origBC ++ if (origBC == bc_ldc) { ++ putu1ref(ref); ++ } else { ++ putref(ref); ++ } ++ if (origBC == bc_multianewarray) { ++ // Copy the trailing byte also. ++ int val = bc_byte.getByte(); ++ putu1_fast(val); ++ } else if (origBC == bc_invokeinterface) { ++ int argSize = ref->memberDescr()->descrType()->typeSize(); ++ putu1_fast(1 + argSize); ++ putu1_fast(0); ++ } ++ continue; + } + if (is_local_slot_op(bc)) { +- int local = bc_local.getInt(); +- if (isWide) { +- putu2(local); +- if (bc == bc_iinc) { +- int iVal = bc_short.getInt(); +- putu2(iVal); +- } +- } else { +- putu1_fast(local); +- if (bc == bc_iinc) { +- int iVal = bc_byte.getByte(); +- putu1_fast(iVal); +- } +- } +- continue; ++ int local = bc_local.getInt(); ++ if (isWide) { ++ putu2(local); ++ if (bc == bc_iinc) { ++ int iVal = bc_short.getInt(); ++ putu2(iVal); ++ } ++ } else { ++ putu1_fast(local); ++ if (bc == bc_iinc) { ++ int iVal = bc_byte.getByte(); ++ putu1_fast(iVal); ++ } ++ } ++ continue; + } + // Random bytecode. Just copy it. + assert(bc < bc_bytecode_limit); +@@ -4073,78 +4083,80 @@ int unpacker::write_attrs(int attrc, jul + case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_OVERFLOW): + case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_OVERFLOW): + case ADH_BYTE(ATTR_CONTEXT_CODE, X_ATTR_OVERFLOW): +- // no attribute at all, so back up on this one +- wp = wp_at(abase); +- continue; ++ // no attribute at all, so back up on this one ++ wp = wp_at(abase); ++ continue; + + case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_ClassFile_version): +- cur_class_minver = class_ClassFile_version_minor_H.getInt(); +- cur_class_majver = class_ClassFile_version_major_H.getInt(); +- // back up; not a real attribute +- wp = wp_at(abase); +- continue; ++ cur_class_minver = class_ClassFile_version_minor_H.getInt(); ++ cur_class_majver = class_ClassFile_version_major_H.getInt(); ++ // back up; not a real attribute ++ wp = wp_at(abase); ++ continue; + + case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_InnerClasses): +- // note the existence of this attr, but save for later +- if (cur_class_has_local_ics) +- abort("too many InnerClasses attrs"); +- cur_class_has_local_ics = true; +- wp = wp_at(abase); +- continue; ++ // note the existence of this attr, but save for later ++ if (cur_class_has_local_ics) ++ abort("too many InnerClasses attrs"); ++ cur_class_has_local_ics = true; ++ wp = wp_at(abase); ++ continue; + + case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_SourceFile): +- aname = cp.sym[cpool::s_SourceFile]; +- ref = class_SourceFile_RUN.getRefN(); +- CHECK_0; +- if (ref == null) { +- bytes& n = cur_class->ref(0)->value.b; +- // parse n = (<pkg>/)*<outer>?($<id>)* +- int pkglen = lastIndexOf(SLASH_MIN, SLASH_MAX, n, n.len)+1; +- bytes prefix = n.slice(pkglen, n.len); +- for (;;) { +- // Work backwards, finding all '$', '#', etc. +- int dollar = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, prefix, prefix.len); +- if (dollar < 0) break; +- prefix = prefix.slice(0, dollar); +- } +- const char* suffix = ".java"; +- int len = prefix.len + strlen(suffix); +- bytes name; name.set(T_NEW(byte, add_size(len, 1)), len); +- name.strcat(prefix).strcat(suffix); +- ref = cp.ensureUtf8(name); +- } +- putref(ref); +- break; ++ aname = cp.sym[cpool::s_SourceFile]; ++ ref = class_SourceFile_RUN.getRefN(); ++ CHECK_0; ++ if (ref == null) { ++ bytes& n = cur_class->ref(0)->value.b; ++ // parse n = (<pkg>/)*<outer>?($<id>)* ++ int pkglen = lastIndexOf(SLASH_MIN, SLASH_MAX, n, n.len)+1; ++ bytes prefix = n.slice(pkglen, n.len); ++ for (;;) { ++ // Work backwards, finding all '$', '#', etc. ++ int dollar = lastIndexOf(DOLLAR_MIN, DOLLAR_MAX, prefix, prefix.len); ++ if (dollar < 0) break; ++ prefix = prefix.slice(0, dollar); ++ } ++ const char* suffix = ".java"; ++ int len = prefix.len + strlen(suffix); ++ bytes name; name.set(T_NEW(byte, add_size(len, 1)), len); ++ name.strcat(prefix).strcat(suffix); ++ ref = cp.ensureUtf8(name); ++ } ++ putref(ref); ++ break; + + case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_EnclosingMethod): +- aname = cp.sym[cpool::s_EnclosingMethod]; +- putref(class_EnclosingMethod_RC.getRefN()); +- putref(class_EnclosingMethod_RDN.getRefN()); +- break; ++ aname = cp.sym[cpool::s_EnclosingMethod]; ++ putref(class_EnclosingMethod_RC.getRefN()); ++ CHECK_0; ++ putref(class_EnclosingMethod_RDN.getRefN()); ++ break; + + case ADH_BYTE(ATTR_CONTEXT_FIELD, FIELD_ATTR_ConstantValue): +- aname = cp.sym[cpool::s_ConstantValue]; +- putref(field_ConstantValue_KQ.getRefUsing(cp.getKQIndex())); +- break; ++ aname = cp.sym[cpool::s_ConstantValue]; ++ putref(field_ConstantValue_KQ.getRefUsing(cp.getKQIndex())); ++ break; + + case ADH_BYTE(ATTR_CONTEXT_METHOD, METHOD_ATTR_Code): +- aname = cp.sym[cpool::s_Code]; +- write_code(); +- break; ++ aname = cp.sym[cpool::s_Code]; ++ write_code(); ++ break; + + case ADH_BYTE(ATTR_CONTEXT_METHOD, METHOD_ATTR_Exceptions): +- aname = cp.sym[cpool::s_Exceptions]; +- putu2(count = method_Exceptions_N.getInt()); +- for (j = 0; j < count; j++) { +- putref(method_Exceptions_RC.getRefN()); +- } +- break; ++ aname = cp.sym[cpool::s_Exceptions]; ++ putu2(count = method_Exceptions_N.getInt()); ++ for (j = 0; j < count; j++) { ++ putref(method_Exceptions_RC.getRefN()); ++ CHECK_0; ++ } ++ break; + + case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_StackMapTable): +- aname = cp.sym[cpool::s_StackMapTable]; ++ aname = cp.sym[cpool::s_StackMapTable]; + // (keep this code aligned with its brother in unpacker::read_attrs) +- putu2(count = code_StackMapTable_N.getInt()); +- for (j = 0; j < count; j++) { ++ putu2(count = code_StackMapTable_N.getInt()); ++ for (j = 0; j < count; j++) { + int tag = code_StackMapTable_frame_T.getByte(); + putu1(tag); + if (tag <= 127) { +@@ -4160,109 +4172,115 @@ int unpacker::write_attrs(int attrc, jul + // (253) [(1)(2)(2)] + // (254) [(1)(2)(2)(2)] + putu2(code_StackMapTable_offset.getInt()); ++ CHECK_0; + for (int j2 = (tag - 251); j2 > 0; j2--) { + put_stackmap_type(); ++ CHECK_0; + } + } else { + // (255) [(1)NH[(2)]NH[(2)]] + putu2(code_StackMapTable_offset.getInt()); + putu2(j2 = code_StackMapTable_local_N.getInt()); +- while (j2-- > 0) put_stackmap_type(); ++ while (j2-- > 0) {put_stackmap_type(); CHECK_0;} + putu2(j2 = code_StackMapTable_stack_N.getInt()); +- while (j2-- > 0) put_stackmap_type(); ++ while (j2-- > 0) {put_stackmap_type(); CHECK_0;} + } +- } +- break; ++ } ++ break; + + case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LineNumberTable): +- aname = cp.sym[cpool::s_LineNumberTable]; +- putu2(count = code_LineNumberTable_N.getInt()); +- for (j = 0; j < count; j++) { +- putu2(to_bci(code_LineNumberTable_bci_P.getInt())); +- putu2(code_LineNumberTable_line.getInt()); +- } +- break; ++ aname = cp.sym[cpool::s_LineNumberTable]; ++ putu2(count = code_LineNumberTable_N.getInt()); ++ for (j = 0; j < count; j++) { ++ putu2(to_bci(code_LineNumberTable_bci_P.getInt())); ++ putu2(code_LineNumberTable_line.getInt()); ++ } ++ break; + + case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LocalVariableTable): +- aname = cp.sym[cpool::s_LocalVariableTable]; +- putu2(count = code_LocalVariableTable_N.getInt()); +- for (j = 0; j < count; j++) { +- int bii = code_LocalVariableTable_bci_P.getInt(); +- int bci = to_bci(bii); +- putu2(bci); +- bii += code_LocalVariableTable_span_O.getInt(); +- putu2(to_bci(bii) - bci); +- putref(code_LocalVariableTable_name_RU.getRefN()); +- putref(code_LocalVariableTable_type_RS.getRefN()); +- putu2(code_LocalVariableTable_slot.getInt()); +- } +- break; ++ aname = cp.sym[cpool::s_LocalVariableTable]; ++ putu2(count = code_LocalVariableTable_N.getInt()); ++ for (j = 0; j < count; j++) { ++ int bii = code_LocalVariableTable_bci_P.getInt(); ++ int bci = to_bci(bii); ++ putu2(bci); ++ bii += code_LocalVariableTable_span_O.getInt(); ++ putu2(to_bci(bii) - bci); ++ putref(code_LocalVariableTable_name_RU.getRefN()); ++ CHECK_0; ++ putref(code_LocalVariableTable_type_RS.getRefN()); ++ CHECK_0; ++ putu2(code_LocalVariableTable_slot.getInt()); ++ } ++ break; + + case ADH_BYTE(ATTR_CONTEXT_CODE, CODE_ATTR_LocalVariableTypeTable): +- aname = cp.sym[cpool::s_LocalVariableTypeTable]; +- putu2(count = code_LocalVariableTypeTable_N.getInt()); +- for (j = 0; j < count; j++) { +- int bii = code_LocalVariableTypeTable_bci_P.getInt(); +- int bci = to_bci(bii); +- putu2(bci); +- bii += code_LocalVariableTypeTable_span_O.getInt(); +- putu2(to_bci(bii) - bci); +- putref(code_LocalVariableTypeTable_name_RU.getRefN()); +- putref(code_LocalVariableTypeTable_type_RS.getRefN()); +- putu2(code_LocalVariableTypeTable_slot.getInt()); +- } +- break; ++ aname = cp.sym[cpool::s_LocalVariableTypeTable]; ++ putu2(count = code_LocalVariableTypeTable_N.getInt()); ++ for (j = 0; j < count; j++) { ++ int bii = code_LocalVariableTypeTable_bci_P.getInt(); ++ int bci = to_bci(bii); ++ putu2(bci); ++ bii += code_LocalVariableTypeTable_span_O.getInt(); ++ putu2(to_bci(bii) - bci); ++ putref(code_LocalVariableTypeTable_name_RU.getRefN()); ++ CHECK_0; ++ putref(code_LocalVariableTypeTable_type_RS.getRefN()); ++ CHECK_0; ++ putu2(code_LocalVariableTypeTable_slot.getInt()); ++ } ++ break; + + case ADH_BYTE(ATTR_CONTEXT_CLASS, X_ATTR_Signature): +- aname = cp.sym[cpool::s_Signature]; +- putref(class_Signature_RS.getRefN()); +- break; ++ aname = cp.sym[cpool::s_Signature]; ++ putref(class_Signature_RS.getRefN()); ++ break; + + case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_Signature): +- aname = cp.sym[cpool::s_Signature]; +- putref(field_Signature_RS.getRefN()); +- break; ++ aname = cp.sym[cpool::s_Signature]; ++ putref(field_Signature_RS.getRefN()); ++ break; + + case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_Signature): +- aname = cp.sym[cpool::s_Signature]; +- putref(method_Signature_RS.getRefN()); +- break; ++ aname = cp.sym[cpool::s_Signature]; ++ putref(method_Signature_RS.getRefN()); ++ break; + + case ADH_BYTE(ATTR_CONTEXT_CLASS, X_ATTR_Deprecated): + case ADH_BYTE(ATTR_CONTEXT_FIELD, X_ATTR_Deprecated): + case ADH_BYTE(ATTR_CONTEXT_METHOD, X_ATTR_Deprecated): +- aname = cp.sym[cpool::s_Deprecated]; +- // no data +- break; +- } +- } +- ++ aname = cp.sym[cpool::s_Deprecated]; ++ // no data ++ break; ++ } ++ } ++ CHECK_0; + if (aname == null) { + // Unparse a compressor-defined attribute. + layout_definition* lo = ad.getLayout(idx); + if (lo == null) { +- abort("bad layout index"); +- break; ++ abort("bad layout index"); ++ break; + } + assert(lo->idx == idx); + aname = lo->nameEntry; + if (aname == null) { +- bytes nameb; nameb.set(lo->name); +- aname = cp.ensureUtf8(nameb); +- // Cache the name entry for next time. +- lo->nameEntry = aname; ++ bytes nameb; nameb.set(lo->name); ++ aname = cp.ensureUtf8(nameb); ++ // Cache the name entry for next time. ++ lo->nameEntry = aname; + } + // Execute all the layout elements. + band** bands = lo->bands(); + if (lo->hasCallables()) { +- band& cble = *bands[0]; +- assert(cble.le_kind == EK_CBLE); +- bands = cble.le_body; ++ band& cble = *bands[0]; ++ assert(cble.le_kind == EK_CBLE); ++ bands = cble.le_body; + } + putlayout(bands); + } + +- if (aname == null) ++ if (aname == null) + abort("bad attribute index"); + CHECK_0; + +@@ -4335,8 +4353,8 @@ void unpacker::write_classfile_tail() { + julong indexMask = ad.flagIndexMask(); + + cur_class = class_this.getRef(); ++ CHECK; + cur_super = class_super.getRef(); +- + CHECK; + + if (cur_super == cur_class) cur_super = null; +@@ -4349,6 +4367,7 @@ void unpacker::write_classfile_tail() { + putu2(num = class_interface_count.getInt()); + for (i = 0; i < num; i++) { + putref(class_interface.getRef()); ++ CHECK; + } + + write_members(class_field_count.getInt(), ATTR_CONTEXT_FIELD); +@@ -4389,8 +4408,8 @@ void unpacker::write_classfile_tail() { + entry& e = *oes[i]; + if (e.tag != CONSTANT_Class) continue; // wrong sort + for (inner_class* ic = cp.getIC(&e); +- ic != null; +- ic = cp.getIC(ic->outer)) { ++ ic != null; ++ ic = cp.getIC(ic->outer)) { + if (ic->requested) break; // already processed + ic->requested = true; + requested_ics.add(ic); +@@ -4421,22 +4440,24 @@ void unpacker::write_classfile_tail() { + if (flags == 0) { + // The extra IC is simply a copy of a global IC. + if (global_ic == null) { +- abort("bad reference to inner class"); +- break; ++ abort("bad reference to inner class"); ++ break; + } + extra_ic = (*global_ic); // fill in rest of fields + } else { + flags &= ~ACC_IC_LONG_FORM; // clear high bit if set to get clean zero + extra_ic.flags = flags; + extra_ic.outer = class_InnerClasses_outer_RCN.getRefN(); ++ CHECK; + extra_ic.name = class_InnerClasses_name_RUN.getRefN(); ++ CHECK; + // Detect if this is an exact copy of the global tuple. + if (global_ic != null) { +- if (global_ic->flags != extra_ic.flags || +- global_ic->outer != extra_ic.outer || +- global_ic->name != extra_ic.name) { +- global_ic = null; // not really the same, so break the link +- } ++ if (global_ic->flags != extra_ic.flags || ++ global_ic->outer != extra_ic.outer || ++ global_ic->name != extra_ic.name) { ++ global_ic = null; // not really the same, so break the link ++ } + } + } + if (global_ic != null && global_ic->requested) { +@@ -4465,15 +4486,15 @@ void unpacker::write_classfile_tail() { + for (i = -num_global_ics; i < num_extra_ics; i++) { + inner_class* ic; + if (i < 0) +- ic = (inner_class*) requested_ics.get(num_global_ics+i); ++ ic = (inner_class*) requested_ics.get(num_global_ics+i); + else +- ic = &extra_ics[i]; ++ ic = &extra_ics[i]; + if (ic->requested) { +- putref(ic->inner); +- putref(ic->outer); +- putref(ic->name); +- putu2(ic->flags); +- NOT_PRODUCT(local_ics--); ++ putref(ic->inner); ++ putref(ic->outer); ++ putref(ic->name); ++ putu2(ic->flags); ++ NOT_PRODUCT(local_ics--); + } + } + assert(local_ics == 0); // must balance +@@ -4573,7 +4594,7 @@ unpacker::file* unpacker::get_next_file( + if (archive_size != 0) { + julong predicted_size = unsized_bytes_read + archive_size; + if (predicted_size != bytes_read) +- abort("archive header had incorrect size"); ++ abort("archive header had incorrect size"); + } + return null; + } +@@ -4637,7 +4658,7 @@ unpacker::file* unpacker::get_next_file( + size_t rpleft = input_remaining(); + if (rpleft > 0) { + if (rpleft > cur_file.size) +- rpleft = (size_t) cur_file.size; ++ rpleft = (size_t) cur_file.size; + cur_file.data[0].set(rp, rpleft); + rp += rpleft; + } +@@ -4655,7 +4676,7 @@ unpacker::file* unpacker::get_next_file( + + // Write a file to jarout. + void unpacker::write_file_to_jar(unpacker::file* f) { +- size_t htsize = f->data[0].len + f->data[1].len; ++ size_t htsize = f->data[0].len + f->data[1].len; + julong fsize = f->size; + #ifndef PRODUCT + if (nowrite NOT_PRODUCT(|| skipfiles-- > 0)) { +@@ -4665,7 +4686,7 @@ void unpacker::write_file_to_jar(unpacke + #endif + if (htsize == fsize) { + jarout->addJarEntry(f->name, f->deflate_hint(), f->modtime, +- f->data[0], f->data[1]); ++ f->data[0], f->data[1]); + } else { + assert(input_remaining() == 0); + bytes part1, part2; +@@ -4680,27 +4701,27 @@ void unpacker::write_file_to_jar(unpacke + if (fleft > 0) { + // Must read some more. + if (live_input) { +- // Stop using the input buffer. Make a new one: +- if (free_input) input.free(); +- input.init(fleft > (1<<12) ? fleft : (1<<12)); +- free_input = true; +- live_input = false; ++ // Stop using the input buffer. Make a new one: ++ if (free_input) input.free(); ++ input.init(fleft > (1<<12) ? fleft : (1<<12)); ++ free_input = true; ++ live_input = false; + } else { +- // Make it large enough. +- assert(free_input); // must be reallocable +- input.ensureSize(fleft); ++ // Make it large enough. ++ assert(free_input); // must be reallocable ++ input.ensureSize(fleft); + } + rplimit = rp = input.base(); + CHECK; + input.setLimit(rp + fleft); + if (!ensure_input(fleft)) +- abort("EOF reading resource file"); ++ abort("EOF reading resource file"); + part2.ptr = input_scan(); + part2.len = input_remaining(); + rplimit = rp = input.base(); + } + jarout->addJarEntry(f->name, f->deflate_hint(), f->modtime, +- part1, part2); ++ part1, part2); + } + if (verbose >= 3) { + fprintf(errstrm, "Wrote %lld bytes to: %s\n", fsize, f->name); +@@ -4722,7 +4743,7 @@ void unpacker::redirect_stdio() { + } else if (strcmp(log_file, LOGFILE_STDOUT) == 0) { + errstrm = stdout; + return; +- } else if (log_file[0] != '\0' && (errstrm = fopen(log_file,"a+")) != NULL) { ++ } else if (log_file[0] != '\0' && (errstrm = fopen(log_file,"a+")) != NULL) { + return; + } else { + char log_file_name[PATH_MAX+100]; +@@ -4732,7 +4753,7 @@ void unpacker::redirect_stdio() { + if (n < 1 || n > PATH_MAX) { + sprintf(tmpdir,"C:\\"); + } +- sprintf(log_file_name, "%sunpack.log", tmpdir); ++ sprintf(log_file_name, "%sunpack.log", tmpdir); + #else + sprintf(tmpdir,"/tmp"); + sprintf(log_file_name, "/tmp/unpack.log"); +@@ -4742,7 +4763,7 @@ void unpacker::redirect_stdio() { + return ; + } + +- char *tname = tempnam(tmpdir,"#upkg"); ++ char *tname = tempnam(tmpdir,"#upkg"); + sprintf(log_file_name, "%s", tname); + if ((errstrm = fopen(log_file_name, "a+")) != NULL) { + log_file = errstrm_name = saveStr(log_file_name); +@@ -4758,7 +4779,7 @@ void unpacker::redirect_stdio() { + #endif + // Last resort + // (Do not use stdout, since it might be jarout->jarfp.) +- errstrm = stderr; ++ errstrm = stderr; + log_file = errstrm_name = LOGFILE_STDERR; + } + } +@@ -4799,3 +4820,5 @@ void unpacker::abort(const char* message + #endif + #endif // JNI + } ++ ++ diff --git a/java/openjdk6/files/icedtea/security/20130201/7186948.patch b/java/openjdk6/files/icedtea/security/20130201/7186948.patch new file mode 100644 index 000000000000..1313561fda6a --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7186948.patch @@ -0,0 +1,20 @@ +# HG changeset patch +# User rupashka +# Date 1350390610 -14400 +# Node ID 6deb10c2d5d0c8925fd2012d9fc3b9325c997f21 +# Parent ce11c5c59cb8672eeddf9d5ce49563ccbc387854 +7186948: Improve Swing data validation +Reviewed-by: art, ahgross + +diff --git a/src/share/classes/javax/swing/UIDefaults.java b/src/share/classes/javax/swing/UIDefaults.java +--- jdk/src/share/classes/javax/swing/UIDefaults.java ++++ jdk/src/share/classes/javax/swing/UIDefaults.java +@@ -677,6 +677,8 @@ public class UIDefaults extends Hashtabl + try { + String className = (String)get(uiClassID); + if (className != null) { ++ ReflectUtil.checkPackageAccess(className); ++ + Class cls = (Class)get(className); + if (cls == null) { + if (uiClassLoader == null) { diff --git a/java/openjdk6/files/icedtea/security/20130201/7186952.patch b/java/openjdk6/files/icedtea/security/20130201/7186952.patch new file mode 100644 index 000000000000..0c6c8ee2e67e --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7186952.patch @@ -0,0 +1,127 @@ +# HG changeset patch +# User denis +# Date 1353947054 -14400 +# Node ID 9bbc6817b00c3e9d4eba05d53a8a20b45947ea03 +# Parent c684d497e159d3eebded29e997d953019305ec45 +7186952: Improve clipboard access +Reviewed-by: serb, ahgross + +diff --git a/src/share/classes/java/awt/TextComponent.java b/src/share/classes/java/awt/TextComponent.java +--- jdk/src/share/classes/java/awt/TextComponent.java ++++ jdk/src/share/classes/java/awt/TextComponent.java +@@ -107,12 +107,6 @@ public class TextComponent extends Compo + // the background color of non-editable TextComponents. + boolean backgroundSetByClientCode = false; + +- /** +- * True if this <code>TextComponent</code> has access +- * to the System clipboard. +- */ +- transient private boolean canAccessClipboard; +- + transient protected TextListener textListener; + + /* +@@ -137,7 +131,6 @@ public class TextComponent extends Compo + GraphicsEnvironment.checkHeadless(); + this.text = (text != null) ? text : ""; + setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); +- checkSystemClipboardAccess(); + } + + private void enableInputMethodsIfNecessary() { +@@ -727,17 +720,14 @@ public class TextComponent extends Compo + /** + * Assigns a valid value to the canAccessClipboard instance variable. + */ +- private void checkSystemClipboardAccess() { +- canAccessClipboard = true; ++ private boolean canAccessClipboard() { + SecurityManager sm = System.getSecurityManager(); +- if (sm != null) { +- try { +- sm.checkSystemClipboardAccess(); +- } +- catch (SecurityException e) { +- canAccessClipboard = false; +- } +- } ++ if (sm == null) return true; ++ try { ++ sm.checkSystemClipboardAccess(); ++ return true; ++ } catch (SecurityException e) {} ++ return false; + } + + /* +@@ -820,7 +810,6 @@ public class TextComponent extends Compo + } + } + enableInputMethodsIfNecessary(); +- checkSystemClipboardAccess(); + } + + +diff --git a/src/windows/native/sun/windows/awt_TextComponent.cpp b/src/windows/native/sun/windows/awt_TextComponent.cpp +--- jdk/src/windows/native/sun/windows/awt_TextComponent.cpp ++++ jdk/src/windows/native/sun/windows/awt_TextComponent.cpp +@@ -52,13 +52,11 @@ struct EnableEditingStruct { + * AwtTextComponent fields + */ + +-/* java.awt.TextComponent fields */ +-jfieldID AwtTextComponent::canAccessClipboardID; +- +- + /************************************************************************ + * AwtTextComponent methods + */ ++ ++jmethodID AwtTextComponent::canAccessClipboardMID; + + AwtTextComponent::AwtTextComponent() { + m_synthetic = FALSE; +@@ -188,8 +186,7 @@ AwtTextComponent::WmPaste() + } + jobject target = GetTarget(env); + jboolean canAccessClipboard = +- env->GetBooleanField(target, +- AwtTextComponent::canAccessClipboardID); ++ env->CallBooleanMethod (target, AwtTextComponent::canAccessClipboardMID); + env->DeleteLocalRef(target); + return (canAccessClipboard) ? mrDoDefault : mrConsume; + } +@@ -622,12 +619,13 @@ Java_sun_awt_windows_WTextComponentPeer_ + { + TRY; + +- cls = env->FindClass("java/awt/TextComponent"); +- if (cls != NULL) { +- AwtTextComponent::canAccessClipboardID = +- env->GetFieldID(cls, "canAccessClipboard", "Z"); +- DASSERT(AwtTextComponent::canAccessClipboardID != NULL); +- } ++ jclass textComponentClassID = env->FindClass("java/awt/TextComponent"); ++ AwtTextComponent::canAccessClipboardMID = ++ env->GetMethodID(textComponentClassID, ++ "canAccessClipboard", "()Z"); ++ env->DeleteLocalRef(textComponentClassID); ++ ++ DASSERT(AwtTextComponent::canAccessClipboardMID != NULL) + + CATCH_BAD_ALLOC; + } +diff --git a/src/windows/native/sun/windows/awt_TextComponent.h b/src/windows/native/sun/windows/awt_TextComponent.h +--- jdk/src/windows/native/sun/windows/awt_TextComponent.h ++++ jdk/src/windows/native/sun/windows/awt_TextComponent.h +@@ -42,8 +42,7 @@ + + class AwtTextComponent : public AwtComponent { + public: +- /* java.awt.TextComponent canAccessClipboard field ID */ +- static jfieldID canAccessClipboardID; ++ static jmethodID canAccessClipboardMID; + + AwtTextComponent(); + diff --git a/java/openjdk6/files/icedtea/security/20130201/7186954.patch b/java/openjdk6/files/icedtea/security/20130201/7186954.patch new file mode 100644 index 000000000000..b3fbfcaafb0b --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7186954.patch @@ -0,0 +1,81 @@ +# HG changeset patch +# User dmeetry +# Date 1352295947 -14400 +# Node ID ee4632a30696050ebd5c014fb3da64112ab48dd3 +# Parent 6e2d4ed84b41667df189abb7bd0915cda01a85a0 +7186954: Improve connection performance +Reviewed-by: khazra + +diff --git a/src/share/classes/sun/net/httpserver/ChunkedInputStream.java b/src/share/classes/sun/net/httpserver/ChunkedInputStream.java +--- jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java ++++ jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -41,8 +41,12 @@ class ChunkedInputStream extends LeftOve + + private boolean needToReadHeader = true; + +- static char CR = '\r'; +- static char LF = '\n'; ++ final static char CR = '\r'; ++ final static char LF = '\n'; ++ /* ++ * Maximum chunk header size of 2KB + 2 bytes for CRLF ++ */ ++ private final static int MAX_CHUNK_HEADER_SIZE = 2050; + + private int numeric (char[] arr, int nchars) throws IOException { + assert arr.length >= nchars; +@@ -73,9 +77,13 @@ class ChunkedInputStream extends LeftOve + char[] len_arr = new char [16]; + int len_size = 0; + boolean end_of_len = false; ++ int read = 0; + + while ((c=(char)in.read())!= -1) { +- if (len_size == len_arr.length -1) { ++ read++; ++ if ((len_size == len_arr.length -1) || ++ (read > MAX_CHUNK_HEADER_SIZE)) ++ { + throw new IOException ("invalid chunk header"); + } + if (gotCR) { +diff --git a/src/share/classes/sun/net/www/http/ChunkedInputStream.java b/src/share/classes/sun/net/www/http/ChunkedInputStream.java +--- jdk/src/share/classes/sun/net/www/http/ChunkedInputStream.java ++++ jdk/src/share/classes/sun/net/www/http/ChunkedInputStream.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -125,6 +125,11 @@ class ChunkedInputStream extends InputSt + */ + private boolean closed; + ++ /* ++ * Maximum chunk header size of 2KB + 2 bytes for CRLF ++ */ ++ private final static int MAX_CHUNK_HEADER_SIZE = 2050; ++ + /** + * State to indicate that next field should be :- + * chunk-size [ chunk-extension ] CRLF +@@ -290,6 +295,10 @@ class ChunkedInputStream extends InputSt + break; + } + pos++; ++ if ((pos - rawPos) >= MAX_CHUNK_HEADER_SIZE) { ++ error = true; ++ throw new IOException("Chunk header too long"); ++ } + } + if (pos >= rawCount) { + return; diff --git a/java/openjdk6/files/icedtea/security/20130201/7192392.patch b/java/openjdk6/files/icedtea/security/20130201/7192392.patch new file mode 100644 index 000000000000..5e51b99c7e64 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7192392.patch @@ -0,0 +1,695 @@ +# HG changeset patch +# User mbankal +# Date 1355226562 28800 +# Node ID 726b9456757648efb7c68e41c6bcc08a401eef83 +# Parent aade089d4505d382f49306a90873c4217367e709 +7192392: Better validation of client keys +Reviewed-by: xuelei + +diff --git a/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java b/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java +--- jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java ++++ jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -39,6 +39,7 @@ import javax.crypto.ShortBufferException + import javax.crypto.ShortBufferException; + import javax.crypto.SecretKey; + import javax.crypto.spec.*; ++import sun.security.util.KeyUtil; + + /** + * This class implements the Diffie-Hellman key agreement protocol between +@@ -205,6 +206,9 @@ extends KeyAgreementSpi { + if (pub_g != null && !(init_g.equals(pub_g))) { + throw new InvalidKeyException("Incompatible parameters"); + } ++ ++ // validate the Diffie-Hellman public key ++ KeyUtil.validate(dhPubKey); + + // store the y value + this.y = dhPubKey.getY(); +diff --git a/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java b/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java +--- jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java ++++ jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -37,6 +37,7 @@ import static sun.security.pkcs11.Templa + import static sun.security.pkcs11.TemplateManager.*; + import sun.security.pkcs11.wrapper.*; + import static sun.security.pkcs11.wrapper.PKCS11Constants.*; ++import sun.security.util.KeyUtil; + + /** + * KeyAgreement implementation class. This class currently supports +@@ -134,6 +135,8 @@ final class P11KeyAgreement extends KeyA + BigInteger p, g, y; + if (key instanceof DHPublicKey) { + DHPublicKey dhKey = (DHPublicKey)key; ++ // validate the Diffie-Hellman public key ++ KeyUtil.validate(dhKey); + y = dhKey.getY(); + DHParameterSpec params = dhKey.getParams(); + p = params.getP(); +@@ -145,6 +148,8 @@ final class P11KeyAgreement extends KeyA + try { + DHPublicKeySpec spec = (DHPublicKeySpec)kf.engineGetKeySpec + (key, DHPublicKeySpec.class); ++ // validate the Diffie-Hellman public key ++ KeyUtil.validate(spec); + y = spec.getY(); + p = spec.getP(); + g = spec.getG(); +diff --git a/src/share/classes/sun/security/ssl/ClientHandshaker.java b/src/share/classes/sun/security/ssl/ClientHandshaker.java +--- jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java ++++ jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -168,7 +168,11 @@ final class ClientHandshaker extends Han + } + break; + case K_DH_ANON: +- this.serverKeyExchange(new DH_ServerKeyExchange(input)); ++ try { ++ this.serverKeyExchange(new DH_ServerKeyExchange(input)); ++ } catch (GeneralSecurityException e) { ++ throwSSLException("Server key", e); ++ } + break; + case K_DHE_DSS: + case K_DHE_RSA: +@@ -811,7 +815,7 @@ final class ClientHandshaker extends Han + case K_DHE_RSA: + case K_DHE_DSS: + case K_DH_ANON: +- preMasterSecret = dh.getAgreedSecret(serverDH); ++ preMasterSecret = dh.getAgreedSecret(serverDH, true); + break; + case K_ECDHE_RSA: + case K_ECDHE_ECDSA: +diff --git a/src/share/classes/sun/security/ssl/DHClientKeyExchange.java b/src/share/classes/sun/security/ssl/DHClientKeyExchange.java +--- jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java ++++ jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -29,7 +29,7 @@ import java.io.IOException; + import java.io.IOException; + import java.io.PrintStream; + import java.math.BigInteger; +- ++import javax.net.ssl.SSLHandshakeException; + + /* + * Message used by clients to send their Diffie-Hellman public +@@ -50,7 +50,7 @@ final class DHClientKeyExchange extends + private byte dh_Yc[]; // 1 to 2^16 -1 bytes + + BigInteger getClientPublicKey() { +- return new BigInteger(1, dh_Yc); ++ return dh_Yc == null ? null : new BigInteger(1, dh_Yc); + } + + /* +@@ -72,7 +72,14 @@ final class DHClientKeyExchange extends + * but that's what the protocol spec requires.) + */ + DHClientKeyExchange(HandshakeInStream input) throws IOException { +- dh_Yc = input.getBytes16(); ++ if (input.available() >= 2) { ++ dh_Yc = input.getBytes16(); ++ } else { ++ // currently, we don't support cipher suites that requires ++ // implicit public key of client. ++ throw new SSLHandshakeException( ++ "Unsupported implicit client DiffieHellman public key"); ++ } + } + + int messageLength() { +@@ -84,7 +91,9 @@ final class DHClientKeyExchange extends + } + + void send(HandshakeOutStream s) throws IOException { +- s.putBytes16(dh_Yc); ++ if (dh_Yc != null && dh_Yc.length != 0) { ++ s.putBytes16(dh_Yc); ++ } + } + + void print(PrintStream s) throws IOException { +diff --git a/src/share/classes/sun/security/ssl/DHCrypt.java b/src/share/classes/sun/security/ssl/DHCrypt.java +--- jdk/src/share/classes/sun/security/ssl/DHCrypt.java ++++ jdk/src/share/classes/sun/security/ssl/DHCrypt.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -28,11 +28,14 @@ package sun.security.ssl; + + import java.math.BigInteger; + import java.security.*; ++import java.io.IOException; ++import javax.net.ssl.SSLHandshakeException; + + import javax.crypto.SecretKey; + import javax.crypto.KeyAgreement; + import javax.crypto.interfaces.DHPublicKey; + import javax.crypto.spec.*; ++import sun.security.util.KeyUtil; + + /** + * This class implements the Diffie-Hellman key exchange algorithm. +@@ -54,7 +57,8 @@ import javax.crypto.spec.*; + * . if we are server, call DHCrypt(keyLength,random). This generates + * an ephemeral keypair of the request length. + * . if we are client, call DHCrypt(modulus, base, random). This +- * generates an ephemeral keypair using the parameters specified by the server. ++ * generates an ephemeral keypair using the parameters specified by ++ * the server. + * . send parameters and public value to remote peer + * . receive peers ephemeral public key + * . call getAgreedSecret() to calculate the shared secret +@@ -83,6 +87,9 @@ final class DHCrypt { + // public component of our key, X = (g ^ x) mod p + private BigInteger publicValue; // X (aka y) + ++ // the times to recover from failure if public key validation ++ private static int MAX_FAILOVER_TIMES = 2; ++ + /** + * Generate a Diffie-Hellman keypair of the specified size. + */ +@@ -90,9 +97,10 @@ final class DHCrypt { + try { + KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman"); + kpg.initialize(keyLength, random); +- KeyPair kp = kpg.generateKeyPair(); +- privateKey = kp.getPrivate(); +- DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic()); ++ DHPublicKeySpec spec = generateDHPublicKeySpec(kpg); ++ if (spec == null) { ++ throw new RuntimeException("Could not generate DH keypair"); ++ } + publicValue = spec.getY(); + modulus = spec.getP(); + base = spec.getG(); +@@ -115,9 +123,10 @@ final class DHCrypt { + KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman"); + DHParameterSpec params = new DHParameterSpec(modulus, base); + kpg.initialize(params, random); +- KeyPair kp = kpg.generateKeyPair(); +- privateKey = kp.getPrivate(); +- DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic()); ++ DHPublicKeySpec spec = generateDHPublicKeySpec(kpg); ++ if (spec == null) { ++ throw new RuntimeException("Could not generate DH keypair"); ++ } + publicValue = spec.getY(); + } catch (GeneralSecurityException e) { + throw new RuntimeException("Could not generate DH keypair", e); +@@ -128,7 +137,8 @@ final class DHCrypt { + if (key instanceof DHPublicKey) { + DHPublicKey dhKey = (DHPublicKey)key; + DHParameterSpec params = dhKey.getParams(); +- return new DHPublicKeySpec(dhKey.getY(), params.getP(), params.getG()); ++ return new DHPublicKeySpec(dhKey.getY(), ++ params.getP(), params.getG()); + } + try { + KeyFactory factory = JsseJce.getKeyFactory("DH"); +@@ -168,16 +178,29 @@ final class DHCrypt { + * has not been set (or generated). + * + * @param peerPublicKey the peer's public key. +- * @returns the secret, which is an unsigned big-endian integer ++ * @param keyIsValidated whether the {@code peerPublicKey} has beed ++ * validated ++ * @return the secret, which is an unsigned big-endian integer + * the same size as the Diffie-Hellman modulus. + */ +- SecretKey getAgreedSecret(BigInteger peerPublicValue) { ++ SecretKey getAgreedSecret(BigInteger peerPublicValue, ++ boolean keyIsValidated) throws IOException { + try { + KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman"); + DHPublicKeySpec spec = + new DHPublicKeySpec(peerPublicValue, modulus, base); + PublicKey publicKey = kf.generatePublic(spec); + KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman"); ++ // validate the Diffie-Hellman public key ++ if (!keyIsValidated && ++ !KeyUtil.isOracleJCEProvider(ka.getProvider().getName())) { ++ try { ++ KeyUtil.validate(spec); ++ } catch (InvalidKeyException ike) { ++ // prefer handshake_failure alert to internal_error alert ++ throw new SSLHandshakeException(ike.getMessage()); ++ } ++ } + ka.init(privateKey); + ka.doPhase(publicKey, true); + return ka.generateSecret("TlsPremasterSecret"); +@@ -186,4 +209,33 @@ final class DHCrypt { + } + } + ++ // Generate and validate DHPublicKeySpec ++ private DHPublicKeySpec generateDHPublicKeySpec(KeyPairGenerator kpg) ++ throws GeneralSecurityException { ++ ++ boolean doExtraValiadtion = ++ (!KeyUtil.isOracleJCEProvider(kpg.getProvider().getName())); ++ for (int i = 0; i <= MAX_FAILOVER_TIMES; i++) { ++ KeyPair kp = kpg.generateKeyPair(); ++ privateKey = kp.getPrivate(); ++ DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic()); ++ ++ // validate the Diffie-Hellman public key ++ if (doExtraValiadtion) { ++ try { ++ KeyUtil.validate(spec); ++ } catch (InvalidKeyException ivke) { ++ if (i == MAX_FAILOVER_TIMES) { ++ throw ivke; ++ } ++ // otherwise, ignore the exception and try the next one ++ continue; ++ } ++ } ++ ++ return spec; ++ } ++ ++ return null; ++ } + } +diff --git a/src/share/classes/sun/security/ssl/HandshakeMessage.java b/src/share/classes/sun/security/ssl/HandshakeMessage.java +--- jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java ++++ jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -42,6 +42,7 @@ import javax.security.auth.x500.X500Prin + + import javax.crypto.KeyGenerator; + import javax.crypto.SecretKey; ++import javax.crypto.spec.DHPublicKeySpec; + import javax.crypto.spec.SecretKeySpec; + + import javax.net.ssl.*; +@@ -51,6 +52,7 @@ import sun.security.internal.spec.TlsPrf + import sun.security.internal.spec.TlsPrfParameterSpec; + + import sun.security.ssl.CipherSuite.*; ++import sun.security.util.KeyUtil; + + /** + * Many data structures are involved in the handshake messages. These +@@ -715,6 +717,7 @@ class DH_ServerKeyExchange extends Serve + * key exchange. + */ + DH_ServerKeyExchange(DHCrypt obj) { ++ // The DH key has been validated in the constructor of DHCrypt. + getValues(obj); + signature = null; + } +@@ -727,6 +730,7 @@ class DH_ServerKeyExchange extends Serve + DH_ServerKeyExchange(DHCrypt obj, PrivateKey key, byte clntNonce[], + byte svrNonce[], SecureRandom sr) throws GeneralSecurityException { + ++ // The DH key has been validated in the constructor of DHCrypt. + getValues(obj); + + Signature sig; +@@ -751,10 +755,14 @@ class DH_ServerKeyExchange extends Serve + * stream, as if sent from server to client for use with + * DH_anon key exchange + */ +- DH_ServerKeyExchange(HandshakeInStream input) throws IOException { ++ DH_ServerKeyExchange(HandshakeInStream input) ++ throws IOException, GeneralSecurityException { + dh_p = input.getBytes16(); + dh_g = input.getBytes16(); + dh_Ys = input.getBytes16(); ++ KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys), ++ new BigInteger(1, dh_p), ++ new BigInteger(1, dh_g))); + signature = null; + } + +@@ -770,7 +778,9 @@ class DH_ServerKeyExchange extends Serve + dh_p = input.getBytes16(); + dh_g = input.getBytes16(); + dh_Ys = input.getBytes16(); +- ++ KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys), ++ new BigInteger(1, dh_p), ++ new BigInteger(1, dh_g))); + byte signature[]; + if (dhKeyExchangeFix) { + signature = input.getBytes16(); +diff --git a/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java b/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java +--- jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java ++++ jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java +@@ -36,7 +36,7 @@ import javax.net.ssl.*; + import javax.net.ssl.*; + + import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; +-import sun.security.util.KeyLength; ++import sun.security.util.KeyUtil; + + /** + * This is the client key exchange message (CLIENT --> SERVER) used with +@@ -194,7 +194,7 @@ final class RSAClientKeyExchange extends + "unable to get the plaintext of the premaster secret"); + } + +- int keySize = KeyLength.getKeySize(secretKey); ++ int keySize = KeyUtil.getKeySize(secretKey); + if (keySize > 0 && keySize != 384) { // 384 = 48 * 8 + if (debug != null && Debug.isOn("handshake")) { + System.out.println( +diff --git a/src/share/classes/sun/security/ssl/ServerHandshaker.java b/src/share/classes/sun/security/ssl/ServerHandshaker.java +--- jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java ++++ jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java +@@ -1147,7 +1147,7 @@ final class ServerHandshaker extends Han + if (debug != null && Debug.isOn("handshake")) { + mesg.print(System.out); + } +- return dh.getAgreedSecret(mesg.getClientPublicKey()); ++ return dh.getAgreedSecret(mesg.getClientPublicKey(), false); + } + + private SecretKey clientKeyExchange(ECDHClientKeyExchange mesg) +diff --git a/src/share/classes/sun/security/util/KeyLength.java b/src/share/classes/sun/security/util/KeyLength.java +deleted file mode 100644 +--- jdk/src/share/classes/sun/security/util/KeyLength.java ++++ /dev/null +@@ -1,91 +0,0 @@ +-/* +- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License version 2 only, as +- * published by the Free Software Foundation. Oracle designates this +- * particular file as subject to the "Classpath" exception as provided +- * by Oracle in the LICENSE file that accompanied this code. +- * +- * This code is distributed in the hope that it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +- * version 2 for more details (a copy is included in the LICENSE file that +- * accompanied this code). +- * +- * You should have received a copy of the GNU General Public License version +- * 2 along with this work; if not, write to the Free Software Foundation, +- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +- * or visit www.oracle.com if you need additional information or have any +- * questions. +- */ +- +-package sun.security.util; +- +-import java.security.Key; +-import java.security.PrivilegedAction; +-import java.security.AccessController; +-import java.security.interfaces.ECKey; +-import java.security.interfaces.RSAKey; +-import java.security.interfaces.DSAKey; +-import javax.crypto.SecretKey; +-import javax.crypto.interfaces.DHKey; +- +-/** +- * A utility class to get key length +- */ +-public final class KeyLength { +- +- /** +- * Returns the key size of the given key object in bits. +- * +- * @param key the key object, cannot be null +- * @return the key size of the given key object in bits, or -1 if the +- * key size is not accessible +- */ +- final public static int getKeySize(Key key) { +- int size = -1; +- +- if (key instanceof Length) { +- try { +- Length ruler = (Length)key; +- size = ruler.length(); +- } catch (UnsupportedOperationException usoe) { +- // ignore the exception +- } +- +- if (size >= 0) { +- return size; +- } +- } +- +- // try to parse the length from key specification +- if (key instanceof SecretKey) { +- SecretKey sk = (SecretKey)key; +- String format = sk.getFormat(); +- if ("RAW".equals(format) && sk.getEncoded() != null) { +- size = (sk.getEncoded().length * 8); +- } // Otherwise, it may be a unextractable key of PKCS#11, or +- // a key we are not able to handle. +- } else if (key instanceof RSAKey) { +- RSAKey pubk = (RSAKey)key; +- size = pubk.getModulus().bitLength(); +- } else if (key instanceof ECKey) { +- ECKey pubk = (ECKey)key; +- size = pubk.getParams().getOrder().bitLength(); +- } else if (key instanceof DSAKey) { +- DSAKey pubk = (DSAKey)key; +- size = pubk.getParams().getP().bitLength(); +- } else if (key instanceof DHKey) { +- DHKey pubk = (DHKey)key; +- size = pubk.getParams().getP().bitLength(); +- } // Otherwise, it may be a unextractable key of PKCS#11, or +- // a key we are not able to handle. +- +- return size; +- } +-} +- +diff --git a/src/share/classes/sun/security/util/KeyUtil.java b/src/share/classes/sun/security/util/KeyUtil.java +new file mode 100644 +--- /dev/null ++++ jdk/src/share/classes/sun/security/util/KeyUtil.java +@@ -0,0 +1,184 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ */ ++ ++package sun.security.util; ++ ++import java.security.Key; ++import java.security.PrivilegedAction; ++import java.security.AccessController; ++import java.security.InvalidKeyException; ++import java.security.interfaces.ECKey; ++import java.security.interfaces.RSAKey; ++import java.security.interfaces.DSAKey; ++import java.security.spec.KeySpec; ++import javax.crypto.SecretKey; ++import javax.crypto.interfaces.DHKey; ++import javax.crypto.interfaces.DHPublicKey; ++import javax.crypto.spec.DHParameterSpec; ++import javax.crypto.spec.DHPublicKeySpec; ++import java.math.BigInteger; ++ ++/** ++ * A utility class to get key length, valiate keys, etc. ++ */ ++public final class KeyUtil { ++ ++ /** ++ * Returns the key size of the given key object in bits. ++ * ++ * @param key the key object, cannot be null ++ * @return the key size of the given key object in bits, or -1 if the ++ * key size is not accessible ++ */ ++ public static final int getKeySize(Key key) { ++ int size = -1; ++ ++ if (key instanceof Length) { ++ try { ++ Length ruler = (Length)key; ++ size = ruler.length(); ++ } catch (UnsupportedOperationException usoe) { ++ // ignore the exception ++ } ++ ++ if (size >= 0) { ++ return size; ++ } ++ } ++ ++ // try to parse the length from key specification ++ if (key instanceof SecretKey) { ++ SecretKey sk = (SecretKey)key; ++ String format = sk.getFormat(); ++ if ("RAW".equals(format) && sk.getEncoded() != null) { ++ size = (sk.getEncoded().length * 8); ++ } // Otherwise, it may be a unextractable key of PKCS#11, or ++ // a key we are not able to handle. ++ } else if (key instanceof RSAKey) { ++ RSAKey pubk = (RSAKey)key; ++ size = pubk.getModulus().bitLength(); ++ } else if (key instanceof ECKey) { ++ ECKey pubk = (ECKey)key; ++ size = pubk.getParams().getOrder().bitLength(); ++ } else if (key instanceof DSAKey) { ++ DSAKey pubk = (DSAKey)key; ++ size = pubk.getParams().getP().bitLength(); ++ } else if (key instanceof DHKey) { ++ DHKey pubk = (DHKey)key; ++ size = pubk.getParams().getP().bitLength(); ++ } // Otherwise, it may be a unextractable key of PKCS#11, or ++ // a key we are not able to handle. ++ ++ return size; ++ } ++ ++ /** ++ * Returns whether the key is valid or not. ++ * <P> ++ * Note that this method is only apply to DHPublicKey at present. ++ * ++ * @param publicKey ++ * the key object, cannot be null ++ * ++ * @throws NullPointerException if {@code publicKey} is null ++ * @throws InvalidKeyException if {@code publicKey} is invalid ++ */ ++ public static final void validate(Key key) ++ throws InvalidKeyException { ++ if (key == null) { ++ throw new NullPointerException( ++ "The key to be validated cannot be null"); ++ } ++ ++ if (key instanceof DHPublicKey) { ++ validateDHPublicKey((DHPublicKey)key); ++ } ++ } ++ ++ ++ /** ++ * Returns whether the key spec is valid or not. ++ * <P> ++ * Note that this method is only apply to DHPublicKeySpec at present. ++ * ++ * @param keySpec ++ * the key spec object, cannot be null ++ * ++ * @throws NullPointerException if {@code keySpec} is null ++ * @throws InvalidKeyException if {@code keySpec} is invalid ++ */ ++ public static final void validate(KeySpec keySpec) ++ throws InvalidKeyException { ++ if (keySpec == null) { ++ throw new NullPointerException( ++ "The key spec to be validated cannot be null"); ++ } ++ ++ if (keySpec instanceof DHPublicKeySpec) { ++ validateDHPublicKey((DHPublicKeySpec)keySpec); ++ } ++ } ++ ++ /** ++ * Returns whether the specified provider is Oracle provider or not. ++ * <P> ++ * Note that this method is only apply to SunJCE and SunPKCS11 at present. ++ * ++ * @param providerName ++ * the provider name ++ * @return true if, and only if, the provider of the specified ++ * {@code providerName} is Oracle provider ++ */ ++ public static final boolean isOracleJCEProvider(String providerName) { ++ return providerName != null && (providerName.equals("SunJCE") || ++ providerName.startsWith("SunPKCS11")); ++ } ++ ++ /** ++ * Returns whether the Diffie-Hellman public key is valid or not. ++ * ++ * Per RFC 2631 and NIST SP800-56A, the following algorithm is used to ++ * validate Diffie-Hellman public keys: ++ * 1. Verify that y lies within the interval [2,p-1]. If it does not, ++ * the key is invalid. ++ * 2. Compute y^q mod p. If the result == 1, the key is valid. ++ * Otherwise the key is invalid. ++ */ ++ private static void validateDHPublicKey(DHPublicKey publicKey) ++ throws InvalidKeyException { ++ DHParameterSpec paramSpec = publicKey.getParams(); ++ ++ BigInteger p = paramSpec.getP(); ++ BigInteger g = paramSpec.getG(); ++ BigInteger y = publicKey.getY(); ++ ++ validateDHPublicKey(p, g, y); ++ } ++ ++ private static void validateDHPublicKey(DHPublicKeySpec publicKeySpec) ++ throws InvalidKeyException { ++ validateDHPublicKey(publicKeySpec.getP(), ++ publicKeySpec.getG(), publicKeySpec.getY()); ++ } ++ ++ private static void validateDHPublicKey(BigInteger p, ++ BigInteger g, BigInteger y) throws InvalidKeyException { ++ ++ // For better interoperability, the interval is limited to [2, p-2]. ++ BigInteger leftOpen = BigInteger.ONE; ++ BigInteger rightOpen = p.subtract(BigInteger.ONE); ++ if (y.compareTo(leftOpen) <= 0) { ++ throw new InvalidKeyException( ++ "Diffie-Hellman public key is too small"); ++ } ++ if (y.compareTo(rightOpen) >= 0) { ++ throw new InvalidKeyException( ++ "Diffie-Hellman public key is too large"); ++ } ++ ++ // Don't bother to check against the y^q mod p if safe primes are used. ++ } ++} diff --git a/java/openjdk6/files/icedtea/security/20130201/7192393.patch b/java/openjdk6/files/icedtea/security/20130201/7192393.patch new file mode 100644 index 000000000000..f9c312d5f019 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7192393.patch @@ -0,0 +1,60 @@ +# HG changeset patch +# User mbankal +# Date 1355294606 28800 +# Node ID 708c134c36312faf8721c0c981be6553e4ebf49f +# Parent 175c95df5b8609142188946b59040de2e4cbe0af +7192393: Better Checking of order of TLS Messages +Reviewed-by: xuelei + +diff --git a/src/share/classes/sun/security/ssl/ClientHandshaker.java b/src/share/classes/sun/security/ssl/ClientHandshaker.java +--- jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java ++++ jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java +@@ -128,9 +128,8 @@ final class ClientHandshaker extends Han + * in the constructor. + */ + void processMessage(byte type, int messageLen) throws IOException { +- if (state > type +- && (type != HandshakeMessage.ht_hello_request +- && state != HandshakeMessage.ht_client_hello)) { ++ if (state >= type ++ && (type != HandshakeMessage.ht_hello_request)) { + throw new SSLProtocolException( + "Handshake message sequence violation, " + type); + } +diff --git a/src/share/classes/sun/security/ssl/ServerHandshaker.java b/src/share/classes/sun/security/ssl/ServerHandshaker.java +--- jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java ++++ jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java +@@ -153,7 +153,7 @@ final class ServerHandshaker extends Han + // In SSLv3 and TLS, messages follow strictly increasing + // numerical order _except_ for one annoying special case. + // +- if ((state > type) ++ if ((state >= type) + && (state != HandshakeMessage.ht_client_key_exchange + && type != HandshakeMessage.ht_certificate_verify)) { + throw new SSLProtocolException( +@@ -250,16 +250,17 @@ final class ServerHandshaker extends Han + } + + // +- // Move the state machine forward except for that annoying +- // special case. This means that clients could send extra +- // cert verify messages; not a problem so long as all of +- // them actually check out. ++ // Move state machine forward if the message handling ++ // code didn't already do so + // +- if (state < type && type != HandshakeMessage.ht_certificate_verify) { +- state = type; ++ if (state < type) { ++ if(type == HandshakeMessage.ht_certificate_verify) { ++ state = type + 2; // an annoying special case ++ } else { ++ state = type; ++ } + } + } +- + + /* + * ClientHello presents the server with a bunch of options, to which the diff --git a/java/openjdk6/files/icedtea/security/20130201/7192977.patch b/java/openjdk6/files/icedtea/security/20130201/7192977.patch new file mode 100644 index 000000000000..19e366b08377 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7192977.patch @@ -0,0 +1,436 @@ +diff --git a/src/share/classes/java/awt/EventQueue.java b/src/share/classes/java/awt/EventQueue.java +--- jdk/src/share/classes/java/awt/EventQueue.java ++++ jdk/src/share/classes/java/awt/EventQueue.java +@@ -173,8 +173,14 @@ public class EventQueue { + } + public void removeSourceEvents(EventQueue eventQueue, + Object source, +- boolean removeAllEvents) { ++ boolean removeAllEvents) ++ { + eventQueue.removeSourceEvents(source, removeAllEvents); ++ } ++ public void invokeAndWait(Object source, Runnable r) ++ throws InterruptedException, InvocationTargetException ++ { ++ EventQueue.invokeAndWait(source, r); + } + }); + } +@@ -1042,8 +1048,14 @@ public class EventQueue { + * @since 1.2 + */ + public static void invokeAndWait(Runnable runnable) +- throws InterruptedException, InvocationTargetException { ++ throws InterruptedException, InvocationTargetException ++ { ++ invokeAndWait(Toolkit.getDefaultToolkit(), runnable); ++ } + ++ static void invokeAndWait(Object source, Runnable runnable) ++ throws InterruptedException, InvocationTargetException ++ { + if (EventQueue.isDispatchThread()) { + throw new Error("Cannot call invokeAndWait from the event dispatcher thread"); + } +@@ -1052,8 +1064,7 @@ public class EventQueue { + Object lock = new AWTInvocationLock(); + + InvocationEvent event = +- new InvocationEvent(Toolkit.getDefaultToolkit(), runnable, lock, +- true); ++ new InvocationEvent(source, runnable, lock, true); + + synchronized (lock) { + Toolkit.getEventQueue().postEvent(event); +diff --git a/src/share/classes/java/awt/Window.java b/src/share/classes/java/awt/Window.java +--- jdk/src/share/classes/java/awt/Window.java ++++ jdk/src/share/classes/java/awt/Window.java +@@ -1036,7 +1036,7 @@ public class Window extends Container im + } + else { + try { +- EventQueue.invokeAndWait(action); ++ EventQueue.invokeAndWait(this, action); + } + catch (InterruptedException e) { + System.err.println("Disposal was interrupted:"); +diff --git a/src/share/classes/javax/swing/RepaintManager.java b/src/share/classes/javax/swing/RepaintManager.java +--- jdk/src/share/classes/javax/swing/RepaintManager.java ++++ jdk/src/share/classes/javax/swing/RepaintManager.java +@@ -27,17 +27,21 @@ package javax.swing; + + import java.awt.*; + import java.awt.event.*; +-import java.awt.peer.ComponentPeer; +-import java.awt.peer.ContainerPeer; + import java.awt.image.VolatileImage; ++import java.security.AccessControlContext; + import java.security.AccessController; ++import java.security.PrivilegedAction; + import java.util.*; ++import java.util.concurrent.atomic.AtomicInteger; + import java.applet.*; + + import sun.awt.AppContext; ++import sun.awt.AWTAccessor; + import sun.awt.DisplayChangedListener; + import sun.awt.SunToolkit; + import sun.java2d.SunGraphicsEnvironment; ++import sun.misc.JavaSecurityAccess; ++import sun.misc.SharedSecrets; + import sun.security.action.GetPropertyAction; + + +@@ -168,6 +172,9 @@ public class RepaintManager + * Runnable used to process all repaint/revalidate requests. + */ + private final ProcessingRunnable processingRunnable; ++ ++ private final static JavaSecurityAccess javaSecurityAccess = ++ SharedSecrets.getJavaSecurityAccess(); + + + static { +@@ -553,13 +560,26 @@ public class RepaintManager + // This is called from the toolkit thread when awt needs to run a + // Runnable before we paint. + // +- void nativeQueueSurfaceDataRunnable(AppContext appContext, Component c, +- Runnable r) { ++ void nativeQueueSurfaceDataRunnable(AppContext appContext, ++ final Component c, final Runnable r) ++ { + synchronized(this) { + if (runnableList == null) { + runnableList = new LinkedList<Runnable>(); + } +- runnableList.add(r); ++ runnableList.add(new Runnable() { ++ public void run() { ++ AccessControlContext stack = AccessController.getContext(); ++ AccessControlContext acc = ++ AWTAccessor.getComponentAccessor().getAccessControlContext(c); ++ javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Void>() { ++ public Void run() { ++ r.run(); ++ return null; ++ } ++ }, stack, acc); ++ } ++ }); + } + scheduleProcessingRunnable(appContext); + } +@@ -639,9 +659,9 @@ public class RepaintManager + * @see #addInvalidComponent + */ + public void validateInvalidComponents() { +- java.util.List<Component> ic; ++ final java.util.List<Component> ic; + synchronized(this) { +- if(invalidComponents == null) { ++ if (invalidComponents == null) { + return; + } + ic = invalidComponents; +@@ -649,7 +669,17 @@ public class RepaintManager + } + int n = ic.size(); + for(int i = 0; i < n; i++) { +- ic.get(i).validate(); ++ final Component c = ic.get(i); ++ AccessControlContext stack = AccessController.getContext(); ++ AccessControlContext acc = ++ AWTAccessor.getComponentAccessor().getAccessControlContext(c); ++ javaSecurityAccess.doIntersectionPrivilege( ++ new PrivilegedAction<Void>() { ++ public Void run() { ++ c.validate(); ++ return null; ++ } ++ }, stack, acc); + } + } + +@@ -696,76 +726,75 @@ public class RepaintManager + paintDirtyRegions(tmpDirtyComponents); + } + +- private void paintDirtyRegions(Map<Component,Rectangle> +- tmpDirtyComponents){ +- int i, count; +- java.util.List<Component> roots; +- Component dirtyComponent; +- +- count = tmpDirtyComponents.size(); +- if (count == 0) { ++ private void paintDirtyRegions( ++ final Map<Component,Rectangle> tmpDirtyComponents) ++ { ++ if (tmpDirtyComponents.isEmpty()) { + return; + } + +- Rectangle rect; +- int localBoundsX = 0; +- int localBoundsY = 0; +- int localBoundsH = 0; +- int localBoundsW = 0; +- Enumeration keys; +- +- roots = new ArrayList<Component>(count); ++ final java.util.List<Component> roots = ++ new ArrayList<Component>(tmpDirtyComponents.size()); + + for (Component dirty : tmpDirtyComponents.keySet()) { + collectDirtyComponents(tmpDirtyComponents, dirty, roots); + } + +- count = roots.size(); +- // System.out.println("roots size is " + count); ++ final AtomicInteger count = new AtomicInteger(roots.size()); + painting = true; + try { +- for(i=0 ; i < count ; i++) { +- dirtyComponent = roots.get(i); +- rect = tmpDirtyComponents.get(dirtyComponent); +- // System.out.println("Should refresh :" + rect); +- localBoundsH = dirtyComponent.getHeight(); +- localBoundsW = dirtyComponent.getWidth(); ++ for(int j = 0; j < count.get(); j++) { ++ final int i = j; ++ final Component dirtyComponent = roots.get(j); + +- SwingUtilities.computeIntersection(localBoundsX, +- localBoundsY, +- localBoundsW, +- localBoundsH, +- rect); +- if (dirtyComponent instanceof JComponent) { +- ((JComponent)dirtyComponent).paintImmediately( +- rect.x,rect.y,rect.width, rect.height); +- } +- else if (dirtyComponent.isShowing()) { +- Graphics g = JComponent.safelyGetGraphics( +- dirtyComponent, dirtyComponent); +- // If the Graphics goes away, it means someone disposed of +- // the window, don't do anything. +- if (g != null) { +- g.setClip(rect.x, rect.y, rect.width, rect.height); +- try { +- dirtyComponent.paint(g); +- } finally { +- g.dispose(); ++ AccessControlContext stack = AccessController.getContext(); ++ AccessControlContext acc = ++ AWTAccessor.getComponentAccessor().getAccessControlContext(dirtyComponent); ++ javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Void>() { ++ public Void run() { ++ Rectangle rect = tmpDirtyComponents.get(dirtyComponent); ++ ++ int localBoundsH = dirtyComponent.getHeight(); ++ int localBoundsW = dirtyComponent.getWidth(); ++ SwingUtilities.computeIntersection(0, ++ 0, ++ localBoundsW, ++ localBoundsH, ++ rect); ++ if (dirtyComponent instanceof JComponent) { ++ ((JComponent)dirtyComponent).paintImmediately( ++ rect.x,rect.y,rect.width, rect.height); + } ++ else if (dirtyComponent.isShowing()) { ++ Graphics g = JComponent.safelyGetGraphics( ++ dirtyComponent, dirtyComponent); ++ // If the Graphics goes away, it means someone disposed of ++ // the window, don't do anything. ++ if (g != null) { ++ g.setClip(rect.x, rect.y, rect.width, rect.height); ++ try { ++ dirtyComponent.paint(g); ++ } finally { ++ g.dispose(); ++ } ++ } ++ } ++ // If the repaintRoot has been set, service it now and ++ // remove any components that are children of repaintRoot. ++ if (repaintRoot != null) { ++ adjustRoots(repaintRoot, roots, i + 1); ++ count.set(roots.size()); ++ paintManager.isRepaintingRoot = true; ++ repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(), ++ repaintRoot.getHeight()); ++ paintManager.isRepaintingRoot = false; ++ // Only service repaintRoot once. ++ repaintRoot = null; ++ } ++ ++ return null; + } +- } +- // If the repaintRoot has been set, service it now and +- // remove any components that are children of repaintRoot. +- if (repaintRoot != null) { +- adjustRoots(repaintRoot, roots, i + 1); +- count = roots.size(); +- paintManager.isRepaintingRoot = true; +- repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(), +- repaintRoot.getHeight()); +- paintManager.isRepaintingRoot = false; +- // Only service repaintRoot once. +- repaintRoot = null; +- } ++ }, stack, acc); + } + } finally { + painting = false; +diff --git a/src/share/classes/sun/applet/AppletPanel.java b/src/share/classes/sun/applet/AppletPanel.java +--- jdk/src/share/classes/sun/applet/AppletPanel.java ++++ jdk/src/share/classes/sun/applet/AppletPanel.java +@@ -47,6 +47,7 @@ import java.util.WeakHashMap; + import java.util.WeakHashMap; + import javax.swing.SwingUtilities; + import sun.awt.AppContext; ++import sun.awt.AWTAccessor; + import sun.awt.EmbeddedFrame; + import sun.awt.SunToolkit; + import sun.misc.MessageUtils; +@@ -449,12 +450,12 @@ abstract class AppletPanel extends Panel + // to avoid deadlock. + try { + final AppletPanel p = this; +- +- SwingUtilities.invokeAndWait(new Runnable() { +- public void run() { +- p.validate(); +- } +- }); ++ Runnable r = new Runnable() { ++ public void run() { ++ p.validate(); ++ } ++ }; ++ AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r); + } + catch(InterruptedException ie) { + } +@@ -479,18 +480,19 @@ abstract class AppletPanel extends Panel + try { + final AppletPanel p = this; + final Applet a = applet; ++ Runnable r = new Runnable() { ++ public void run() { ++ p.validate(); ++ a.setVisible(true); + +- SwingUtilities.invokeAndWait(new Runnable() { +- public void run() { +- p.validate(); +- a.setVisible(true); +- +- // Fix for BugTraq ID 4041703. +- // Set the default focus for an applet. +- if (hasInitialFocus()) +- setDefaultFocus(); ++ // Fix for BugTraq ID 4041703. ++ // Set the default focus for an applet. ++ if (hasInitialFocus()) { ++ setDefaultFocus(); + } +- }); ++ } ++ }; ++ AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r); + } + catch(InterruptedException ie) { + } +@@ -513,13 +515,12 @@ abstract class AppletPanel extends Panel + // to avoid deadlock. + try { + final Applet a = applet; +- +- SwingUtilities.invokeAndWait(new Runnable() { +- public void run() +- { +- a.setVisible(false); +- } +- }); ++ Runnable r = new Runnable() { ++ public void run() { ++ a.setVisible(false); ++ } ++ }; ++ AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r); + } + catch(InterruptedException ie) { + } +@@ -571,17 +572,14 @@ abstract class AppletPanel extends Panel + } + status = APPLET_DISPOSE; + +- try +- { ++ try { + final Applet a = applet; +- +- EventQueue.invokeAndWait(new Runnable() +- { +- public void run() +- { ++ Runnable r = new Runnable() { ++ public void run() { + remove(a); + } +- }); ++ }; ++ AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r); + } + catch(InterruptedException ie) + { +diff --git a/src/share/classes/sun/awt/AWTAccessor.java b/src/share/classes/sun/awt/AWTAccessor.java +--- jdk/src/share/classes/sun/awt/AWTAccessor.java ++++ jdk/src/share/classes/sun/awt/AWTAccessor.java +@@ -29,6 +29,7 @@ import java.awt.*; + + import sun.misc.Unsafe; + ++import java.lang.reflect.InvocationTargetException; + import java.security.AccessControlContext; + + import java.util.Vector; +@@ -198,6 +199,11 @@ public final class AWTAccessor { + */ + void removeSourceEvents(EventQueue eventQueue, Object source, + boolean removeAllEvents); ++ /** ++ * Static in EventQueue ++ */ ++ void invokeAndWait(Object source, Runnable r) ++ throws InterruptedException, InvocationTargetException; + } + + /** +diff --git a/src/windows/classes/sun/awt/windows/WComponentPeer.java b/src/windows/classes/sun/awt/windows/WComponentPeer.java +--- jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java ++++ jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java +@@ -427,14 +427,15 @@ public abstract class WComponentPeer ext + try { + replaceSurfaceData(); + } catch (InvalidPipeException e) { +- // REMIND : what do we do if our surface creation failed? ++ // REMIND : what do we do if our surface creation failed? + } + } + } + }; ++ Component c = (Component)target; + // Fix 6255371. +- if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing((Component)target, r)) { +- postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), r)); ++ if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing(c, r)) { ++ postEvent(new InvocationEvent(c, r)); + } + } + diff --git a/java/openjdk6/files/icedtea/security/20130201/7197546.patch b/java/openjdk6/files/icedtea/security/20130201/7197546.patch new file mode 100644 index 000000000000..890ae091d9f0 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7197546.patch @@ -0,0 +1,479 @@ +# HG changeset patch +# User mbankal +# Date 1355327990 28800 +# Node ID 41f8dd88c5e9aec4975c36414a865aed5643c880 +# Parent 708c134c36312faf8721c0c981be6553e4ebf49f +7197546: (proxy) Reflect about creating reflective proxies +Reviewed-by: mchung + +diff --git a/src/share/classes/java/lang/Class.java b/src/share/classes/java/lang/Class.java +--- jdk/src/share/classes/java/lang/Class.java ++++ jdk/src/share/classes/java/lang/Class.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -65,7 +65,9 @@ import sun.reflect.generics.scope.ClassS + import sun.reflect.generics.scope.ClassScope; + import sun.security.util.SecurityConstants; + import java.lang.annotation.Annotation; ++import java.lang.reflect.Proxy; + import sun.reflect.annotation.*; ++import sun.reflect.misc.ReflectUtil; + + /** + * Instances of the class {@code Class} represent classes and +@@ -320,7 +322,7 @@ public final + throws InstantiationException, IllegalAccessException + { + if (System.getSecurityManager() != null) { +- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false); + } + return newInstance0(); + } +@@ -1294,7 +1296,7 @@ public final + // be very careful not to change the stack depth of this + // checkMemberAccess call for security reasons + // see java.lang.SecurityManager.checkMemberAccess +- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false); + + // Privileged so this implementation can look at DECLARED classes, + // something the caller might not have privilege to do. The code here +@@ -1372,7 +1374,7 @@ public final + // be very careful not to change the stack depth of this + // checkMemberAccess call for security reasons + // see java.lang.SecurityManager.checkMemberAccess +- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); + return copyFields(privateGetPublicFields(null)); + } + +@@ -1423,7 +1425,7 @@ public final + // be very careful not to change the stack depth of this + // checkMemberAccess call for security reasons + // see java.lang.SecurityManager.checkMemberAccess +- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); + return copyMethods(privateGetPublicMethods()); + } + +@@ -1472,7 +1474,7 @@ public final + // be very careful not to change the stack depth of this + // checkMemberAccess call for security reasons + // see java.lang.SecurityManager.checkMemberAccess +- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); + return copyConstructors(privateGetDeclaredConstructors(true)); + } + +@@ -1531,7 +1533,7 @@ public final + // be very careful not to change the stack depth of this + // checkMemberAccess call for security reasons + // see java.lang.SecurityManager.checkMemberAccess +- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); + Field field = getField0(name); + if (field == null) { + throw new NoSuchFieldException(name); +@@ -1616,7 +1618,7 @@ public final + // be very careful not to change the stack depth of this + // checkMemberAccess call for security reasons + // see java.lang.SecurityManager.checkMemberAccess +- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); + Method method = getMethod0(name, parameterTypes); + if (method == null) { + throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); +@@ -1670,7 +1672,7 @@ public final + // be very careful not to change the stack depth of this + // checkMemberAccess call for security reasons + // see java.lang.SecurityManager.checkMemberAccess +- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); + return getConstructor0(parameterTypes, Member.PUBLIC); + } + +@@ -1712,7 +1714,7 @@ public final + // be very careful not to change the stack depth of this + // checkMemberAccess call for security reasons + // see java.lang.SecurityManager.checkMemberAccess +- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), false); + return getDeclaredClasses0(); + } + +@@ -1756,7 +1758,7 @@ public final + // be very careful not to change the stack depth of this + // checkMemberAccess call for security reasons + // see java.lang.SecurityManager.checkMemberAccess +- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); + return copyFields(privateGetDeclaredFields(false)); + } + +@@ -1804,7 +1806,7 @@ public final + // be very careful not to change the stack depth of this + // checkMemberAccess call for security reasons + // see java.lang.SecurityManager.checkMemberAccess +- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); + return copyMethods(privateGetDeclaredMethods(false)); + } + +@@ -1849,7 +1851,7 @@ public final + // be very careful not to change the stack depth of this + // checkMemberAccess call for security reasons + // see java.lang.SecurityManager.checkMemberAccess +- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); + return copyConstructors(privateGetDeclaredConstructors(false)); + } + +@@ -1893,7 +1895,7 @@ public final + // be very careful not to change the stack depth of this + // checkMemberAccess call for security reasons + // see java.lang.SecurityManager.checkMemberAccess +- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); + Field field = searchFields(privateGetDeclaredFields(false), name); + if (field == null) { + throw new NoSuchFieldException(name); +@@ -1948,7 +1950,7 @@ public final + // be very careful not to change the stack depth of this + // checkMemberAccess call for security reasons + // see java.lang.SecurityManager.checkMemberAccess +- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); + Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); + if (method == null) { + throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); +@@ -1998,7 +2000,7 @@ public final + // be very careful not to change the stack depth of this + // checkMemberAccess call for security reasons + // see java.lang.SecurityManager.checkMemberAccess +- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); ++ checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); + return getConstructor0(parameterTypes, Member.DECLARED); + } + +@@ -2168,18 +2170,26 @@ public final + * <p> Default policy: allow all clients access with normal Java access + * control. + */ +- private void checkMemberAccess(int which, ClassLoader ccl) { ++ private void checkMemberAccess(int which, ClassLoader ccl, boolean checkProxyInterfaces) { + SecurityManager s = System.getSecurityManager(); + if (s != null) { + s.checkMemberAccess(this, which); + ClassLoader cl = getClassLoader0(); +- if ((ccl != null) && (ccl != cl) && +- ((cl == null) || !cl.isAncestor(ccl))) { ++ if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { ++ + String name = this.getName(); + int i = name.lastIndexOf('.'); + if (i != -1) { +- s.checkPackageAccess(name.substring(0, i)); ++ // skip the package access check on a proxy class in default proxy package ++ String pkg = name.substring(0, i); ++ if (!Proxy.isProxyClass(this) || !pkg.equals(ReflectUtil.PROXY_PACKAGE)) { ++ s.checkPackageAccess(pkg); ++ } + } ++ } ++ // check package access on the proxy interfaces ++ if (checkProxyInterfaces && Proxy.isProxyClass(this)) { ++ ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces()); + } + } + } +diff --git a/src/share/classes/java/lang/reflect/Proxy.java b/src/share/classes/java/lang/reflect/Proxy.java +--- jdk/src/share/classes/java/lang/reflect/Proxy.java ++++ jdk/src/share/classes/java/lang/reflect/Proxy.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -27,6 +27,9 @@ package java.lang.reflect; + + import java.lang.ref.Reference; + import java.lang.ref.WeakReference; ++import java.security.AccessController; ++import java.security.Permission; ++import java.security.PrivilegedAction; + import java.util.Arrays; + import java.util.Collections; + import java.util.HashMap; +@@ -35,6 +38,9 @@ import java.util.Set; + import java.util.Set; + import java.util.WeakHashMap; + import sun.misc.ProxyGenerator; ++import sun.reflect.Reflection; ++import sun.reflect.misc.ReflectUtil; ++import sun.security.util.SecurityConstants; + + /** + * {@code Proxy} provides static methods for creating dynamic proxy +@@ -263,7 +269,67 @@ public class Proxy implements java.io.Se + * @param h the invocation handler for this proxy instance + */ + protected Proxy(InvocationHandler h) { ++ doNewInstanceCheck(); + this.h = h; ++ } ++ ++ private static class ProxyAccessHelper { ++ // The permission is implementation specific. ++ static final Permission PROXY_PERMISSION = ++ new ReflectPermission("proxyConstructorNewInstance"); ++ // These system properties are defined to provide a short-term ++ // workaround if customers need to disable the new security checks. ++ static final boolean allowNewInstance; ++ static final boolean allowNullLoader; ++ static { ++ allowNewInstance = getBooleanProperty("sun.reflect.proxy.allowsNewInstance"); ++ allowNullLoader = getBooleanProperty("sun.reflect.proxy.allowsNullLoader"); ++ } ++ ++ private static boolean getBooleanProperty(final String key) { ++ String s = AccessController.doPrivileged(new PrivilegedAction<String>() { ++ public String run() { ++ return System.getProperty(key); ++ } ++ }); ++ return Boolean.valueOf(s); ++ } ++ ++ static boolean needsNewInstanceCheck(Class<?> proxyClass) { ++ if (!Proxy.isProxyClass(proxyClass) || allowNewInstance) { ++ return false; ++ } ++ ++ if (proxyClass.getName().startsWith(ReflectUtil.PROXY_PACKAGE + ".")) { ++ // all proxy interfaces are public ++ return false; ++ } ++ for (Class<?> intf : proxyClass.getInterfaces()) { ++ if (!Modifier.isPublic(intf.getModifiers())) { ++ return true; ++ } ++ } ++ return false; ++ } ++ } ++ ++ /* ++ * Access check on a proxy class that implements any non-public interface. ++ * ++ * @throws SecurityException if a security manager exists, and ++ * the caller does not have the permission. ++ */ ++ private void doNewInstanceCheck() { ++ SecurityManager sm = System.getSecurityManager(); ++ Class<?> proxyClass = this.getClass(); ++ if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(proxyClass)) { ++ try { ++ sm.checkPermission(ProxyAccessHelper.PROXY_PERMISSION); ++ } catch (SecurityException e) { ++ throw new SecurityException("Not allowed to construct a Proxy " ++ + "instance that implements a non-public interface", e); ++ } ++ } + } + + /** +@@ -344,6 +410,50 @@ public class Proxy implements java.io.Se + Class<?>... interfaces) + throws IllegalArgumentException + { ++ return getProxyClass0(loader, interfaces); // stack walk magic: do not refactor ++ } ++ ++ private static void checkProxyLoader(ClassLoader ccl, ++ ClassLoader loader) ++ { ++ SecurityManager sm = System.getSecurityManager(); ++ if (sm != null) { ++ if (loader == null && ccl != null) { ++ if (!ProxyAccessHelper.allowNullLoader) { ++ sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); ++ } ++ } ++ } ++ } ++ ++ /* ++ * Generate a proxy class (caller-sensitive). ++ * ++ * To define a proxy class, it performs the access checks as in ++ * Class.forName (VM will invoke ClassLoader.checkPackageAccess): ++ * 1. "getClassLoader" permission check if loader == null ++ * 2. checkPackageAccess on the interfaces it implements ++ * ++ * To get a constructor and new instance of a proxy class, it performs ++ * the package access check on the interfaces it implements ++ * as in Class.getConstructor. ++ * ++ * If an interface is non-public, the proxy class must be defined by ++ * the defining loader of the interface. If the caller's class loader ++ * is not the same as the defining loader of the interface, the VM ++ * will throw IllegalAccessError when the generated proxy class is ++ * being defined via the defineClass0 method. ++ */ ++ private static Class<?> getProxyClass0(ClassLoader loader, ++ Class<?>... interfaces) { ++ SecurityManager sm = System.getSecurityManager(); ++ if (sm != null) { ++ final int CALLER_FRAME = 3; // 0: Reflection, 1: getProxyClass0 2: Proxy 3: caller ++ final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME); ++ final ClassLoader ccl = caller.getClassLoader(); ++ checkProxyLoader(ccl, loader); ++ ReflectUtil.checkProxyPackageAccess(ccl, interfaces); ++ } + if (interfaces.length > 65535) { + throw new IllegalArgumentException("interface limit exceeded"); + } +@@ -494,8 +604,9 @@ public class Proxy implements java.io.Se + } + } + +- if (proxyPkg == null) { // if no non-public proxy interfaces, +- proxyPkg = ""; // use the unnamed package ++ if (proxyPkg == null) { ++ // if no non-public proxy interfaces, use sun.proxy package ++ proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; + } + + { +@@ -595,22 +706,45 @@ public class Proxy implements java.io.Se + /* + * Look up or generate the designated proxy class. + */ +- Class cl = getProxyClass(loader, interfaces); ++ Class<?> cl = getProxyClass0(loader, interfaces); // stack walk magic: do not refactor + + /* + * Invoke its constructor with the designated invocation handler. + */ + try { +- Constructor cons = cl.getConstructor(constructorParams); +- return (Object) cons.newInstance(new Object[] { h }); ++ final Constructor<?> cons = cl.getConstructor(constructorParams); ++ final InvocationHandler ih = h; ++ SecurityManager sm = System.getSecurityManager(); ++ if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { ++ // create proxy instance with doPrivilege as the proxy class may ++ // implement non-public interfaces that requires a special permission ++ return AccessController.doPrivileged(new PrivilegedAction<Object>() { ++ public Object run() { ++ return newInstance(cons, ih); ++ } ++ }); ++ } else { ++ return newInstance(cons, ih); ++ } + } catch (NoSuchMethodException e) { + throw new InternalError(e.toString()); ++ } ++ } ++ ++ private static Object newInstance(Constructor<?> cons, InvocationHandler h) { ++ try { ++ return cons.newInstance(new Object[] {h} ); + } catch (IllegalAccessException e) { + throw new InternalError(e.toString()); + } catch (InstantiationException e) { + throw new InternalError(e.toString()); + } catch (InvocationTargetException e) { +- throw new InternalError(e.toString()); ++ Throwable t = e.getCause(); ++ if (t instanceof RuntimeException) { ++ throw (RuntimeException) t; ++ } else { ++ throw new InternalError(t.toString()); ++ } + } + } + +diff --git a/src/share/classes/sun/reflect/misc/ReflectUtil.java b/src/share/classes/sun/reflect/misc/ReflectUtil.java +--- jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java ++++ jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -144,4 +144,63 @@ public final class ReflectUtil { + } + return true; + } ++ ++ // Returns true if p is an ancestor of cl i.e. class loader 'p' can ++ // be found in the cl's delegation chain ++ private static boolean isAncestor(ClassLoader p, ClassLoader cl) { ++ ClassLoader acl = cl; ++ do { ++ acl = acl.getParent(); ++ if (p == acl) { ++ return true; ++ } ++ } while (acl != null); ++ return false; ++ } ++ ++ /** ++ * Returns true if package access check is needed for reflective ++ * access from a class loader 'from' to classes or members in ++ * a class defined by class loader 'to'. This method returns true ++ * if 'from' is not the same as or an ancestor of 'to'. All code ++ * in a system domain are granted with all permission and so this ++ * method returns false if 'from' class loader is a class loader ++ * loading system classes. On the other hand, if a class loader ++ * attempts to access system domain classes, it requires package ++ * access check and this method will return true. ++ */ ++ public static boolean needsPackageAccessCheck(ClassLoader from, ClassLoader to) { ++ if (from == null || from == to) ++ return false; ++ ++ if (to == null) ++ return true; ++ ++ return !isAncestor(from, to); ++ } ++ ++ /** ++ * Access check on the interfaces that a proxy class implements and throw ++ * {@code SecurityException} if it accesses a restricted package. ++ * ++ * @param ccl the caller's class loader ++ * @param interfaces the list of interfaces that a proxy class implements ++ * ++ * @see Proxy#checkProxyAccess ++ */ ++ public static void checkProxyPackageAccess(ClassLoader ccl, ++ Class<?>... interfaces) ++ { ++ SecurityManager sm = System.getSecurityManager(); ++ if (sm != null) { ++ for (Class<?> intf : interfaces) { ++ ClassLoader cl = intf.getClassLoader(); ++ if (needsPackageAccessCheck(ccl, cl)) { ++ checkPackageAccess(intf); ++ } ++ } ++ } ++ } ++ ++ public static final String PROXY_PACKAGE = "sun.proxy"; + } diff --git a/java/openjdk6/files/icedtea/security/20130201/7200491.patch b/java/openjdk6/files/icedtea/security/20130201/7200491.patch new file mode 100644 index 000000000000..c8bfbf50eb27 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7200491.patch @@ -0,0 +1,49 @@ +# HG changeset patch +# User rupashka +# Date 1352203457 -14400 +# Node ID ac55f56db9ab0280853c4a6bfbdc2c578027f9f2 +# Parent 6deb10c2d5d0c8925fd2012d9fc3b9325c997f21 +7200491: Tighten up JTable layout code +Reviewed-by: art, skoivu + +diff --git a/src/share/classes/com/sun/java/swing/plaf/nimbus/NimbusLookAndFeel.java b/src/share/classes/com/sun/java/swing/plaf/nimbus/NimbusLookAndFeel.java +--- jdk/src/share/classes/com/sun/java/swing/plaf/nimbus/NimbusLookAndFeel.java ++++ jdk/src/share/classes/com/sun/java/swing/plaf/nimbus/NimbusLookAndFeel.java +@@ -159,7 +159,12 @@ public class NimbusLookAndFeel extends S + + // Store Table ScrollPane Corner Component + uiDefaults.put("Table.scrollPaneCornerComponent", +- TableScrollPaneCorner.class); ++ new UIDefaults.ActiveValue() { ++ @Override ++ public Object createValue(UIDefaults table) { ++ return new TableScrollPaneCorner(); ++ } ++ }); + + // Setup the settings for ToolBarSeparator which is custom + // installed for Nimbus +diff --git a/src/share/classes/javax/swing/JTable.java b/src/share/classes/javax/swing/JTable.java +--- jdk/src/share/classes/javax/swing/JTable.java ++++ jdk/src/share/classes/javax/swing/JTable.java +@@ -777,15 +777,11 @@ public class JTable extends JComponent i + scrollPane.getCorner(JScrollPane.UPPER_TRAILING_CORNER); + if (corner == null || corner instanceof UIResource){ + corner = null; +- Object componentClass = UIManager.get( +- "Table.scrollPaneCornerComponent"); +- if (componentClass instanceof Class){ +- try { +- corner = (Component) +- ((Class)componentClass).newInstance(); +- } catch (Exception e) { +- // just ignore and don't set corner +- } ++ try { ++ corner = (Component) UIManager.get( ++ "Table.scrollPaneCornerComponent"); ++ } catch (Exception e) { ++ // just ignore and don't set corner + } + scrollPane.setCorner(JScrollPane.UPPER_TRAILING_CORNER, + corner); diff --git a/java/openjdk6/files/icedtea/security/20130201/7200500.patch b/java/openjdk6/files/icedtea/security/20130201/7200500.patch new file mode 100644 index 000000000000..20106060ee3b --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7200500.patch @@ -0,0 +1,60 @@ +# HG changeset patch +# User coffeys +# Date 1353019348 0 +# Node ID 27bb245457d801fab2a5a835e42a4adefdf7ce85 +# Parent 46582c3c96b3fdd43b58761c3869ce55fad1c755 +7200500: Launcher better input validation +Reviewed-by: ksrini + +diff --git a/src/share/bin/parse_manifest.c b/src/share/bin/parse_manifest.c +--- jdk/src/share/bin/parse_manifest.c ++++ jdk/src/share/bin/parse_manifest.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -487,9 +487,9 @@ JLI_ParseManifest(char *jarfile, manifes + #ifdef O_BINARY + | O_BINARY /* use binary mode on windows */ + #endif +- )) == -1) ++ )) == -1) { + return (-1); +- ++ } + info->manifest_version = NULL; + info->main_class = NULL; + info->jre_version = NULL; +@@ -536,12 +536,14 @@ JLI_JarUnpackFile(const char *jarfile, c + zentry entry; + void *data = NULL; + +- fd = open(jarfile, O_RDONLY ++ if ((fd = open(jarfile, O_RDONLY + #ifdef O_BINARY + | O_BINARY /* use binary mode on windows */ + #endif +- ); +- if (fd != -1 && find_file(fd, &entry, filename) == 0) { ++ )) == -1) { ++ return NULL; ++ } ++ if (find_file(fd, &entry, filename) == 0) { + data = inflate_file(fd, &entry, size); + } + close(fd); +@@ -583,9 +585,9 @@ JLI_ManifestIterate(const char *jarfile, + #ifdef O_BINARY + | O_BINARY /* use binary mode on windows */ + #endif +- )) == -1) ++ )) == -1) { + return (-1); +- ++ } + if (rc = find_file(fd, &entry, manifest_name) != 0) { + close(fd); + return (-2); diff --git a/java/openjdk6/files/icedtea/security/20130201/7201064.patch b/java/openjdk6/files/icedtea/security/20130201/7201064.patch new file mode 100644 index 000000000000..3ab97af24fc9 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7201064.patch @@ -0,0 +1,117 @@ +diff --git a/src/share/classes/java/awt/Dialog.java b/src/share/classes/java/awt/Dialog.java +--- jdk/src/share/classes/java/awt/Dialog.java ++++ jdk/src/share/classes/java/awt/Dialog.java +@@ -34,6 +34,7 @@ import java.security.PrivilegedAction; + import java.security.PrivilegedAction; + import javax.accessibility.*; + import sun.awt.AppContext; ++import java.security.AccessControlException; + import sun.awt.SunToolkit; + import sun.awt.PeerEvent; + import sun.awt.util.IdentityArrayList; +@@ -127,6 +128,8 @@ public class Dialog extends Window { + * @since 1.4 + */ + boolean undecorated = false; ++ ++ private transient boolean initialized = false; + + /** + * Modal dialogs block all input to some top-level windows. +@@ -679,6 +682,7 @@ public class Dialog extends Window { + this.title = title; + setModalityType(modalityType); + SunToolkit.checkAndSetPolicy(this, false); ++ initialized = true; + } + + /** +@@ -730,6 +734,7 @@ public class Dialog extends Window { + this.title = title; + setModalityType(modalityType); + SunToolkit.checkAndSetPolicy(this, false); ++ initialized = true; + } + + /** +@@ -859,12 +864,9 @@ public class Dialog extends Window { + if (modalityType == type) { + return; + } +- if (type == ModalityType.TOOLKIT_MODAL) { +- SecurityManager sm = System.getSecurityManager(); +- if (sm != null) { +- sm.checkPermission(SecurityConstants.TOOLKIT_MODALITY_PERMISSION); +- } +- } ++ ++ checkModalityPermission(type); ++ + modalityType = type; + modal = (modalityType != ModalityType.MODELESS); + } +@@ -1039,6 +1041,11 @@ public class Dialog extends Window { + */ + @Deprecated + public void show() { ++ if (!initialized) { ++ throw new IllegalStateException("The dialog component " + ++ "has not been initialized properly"); ++ } ++ + beforeFirstShow = false; + if (!isModal()) { + conditionalShow(null, null); +@@ -1614,18 +1621,50 @@ public class Dialog extends Window { + } + } + ++ private void checkModalityPermission(ModalityType mt) { ++ if (mt == ModalityType.TOOLKIT_MODAL) { ++ SecurityManager sm = System.getSecurityManager(); ++ if (sm != null) { ++ sm.checkPermission( ++ SecurityConstants.TOOLKIT_MODALITY_PERMISSION ++ ); ++ } ++ } ++ } ++ + private void readObject(ObjectInputStream s) + throws ClassNotFoundException, IOException, HeadlessException + { + GraphicsEnvironment.checkHeadless(); +- s.defaultReadObject(); ++ ++ java.io.ObjectInputStream.GetField fields = ++ s.readFields(); ++ ++ ModalityType localModalityType = (ModalityType)fields.get("modalityType", null); ++ ++ try { ++ checkModalityPermission(localModalityType); ++ } catch (AccessControlException ace) { ++ localModalityType = DEFAULT_MODALITY_TYPE; ++ } + + // in 1.5 or earlier modalityType was absent, so use "modal" instead +- if (modalityType == null) { ++ if (localModalityType == null) { ++ this.modal = fields.get("modal", false); + setModal(modal); + } + ++ this.resizable = fields.get("resizable", true); ++ this.undecorated = fields.get("undecorated", false); ++ this.title = (String)fields.get("title", ""); ++ this.modalityType = localModalityType; ++ + blockedWindows = new IdentityArrayList(); ++ ++ SunToolkit.checkAndSetPolicy(this, false); ++ ++ initialized = true; ++ + } + + /* diff --git a/java/openjdk6/files/icedtea/security/20130201/7201066.patch b/java/openjdk6/files/icedtea/security/20130201/7201066.patch new file mode 100644 index 000000000000..2a38f116a6f0 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7201066.patch @@ -0,0 +1,66 @@ +# HG changeset patch +# User coffeys +# Date 1352217014 0 +# Node ID 58fdb67fcacc67693fc43b5601e88bd7c216f850 +# Parent 42b1142b39b5a511e1e07b5877cc55e93767064e +7201066: Change modifiers on unused fields +Reviewed-by: alanb, skoivu + +diff --git a/src/share/classes/com/sun/corba/se/impl/activation/ServerMain.java b/src/share/classes/com/sun/corba/se/impl/activation/ServerMain.java +--- corba/src/share/classes/com/sun/corba/se/impl/activation/ServerMain.java ++++ corba/src/share/classes/com/sun/corba/se/impl/activation/ServerMain.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -322,9 +322,9 @@ class ServerCallback extends + com.sun.corba.se.spi.activation._ServerImplBase + { + private ORB orb; +- private Method installMethod ; +- private Method uninstallMethod ; +- private Method shutdownMethod ; ++ private transient Method installMethod ; ++ private transient Method uninstallMethod ; ++ private transient Method shutdownMethod ; + private Object methodArgs[] ; + + ServerCallback(ORB orb, Method installMethod, Method uninstallMethod, +diff --git a/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java b/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java +--- corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java ++++ corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java +@@ -1536,8 +1536,8 @@ public class ObjectStreamClass implement + private boolean hasExternalizableBlockData; + Method writeObjectMethod; + Method readObjectMethod; +- private Method writeReplaceObjectMethod; +- private Method readResolveObjectMethod; ++ private transient Method writeReplaceObjectMethod; ++ private transient Method readResolveObjectMethod; + private Constructor cons ; + + /** +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClass_1_3_1.java b/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClass_1_3_1.java +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClass_1_3_1.java ++++ corba/src/share/classes/com/sun/corba/se/impl/orbutil/ObjectStreamClass_1_3_1.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -1119,8 +1119,8 @@ public class ObjectStreamClass_1_3_1 imp + private boolean hasExternalizableBlockData; + Method writeObjectMethod; + Method readObjectMethod; +- private Method writeReplaceObjectMethod; +- private Method readResolveObjectMethod; ++ private transient Method writeReplaceObjectMethod; ++ private transient Method readResolveObjectMethod; + + /* + * ObjectStreamClass_1_3_1 that this one was built from. diff --git a/java/openjdk6/files/icedtea/security/20130201/7201068.patch b/java/openjdk6/files/icedtea/security/20130201/7201068.patch new file mode 100644 index 000000000000..a9e9e7f859ad --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7201068.patch @@ -0,0 +1,83 @@ +# HG changeset patch +# User coffeys +# Date 1352286387 0 +# Node ID 6e2d4ed84b41667df189abb7bd0915cda01a85a0 +# Parent ac55f56db9ab0280853c4a6bfbdc2c578027f9f2 +7201068: Better handling of UI elements +Reviewed-by: mullan, skoivu + +diff --git a/src/share/lib/security/java.security b/src/share/lib/security/java.security +--- jdk/src/share/lib/security/java.security ++++ jdk/src/share/lib/security/java.security +@@ -127,7 +127,9 @@ system.scope=sun.security.provider.Ident + # passed to checkPackageAccess unless the + # corresponding RuntimePermission ("accessClassInPackage."+package) has + # been granted. +-package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio. ++package.access=sun.,\ ++ com.sun.xml.internal.,\ ++ com.sun.imageio. + + # + # List of comma-separated packages that start with or equal this string +@@ -139,7 +141,9 @@ package.access=sun.,com.sun.xml.internal + # by default, none of the class loaders supplied with the JDK call + # checkPackageDefinition. + # +-package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio. ++package.definition=sun.,\ ++ com.sun.xml.internal.,\ ++ com.sun.imageio. + + # + # Determines whether this properties file can be appended to +diff --git a/src/share/lib/security/java.security-solaris b/src/share/lib/security/java.security-solaris +--- jdk/src/share/lib/security/java.security-solaris ++++ jdk/src/share/lib/security/java.security-solaris +@@ -128,7 +128,9 @@ system.scope=sun.security.provider.Ident + # passed to checkPackageAccess unless the + # corresponding RuntimePermission ("accessClassInPackage."+package) has + # been granted. +-package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio. ++package.access=sun.,\ ++ com.sun.xml.internal.,\ ++ com.sun.imageio. + + # + # List of comma-separated packages that start with or equal this string +@@ -140,7 +142,9 @@ package.access=sun.,com.sun.xml.internal + # by default, none of the class loaders supplied with the JDK call + # checkPackageDefinition. + # +-package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio. ++package.definition=sun.,\ ++ com.sun.xml.internal.,\ ++ com.sun.imageio. + + # + # Determines whether this properties file can be appended to +diff --git a/src/share/lib/security/java.security-windows b/src/share/lib/security/java.security-windows +--- jdk/src/share/lib/security/java.security-windows ++++ jdk/src/share/lib/security/java.security-windows +@@ -128,7 +128,9 @@ system.scope=sun.security.provider.Ident + # passed to checkPackageAccess unless the + # corresponding RuntimePermission ("accessClassInPackage."+package) has + # been granted. +-package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio. ++package.access=sun.,\ ++ com.sun.xml.internal.,\ ++ com.sun.imageio. + + # + # List of comma-separated packages that start with or equal this string +@@ -140,7 +142,9 @@ package.access=sun.,com.sun.xml.internal + # by default, none of the class loaders supplied with the JDK call + # checkPackageDefinition. + # +-package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio. ++package.definition=sun.,\ ++ com.sun.xml.internal.,\ ++ com.sun.imageio. + + # + # Determines whether this properties file can be appended to diff --git a/java/openjdk6/files/icedtea/security/20130201/7201070.patch b/java/openjdk6/files/icedtea/security/20130201/7201070.patch new file mode 100644 index 000000000000..77df21d28374 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7201070.patch @@ -0,0 +1,31 @@ +# HG changeset patch +# User coffeys +# Date 1355322673 0 +# Node ID 042882b32f75d0e736c19f93688d37fb98d7d26d +# Parent 708c134c36312faf8721c0c981be6553e4ebf49f +7201070: Serialization to conform to protocol +Reviewed-by: smarks, skoivu + +diff --git a/src/share/classes/java/io/ObjectInputStream.java b/src/share/classes/java/io/ObjectInputStream.java +--- jdk/src/share/classes/java/io/ObjectInputStream.java ++++ jdk/src/share/classes/java/io/ObjectInputStream.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -1749,6 +1749,12 @@ public class ObjectInputStream + ObjectStreamClass desc = readClassDesc(false); + desc.checkDeserialize(); + ++ Class<?> cl = desc.forClass(); ++ if (cl == String.class || cl == Class.class ++ || cl == ObjectStreamClass.class) { ++ throw new InvalidClassException("invalid class descriptor"); ++ } ++ + Object obj; + try { + obj = desc.isInstantiable() ? desc.newInstance() : null; diff --git a/java/openjdk6/files/icedtea/security/20130201/7201071.patch b/java/openjdk6/files/icedtea/security/20130201/7201071.patch new file mode 100644 index 000000000000..58329d174c3a --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/7201071.patch @@ -0,0 +1,553 @@ +# HG changeset patch +# User robm +# Date 1352819613 0 +# Node ID 46582c3c96b3fdd43b58761c3869ce55fad1c755 +# Parent ee4632a30696050ebd5c014fb3da64112ab48dd3 +7201071: InetSocketAddress serialization issue +Reviewed-by: chegar + +diff --git a/src/share/classes/java/net/InetSocketAddress.java b/src/share/classes/java/net/InetSocketAddress.java +--- jdk/src/share/classes/java/net/InetSocketAddress.java ++++ jdk/src/share/classes/java/net/InetSocketAddress.java +@@ -24,9 +24,12 @@ + */ + package java.net; + +-import java.io.ObjectInputStream; + import java.io.IOException; + import java.io.InvalidObjectException; ++import java.io.ObjectInputStream; ++import java.io.ObjectOutputStream; ++import java.io.ObjectStreamException; ++import java.io.ObjectStreamField; + + /** + * +@@ -46,24 +49,106 @@ import java.io.InvalidObjectException; + * @see java.net.ServerSocket + * @since 1.4 + */ +-public class InetSocketAddress extends SocketAddress { +- /* The hostname of the Socket Address +- * @serial +- */ +- private String hostname = null; +- /* The IP address of the Socket Address +- * @serial +- */ +- private InetAddress addr = null; +- /* The port number of the Socket Address +- * @serial +- */ +- private int port; ++public class InetSocketAddress ++ extends SocketAddress ++{ ++ // Private implementation class pointed to by all public methods. ++ private static class InetSocketAddressHolder { ++ // The hostname of the Socket Address ++ private String hostname; ++ // The IP address of the Socket Address ++ private InetAddress addr; ++ // The port number of the Socket Address ++ private int port; ++ ++ private InetSocketAddressHolder(String hostname, InetAddress addr, int port) { ++ this.hostname = hostname; ++ this.addr = addr; ++ this.port = port; ++ } ++ ++ private int getPort() { ++ return port; ++ } ++ ++ private InetAddress getAddress() { ++ return addr; ++ } ++ ++ private String getHostName() { ++ if (hostname != null) ++ return hostname; ++ if (addr != null) ++ return addr.getHostName(); ++ return null; ++ } ++ ++ private String getHostString() { ++ if (hostname != null) ++ return hostname; ++ if (addr != null) { ++ if (addr.hostName != null) ++ return addr.hostName; ++ else ++ return addr.getHostAddress(); ++ } ++ return null; ++ } ++ ++ private boolean isUnresolved() { ++ return addr == null; ++ } ++ ++ @Override ++ public String toString() { ++ if (isUnresolved()) { ++ return hostname + ":" + port; ++ } else { ++ return addr.toString() + ":" + port; ++ } ++ } ++ ++ @Override ++ public final boolean equals(Object obj) { ++ if (obj == null || !(obj instanceof InetSocketAddressHolder)) ++ return false; ++ InetSocketAddressHolder that = (InetSocketAddressHolder)obj; ++ boolean sameIP; ++ if (addr != null) ++ sameIP = addr.equals(that.addr); ++ else if (hostname != null) ++ sameIP = (that.addr == null) && ++ hostname.equalsIgnoreCase(that.hostname); ++ else ++ sameIP = (that.addr == null) && (that.hostname == null); ++ return sameIP && (port == that.port); ++ } ++ ++ @Override ++ public final int hashCode() { ++ if (addr != null) ++ return addr.hashCode() + port; ++ if (hostname != null) ++ return hostname.toLowerCase().hashCode() + port; ++ return port; ++ } ++ } ++ ++ private final transient InetSocketAddressHolder holder; + + private static final long serialVersionUID = 5076001401234631237L; + +- private InetSocketAddress() { ++ private static int checkPort(int port) { ++ if (port < 0 || port > 0xFFFF) ++ throw new IllegalArgumentException("port out of range:" + port); ++ return port; + } ++ ++ private static String checkHost(String hostname) { ++ if (hostname == null) ++ throw new IllegalArgumentException("hostname can't be null"); ++ return hostname; ++ } + + /** + * Creates a socket address where the IP address is the wildcard address +@@ -97,14 +182,10 @@ public class InetSocketAddress extends S + * range of valid port values. + */ + public InetSocketAddress(InetAddress addr, int port) { +- if (port < 0 || port > 0xFFFF) { +- throw new IllegalArgumentException("port out of range:" + port); +- } +- this.port = port; +- if (addr == null) +- this.addr = InetAddress.anyLocalAddress(); +- else +- this.addr = addr; ++ holder = new InetSocketAddressHolder( ++ null, ++ addr == null ? InetAddress.anyLocalAddress() : addr, ++ checkPort(port)); + } + + /** +@@ -132,19 +213,20 @@ public class InetSocketAddress extends S + * @see #isUnresolved() + */ + public InetSocketAddress(String hostname, int port) { +- if (port < 0 || port > 0xFFFF) { +- throw new IllegalArgumentException("port out of range:" + port); +- } +- if (hostname == null) { +- throw new IllegalArgumentException("hostname can't be null"); +- } ++ checkHost(hostname); ++ InetAddress addr = null; ++ String host = null; + try { + addr = InetAddress.getByName(hostname); + } catch(UnknownHostException e) { +- this.hostname = hostname; +- addr = null; ++ host = hostname; + } +- this.port = port; ++ holder = new InetSocketAddressHolder(host, addr, checkPort(port)); ++ } ++ ++ // private constructor for creating unresolved instances ++ private InetSocketAddress(int port, String hostname) { ++ holder = new InetSocketAddressHolder(hostname, null, port); + } + + /** +@@ -169,31 +251,67 @@ public class InetSocketAddress extends S + * @since 1.5 + */ + public static InetSocketAddress createUnresolved(String host, int port) { +- if (port < 0 || port > 0xFFFF) { +- throw new IllegalArgumentException("port out of range:" + port); +- } +- if (host == null) { +- throw new IllegalArgumentException("hostname can't be null"); +- } +- InetSocketAddress s = new InetSocketAddress(); +- s.port = port; +- s.hostname = host; +- s.addr = null; +- return s; ++ return new InetSocketAddress(checkPort(port), checkHost(host)); ++ } ++ ++ /** ++ * @serialField hostname String ++ * @serialField addr InetAddress ++ * @serialField port int ++ */ ++ private static final ObjectStreamField[] serialPersistentFields = { ++ new ObjectStreamField("hostname", String.class), ++ new ObjectStreamField("addr", InetAddress.class), ++ new ObjectStreamField("port", int.class)}; ++ ++ private void writeObject(ObjectOutputStream out) ++ throws IOException ++ { ++ // Don't call defaultWriteObject() ++ ObjectOutputStream.PutField pfields = out.putFields(); ++ pfields.put("hostname", holder.hostname); ++ pfields.put("addr", holder.addr); ++ pfields.put("port", holder.port); ++ out.writeFields(); + } + +- private void readObject(ObjectInputStream s) +- throws IOException, ClassNotFoundException { +- s.defaultReadObject(); ++ private void readObject(ObjectInputStream in) ++ throws IOException, ClassNotFoundException ++ { ++ // Don't call defaultReadObject() ++ ObjectInputStream.GetField oisFields = in.readFields(); ++ final String oisHostname = (String)oisFields.get("hostname", null); ++ final InetAddress oisAddr = (InetAddress)oisFields.get("addr", null); ++ final int oisPort = oisFields.get("port", -1); + + // Check that our invariants are satisfied +- if (port < 0 || port > 0xFFFF) { +- throw new InvalidObjectException("port out of range:" + port); +- } +- +- if (hostname == null && addr == null) { ++ checkPort(oisPort); ++ if (oisHostname == null && oisAddr == null) + throw new InvalidObjectException("hostname and addr " + + "can't both be null"); ++ ++ InetSocketAddressHolder h = new InetSocketAddressHolder(oisHostname, ++ oisAddr, ++ oisPort); ++ UNSAFE.putObject(this, FIELDS_OFFSET, h); ++ } ++ ++ private void readObjectNoData() ++ throws ObjectStreamException ++ { ++ throw new InvalidObjectException("Stream data required"); ++ } ++ ++ private static final long FIELDS_OFFSET; ++ private static final sun.misc.Unsafe UNSAFE; ++ static { ++ try { ++ sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); ++ FIELDS_OFFSET = unsafe.objectFieldOffset( ++ InetSocketAddress.class.getDeclaredField("holder")); ++ UNSAFE = unsafe; ++ } catch (NoSuchFieldException e) { ++ throw new Error(e); + } + } + +@@ -203,7 +321,7 @@ public class InetSocketAddress extends S + * @return the port number. + */ + public final int getPort() { +- return port; ++ return holder.getPort(); + } + + /** +@@ -213,7 +331,7 @@ public class InetSocketAddress extends S + * @return the InetAdress or <code>null</code> if it is unresolved. + */ + public final InetAddress getAddress() { +- return addr; ++ return holder.getAddress(); + } + + /** +@@ -222,11 +340,7 @@ public class InetSocketAddress extends S + * @return the hostname part of the address. + */ + public final String getHostName() { +- if (hostname != null) +- return hostname; +- if (addr != null) +- return addr.getHostName(); +- return null; ++ return holder.getHostName(); + } + + /** +@@ -238,15 +352,7 @@ public class InetSocketAddress extends S + * @since 1.6 + */ + final String getHostString() { +- if (hostname != null) +- return hostname; +- if (addr != null) { +- if (addr.hostName != null) +- return addr.hostName; +- else +- return addr.getHostAddress(); +- } +- return null; ++ return holder.getHostString(); + } + + /** +@@ -256,7 +362,7 @@ public class InetSocketAddress extends S + * an <code>InetAddress</code>. + */ + public final boolean isUnresolved() { +- return addr == null; ++ return holder.isUnresolved(); + } + + /** +@@ -267,12 +373,9 @@ public class InetSocketAddress extends S + * + * @return a string representation of this object. + */ ++ @Override + public String toString() { +- if (isUnresolved()) { +- return hostname + ":" + port; +- } else { +- return addr.toString() + ":" + port; +- } ++ return holder.toString(); + } + + /** +@@ -295,16 +398,7 @@ public class InetSocketAddress extends S + public final boolean equals(Object obj) { + if (obj == null || !(obj instanceof InetSocketAddress)) + return false; +- InetSocketAddress sockAddr = (InetSocketAddress) obj; +- boolean sameIP = false; +- if (this.addr != null) +- sameIP = this.addr.equals(sockAddr.addr); +- else if (this.hostname != null) +- sameIP = (sockAddr.addr == null) && +- this.hostname.equals(sockAddr.hostname); +- else +- sameIP = (sockAddr.addr == null) && (sockAddr.hostname == null); +- return sameIP && (this.port == sockAddr.port); ++ return holder.equals(((InetSocketAddress) obj).holder); + } + + /** +@@ -312,11 +406,8 @@ public class InetSocketAddress extends S + * + * @return a hash code value for this socket address. + */ ++ @Override + public final int hashCode() { +- if (addr != null) +- return addr.hashCode() + port; +- if (hostname != null) +- return hostname.hashCode() + port; +- return port; ++ return holder.hashCode(); + } + } +diff --git a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java +--- jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java ++++ jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java +@@ -239,7 +239,7 @@ class DatagramChannelImpl + + synchronized (writeLock) { + ensureOpen(); +- InetSocketAddress isa = (InetSocketAddress)target; ++ InetSocketAddress isa = Net.checkAddress(target); + InetAddress ia = isa.getAddress(); + if (ia == null) + throw new IOException("Target address not resolved"); +@@ -250,9 +250,9 @@ class DatagramChannelImpl + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (ia.isMulticastAddress()) { +- sm.checkMulticast(isa.getAddress()); ++ sm.checkMulticast(ia); + } else { +- sm.checkConnect(isa.getAddress().getHostAddress(), ++ sm.checkConnect(ia.getHostAddress(), + isa.getPort()); + } + } +@@ -272,7 +272,7 @@ class DatagramChannelImpl + return 0; + writerThread = NativeThread.current(); + do { +- n = send(fd, src, target); ++ n = send(fd, src, isa); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + return IOStatus.normalize(n); + } finally { +@@ -283,7 +283,7 @@ class DatagramChannelImpl + } + } + +- private int send(FileDescriptor fd, ByteBuffer src, SocketAddress target) ++ private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target) + throws IOException + { + if (src instanceof DirectBuffer) +@@ -315,7 +315,7 @@ class DatagramChannelImpl + } + + private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, +- SocketAddress target) ++ InetSocketAddress target) + throws IOException + { + int pos = bb.position(); +@@ -324,7 +324,7 @@ class DatagramChannelImpl + int rem = (pos <= lim ? lim - pos : 0); + + int written = send0(fd, ((DirectBuffer)bb).address() + pos, +- rem, target); ++ rem, target.getAddress(), target.getPort()); + if (written > 0) + bb.position(pos + written); + return written; +@@ -703,8 +703,8 @@ class DatagramChannelImpl + boolean connected) + throws IOException; + +- private native int send0(FileDescriptor fd, long address, int len, +- SocketAddress sa) ++ private native int send0(FileDescriptor fd, long address, ++ int len, InetAddress addr, int port) + throws IOException; + + static { +diff --git a/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c b/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c +--- jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c ++++ jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c +@@ -46,8 +46,6 @@ + + #include "sun_nio_ch_DatagramChannelImpl.h" + +-static jfieldID isa_addrID; /* address in java.net.InetSocketAddress */ +-static jfieldID isa_portID; /* port in java.net.InetSocketAddress */ + static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */ + static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */ + static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */ +@@ -61,9 +59,6 @@ Java_sun_nio_ch_DatagramChannelImpl_init + isa_class = (*env)->NewGlobalRef(env, clazz); + isa_ctorID = (*env)->GetMethodID(env, clazz, "<init>", + "(Ljava/net/InetAddress;I)V"); +- isa_addrID = (*env)->GetFieldID(env, clazz, "addr", +- "Ljava/net/InetAddress;"); +- isa_portID = (*env)->GetFieldID(env, clazz, "port", "I"); + + clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl"); + dci_senderID = (*env)->GetFieldID(env, clazz, "sender", +@@ -198,16 +193,15 @@ Java_sun_nio_ch_DatagramChannelImpl_rece + + JNIEXPORT jint JNICALL + Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this, +- jobject fdo, jlong address, +- jint len, jobject dest) ++ jobject fdo, jlong address, ++ jint len, jobject destAddress, ++ jint destPort) + { + jint fd = fdval(env, fdo); + void *buf = (void *)jlong_to_ptr(address); + SOCKADDR sa; + int sa_len = SOCKADDR_LEN; + jint n = 0; +- jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID); +- jint destPort = (*env)->GetIntField(env, dest, isa_portID); + + if (len > MAX_PACKET_LEN) { + len = MAX_PACKET_LEN; +diff --git a/src/windows/native/sun/nio/ch/DatagramChannelImpl.c b/src/windows/native/sun/nio/ch/DatagramChannelImpl.c +--- jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c ++++ jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c +@@ -34,8 +34,6 @@ + #include "net_util.h" + #include <winsock2.h> + +-static jfieldID isa_addrID; /* address in java.net.InetSocketAddress */ +-static jfieldID isa_portID; /* port in java.net.InetSocketAddress */ + static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */ + static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */ + static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */ +@@ -87,9 +85,6 @@ Java_sun_nio_ch_DatagramChannelImpl_init + isa_class = (*env)->NewGlobalRef(env, clazz); + isa_ctorID = (*env)->GetMethodID(env, clazz, "<init>", + "(Ljava/net/InetAddress;I)V"); +- isa_addrID = (*env)->GetFieldID(env, clazz, "addr", +- "Ljava/net/InetAddress;"); +- isa_portID = (*env)->GetFieldID(env, clazz, "port", "I"); + + clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl"); + dci_senderID = (*env)->GetFieldID(env, clazz, "sender", +@@ -268,17 +263,14 @@ Java_sun_nio_ch_DatagramChannelImpl_rece + + JNIEXPORT jint JNICALL + Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this, +- jobject fdo, jlong address, +- jint len, jobject dest) ++ jobject fdo, jlong address, jint len, ++ jobject destAddress, jint destPort) + { + jint fd = fdval(env, fdo); + void *buf = (void *)jlong_to_ptr(address); + SOCKETADDRESS psa; + int sa_len = sizeof(psa); + jint rv = 0; +- jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID); +- jint destPort = (*env)->GetIntField(env, dest, isa_portID); +- + + if (NET_InetAddressToSockaddr(env, destAddress, destPort, + (struct sockaddr *)&psa, +diff --git a/test/java/nio/channels/DatagramChannel/SendToUnresolved.java b/test/java/nio/channels/DatagramChannel/SendToUnresolved.java +--- jdk/test/java/nio/channels/DatagramChannel/SendToUnresolved.java ++++ jdk/test/java/nio/channels/DatagramChannel/SendToUnresolved.java +@@ -44,6 +44,8 @@ public class SendToUnresolved { + throw new RuntimeException("Expected exception not thrown"); + } catch (IOException e) { + // Correct result ++ } catch (UnresolvedAddressException e) { ++ // Correct result + } + dc.close(); + } diff --git a/java/openjdk6/files/icedtea/security/20130201/8000210.patch b/java/openjdk6/files/icedtea/security/20130201/8000210.patch new file mode 100644 index 000000000000..28bcddfb2ab6 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/8000210.patch @@ -0,0 +1,104 @@ +# HG changeset patch +# User weijun +# Date 1350962115 -28800 +# Node ID 9c2a2aae44a46e0b63b913987672d1488fa4e7a5 +# Parent 6088f35106866940de257456c8eee21b130d5ff5 +8000210: Improve JarFile code quality +Reviewed-by: ahgross, xuelei, mschoene + +diff --git a/src/share/classes/java/util/jar/JarFile.java b/src/share/classes/java/util/jar/JarFile.java +--- jdk/src/share/classes/java/util/jar/JarFile.java ++++ jdk/src/share/classes/java/util/jar/JarFile.java +@@ -32,6 +32,7 @@ import java.security.CodeSigner; + import java.security.CodeSigner; + import java.security.cert.Certificate; + import java.security.AccessController; ++import sun.misc.IOUtils; + import sun.security.action.GetPropertyAction; + import sun.security.util.ManifestEntryVerifier; + import sun.misc.SharedSecrets; +@@ -326,6 +327,9 @@ class JarFile extends ZipFile { + if (names != null) { + for (int i = 0; i < names.length; i++) { + JarEntry e = getJarEntry(names[i]); ++ if (e == null) { ++ throw new JarException("corrupted jar file"); ++ } + if (!e.isDirectory()) { + if (mev == null) { + mev = new ManifestEntryVerifier +@@ -345,6 +349,10 @@ class JarFile extends ZipFile { + // treat the jar file as being unsigned + jv = null; + verify = false; ++ if (JarVerifier.debug != null) { ++ JarVerifier.debug.println("jarfile parsing error!"); ++ ex.printStackTrace(); ++ } + } + + // if after initializing the verifier we have nothing +@@ -372,9 +380,8 @@ class JarFile extends ZipFile { + * META-INF files. + */ + private byte[] getBytes(ZipEntry ze) throws IOException { +- byte[] b = new byte[(int)ze.getSize()]; +- DataInputStream is = new DataInputStream(super.getInputStream(ze)); +- is.readFully(b, 0, b.length); ++ InputStream is = super.getInputStream(ze); ++ byte[] b = IOUtils.readFully(is, (int)ze.getSize(), true); + is.close(); + return b; + } +@@ -476,12 +483,7 @@ class JarFile extends ZipFile { + if (!isKnownToNotHaveClassPathAttribute()) { + JarEntry manEntry = getManEntry(); + if (manEntry != null) { +- byte[] b = new byte[(int)manEntry.getSize()]; +- DataInputStream dis = new DataInputStream( +- super.getInputStream(manEntry)); +- dis.readFully(b, 0, b.length); +- dis.close(); +- ++ byte[] b = getBytes(manEntry); + int last = b.length - src.length; + int i = 0; + next: +diff --git a/src/share/classes/sun/security/util/DerIndefLenConverter.java b/src/share/classes/sun/security/util/DerIndefLenConverter.java +--- jdk/src/share/classes/sun/security/util/DerIndefLenConverter.java ++++ jdk/src/share/classes/sun/security/util/DerIndefLenConverter.java +@@ -50,6 +50,7 @@ class DerIndefLenConverter { + + private byte[] data, newData; + private int newDataPos, dataPos, dataSize, index; ++ private int unresolved = 0; + + private ArrayList<Object> ndefsList = new ArrayList<Object>(); + +@@ -113,6 +114,7 @@ class DerIndefLenConverter { + numOfEncapsulatedLenBytes; + byte[] sectionLenBytes = getLengthBytes(sectionLen); + ndefsList.set(index, sectionLenBytes); ++ unresolved--; + + // Add the number of bytes required to represent this section + // to the total number of length bytes, +@@ -149,6 +151,7 @@ class DerIndefLenConverter { + int lenByte = data[dataPos++] & 0xff; + if (isIndefinite(lenByte)) { + ndefsList.add(new Integer(dataPos)); ++ unresolved++; + return curLen; + } + if (isLongForm(lenByte)) { +@@ -316,6 +319,10 @@ class DerIndefLenConverter { + parseValue(len); + } + ++ if (unresolved != 0) { ++ throw new IOException("not all indef len BER resolved"); ++ } ++ + newData = new byte[dataSize + numOfTotalLenBytes]; + dataPos=0; newDataPos=0; index=0; + diff --git a/java/openjdk6/files/icedtea/security/20130201/8000537.patch b/java/openjdk6/files/icedtea/security/20130201/8000537.patch new file mode 100644 index 000000000000..8e7bb54a4644 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/8000537.patch @@ -0,0 +1,334 @@ +# HG changeset patch +# User ewendeli +# Date 1353844618 -3600 +# Node ID 21415f01c66add2891500f10e41c7e99b2b10447 +# Parent 787e9230b414f346f9c318918aaf58b872b9912e +8000537: Contextualize RequiredModelMBean class +Reviewed-by: jbachorik +Contributed-by: Andreas Eriksson <andreas.eriksson@oracle.com> + +diff --git a/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java b/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java +--- jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java ++++ jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -39,6 +39,9 @@ import java.lang.reflect.InvocationTarge + import java.lang.reflect.InvocationTargetException; + + import java.lang.reflect.Method; ++import java.security.AccessControlContext; ++import java.security.AccessController; ++import java.security.PrivilegedAction; + + import java.util.Date; + import java.util.HashMap; +@@ -77,6 +80,8 @@ import javax.management.RuntimeOperation + import javax.management.RuntimeOperationsException; + import javax.management.ServiceNotFoundException; + import javax.management.loading.ClassLoaderRepository; ++import sun.misc.JavaSecurityAccess; ++import sun.misc.SharedSecrets; + + import sun.reflect.misc.MethodUtil; + import sun.reflect.misc.ReflectUtil; +@@ -138,6 +143,9 @@ public class RequiredModelMBean + private boolean registered = false; + private transient MBeanServer server = null; + ++ private final static JavaSecurityAccess javaSecurityAccess = SharedSecrets.getJavaSecurityAccess(); ++ final private AccessControlContext acc = AccessController.getContext(); ++ + /*************************************/ + /* constructors */ + /*************************************/ +@@ -1025,10 +1033,30 @@ public class RequiredModelMBean + + if (opClassName != null) { + try { +- final ClassLoader targetClassLoader = +- targetObject.getClass().getClassLoader(); +- targetClass = Class.forName(opClassName, false, +- targetClassLoader); ++ AccessControlContext stack = AccessController.getContext(); ++ final Object obj = targetObject; ++ final String className = opClassName; ++ final ClassNotFoundException[] caughtException = new ClassNotFoundException[1]; ++ ++ targetClass = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() { ++ ++ public Class<?> run() { ++ try { ++ ReflectUtil.checkPackageAccess(className); ++ final ClassLoader targetClassLoader = ++ obj.getClass().getClassLoader(); ++ return Class.forName(className, false, ++ targetClassLoader); ++ } catch (ClassNotFoundException e) { ++ caughtException[0] = e; ++ } ++ return null; ++ } ++ }, stack, acc); ++ ++ if (caughtException[0] != null) { ++ throw caughtException[0]; ++ } + } catch (ClassNotFoundException e) { + final String msg = + "class for invoke " + opName + " not found"; +@@ -1061,9 +1090,9 @@ public class RequiredModelMBean + return result; + } + +- private static Method resolveMethod(Class<?> targetClass, ++ private Method resolveMethod(Class<?> targetClass, + String opMethodName, +- String[] sig) ++ final String[] sig) + throws ReflectionException { + final boolean tracing = MODELMBEAN_LOGGER.isLoggable(Level.FINER); + +@@ -1078,30 +1107,44 @@ public class RequiredModelMBean + if (sig == null) + argClasses = null; + else { ++ final AccessControlContext stack = AccessController.getContext(); ++ final ReflectionException[] caughtException = new ReflectionException[1]; + final ClassLoader targetClassLoader = targetClass.getClassLoader(); +- argClasses = new Class[sig.length]; +- for (int i = 0; i < sig.length; i++) { +- if (tracing) { +- MODELMBEAN_LOGGER.logp(Level.FINER, +- RequiredModelMBean.class.getName(),"resolveMethod", +- "resolve type " + sig[i]); +- } +- argClasses[i] = (Class) primitiveClassMap.get(sig[i]); +- if (argClasses[i] == null) { +- try { +- argClasses[i] = +- Class.forName(sig[i], false, targetClassLoader); +- } catch (ClassNotFoundException e) { ++ argClasses = new Class<?>[sig.length]; ++ ++ javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Void>() { ++ ++ public Void run() { ++ for (int i = 0; i < sig.length; i++) { + if (tracing) { + MODELMBEAN_LOGGER.logp(Level.FINER, +- RequiredModelMBean.class.getName(), +- "resolveMethod", +- "class not found"); ++ RequiredModelMBean.class.getName(),"resolveMethod", ++ "resolve type " + sig[i]); + } +- final String msg = "Parameter class not found"; +- throw new ReflectionException(e, msg); ++ argClasses[i] = (Class<?>) primitiveClassMap.get(sig[i]); ++ if (argClasses[i] == null) { ++ try { ++ ReflectUtil.checkPackageAccess(sig[i]); ++ argClasses[i] = ++ Class.forName(sig[i], false, targetClassLoader); ++ } catch (ClassNotFoundException e) { ++ if (tracing) { ++ MODELMBEAN_LOGGER.logp(Level.FINER, ++ RequiredModelMBean.class.getName(), ++ "resolveMethod", ++ "class not found"); ++ } ++ final String msg = "Parameter class not found"; ++ caughtException[0] = new ReflectionException(e, msg); ++ } ++ } + } ++ return null; + } ++ }, stack, acc); ++ ++ if (caughtException[0] != null) { ++ throw caughtException[0]; + } + } + +@@ -1133,7 +1177,7 @@ public class RequiredModelMBean + /* Find a method in RequiredModelMBean as determined by the given + parameters. Return null if there is none, or if the parameters + exclude using it. Called from invoke. */ +- private static Method findRMMBMethod(String opMethodName, ++ private Method findRMMBMethod(String opMethodName, + Object targetObjectField, + String opClassName, + String[] sig) { +@@ -1155,19 +1199,28 @@ public class RequiredModelMBean + if (opClassName == null) + targetClass = rmmbClass; + else { +- try { +- final ClassLoader targetClassLoader = +- rmmbClass.getClassLoader(); +- targetClass = Class.forName(opClassName, false, +- targetClassLoader); +- if (!rmmbClass.isAssignableFrom(targetClass)) +- return null; +- } catch (ClassNotFoundException e) { +- return null; +- } ++ AccessControlContext stack = AccessController.getContext(); ++ final String className = opClassName; ++ targetClass = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() { ++ ++ public Class<?> run() { ++ try { ++ ReflectUtil.checkPackageAccess(className); ++ final ClassLoader targetClassLoader = ++ rmmbClass.getClassLoader(); ++ Class clz = Class.forName(className, false, ++ targetClassLoader); ++ if (!rmmbClass.isAssignableFrom(clz)) ++ return null; ++ return clz; ++ } catch (ClassNotFoundException e) { ++ return null; ++ } ++ } ++ }, stack, acc); + } + try { +- return resolveMethod(targetClass, opMethodName, sig); ++ return targetClass != null ? resolveMethod(targetClass, opMethodName, sig) : null; + } catch (ReflectionException e) { + return null; + } +@@ -1177,12 +1231,34 @@ public class RequiredModelMBean + * Invoke the given method, and throw the somewhat unpredictable + * appropriate exception if the method itself gets an exception. + */ +- private Object invokeMethod(String opName, Method method, +- Object targetObject, Object[] opArgs) ++ private Object invokeMethod(String opName, final Method method, ++ final Object targetObject, final Object[] opArgs) + throws MBeanException, ReflectionException { + try { +- ReflectUtil.checkPackageAccess(method.getDeclaringClass()); +- return MethodUtil.invoke(method, targetObject, opArgs); ++ final Throwable[] caughtException = new Throwable[1]; ++ AccessControlContext stack = AccessController.getContext(); ++ Object rslt = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Object>() { ++ ++ public Object run() { ++ try { ++ ReflectUtil.checkPackageAccess(method.getDeclaringClass()); ++ return MethodUtil.invoke(method, targetObject, opArgs); ++ } catch (InvocationTargetException e) { ++ caughtException[0] = e; ++ } catch (IllegalAccessException e) { ++ caughtException[0] = e; ++ } ++ return null; ++ } ++ }, stack, acc); ++ if (caughtException[0] != null) { ++ if (caughtException[0] instanceof Exception) { ++ throw (Exception)caughtException[0]; ++ } else if(caughtException[0] instanceof Error) { ++ throw (Error)caughtException[0]; ++ } ++ } ++ return rslt; + } catch (RuntimeErrorException ree) { + throw new RuntimeOperationsException(ree, + "RuntimeException occurred in RequiredModelMBean "+ +@@ -1569,7 +1646,7 @@ public class RequiredModelMBean + } + + // make sure response class matches type field +- String respType = attrInfo.getType(); ++ final String respType = attrInfo.getType(); + if (response != null) { + String responseClass = response.getClass().getName(); + if (!respType.equals(responseClass)) { +@@ -1592,9 +1669,30 @@ public class RequiredModelMBean + // inequality may come from type subclassing + boolean subtype; + try { +- ClassLoader cl = +- response.getClass().getClassLoader(); +- Class c = Class.forName(respType, true, cl); ++ final Class respClass = response.getClass(); ++ final Exception[] caughException = new Exception[1]; ++ ++ AccessControlContext stack = AccessController.getContext(); ++ ++ Class c = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() { ++ ++ public Class<?> run() { ++ try { ++ ReflectUtil.checkPackageAccess(respType); ++ ClassLoader cl = ++ respClass.getClassLoader(); ++ return Class.forName(respType, true, cl); ++ } catch (Exception e) { ++ caughException[0] = e; ++ } ++ return null; ++ } ++ }, stack, acc); ++ ++ if (caughException[0] != null) { ++ throw caughException[0]; ++ } ++ + subtype = c.isInstance(response); + } catch (Exception e) { + subtype = false; +@@ -2748,16 +2847,36 @@ public class RequiredModelMBean + return MBeanServerFactory.getClassLoaderRepository(server); + } + +- private Class loadClass(String className) ++ private Class<?> loadClass(final String className) + throws ClassNotFoundException { +- try { +- return Class.forName(className); +- } catch (ClassNotFoundException e) { +- final ClassLoaderRepository clr = +- getClassLoaderRepository(); +- if (clr == null) throw new ClassNotFoundException(className); +- return clr.loadClass(className); ++ AccessControlContext stack = AccessController.getContext(); ++ final ClassNotFoundException[] caughtException = new ClassNotFoundException[1]; ++ ++ Class c = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() { ++ ++ public Class<?> run() { ++ try { ++ ReflectUtil.checkPackageAccess(className); ++ return Class.forName(className); ++ } catch (ClassNotFoundException e) { ++ final ClassLoaderRepository clr = ++ getClassLoaderRepository(); ++ try { ++ if (clr == null) throw new ClassNotFoundException(className); ++ return clr.loadClass(className); ++ } catch (ClassNotFoundException ex) { ++ caughtException[0] = ex; ++ } ++ } ++ return null; ++ } ++ }, stack, acc); ++ ++ if (caughtException[0] != null) { ++ throw caughtException[0]; + } ++ ++ return c; + } + + diff --git a/java/openjdk6/files/icedtea/security/20130201/8000540.patch b/java/openjdk6/files/icedtea/security/20130201/8000540.patch new file mode 100644 index 000000000000..4b0495c400f4 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/8000540.patch @@ -0,0 +1,187 @@ +# HG changeset patch +# User ngmr +# Date 1354993606 0 +# Node ID 42b1142b39b5a511e1e07b5877cc55e93767064e +# Parent c5203e9e0e07559914a9c46dbba4fe85df945624 +8000540: Improve IIOP type reuse management +Reviewed-by: alanb, ahgross, coffeys + +diff --git a/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java b/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java +--- corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java ++++ corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -25,7 +25,7 @@ + /* + * Licensed Materials - Property of IBM + * RMI-IIOP v1.0 +- * Copyright IBM Corp. 1998 1999 All Rights Reserved ++ * Copyright IBM Corp. 1998 2012 All Rights Reserved + * + */ + +@@ -56,7 +56,8 @@ import java.io.Serializable; + + import java.util.Arrays; + import java.util.Comparator; +-import java.util.Hashtable; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.concurrent.ConcurrentMap; + + import com.sun.corba.se.impl.util.RepositoryId; + +@@ -82,8 +83,6 @@ public class ObjectStreamClass implement + + private static Object noArgsList[] = {}; + private static Class noTypesList[] = {}; +- +- private static Hashtable translatedFields; + + private static final Bridge bridge = + (Bridge)AccessController.doPrivileged( +@@ -380,6 +379,58 @@ public class ObjectStreamClass implement + */ + } + ++ private static final class PersistentFieldsValue { ++ private final ConcurrentMap map = new ConcurrentHashMap(); ++ private static final Object NULL_VALUE = ++ (PersistentFieldsValue.class.getName() + ".NULL_VALUE"); ++ ++ PersistentFieldsValue() { } ++ ++ ObjectStreamField[] get(Class type) { ++ Object value = map.get(type); ++ if (value == null) { ++ value = computeValue(type); ++ Object oldValue = map.putIfAbsent(type, value); ++ if (oldValue != null) { ++ value = oldValue; ++ } ++ } ++ return ((value == NULL_VALUE) ? null : (ObjectStreamField[])value); ++ } ++ ++ private static Object computeValue(Class<?> type) { ++ try { ++ Field pf = type.getDeclaredField("serialPersistentFields"); ++ int mods = pf.getModifiers(); ++ if (Modifier.isPrivate(mods) && Modifier.isStatic(mods) && ++ Modifier.isFinal(mods)) { ++ pf.setAccessible(true); ++ java.io.ObjectStreamField[] fields = ++ (java.io.ObjectStreamField[])pf.get(type); ++ return translateFields(fields); ++ } ++ } catch (NoSuchFieldException e1) { ++ } catch (IllegalAccessException e2) { ++ } catch (IllegalArgumentException e3) { ++ } catch (ClassCastException e4) { } ++ return NULL_VALUE; ++ } ++ ++ private static ObjectStreamField[] translateFields( ++ java.io.ObjectStreamField[] fields) { ++ ObjectStreamField[] translation = ++ new ObjectStreamField[fields.length]; ++ for (int i = 0; i < fields.length; i++) { ++ translation[i] = new ObjectStreamField(fields[i].getName(), ++ fields[i].getType()); ++ } ++ return translation; ++ } ++ } ++ ++ private static final PersistentFieldsValue persistentFieldsValue = ++ new PersistentFieldsValue(); ++ + /* + * Initialize class descriptor. This method is only invoked on class + * descriptors created via calls to lookupInternal(). This method is kept +@@ -412,35 +463,7 @@ public class ObjectStreamClass implement + * If it is declared, use the declared serialPersistentFields. + * Otherwise, extract the fields from the class itself. + */ +- try { +- Field pf = cl.getDeclaredField("serialPersistentFields"); +- // serial bug 7; the serialPersistentFields were not +- // being read and stored as Accessible bit was not set +- pf.setAccessible(true); +- // serial bug 7; need to find if the field is of type +- // java.io.ObjectStreamField +- java.io.ObjectStreamField[] f = +- (java.io.ObjectStreamField[])pf.get(cl); +- int mods = pf.getModifiers(); +- if ((Modifier.isPrivate(mods)) && +- (Modifier.isStatic(mods)) && +- (Modifier.isFinal(mods))) +- { +- fields = (ObjectStreamField[])translateFields((Object[])pf.get(cl)); +- } +- } catch (NoSuchFieldException e) { +- fields = null; +- } catch (IllegalAccessException e) { +- fields = null; +- } catch (IllegalArgumentException e) { +- fields = null; +- } catch (ClassCastException e) { +- /* Thrown if a field serialPersistentField exists +- * but it is not of type ObjectStreamField. +- */ +- fields = null; +- } +- ++ fields = persistentFieldsValue.get(cl); + + if (fields == null) { + /* Get all of the declared fields for this +@@ -635,44 +658,6 @@ public class ObjectStreamClass implement + name = n; + suid = s; + superclass = null; +- } +- +- private static Object[] translateFields(Object objs[]) +- throws NoSuchFieldException { +- try{ +- java.io.ObjectStreamField fields[] = (java.io.ObjectStreamField[])objs; +- Object translation[] = null; +- +- if (translatedFields == null) +- translatedFields = new Hashtable(); +- +- translation = (Object[])translatedFields.get(fields); +- +- if (translation != null) +- return translation; +- else { +- Class osfClass = Class.forName("com.sun.corba.se.impl.io.ObjectStreamField"); +- translation = (Object[])java.lang.reflect.Array.newInstance(osfClass, objs.length); +- Object arg[] = new Object[2]; +- Class types[] = {String.class, Class.class}; +- Constructor constructor = osfClass.getDeclaredConstructor(types); +- for (int i = fields.length -1; i >= 0; i--){ +- arg[0] = fields[i].getName(); +- arg[1] = fields[i].getType(); +- +- translation[i] = constructor.newInstance(arg); +- } +- translatedFields.put(fields, translation); +- +- } +- +- return (Object[])translation; +- } +- catch(Throwable t){ +- NoSuchFieldException nsfe = new NoSuchFieldException(); +- nsfe.initCause( t ) ; +- throw nsfe ; +- } + } + + /* diff --git a/java/openjdk6/files/icedtea/security/20130201/8000631.patch b/java/openjdk6/files/icedtea/security/20130201/8000631.patch new file mode 100644 index 000000000000..bdf6781e30a5 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/8000631.patch @@ -0,0 +1,3964 @@ +# HG changeset patch +# User coffeys +# Date 1354992561 0 +# Node ID c5203e9e0e07559914a9c46dbba4fe85df945624 +# Parent 7f904eacf818c104549b94b957f34896a8548d9b +8000631: Restrict access to class constructor +Reviewed-by: alanb, ahgross + +diff --git a/make/com/sun/corba/minclude/com_sun_corba_se_impl_orbutil.jmk b/make/com/sun/corba/minclude/com_sun_corba_se_impl_orbutil.jmk +--- corba/make/com/sun/corba/minclude/com_sun_corba_se_impl_orbutil.jmk ++++ corba/make/com/sun/corba/minclude/com_sun_corba_se_impl_orbutil.jmk +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. ++# Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + # + # This code is free software; you can redistribute it and/or modify it +@@ -29,10 +29,6 @@ com_sun_corba_se_impl_orbutil_java = \ + com/sun/corba/se/impl/orbutil/DenseIntMapImpl.java \ + com/sun/corba/se/impl/orbutil/GetPropertyAction.java \ + com/sun/corba/se/impl/orbutil/HexOutputStream.java \ +- com/sun/corba/se/impl/orbutil/IIOPInputStream_1_3.java \ +- com/sun/corba/se/impl/orbutil/IIOPInputStream_1_3_1.java \ +- com/sun/corba/se/impl/orbutil/IIOPOutputStream_1_3.java \ +- com/sun/corba/se/impl/orbutil/IIOPOutputStream_1_3_1.java \ + com/sun/corba/se/impl/orbutil/LegacyHookGetFields.java \ + com/sun/corba/se/impl/orbutil/LegacyHookPutFields.java \ + com/sun/corba/se/impl/orbutil/LogKeywords.java \ +@@ -45,19 +41,11 @@ com_sun_corba_se_impl_orbutil_java = \ + com/sun/corba/se/impl/orbutil/ORBUtility.java \ + com/sun/corba/se/impl/orbutil/ORBClassLoader.java \ + com/sun/corba/se/impl/orbutil/RepIdDelegator.java \ +- com/sun/corba/se/impl/orbutil/RepIdDelegator_1_3.java \ +- com/sun/corba/se/impl/orbutil/RepIdDelegator_1_3_1.java \ +- com/sun/corba/se/impl/orbutil/RepositoryIdCache_1_3.java \ +- com/sun/corba/se/impl/orbutil/RepositoryId_1_3.java \ + com/sun/corba/se/impl/orbutil/RepositoryIdFactory.java \ + com/sun/corba/se/impl/orbutil/RepositoryIdStrings.java \ + com/sun/corba/se/impl/orbutil/RepositoryIdUtility.java \ + com/sun/corba/se/impl/orbutil/RepositoryIdInterface.java \ +- com/sun/corba/se/impl/orbutil/RepositoryIdCache_1_3_1.java \ +- com/sun/corba/se/impl/orbutil/RepositoryId_1_3_1.java \ + com/sun/corba/se/impl/orbutil/StackImpl.java \ +- com/sun/corba/se/impl/orbutil/ValueHandlerImpl_1_3_1.java \ +- com/sun/corba/se/impl/orbutil/ValueHandlerImpl_1_3.java \ + com/sun/corba/se/impl/orbutil/closure/Future.java \ + com/sun/corba/se/impl/orbutil/closure/Constant.java \ + com/sun/corba/se/impl/orbutil/concurrent/Sync.java \ +diff --git a/src/share/classes/com/sun/corba/se/impl/corba/AnyImpl.java b/src/share/classes/com/sun/corba/se/impl/corba/AnyImpl.java +--- corba/src/share/classes/com/sun/corba/se/impl/corba/AnyImpl.java ++++ corba/src/share/classes/com/sun/corba/se/impl/corba/AnyImpl.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -1218,7 +1218,7 @@ public class AnyImpl extends Any + // See bug 4391648 for more info about the tcORB in this + // case. + RepositoryIdStrings repStrs +- = RepositoryIdFactory.getRepIdStringsFactory(tcORB); ++ = RepositoryIdFactory.getRepIdStringsFactory(); + + + // Assertion: c instanceof Serializable? +@@ -1251,7 +1251,7 @@ public class AnyImpl extends Any + // Anything else + // We know that this is a TypeCodeImpl since it is our ORB + classTC = (TypeCodeImpl)ValueUtility.createTypeCodeForClass( +- tcORB, c, ORBUtility.createValueHandler(tcORB)); ++ tcORB, c, ORBUtility.createValueHandler()); + // Intruct classTC to store its buffer + classTC.setCaching(true); + // Update the cache +diff --git a/src/share/classes/com/sun/corba/se/impl/encoding/CDRInputStream_1_0.java b/src/share/classes/com/sun/corba/se/impl/encoding/CDRInputStream_1_0.java +--- corba/src/share/classes/com/sun/corba/se/impl/encoding/CDRInputStream_1_0.java ++++ corba/src/share/classes/com/sun/corba/se/impl/encoding/CDRInputStream_1_0.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -269,8 +269,8 @@ public class CDRInputStream_1_0 extends + + private final void createRepositoryIdHandlers() + { +- repIdUtil = RepositoryIdFactory.getRepIdUtility(orb); +- repIdStrs = RepositoryIdFactory.getRepIdStringsFactory(orb); ++ repIdUtil = RepositoryIdFactory.getRepIdUtility(); ++ repIdStrs = RepositoryIdFactory.getRepIdStringsFactory(); + } + + public GIOPVersion getGIOPVersion() { +@@ -564,10 +564,7 @@ public class CDRInputStream_1_0 extends + + checkForNegativeLength(len); + +- if (orb != null && ORBUtility.isLegacyORB((ORB)orb)) +- return legacyReadString(len); +- else +- return internalReadString(len); ++ return internalReadString(len); + } + + private final String internalReadString(int len) { +@@ -586,54 +583,6 @@ public class CDRInputStream_1_0 extends + read_octet(); + + return new String(result, 0, getCharConverter().getNumChars()); +- } +- +- private final String legacyReadString(int len) { +- +- // +- // Workaround for ORBs which send string lengths of +- // zero to mean empty string. +- // +- // +- // IMPORTANT: Do not replace 'new String("")' with "", it may result +- // in a Serialization bug (See serialization.zerolengthstring) and +- // bug id: 4728756 for details +- if (len == 0) +- return new String(""); +- +- len--; +- char[] c = new char[len]; +- +- int n = 0; +- while (n < len) { +- int avail; +- int bytes; +- int wanted; +- +- avail = bbwi.buflen - bbwi.position(); +- if (avail <= 0) { +- grow(1, 1); +- avail = bbwi.buflen - bbwi.position(); +- } +- wanted = len - n; +- bytes = (wanted < avail) ? wanted : avail; +- // Microbenchmarks are showing a loop of ByteBuffer.get(int) being +- // faster than ByteBuffer.get(byte[], int, int). +- for (int i=0; i<bytes; i++) { +- c[n+i] = (char) (bbwi.byteBuffer.get(bbwi.position()+i) & 0xFF); +- } +- bbwi.position(bbwi.position() + bytes); +- n += bytes; +- } +- +- // +- // Skip past terminating null byte +- // +- if (bbwi.position() + 1 > bbwi.buflen) +- alignAndCheck(1, 1); +- bbwi.position(bbwi.position() + 1); +- +- return new String(c); + } + + public final String read_string() { +@@ -1045,7 +994,7 @@ public class CDRInputStream_1_0 extends + + try { + if (valueHandler == null) +- valueHandler = ORBUtility.createValueHandler(orb); ++ valueHandler = ORBUtility.createValueHandler(); + + value = valueHandler.readValue(parent, + indirection, +diff --git a/src/share/classes/com/sun/corba/se/impl/encoding/CDROutputStream_1_0.java b/src/share/classes/com/sun/corba/se/impl/encoding/CDROutputStream_1_0.java +--- corba/src/share/classes/com/sun/corba/se/impl/encoding/CDROutputStream_1_0.java ++++ corba/src/share/classes/com/sun/corba/se/impl/encoding/CDROutputStream_1_0.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -189,18 +189,8 @@ public class CDROutputStream_1_0 extends + + private final void createRepositoryIdHandlers() + { +- if (orb != null) { +- // Get the appropriate versions based on the ORB version. The +- // ORB versioning info is only in the core ORB. +- repIdUtil +- = RepositoryIdFactory.getRepIdUtility(orb); +- repIdStrs +- = RepositoryIdFactory.getRepIdStringsFactory(orb); +- } else { +- // Get the latest versions +- repIdUtil = RepositoryIdFactory.getRepIdUtility(); +- repIdStrs = RepositoryIdFactory.getRepIdStringsFactory(); +- } ++ repIdUtil = RepositoryIdFactory.getRepIdUtility(); ++ repIdStrs = RepositoryIdFactory.getRepIdStringsFactory(); + } + + public BufferManagerWrite getBufferManager() +@@ -705,7 +695,7 @@ public class CDROutputStream_1_0 extends + private void writeArray(Serializable array, Class clazz) { + + if (valueHandler == null) +- valueHandler = ORBUtility.createValueHandler(orb); //d11638 ++ valueHandler = ORBUtility.createValueHandler(); //d11638 + + // Write value_tag + int indirection = writeValueTag(mustChunk, true, +@@ -768,7 +758,7 @@ public class CDROutputStream_1_0 extends + + private void writeRMIIIOPValueType(Serializable object, Class clazz) { + if (valueHandler == null) +- valueHandler = ORBUtility.createValueHandler(orb); //d11638 ++ valueHandler = ORBUtility.createValueHandler(); //d11638 + + Serializable key = object; + +diff --git a/src/share/classes/com/sun/corba/se/impl/io/FVDCodeBaseImpl.java b/src/share/classes/com/sun/corba/se/impl/io/FVDCodeBaseImpl.java +--- corba/src/share/classes/com/sun/corba/se/impl/io/FVDCodeBaseImpl.java ++++ corba/src/share/classes/com/sun/corba/se/impl/io/FVDCodeBaseImpl.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -86,7 +86,7 @@ public class FVDCodeBaseImpl extends _Co + // default to using the current ORB version in case the + // vhandler is not set + if (vhandler == null) { +- vhandler = new ValueHandlerImpl(false); ++ vhandler = ValueHandlerImpl.getInstance(false); + } + + // Util.getCodebase may return null which would +@@ -120,7 +120,7 @@ public class FVDCodeBaseImpl extends _Co + // default to using the current ORB version in case the + // vhandler is not set + if (vhandler == null) { +- vhandler = new ValueHandlerImpl(false); ++ vhandler = ValueHandlerImpl.getInstance(false); + } + + try{ +@@ -161,7 +161,7 @@ public class FVDCodeBaseImpl extends _Co + // default to using the current ORB version in case the + // vhandler is not set + if (vhandler == null) { +- vhandler = new ValueHandlerImpl(false); ++ vhandler = ValueHandlerImpl.getInstance(false); + } + + Stack repIds = new Stack(); +diff --git a/src/share/classes/com/sun/corba/se/impl/io/ValueHandlerImpl.java b/src/share/classes/com/sun/corba/se/impl/io/ValueHandlerImpl.java +--- corba/src/share/classes/com/sun/corba/se/impl/io/ValueHandlerImpl.java ++++ corba/src/share/classes/com/sun/corba/se/impl/io/ValueHandlerImpl.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -53,7 +53,7 @@ import com.sun.corba.se.impl.logging.OMG + import com.sun.corba.se.impl.logging.OMGSystemException; + import com.sun.corba.se.impl.logging.UtilSystemException; + +-public class ValueHandlerImpl implements javax.rmi.CORBA.ValueHandlerMultiFormat { ++public final class ValueHandlerImpl implements javax.rmi.CORBA.ValueHandlerMultiFormat { + + // Property to override our maximum stream format version + public static final String FORMAT_VERSION_PROPERTY +@@ -150,12 +150,20 @@ public class ValueHandlerImpl implements + writeValueWithVersion(out, value, streamFormatVersion); + } + +- public ValueHandlerImpl(){} ++ private ValueHandlerImpl(){} + +- public ValueHandlerImpl(boolean isInputStream) { ++ private ValueHandlerImpl(boolean isInputStream) { + this(); + useHashtables = false; + this.isInputStream = isInputStream; ++ } ++ ++ static ValueHandlerImpl getInstance() { ++ return new ValueHandlerImpl(); ++ } ++ ++ static ValueHandlerImpl getInstance(boolean isInputStream) { ++ return new ValueHandlerImpl(isInputStream); + } + + /** +@@ -458,12 +466,7 @@ public class ValueHandlerImpl implements + return ObjectStreamClass.lookup(value.getClass()).writeReplace(value); + } + +- /** +- * Encapsulates writing of Java char arrays so that the 1.3 subclass +- * can override it without exposing internals across packages. This +- * is a fix for bug 4367783. +- */ +- protected void writeCharArray(org.omg.CORBA_2_3.portable.OutputStream out, ++ private void writeCharArray(org.omg.CORBA_2_3.portable.OutputStream out, + char[] array, + int offset, + int length) +@@ -576,12 +579,7 @@ public class ValueHandlerImpl implements + } + } + +- /** +- * Encapsulates reading of Java char arrays so that the 1.3 subclass +- * can override it without exposing internals across packages. This +- * is a fix for bug 4367783. +- */ +- protected void readCharArray(org.omg.CORBA_2_3.portable.InputStream in, ++ private void readCharArray(org.omg.CORBA_2_3.portable.InputStream in, + char[] array, + int offset, + int length) +@@ -795,7 +793,7 @@ public class ValueHandlerImpl implements + return RepositoryId.cache.getId(repId).isSequence(); + } + +- protected String getOutputStreamClassName() { ++ private String getOutputStreamClassName() { + return "com.sun.corba.se.impl.io.IIOPOutputStream"; + } + +@@ -843,29 +841,11 @@ public class ValueHandlerImpl implements + private IIOPOutputStream createOutputStreamBuiltInNoPriv( + final String name + ) throws IOException { +- return +- name.equals( +- IIOPOutputStream +- .class.getName() +- ) ? +- new IIOPOutputStream() : +- +- name.equals( +- com.sun.corba.se.impl.orbutil.IIOPOutputStream_1_3 +- .class.getName() +- ) ? +- new com.sun.corba.se.impl.orbutil.IIOPOutputStream_1_3() : +- +- name.equals( +- com.sun.corba.se.impl.orbutil.IIOPOutputStream_1_3_1 +- .class.getName() +- ) ? +- new com.sun.corba.se.impl.orbutil.IIOPOutputStream_1_3_1() : +- +- null; ++ return name.equals(IIOPOutputStream.class.getName()) ? ++ new IIOPOutputStream() : null; + } + +- protected String getInputStreamClassName() { ++ private String getInputStreamClassName() { + return "com.sun.corba.se.impl.io.IIOPInputStream"; + } + +@@ -913,26 +893,8 @@ public class ValueHandlerImpl implements + private IIOPInputStream createInputStreamBuiltInNoPriv( + final String name + ) throws IOException { +- return +- name.equals( +- IIOPInputStream +- .class.getName() +- ) ? +- new IIOPInputStream() : +- +- name.equals( +- com.sun.corba.se.impl.orbutil.IIOPInputStream_1_3 +- .class.getName() +- ) ? +- new com.sun.corba.se.impl.orbutil.IIOPInputStream_1_3() : +- +- name.equals( +- com.sun.corba.se.impl.orbutil.IIOPInputStream_1_3_1 +- .class.getName() +- ) ? +- new com.sun.corba.se.impl.orbutil.IIOPInputStream_1_3_1() : +- +- null; ++ return name.equals(IIOPInputStream.class.getName()) ? ++ new IIOPInputStream() : null; + } + + /** +@@ -958,12 +920,7 @@ public class ValueHandlerImpl implements + + } + +- /** +- * Our JDK 1.3 and JDK 1.3.1 behavior subclasses override this. +- * The correct behavior is for a Java char to map to a CORBA wchar, +- * but our older code mapped it to a CORBA char. +- */ +- protected TCKind getJavaCharTCKind() { ++ TCKind getJavaCharTCKind() { + return TCKind.tk_wchar; + } + } +diff --git a/src/share/classes/com/sun/corba/se/impl/io/ValueUtility.java b/src/share/classes/com/sun/corba/se/impl/io/ValueUtility.java +--- corba/src/share/classes/com/sun/corba/se/impl/io/ValueUtility.java ++++ corba/src/share/classes/com/sun/corba/se/impl/io/ValueUtility.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1999, 2002, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -92,6 +92,14 @@ public class ValueUtility { + null, // tk_native 31 + null, // tk_abstract_interface 32 + }; ++ ++ static { ++ sun.corba.SharedSecrets.setJavaCorbaAccess(new sun.corba.JavaCorbaAccess() { ++ public ValueHandlerImpl newValueHandlerImpl() { ++ return ValueHandlerImpl.getInstance(); ++ } ++ }); ++ } + + public static String getSignature(ValueMember member) + throws ClassNotFoundException { +diff --git a/src/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java b/src/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java +--- corba/src/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java ++++ corba/src/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java +@@ -112,6 +112,9 @@ import com.sun.corba.se.impl.orbutil.ORB + import com.sun.corba.se.impl.orbutil.ORBClassLoader; + import com.sun.corba.se.impl.logging.UtilSystemException; + import com.sun.corba.se.spi.logging.CORBALogDomains; ++import sun.corba.SharedSecrets; ++import sun.corba.JavaCorbaAccess; ++ + + /** + * Provides utility methods that can be used by stubs and ties to +@@ -125,7 +128,8 @@ public class Util implements javax.rmi.C + // Maps targets to ties. + private static IdentityHashtable exportedServants = new IdentityHashtable(); + +- private static ValueHandlerImpl valueHandlerSingleton = new ValueHandlerImpl(); ++ private static final ValueHandlerImpl valueHandlerSingleton = ++ SharedSecrets.getJavaCorbaAccess().newValueHandlerImpl(); + + private UtilSystemException utilWrapper = UtilSystemException.get( + CORBALogDomains.RPC_ENCODING); +diff --git a/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java b/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java +--- corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java ++++ corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java +@@ -848,7 +848,7 @@ public class ORBImpl extends com.sun.cor + // backward compatability 4365188 + CodeBase cb; + +- ValueHandler vh = ORBUtility.createValueHandler(this); ++ ValueHandler vh = ORBUtility.createValueHandler(); + + cb = (CodeBase)vh.getRunTimeCodeBase(); + return ORBUtility.connectAndGetIOR( this, cb ) ; +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/IIOPInputStream_1_3.java b/src/share/classes/com/sun/corba/se/impl/orbutil/IIOPInputStream_1_3.java +deleted file mode 100644 +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/IIOPInputStream_1_3.java ++++ /dev/null +@@ -1,57 +0,0 @@ +-/* +- * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. +- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License version 2 only, as +- * published by the Free Software Foundation. Oracle designates this +- * particular file as subject to the "Classpath" exception as provided +- * by Oracle in the LICENSE file that accompanied this code. +- * +- * This code is distributed in the hope that it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +- * version 2 for more details (a copy is included in the LICENSE file that +- * accompanied this code). +- * +- * You should have received a copy of the GNU General Public License version +- * 2 along with this work; if not, write to the Free Software Foundation, +- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +- * or visit www.oracle.com if you need additional information or have any +- * questions. +- */ +-package com.sun.corba.se.impl.orbutil; +- +-import java.io.*; +-import java.util.Hashtable; +- +-/** +- * Implements legacy behavior from before Ladybird to maintain +- * backwards compatibility. +- */ +-public class IIOPInputStream_1_3 extends com.sun.corba.se.impl.io.IIOPInputStream +-{ +- // The newer version in the io package correctly reads a wstring instead. +- // This concerns bug 4379597. +- protected String internalReadUTF(org.omg.CORBA.portable.InputStream stream) +- { +- return stream.read_string(); +- } +- +- /** +- * Before JDK 1.3.1_01, the PutField/GetField implementation +- * actually sent a Hashtable. +- */ +- public ObjectInputStream.GetField readFields() +- throws IOException, ClassNotFoundException, NotActiveException { +- Hashtable fields = (Hashtable)readObject(); +- return new LegacyHookGetFields(fields); +- } +- +- public IIOPInputStream_1_3() +- throws java.io.IOException { +- super(); +- } +-} +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/IIOPInputStream_1_3_1.java b/src/share/classes/com/sun/corba/se/impl/orbutil/IIOPInputStream_1_3_1.java +deleted file mode 100644 +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/IIOPInputStream_1_3_1.java ++++ /dev/null +@@ -1,54 +0,0 @@ +-/* +- * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. +- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License version 2 only, as +- * published by the Free Software Foundation. Oracle designates this +- * particular file as subject to the "Classpath" exception as provided +- * by Oracle in the LICENSE file that accompanied this code. +- * +- * This code is distributed in the hope that it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +- * version 2 for more details (a copy is included in the LICENSE file that +- * accompanied this code). +- * +- * You should have received a copy of the GNU General Public License version +- * 2 along with this work; if not, write to the Free Software Foundation, +- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +- * or visit www.oracle.com if you need additional information or have any +- * questions. +- */ +- +-/* +- */ +-package com.sun.corba.se.impl.orbutil; +- +-import java.io.*; +-import java.util.Hashtable; +- +-/** +- * Implements legacy behavior from Ladybird to maintain +- * backwards compatibility. +- */ +-public class IIOPInputStream_1_3_1 extends com.sun.corba.se.impl.io.IIOPInputStream +-{ +- public IIOPInputStream_1_3_1() +- throws java.io.IOException { +- super(); +- } +- +- /** +- * Before JDK 1.3.1_01, the PutField/GetField implementation +- * actually sent a Hashtable. +- */ +- public ObjectInputStream.GetField readFields() +- throws IOException, ClassNotFoundException, NotActiveException { +- +- Hashtable fields = (Hashtable)readObject(); +- return new LegacyHookGetFields(fields); +- } +-} +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/IIOPOutputStream_1_3.java b/src/share/classes/com/sun/corba/se/impl/orbutil/IIOPOutputStream_1_3.java +deleted file mode 100644 +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/IIOPOutputStream_1_3.java ++++ /dev/null +@@ -1,68 +0,0 @@ +-/* +- * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. +- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License version 2 only, as +- * published by the Free Software Foundation. Oracle designates this +- * particular file as subject to the "Classpath" exception as provided +- * by Oracle in the LICENSE file that accompanied this code. +- * +- * This code is distributed in the hope that it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +- * version 2 for more details (a copy is included in the LICENSE file that +- * accompanied this code). +- * +- * You should have received a copy of the GNU General Public License version +- * 2 along with this work; if not, write to the Free Software Foundation, +- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +- * or visit www.oracle.com if you need additional information or have any +- * questions. +- */ +-package com.sun.corba.se.impl.orbutil; +- +-import java.io.*; +- +-/** +- * Implements legacy behavior from before Ladybird to maintain +- * backwards compatibility. +- */ +-public class IIOPOutputStream_1_3 extends com.sun.corba.se.impl.io.IIOPOutputStream +-{ +- // We can't assume that the superclass's putFields +- // member will be non-private. We must allow +- // the RI to run on JDK 1.3.1 FCS as well as +- // the JDK 1.3.1_01 patch. +- private ObjectOutputStream.PutField putFields_1_3; +- +- // The newer version in the io package correctly writes a wstring instead. +- // This concerns bug 4379597. +- protected void internalWriteUTF(org.omg.CORBA.portable.OutputStream stream, +- String data) +- { +- stream.write_string(data); +- } +- +- public IIOPOutputStream_1_3() +- throws java.io.IOException { +- super(); +- } +- +- /** +- * Before JDK 1.3.1_01, the PutField/GetField implementation +- * actually sent a Hashtable. +- */ +- public ObjectOutputStream.PutField putFields() +- throws IOException { +- putFields_1_3 = new LegacyHookPutFields(); +- return putFields_1_3; +- } +- +- public void writeFields() +- throws IOException { +- putFields_1_3.write(this); +- } +-} +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/IIOPOutputStream_1_3_1.java b/src/share/classes/com/sun/corba/se/impl/orbutil/IIOPOutputStream_1_3_1.java +deleted file mode 100644 +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/IIOPOutputStream_1_3_1.java ++++ /dev/null +@@ -1,66 +0,0 @@ +-/* +- * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. +- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License version 2 only, as +- * published by the Free Software Foundation. Oracle designates this +- * particular file as subject to the "Classpath" exception as provided +- * by Oracle in the LICENSE file that accompanied this code. +- * +- * This code is distributed in the hope that it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +- * version 2 for more details (a copy is included in the LICENSE file that +- * accompanied this code). +- * +- * You should have received a copy of the GNU General Public License version +- * 2 along with this work; if not, write to the Free Software Foundation, +- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +- * or visit www.oracle.com if you need additional information or have any +- * questions. +- */ +- +-/* +- */ +-package com.sun.corba.se.impl.orbutil; +- +-import java.io.*; +-import java.util.Hashtable; +- +-/** +- * Implements legacy behavior from Ladybird to maintain +- * backwards compatibility. +- */ +-public class IIOPOutputStream_1_3_1 extends com.sun.corba.se.impl.io.IIOPOutputStream +-{ +- // We can't assume that the superclass's putFields +- // member will be non-private. We must allow +- // the RI to run on JDK 1.3.1 FCS as well as +- // the JDK 1.3.1_01 patch. +- private ObjectOutputStream.PutField putFields_1_3_1; +- +- public IIOPOutputStream_1_3_1() +- throws java.io.IOException { +- super(); +- } +- +- /** +- * Before JDK 1.3.1_01, the PutField/GetField implementation +- * actually sent a Hashtable. +- */ +- public ObjectOutputStream.PutField putFields() +- throws IOException { +- +- putFields_1_3_1 = new LegacyHookPutFields(); +- return putFields_1_3_1; +- } +- +- public void writeFields() +- throws IOException { +- +- putFields_1_3_1.write(this); +- } +-} +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/ORBUtility.java b/src/share/classes/com/sun/corba/se/impl/orbutil/ORBUtility.java +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/ORBUtility.java ++++ corba/src/share/classes/com/sun/corba/se/impl/orbutil/ORBUtility.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -160,42 +160,10 @@ public final class ORBUtility { + } + + /** +- * Creates the correct ValueHandler for the given ORB, +- * querying ORBVersion information. If the ORB or +- * ORBVersion is null, gets the ValueHandler from +- * Util.createValueHandler. ++ * Return default ValueHandler + */ +- public static ValueHandler createValueHandler(ORB orb) { +- +- if (orb == null) +- return Util.createValueHandler(); +- +- ORBVersion version = orb.getORBVersion(); +- +- if (version == null) +- return Util.createValueHandler(); +- +- if (version.equals(ORBVersionFactory.getOLD())) +- return new ValueHandlerImpl_1_3(); +- if (version.equals(ORBVersionFactory.getNEW())) +- return new ValueHandlerImpl_1_3_1(); +- ++ public static ValueHandler createValueHandler() { + return Util.createValueHandler(); +- } +- +- /** +- * Returns true if the given ORB could accurately be determined to be a +- * Kestrel or earlier ORB. Note: If passed the ORBSingleton, this will return +- * false. +- */ +- public static boolean isLegacyORB(ORB orb) +- { +- try { +- ORBVersion currentORB = orb.getORBVersion(); +- return currentORB.equals( ORBVersionFactory.getOLD() ) ; +- } catch (SecurityException se) { +- return false; +- } + } + + /** +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/RepIdDelegator_1_3.java b/src/share/classes/com/sun/corba/se/impl/orbutil/RepIdDelegator_1_3.java +deleted file mode 100644 +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/RepIdDelegator_1_3.java ++++ /dev/null +@@ -1,177 +0,0 @@ +-/* +- * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. +- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License version 2 only, as +- * published by the Free Software Foundation. Oracle designates this +- * particular file as subject to the "Classpath" exception as provided +- * by Oracle in the LICENSE file that accompanied this code. +- * +- * This code is distributed in the hope that it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +- * version 2 for more details (a copy is included in the LICENSE file that +- * accompanied this code). +- * +- * You should have received a copy of the GNU General Public License version +- * 2 along with this work; if not, write to the Free Software Foundation, +- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +- * or visit www.oracle.com if you need additional information or have any +- * questions. +- */ +- +-package com.sun.corba.se.impl.orbutil; +- +-import org.omg.CORBA.ORB; +-import java.io.Serializable; +-import java.util.Hashtable; +-import java.net.MalformedURLException; +-import com.sun.corba.se.impl.io.TypeMismatchException; +-import com.sun.corba.se.impl.util.RepositoryId; +- +-/** +- * Delegates to the RepositoryId_1_3 implementation in +- * com.sun.corba.se.impl.orbutil. This is necessary to +- * overcome the fact that many of RepositoryId's methods +- * are static. +- */ +-public final class RepIdDelegator_1_3 +- implements RepositoryIdStrings, +- RepositoryIdUtility, +- RepositoryIdInterface +-{ +- // RepositoryIdFactory methods +- +- public String createForAnyType(Class type) { +- return RepositoryId_1_3.createForAnyType(type); +- } +- +- public String createForJavaType(Serializable ser) +- throws TypeMismatchException +- { +- return RepositoryId_1_3.createForJavaType(ser); +- } +- +- public String createForJavaType(Class clz) +- throws TypeMismatchException +- { +- return RepositoryId_1_3.createForJavaType(clz); +- } +- +- public String createSequenceRepID(java.lang.Object ser) { +- return RepositoryId_1_3.createSequenceRepID(ser); +- } +- +- public String createSequenceRepID(Class clazz) { +- return RepositoryId_1_3.createSequenceRepID(clazz); +- } +- +- public RepositoryIdInterface getFromString(String repIdString) { +- return new RepIdDelegator_1_3(RepositoryId_1_3.cache.getId(repIdString)); +- } +- +- // RepositoryIdUtility methods +- +- public boolean isChunkedEncoding(int valueTag) { +- return RepositoryId.isChunkedEncoding(valueTag); +- } +- +- public boolean isCodeBasePresent(int valueTag) { +- return RepositoryId.isCodeBasePresent(valueTag); +- } +- +- public String getClassDescValueRepId() { +- return RepositoryId_1_3.kClassDescValueRepID; +- } +- +- public String getWStringValueRepId() { +- return RepositoryId_1_3.kWStringValueRepID; +- } +- +- public int getTypeInfo(int valueTag) { +- return RepositoryId.getTypeInfo(valueTag); +- } +- +- public int getStandardRMIChunkedNoRepStrId() { +- return RepositoryId.kPreComputed_StandardRMIChunked_NoRep; +- } +- +- public int getCodeBaseRMIChunkedNoRepStrId() { +- return RepositoryId.kPreComputed_CodeBaseRMIChunked_NoRep; +- } +- +- public int getStandardRMIChunkedId() { +- return RepositoryId.kPreComputed_StandardRMIChunked; +- } +- +- public int getCodeBaseRMIChunkedId() { +- return RepositoryId.kPreComputed_CodeBaseRMIChunked; +- } +- +- public int getStandardRMIUnchunkedId() { +- return RepositoryId.kPreComputed_StandardRMIUnchunked; +- } +- +- public int getCodeBaseRMIUnchunkedId() { +- return RepositoryId.kPreComputed_CodeBaseRMIUnchunked; +- } +- +- public int getStandardRMIUnchunkedNoRepStrId() { +- return RepositoryId.kPreComputed_StandardRMIUnchunked_NoRep; +- } +- +- public int getCodeBaseRMIUnchunkedNoRepStrId() { +- return RepositoryId.kPreComputed_CodeBaseRMIUnchunked_NoRep; +- } +- +- // RepositoryIdInterface methods +- +- public Class getClassFromType() throws ClassNotFoundException { +- return delegate.getClassFromType(); +- } +- +- public Class getClassFromType(String codebaseURL) +- throws ClassNotFoundException, MalformedURLException +- { +- return delegate.getClassFromType(codebaseURL); +- } +- +- public Class getClassFromType(Class expectedType, +- String codebaseURL) +- throws ClassNotFoundException, MalformedURLException +- { +- return delegate.getClassFromType(expectedType, codebaseURL); +- } +- +- public String getClassName() { +- return delegate.getClassName(); +- } +- +- // Constructor used for factory/utility cases +- public RepIdDelegator_1_3() {} +- +- // Constructor used by getIdFromString. All non-static +- // RepositoryId methods will use the provided delegate. +- private RepIdDelegator_1_3(RepositoryId_1_3 _delegate) { +- this.delegate = _delegate; +- } +- +- private RepositoryId_1_3 delegate = null; +- +- public String toString() { +- if (delegate != null) +- return delegate.toString(); +- else +- return this.getClass().getName(); +- } +- +- public boolean equals(Object obj) { +- if (delegate != null) +- return delegate.equals(obj); +- else +- return super.equals(obj); +- } +-} +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/RepIdDelegator_1_3_1.java b/src/share/classes/com/sun/corba/se/impl/orbutil/RepIdDelegator_1_3_1.java +deleted file mode 100644 +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/RepIdDelegator_1_3_1.java ++++ /dev/null +@@ -1,177 +0,0 @@ +-/* +- * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved. +- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License version 2 only, as +- * published by the Free Software Foundation. Oracle designates this +- * particular file as subject to the "Classpath" exception as provided +- * by Oracle in the LICENSE file that accompanied this code. +- * +- * This code is distributed in the hope that it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +- * version 2 for more details (a copy is included in the LICENSE file that +- * accompanied this code). +- * +- * You should have received a copy of the GNU General Public License version +- * 2 along with this work; if not, write to the Free Software Foundation, +- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +- * or visit www.oracle.com if you need additional information or have any +- * questions. +- */ +- +-package com.sun.corba.se.impl.orbutil; +- +-import org.omg.CORBA.ORB; +-import java.io.Serializable; +-import java.util.Hashtable; +-import java.net.MalformedURLException; +-import com.sun.corba.se.impl.io.TypeMismatchException; +-import com.sun.corba.se.impl.util.RepositoryId; +- +-/** +- * Delegates to the RepositoryId_1_3_1 implementation in +- * com.sun.corba.se.impl.orbutil. This is necessary to +- * overcome the fact that many of RepositoryId's methods +- * are static. +- */ +-public final class RepIdDelegator_1_3_1 +- implements RepositoryIdStrings, +- RepositoryIdUtility, +- RepositoryIdInterface +-{ +- // RepositoryIdFactory methods +- +- public String createForAnyType(Class type) { +- return RepositoryId_1_3_1.createForAnyType(type); +- } +- +- public String createForJavaType(Serializable ser) +- throws TypeMismatchException +- { +- return RepositoryId_1_3_1.createForJavaType(ser); +- } +- +- public String createForJavaType(Class clz) +- throws TypeMismatchException +- { +- return RepositoryId_1_3_1.createForJavaType(clz); +- } +- +- public String createSequenceRepID(java.lang.Object ser) { +- return RepositoryId_1_3_1.createSequenceRepID(ser); +- } +- +- public String createSequenceRepID(Class clazz) { +- return RepositoryId_1_3_1.createSequenceRepID(clazz); +- } +- +- public RepositoryIdInterface getFromString(String repIdString) { +- return new RepIdDelegator_1_3_1(RepositoryId_1_3_1.cache.getId(repIdString)); +- } +- +- // RepositoryIdUtility methods +- +- public boolean isChunkedEncoding(int valueTag) { +- return RepositoryId.isChunkedEncoding(valueTag); +- } +- +- public boolean isCodeBasePresent(int valueTag) { +- return RepositoryId.isCodeBasePresent(valueTag); +- } +- +- public String getClassDescValueRepId() { +- return RepositoryId_1_3_1.kClassDescValueRepID; +- } +- +- public String getWStringValueRepId() { +- return RepositoryId_1_3_1.kWStringValueRepID; +- } +- +- public int getTypeInfo(int valueTag) { +- return RepositoryId.getTypeInfo(valueTag); +- } +- +- public int getStandardRMIChunkedNoRepStrId() { +- return RepositoryId.kPreComputed_StandardRMIChunked_NoRep; +- } +- +- public int getCodeBaseRMIChunkedNoRepStrId() { +- return RepositoryId.kPreComputed_CodeBaseRMIChunked_NoRep; +- } +- +- public int getStandardRMIChunkedId() { +- return RepositoryId.kPreComputed_StandardRMIChunked; +- } +- +- public int getCodeBaseRMIChunkedId() { +- return RepositoryId.kPreComputed_CodeBaseRMIChunked; +- } +- +- public int getStandardRMIUnchunkedId() { +- return RepositoryId.kPreComputed_StandardRMIUnchunked; +- } +- +- public int getCodeBaseRMIUnchunkedId() { +- return RepositoryId.kPreComputed_CodeBaseRMIUnchunked; +- } +- +- public int getStandardRMIUnchunkedNoRepStrId() { +- return RepositoryId.kPreComputed_StandardRMIUnchunked_NoRep; +- } +- +- public int getCodeBaseRMIUnchunkedNoRepStrId() { +- return RepositoryId.kPreComputed_CodeBaseRMIUnchunked_NoRep; +- } +- +- // RepositoryIdInterface methods +- +- public Class getClassFromType() throws ClassNotFoundException { +- return delegate.getClassFromType(); +- } +- +- public Class getClassFromType(String codebaseURL) +- throws ClassNotFoundException, MalformedURLException +- { +- return delegate.getClassFromType(codebaseURL); +- } +- +- public Class getClassFromType(Class expectedType, +- String codebaseURL) +- throws ClassNotFoundException, MalformedURLException +- { +- return delegate.getClassFromType(expectedType, codebaseURL); +- } +- +- public String getClassName() { +- return delegate.getClassName(); +- } +- +- // Constructor used for factory/utility cases +- public RepIdDelegator_1_3_1() {} +- +- // Constructor used by getIdFromString. All non-static +- // RepositoryId methods will use the provided delegate. +- private RepIdDelegator_1_3_1(RepositoryId_1_3_1 _delegate) { +- this.delegate = _delegate; +- } +- +- private RepositoryId_1_3_1 delegate = null; +- +- public String toString() { +- if (delegate != null) +- return delegate.toString(); +- else +- return this.getClass().getName(); +- } +- +- public boolean equals(Object obj) { +- if (delegate != null) +- return delegate.equals(obj); +- else +- return super.equals(obj); +- } +-} +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryIdCache_1_3.java b/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryIdCache_1_3.java +deleted file mode 100644 +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryIdCache_1_3.java ++++ /dev/null +@@ -1,108 +0,0 @@ +-/* +- * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. +- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License version 2 only, as +- * published by the Free Software Foundation. Oracle designates this +- * particular file as subject to the "Classpath" exception as provided +- * by Oracle in the LICENSE file that accompanied this code. +- * +- * This code is distributed in the hope that it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +- * version 2 for more details (a copy is included in the LICENSE file that +- * accompanied this code). +- * +- * You should have received a copy of the GNU General Public License version +- * 2 along with this work; if not, write to the Free Software Foundation, +- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +- * or visit www.oracle.com if you need additional information or have any +- * questions. +- */ +-/* +- * Licensed Materials - Property of IBM +- * RMI-IIOP v1.0 +- * Copyright IBM Corp. 1998 1999 All Rights Reserved +- * +- */ +- +-package com.sun.corba.se.impl.orbutil; +- +-import java.util.Stack; +-import java.util.Hashtable; +-import java.util.EmptyStackException; +-import java.util.Enumeration; +- +-// Really limited pool - in this case just creating several at a time... +-class RepositoryIdPool_1_3 extends Stack { +- +- private static int MAX_CACHE_SIZE = 4; +- private RepositoryIdCache_1_3 cache; +- +- public final synchronized RepositoryId_1_3 popId() { +- +- try { +- return (RepositoryId_1_3)super.pop(); +- } +- catch(EmptyStackException e) { +- increasePool(5); +- return (RepositoryId_1_3)super.pop(); +- } +- +- } +- +- // Pool management +- final void increasePool(int size) { +- //if (cache.size() <= MAX_CACHE_SIZE) +- for (int i = size; i > 0; i--) +- push(new RepositoryId_1_3()); +- /* +- // _REVISIT_ This will not work w/out either thread tracing or weak references. I am +- // betting that thread tracing almost completely negates benefit of reuse. Until either +- // 1.2 only inclusion or proof to the contrary, I'll leave it this way... +- else { +- int numToReclaim = cache.size() / 2; +- Enumeration keys = cache.keys(); +- Enumeration elements = cache.elements(); +- for (int i = numToReclaim; i > 0; i--) { +- Object key = keys.nextElement(); +- Object element = elements.nextElement(); +- +- push(element); +- cache.remove(key); +- } +- } +- */ +- } +- +- final void setCaches(RepositoryIdCache_1_3 cache) { +- this.cache = cache; +- } +- +-} +- +-public class RepositoryIdCache_1_3 extends Hashtable { +- +- private RepositoryIdPool_1_3 pool = new RepositoryIdPool_1_3(); +- +- public RepositoryIdCache_1_3() { +- pool.setCaches(this); +- } +- +- public final synchronized RepositoryId_1_3 getId(String key) { +- RepositoryId_1_3 repId = (RepositoryId_1_3)super.get(key); +- +- if (repId != null) +- return repId; +- else { +- //repId = pool.popId().init(key); +- repId = new RepositoryId_1_3(key); +- put(key, repId); +- return repId; +- } +- +- } +-} +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryIdCache_1_3_1.java b/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryIdCache_1_3_1.java +deleted file mode 100644 +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryIdCache_1_3_1.java ++++ /dev/null +@@ -1,102 +0,0 @@ +-/* +- * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. +- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License version 2 only, as +- * published by the Free Software Foundation. Oracle designates this +- * particular file as subject to the "Classpath" exception as provided +- * by Oracle in the LICENSE file that accompanied this code. +- * +- * This code is distributed in the hope that it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +- * version 2 for more details (a copy is included in the LICENSE file that +- * accompanied this code). +- * +- * You should have received a copy of the GNU General Public License version +- * 2 along with this work; if not, write to the Free Software Foundation, +- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +- * or visit www.oracle.com if you need additional information or have any +- * questions. +- */ +- +-package com.sun.corba.se.impl.orbutil; +- +-import java.util.Stack; +-import java.util.Hashtable; +-import java.util.EmptyStackException; +-import java.util.Enumeration; +- +-// Really limited pool - in this case just creating several at a time... +-class RepositoryIdPool_1_3_1 extends Stack { +- +- private static int MAX_CACHE_SIZE = 4; +- private RepositoryIdCache_1_3_1 cache; +- +- public final synchronized RepositoryId_1_3_1 popId() { +- +- try { +- return (RepositoryId_1_3_1)super.pop(); +- } +- catch(EmptyStackException e) { +- increasePool(5); +- return (RepositoryId_1_3_1)super.pop(); +- } +- +- } +- +- // Pool management +- final void increasePool(int size) { +- //if (cache.size() <= MAX_CACHE_SIZE) +- for (int i = size; i > 0; i--) +- push(new RepositoryId_1_3_1()); +- /* +- // _REVISIT_ This will not work w/out either thread tracing or weak references. I am +- // betting that thread tracing almost completely negates benefit of reuse. Until either +- // 1.2 only inclusion or proof to the contrary, I'll leave it this way... +- else { +- int numToReclaim = cache.size() / 2; +- Enumeration keys = cache.keys(); +- Enumeration elements = cache.elements(); +- for (int i = numToReclaim; i > 0; i--) { +- Object key = keys.nextElement(); +- Object element = elements.nextElement(); +- +- push(element); +- cache.remove(key); +- } +- } +- */ +- } +- +- final void setCaches(RepositoryIdCache_1_3_1 cache) { +- this.cache = cache; +- } +- +-} +- +-public class RepositoryIdCache_1_3_1 extends Hashtable { +- +- private RepositoryIdPool_1_3_1 pool = new RepositoryIdPool_1_3_1(); +- +- public RepositoryIdCache_1_3_1() { +- pool.setCaches(this); +- } +- +- public final synchronized RepositoryId_1_3_1 getId(String key) { +- RepositoryId_1_3_1 repId = (RepositoryId_1_3_1)super.get(key); +- +- if (repId != null) +- return repId; +- else { +- //repId = pool.popId().init(key); +- repId = new RepositoryId_1_3_1(key); +- put(key, repId); +- return repId; +- } +- +- } +-} +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryIdFactory.java b/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryIdFactory.java +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryIdFactory.java ++++ corba/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryIdFactory.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -30,12 +30,6 @@ import com.sun.corba.se.spi.orb.ORB; + + public abstract class RepositoryIdFactory + { +- private static final RepIdDelegator_1_3 legacyDelegator +- = new RepIdDelegator_1_3(); +- +- private static final RepIdDelegator_1_3_1 ladybirdDelegator +- = new RepIdDelegator_1_3_1(); +- + private static final RepIdDelegator currentDelegator + = new RepIdDelegator(); + +@@ -48,29 +42,6 @@ public abstract class RepositoryIdFactor + } + + /** +- * Checks the version of the ORB and returns the appropriate +- * RepositoryIdStrings instance. +- */ +- public static RepositoryIdStrings getRepIdStringsFactory(ORB orb) +- { +- if (orb != null) { +- switch (orb.getORBVersion().getORBType()) { +- case ORBVersion.NEWER: +- case ORBVersion.FOREIGN: +- case ORBVersion.JDK1_3_1_01: +- return currentDelegator; +- case ORBVersion.OLD: +- return legacyDelegator; +- case ORBVersion.NEW: +- return ladybirdDelegator; +- default: +- return currentDelegator; +- } +- } else +- return currentDelegator; +- } +- +- /** + * Returns the latest version RepositoryIdUtility instance + */ + public static RepositoryIdUtility getRepIdUtility() +@@ -78,26 +49,4 @@ public abstract class RepositoryIdFactor + return currentDelegator; + } + +- /** +- * Checks the version of the ORB and returns the appropriate +- * RepositoryIdUtility instance. +- */ +- public static RepositoryIdUtility getRepIdUtility(ORB orb) +- { +- if (orb != null) { +- switch (orb.getORBVersion().getORBType()) { +- case ORBVersion.NEWER: +- case ORBVersion.FOREIGN: +- case ORBVersion.JDK1_3_1_01: +- return currentDelegator; +- case ORBVersion.OLD: +- return legacyDelegator; +- case ORBVersion.NEW: +- return ladybirdDelegator; +- default: +- return currentDelegator; +- } +- } else +- return currentDelegator; +- } + } +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryId_1_3.java b/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryId_1_3.java +deleted file mode 100644 +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryId_1_3.java ++++ /dev/null +@@ -1,990 +0,0 @@ +-/* +- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. +- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License version 2 only, as +- * published by the Free Software Foundation. Oracle designates this +- * particular file as subject to the "Classpath" exception as provided +- * by Oracle in the LICENSE file that accompanied this code. +- * +- * This code is distributed in the hope that it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +- * version 2 for more details (a copy is included in the LICENSE file that +- * accompanied this code). +- * +- * You should have received a copy of the GNU General Public License version +- * 2 along with this work; if not, write to the Free Software Foundation, +- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +- * or visit www.oracle.com if you need additional information or have any +- * questions. +- */ +-/* +- * Licensed Materials - Property of IBM +- * RMI-IIOP v1.0 +- * Copyright IBM Corp. 1998 1999 All Rights Reserved +- * +- */ +- +-package com.sun.corba.se.impl.orbutil; +- +-import java.util.StringTokenizer; +-import java.util.Hashtable; +-import java.io.IOException; +-import java.lang.reflect.Method; +- +-// Imports for using codebase URL to load class +-import java.net.MalformedURLException; +-import org.omg.CORBA.portable.ValueBase; +-import org.omg.CORBA.portable.IDLEntity; +- +-import com.sun.corba.se.impl.util.JDKBridge; +-import com.sun.corba.se.impl.util.Utility; +-import com.sun.corba.se.impl.util.PackagePrefixChecker; +-import com.sun.corba.se.impl.util.IdentityHashtable; +-import com.sun.corba.se.impl.io.ObjectStreamClass; +- +-import javax.rmi.CORBA.Util; +- +-// keeping the original RepositoryId class that was shipped in +-// JDK 1.3. It has interoperability bugs +- +-public class RepositoryId_1_3 { +- +- // Legal IDL Identifier characters (1 = legal). Note +- // that '.' (2E) is marked as legal even though it is +- // not legal in IDL. This allows us to treat a fully +- // qualified Java name with '.' package separators +- // uniformly, and is safe because that is the only +- // legal use of '.' in a Java name. +- +- public static final RepositoryIdCache_1_3 cache = new RepositoryIdCache_1_3(); +- private static final byte[] IDL_IDENTIFIER_CHARS = { +- +- // 0 1 2 3 4 5 6 7 8 9 a b c d e f +- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 00-0f +- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 10-1f +- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,0, // 20-2f +- 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, // 30-3f +- 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // 40-4f +- 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,1, // 50-5f +- 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // 60-6f +- 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, // 70-7f +- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 80-8f +- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 90-9f +- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // a0-af +- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // b0-bf +- 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // c0-cf +- 0,1,1,1, 1,1,1,0, 1,1,1,1, 1,0,0,1, // d0-df +- 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // e0-ef +- 0,1,1,1, 1,1,1,0, 1,1,1,1, 1,0,0,1, // f0-ff +- }; +- +- private static String defaultServerURL = null; +- private static boolean useCodebaseOnly = false; +- +- static { +- if (defaultServerURL == null) +- defaultServerURL = (String)JDKBridge.getLocalCodebase(); +- useCodebaseOnly = JDKBridge.useCodebaseOnly(); +- +- } +- +- private static IdentityHashtable classToRepStr = new IdentityHashtable(); +- private static IdentityHashtable classIDLToRepStr = new IdentityHashtable(); +- private static IdentityHashtable classSeqToRepStr = new IdentityHashtable(); +- +- private static IdentityHashtable repStrToByteArray = new IdentityHashtable(); +- private static Hashtable repStrToClass = new Hashtable(); +- +- private String repId = null; +- private boolean isSupportedFormat = true; +- private String typeString = null; +- private String versionString = null; +- private boolean isSequence = false; +- private boolean isRMIValueType = false; +- private boolean isIDLType = false; +- private String completeClassName = null; +- private String unqualifiedName = null; +- private String definedInId = null; +- private Class clazz = null; +- private String suid = null, actualSuid = null; +- private long suidLong = ObjectStreamClass.kDefaultUID, actualSuidLong = ObjectStreamClass.kDefaultUID; +- +- // Repository ID fragments +- private static final String kValuePrefix = "RMI:"; +- private static final String kIDLPrefix = "IDL:"; +- private static final String kIDLNamePrefix = "omg.org/"; +- private static final String kIDLClassnamePrefix = "org.omg."; +- private static final String kSequencePrefix = "["; +- private static final String kCORBAPrefix = "CORBA/"; +- private static final String kArrayPrefix = kValuePrefix + kSequencePrefix + kCORBAPrefix; +- private static final int kValuePrefixLength = kValuePrefix.length(); +- private static final int kIDLPrefixLength = kIDLPrefix.length(); +- private static final int kSequencePrefixLength = kSequencePrefix.length(); +- private static final String kInterfaceHashCode = ":0000000000000000"; +- private static final String kInterfaceOnlyHashStr = "0000000000000000"; +- private static final String kExternalizableHashStr = "0000000000000001"; +- +- // Value tag utility methods and constants +- public static final int kInitialValueTag= 0x7fffff00; +- public static final int kNoTypeInfo = 0; +- public static final int kSingleRepTypeInfo = 0x02; +- public static final int kPartialListTypeInfo = 0x06; +- public static final int kChunkedMask = 0x08; +- +- // Public, well known repository IDs +- +- // _REVISIT_ : A table structure with a good search routine for all of this +- // would be more efficient and easier to maintain... +- +- // String +- public static final String kWStringValueVersion = "1.0"; +- public static final String kWStringValueHash = ":"+kWStringValueVersion; +- public static final String kWStringStubValue = "WStringValue"; +- public static final String kWStringTypeStr = "omg.org/CORBA/"+kWStringStubValue; +- public static final String kWStringValueRepID = kIDLPrefix + kWStringTypeStr + kWStringValueHash; +- +- // Any +- public static final String kAnyRepID = kIDLPrefix + "omg.org/CORBA/Any"; +- +- // Class +- public static final String kClassDescValueHash = ":" + Long.toHexString( +- ObjectStreamClass.getSerialVersionUID(javax.rmi.CORBA.ClassDesc.class)); +- public static final String kClassDescStubValue = "ClassDesc"; +- public static final String kClassDescTypeStr = "javax.rmi.CORBA."+kClassDescStubValue; +- public static final String kClassDescValueRepID = kValuePrefix + kClassDescTypeStr + kClassDescValueHash; +- +- // Object +- public static final String kObjectValueHash = ":1.0"; +- public static final String kObjectStubValue = "Object"; +- +- // Sequence +- public static final String kSequenceValueHash = ":1.0"; +- public static final String kPrimitiveSequenceValueHash = ":0000000000000000"; +- +- // Serializable +- public static final String kSerializableValueHash = ":1.0"; +- public static final String kSerializableStubValue = "Serializable"; +- +- // Externalizable +- public static final String kExternalizableValueHash = ":1.0"; +- public static final String kExternalizableStubValue = "Externalizable"; +- +- // Remote (The empty string is used for java.rmi.Remote) +- public static final String kRemoteValueHash = ""; +- public static final String kRemoteStubValue = ""; +- public static final String kRemoteTypeStr = ""; +- public static final String kRemoteValueRepID = ""; +- +- private static final Hashtable kSpecialArrayTypeStrings = new Hashtable(); +- +- static { +- kSpecialArrayTypeStrings.put("CORBA.WStringValue", new StringBuffer(java.lang.String.class.getName())); +- kSpecialArrayTypeStrings.put("javax.rmi.CORBA.ClassDesc", new StringBuffer(java.lang.Class.class.getName())); +- kSpecialArrayTypeStrings.put("CORBA.Object", new StringBuffer(java.rmi.Remote.class.getName())); +- +- } +- +- private static final Hashtable kSpecialCasesRepIDs = new Hashtable(); +- +- static { +- kSpecialCasesRepIDs.put(java.lang.String.class, kWStringValueRepID); +- kSpecialCasesRepIDs.put(java.lang.Class.class, kClassDescValueRepID); +- kSpecialCasesRepIDs.put(java.rmi.Remote.class, kRemoteValueRepID); +- } +- +- private static final Hashtable kSpecialCasesStubValues = new Hashtable(); +- +- static { +- kSpecialCasesStubValues.put(java.lang.String.class, kWStringStubValue); +- kSpecialCasesStubValues.put(java.lang.Class.class, kClassDescStubValue); +- kSpecialCasesStubValues.put(java.lang.Object.class, kObjectStubValue); +- kSpecialCasesStubValues.put(java.io.Serializable.class, kSerializableStubValue); +- kSpecialCasesStubValues.put(java.io.Externalizable.class, kExternalizableStubValue); +- kSpecialCasesStubValues.put(java.rmi.Remote.class, kRemoteStubValue); +- } +- +- +- private static final Hashtable kSpecialCasesVersions = new Hashtable(); +- +- static { +- kSpecialCasesVersions.put(java.lang.String.class, kWStringValueHash); +- kSpecialCasesVersions.put(java.lang.Class.class, kClassDescValueHash); +- kSpecialCasesVersions.put(java.lang.Object.class, kObjectValueHash); +- kSpecialCasesVersions.put(java.io.Serializable.class, kSerializableValueHash); +- kSpecialCasesVersions.put(java.io.Externalizable.class, kExternalizableValueHash); +- kSpecialCasesVersions.put(java.rmi.Remote.class, kRemoteValueHash); +- } +- +- private static final Hashtable kSpecialCasesClasses = new Hashtable(); +- +- static { +- kSpecialCasesClasses.put(kWStringTypeStr, java.lang.String.class); +- kSpecialCasesClasses.put(kClassDescTypeStr, java.lang.Class.class); +- kSpecialCasesClasses.put(kRemoteTypeStr, java.rmi.Remote.class); +- +- kSpecialCasesClasses.put("org.omg.CORBA.WStringValue", java.lang.String.class); +- kSpecialCasesClasses.put("javax.rmi.CORBA.ClassDesc", java.lang.Class.class); +- //kSpecialCasesClasses.put(kRemoteTypeStr, java.rmi.Remote.class); +- } +- +- private static final Hashtable kSpecialCasesArrayPrefix = new Hashtable(); +- +- static { +- kSpecialCasesArrayPrefix.put(java.lang.String.class, kValuePrefix + kSequencePrefix + kCORBAPrefix); +- kSpecialCasesArrayPrefix.put(java.lang.Class.class, kValuePrefix + kSequencePrefix + "javax/rmi/CORBA/"); +- kSpecialCasesArrayPrefix.put(java.lang.Object.class, kValuePrefix + kSequencePrefix + "java/lang/"); +- kSpecialCasesArrayPrefix.put(java.io.Serializable.class, kValuePrefix + kSequencePrefix + "java/io/"); +- kSpecialCasesArrayPrefix.put(java.io.Externalizable.class, kValuePrefix + kSequencePrefix + "java/io/"); +- kSpecialCasesArrayPrefix.put(java.rmi.Remote.class, kValuePrefix + kSequencePrefix + kCORBAPrefix); +- } +- +- private static final Hashtable kSpecialPrimitives = new Hashtable(); +- +- static { +- kSpecialPrimitives.put("int","long"); +- kSpecialPrimitives.put("long","longlong"); +- kSpecialPrimitives.put("byte","octet"); +- } +- +- /** +- * Used to convert ascii to hex. +- */ +- private static final byte ASCII_HEX[] = { +- (byte)'0', +- (byte)'1', +- (byte)'2', +- (byte)'3', +- (byte)'4', +- (byte)'5', +- (byte)'6', +- (byte)'7', +- (byte)'8', +- (byte)'9', +- (byte)'A', +- (byte)'B', +- (byte)'C', +- (byte)'D', +- (byte)'E', +- (byte)'F', +- }; +- +- +- // Interface Rep ID Strings +- public static final String kjava_rmi_Remote = createForAnyType(java.rmi.Remote.class); +- public static final String korg_omg_CORBA_Object = createForAnyType(org.omg.CORBA.Object.class); +- +- // Dummy arguments for getIdFromHelper method +- public static final Class kNoParamTypes[] ={}; +- public static final Object kNoArgs[] = {}; +- +- +- RepositoryId_1_3(){} +- +- RepositoryId_1_3(String aRepId){ +- init(aRepId); +- } +- +- RepositoryId_1_3 init(String aRepId){ +- +- this.repId = aRepId; +- +- // Special case for remote +- if (aRepId.length() == 0) { +- clazz = java.rmi.Remote.class; +- typeString = ""; +- isRMIValueType = true; +- suid = kInterfaceOnlyHashStr; +- return this; +- } +- else if (aRepId.equals(kWStringValueRepID)) { +- clazz = java.lang.String.class; +- typeString = kWStringTypeStr; +- isIDLType = true; +- versionString = kWStringValueVersion; +- return this; +- } +- else { +- +- String repId = convertFromISOLatin1(aRepId); +- +- versionString = repId.substring(repId.indexOf(':', repId.indexOf(':')+1)); +- if (repId.startsWith(kIDLPrefix)) { +- typeString = +- repId.substring(kIDLPrefixLength, repId.indexOf(':', kIDLPrefixLength)); +- isIDLType = true; +- if (typeString.startsWith(kIDLNamePrefix)) +- completeClassName = kIDLClassnamePrefix + +- typeString.substring(kIDLNamePrefix.length()).replace('/','.'); +- else completeClassName = typeString.replace('/','.'); +- +- } +- else if (repId.startsWith(kValuePrefix)) { +- typeString = +- repId.substring(kValuePrefixLength, repId.indexOf(':', kValuePrefixLength)); +- isRMIValueType = true; +- +- if (versionString.indexOf('.') == -1) { +- actualSuid = versionString.substring(1); +- suid = actualSuid; // default if not explicitly specified +- +- if (actualSuid.indexOf(':') != -1){ +- // we have a declared hash also +- int pos = actualSuid.indexOf(':')+1; +- // actualSuid = suid.substring(pos); +- // suid = suid.substring(0, pos-1); +- suid = actualSuid.substring(pos); +- actualSuid = actualSuid.substring(0, pos-1); +- } +- +- } +- else { +- // _REVISIT_ : Special case version failure ? +- } +- } +- else isSupportedFormat = false; +- +- if (typeString.startsWith(kSequencePrefix)) { +- isSequence = true; +- } +- +- +- return this; +- } +- } +- +- public final String getUnqualifiedName() { +- if (unqualifiedName == null){ +- String className = getClassName(); +- int index = (className != null) ? className.lastIndexOf('.') : -1; +- if (index == -1){ +- unqualifiedName = className; +- definedInId = "IDL::1.0"; +- } +- else { +- unqualifiedName = className.substring(index); +- definedInId = "IDL:" + className.substring(0, index).replace('.','/') + ":1.0"; +- } +- } +- +- return unqualifiedName; +- } +- +- public final String getDefinedInId() { +- if (definedInId == null){ +- getUnqualifiedName(); +- } +- +- return definedInId; +- } +- +- public final String getTypeString() { +- return typeString; +- } +- +- public final String getVersionString() { +- return versionString; +- } +- +- public final String getSerialVersionUID() { +- return suid; +- } +- +- public final String getActualSerialVersionUID() { +- return actualSuid; +- } +- public final long getSerialVersionUIDAsLong() { +- return suidLong; +- } +- +- public final long getActualSerialVersionUIDAsLong() { +- return actualSuidLong; +- } +- +- public final boolean isRMIValueType() { +- return isRMIValueType; +- } +- +- public final boolean isIDLType() { +- return isIDLType; +- } +- +- public final String getRepositoryId() { +- return repId; +- } +- +- public static byte[] getByteArray(String repStr) { +- synchronized (repStrToByteArray){ +- return (byte[]) repStrToByteArray.get(repStr); +- } +- } +- +- public static void setByteArray(String repStr, byte[] repStrBytes) { +- synchronized (repStrToByteArray){ +- repStrToByteArray.put(repStr, repStrBytes); +- } +- } +- +- public final boolean isSequence() { +- return isSequence; +- } +- +- public final boolean isSupportedFormat() { +- return isSupportedFormat; +- } +- +- +- // This method will return the classname from the typestring OR if the classname turns out to be +- // a special class "pseudo" name, then the matching real classname is returned. +- public final String getClassName() { +- +- if (isRMIValueType) +- return typeString; +- else if (isIDLType) +- return completeClassName; +- else return null; +- +- } +- +- // This method calls getClazzFromType() and falls back to the repStrToClass +- // cache if no class was found. It's used where any class matching the +- // given repid is an acceptable result. +- public final Class getAnyClassFromType() throws ClassNotFoundException { +- try { +- return getClassFromType(); +- } catch (ClassNotFoundException cnfe) { +- Class clz = (Class)repStrToClass.get(repId); +- if (clz != null) +- return clz; +- else +- throw cnfe; +- } +- } +- +- public final Class getClassFromType() +- throws ClassNotFoundException { +- if (clazz != null) +- return clazz; +- +- Class specialCase = (Class)kSpecialCasesClasses.get(getClassName()); +- +- if (specialCase != null){ +- clazz = specialCase; +- return specialCase; +- } +- else +- { +- try{ +- return Util.loadClass(getClassName(), null, null); +- } +- catch(ClassNotFoundException cnfe){ +- if (defaultServerURL != null) { +- try{ +- return getClassFromType(defaultServerURL); +- } +- catch(MalformedURLException mue){ +- throw cnfe; +- } +- } +- else throw cnfe; +- } +- } +- +- } +- +- public final Class getClassFromType(Class expectedType, String codebase) +- throws ClassNotFoundException { +- if (clazz != null) +- return clazz; +- +- Class specialCase = (Class)kSpecialCasesClasses.get(getClassName()); +- +- if (specialCase != null){ +- clazz = specialCase; +- return specialCase; +- } else { +- ClassLoader expectedTypeClassLoader = (expectedType == null ? null : expectedType.getClassLoader()); +- return loadClassOfType(getClassName(), +- codebase, +- expectedTypeClassLoader, +- expectedType, +- expectedTypeClassLoader); +- } +- +- } +- +- public final Class getClassFromType(String url) +- throws ClassNotFoundException, MalformedURLException { +- return Util.loadClass(getClassName(), url, null); +- } +- +- public final String toString() { +- return repId; +- } +- +- private static String createHashString(java.io.Serializable ser) { +- +- return createHashString(ser.getClass()); +- } +- +- private static String createHashString(java.lang.Class clazz) { +- +- if (clazz.isInterface() || !java.io.Serializable.class.isAssignableFrom(clazz)) +- return kInterfaceHashCode; +- +- +- long actualLong = ObjectStreamClassUtil_1_3.computeStructuralUID(false, clazz); +- String hash = null; +- if (actualLong == 0) +- hash = kInterfaceOnlyHashStr; +- else if (actualLong == 1) +- hash = kExternalizableHashStr; +- else +- hash = Long.toHexString(actualLong).toUpperCase(); +- while(hash.length() < 16){ +- hash = "0" + hash; +- } +- +- long declaredLong = ObjectStreamClassUtil_1_3.computeSerialVersionUID(clazz); +- String declared = null; +- if (declaredLong == 0) +- declared = kInterfaceOnlyHashStr; +- else if (declaredLong == 1) +- declared = kExternalizableHashStr; +- else +- declared = Long.toHexString(declaredLong).toUpperCase(); +- while (declared.length() < 16){ +- declared = "0" + declared; +- } +- hash = hash + ":" + declared; +- +- return ":" + hash; +- } +- +- /** +- * Creates a repository ID for a sequence. This is for expert users only as +- * this method assumes the object passed is an array. If passed an object +- * that is not an array, it will produce a rep id for a sequence of zero +- * length. This would be an error. +- * @param ser The Java object to create a repository ID for +- **/ +- public static String createSequenceRepID(java.lang.Object ser){ +- return createSequenceRepID(ser.getClass()); +- } +- +- /** +- * Creates a repository ID for a sequence. This is for expert users only as +- * this method assumes the object passed is an array. If passed an object +- * that is not an array, it will produce a malformed rep id. +- * @param clazz The Java class to create a repository ID for +- **/ +- public static String createSequenceRepID(java.lang.Class clazz){ +- synchronized (classSeqToRepStr){ +- +- String repid = (String)classSeqToRepStr.get(clazz); +- if (repid != null) +- return repid; +- +- Class originalClazz = clazz; +- +- Class type = null; +- int numOfDims = 0; +- +- while ((type = clazz.getComponentType()) != null) { +- numOfDims++; +- clazz = type; +- } +- +- if (clazz.isPrimitive()) +- repid = kValuePrefix + originalClazz.getName() + kPrimitiveSequenceValueHash; +- else { +- StringBuffer buf = new StringBuffer(); +- buf.append(kValuePrefix); +- while(numOfDims-- > 0) { +- buf.append("["); +- } +- buf.append("L"); +- buf.append(convertToISOLatin1(clazz.getName())); +- buf.append(";"); +- buf.append(createHashString(clazz)); +- repid = buf.toString(); +- } +- classSeqToRepStr.put(originalClazz,repid); +- return repid; +- } +- +- } +- +- +- public static String createForSpecialCase(java.lang.Class clazz){ +- if (clazz.isArray()){ +- return createSequenceRepID(clazz); +- } +- else { +- return (String)kSpecialCasesRepIDs.get(clazz); +- } +- } +- +- public static String createForSpecialCase(java.io.Serializable ser){ +- Class clazz = ser.getClass(); +- if (clazz.isArray()){ +- return createSequenceRepID(ser); +- } +- else +- return createForSpecialCase(clazz); +- } +- +- /** +- * Creates a repository ID for a normal Java Type. +- * @param ser The Java object to create a repository ID for +- * @exception com.sun.corba.se.impl.io.TypeMismatchException if ser implements the +- * org.omg.CORBA.portable.IDLEntity interface which indicates it is an IDL Value type. +- **/ +- public static String createForJavaType(java.io.Serializable ser) +- throws com.sun.corba.se.impl.io.TypeMismatchException +- { +- synchronized (classToRepStr) { +- String repid = createForSpecialCase(ser); +- if (repid != null) +- return repid; +- Class clazz = ser.getClass(); +- repid = (String)classToRepStr.get(clazz); +- +- if (repid != null) +- return repid; +- +- repid = kValuePrefix + convertToISOLatin1(clazz.getName()) + +- createHashString(clazz); +- +- classToRepStr.put(clazz, repid); +- repStrToClass.put(repid, clazz); +- return repid; +- } +- } +- +- /** +- * Creates a repository ID for a normal Java Type. +- * @param clz The Java class to create a repository ID for +- * @exception com.sun.corba.se.impl.io.TypeMismatchException if ser implements the +- * org.omg.CORBA.portable.IDLEntity interface which indicates it is an IDL Value type. +- **/ +- public static String createForJavaType(Class clz) +- throws com.sun.corba.se.impl.io.TypeMismatchException +- { +- synchronized (classToRepStr){ +- String repid = createForSpecialCase(clz); +- if (repid != null) +- return repid; +- +- repid = (String)classToRepStr.get(clz); +- if (repid != null) +- return repid; +- +- repid = kValuePrefix + convertToISOLatin1(clz.getName()) + +- createHashString(clz); +- +- classToRepStr.put(clz, repid); +- repStrToClass.put(repid, clz); +- return repid; +- } +- } +- +- /** +- * Creates a repository ID for an IDL Java Type. +- * @param ser The IDL Value object to create a repository ID for +- * @param major The major version number +- * @param minor The minor version number +- * @exception com.sun.corba.se.impl.io.TypeMismatchException if ser does not implement the +- * org.omg.CORBA.portable.IDLEntity interface which indicates it is an IDL Value type. +- **/ +- public static String createForIDLType(Class ser, int major, int minor) +- throws com.sun.corba.se.impl.io.TypeMismatchException +- { +- synchronized (classIDLToRepStr){ +- String repid = (String)classIDLToRepStr.get(ser); +- if (repid != null) +- return repid; +- +- repid = kIDLPrefix + convertToISOLatin1(ser.getName()).replace('.','/') + +- ":" + major + "." + minor; +- classIDLToRepStr.put(ser, repid); +- return repid; +- } +- } +- +- private static String getIdFromHelper(Class clazz){ +- try { +- Class helperClazz = Utility.loadClassForClass(clazz.getName()+"Helper", null, +- clazz.getClassLoader(), clazz, clazz.getClassLoader()); +- Method idMethod = helperClazz.getDeclaredMethod("id", kNoParamTypes); +- return (String)idMethod.invoke(null, kNoArgs); +- } +- catch(java.lang.ClassNotFoundException cnfe) +- { +- throw new org.omg.CORBA.MARSHAL(cnfe.toString()); +- } +- catch(java.lang.NoSuchMethodException nsme) +- { +- throw new org.omg.CORBA.MARSHAL(nsme.toString()); +- } +- catch(java.lang.reflect.InvocationTargetException ite) +- { +- throw new org.omg.CORBA.MARSHAL(ite.toString()); +- } +- catch(java.lang.IllegalAccessException iae) +- { +- throw new org.omg.CORBA.MARSHAL(iae.toString()); +- } +- } +- +- /** +- * Createa a repository ID for the type if it is either a java type +- * or an IDL type. +- * @param type The type to create rep. id for +- * @return The rep. id. +- **/ +- public static String createForAnyType(Class type) { +- try{ +- if (type.isArray()) +- return createSequenceRepID(type); +- else if (IDLEntity.class.isAssignableFrom(type)) +- { +- try{ +- return getIdFromHelper(type); +- } +- catch(Throwable t) { +- return createForIDLType(type, 1, 0); +- } +- } +- else return createForJavaType(type); +- } +- catch(com.sun.corba.se.impl.io.TypeMismatchException e){ +- return null; +- } +- +- } +- +- public static boolean isAbstractBase(Class clazz) { +- return (clazz.isInterface() && +- IDLEntity.class.isAssignableFrom(clazz) && +- (!ValueBase.class.isAssignableFrom(clazz)) && +- (!org.omg.CORBA.Object.class.isAssignableFrom(clazz))); +- +- } +- +- /** +- * Convert strings with illegal IDL identifier characters. +- * <p> +- * Section 5.5.7 of OBV spec. +- */ +- private static String convertToISOLatin1 (String name) { +- +- int length = name.length(); +- if (length == 0) { +- return name; +- } +- StringBuffer buffer = null; +- +- for (int i = 0; i < length; i++) { +- +- char c = name.charAt(i); +- +- if (c > 255 || IDL_IDENTIFIER_CHARS[c] == 0) { +- +- // We gotta convert. Have we already started? +- +- if (buffer == null) { +- +- // No, so get set up... +- +- buffer = new StringBuffer(name.substring(0,i)); +- } +- +- // Convert the character into the IDL escape syntax... +- buffer.append( +- "\\U" + +- (char)ASCII_HEX[(c & 0xF000) >>> 12] + +- (char)ASCII_HEX[(c & 0x0F00) >>> 8] + +- (char)ASCII_HEX[(c & 0x00F0) >>> 4] + +- (char)ASCII_HEX[(c & 0x000F)]); +- +- } else { +- if (buffer != null) { +- buffer.append(c); +- } +- } +- } +- +- if (buffer != null) { +- name = buffer.toString(); +- } +- +- return name; +- } +- +- /** +- * Convert strings with ISO Latin 1 escape sequences back to original strings. +- * <p> +- * Section 5.5.7 of OBV spec. +- */ +- private static String convertFromISOLatin1 (String name) { +- +- int index = -1; +- StringBuffer buf = new StringBuffer(name); +- +- while ((index = buf.toString().indexOf("\\U")) != -1){ +- String str = "0000" + buf.toString().substring(index+2, index+6); +- +- // Convert Hexadecimal +- byte[] buffer = new byte[(str.length() - 4) / 2]; +- for (int i=4, j=0; i < str.length(); i +=2, j++) { +- buffer[j] = (byte)((ORBUtility.hexOf(str.charAt(i)) << 4) & 0xF0); +- buffer[j] |= (byte)((ORBUtility.hexOf(str.charAt(i+1)) << 0) & 0x0F); +- } +- buf = new StringBuffer(delete(buf.toString(), index, index+6)); +- buf.insert(index, (char)buffer[1]); +- } +- +- return buf.toString(); +- +- +- } +- +- private static String delete(String str, int from, int to) +- { +- return str.substring(0, from) + str.substring(to, str.length()); +- } +- +- private static String replace(String target, String arg, String source) +- { +- int i = 0; +- i = target.indexOf(arg); +- +- while(i != -1) +- { +- String left = target.substring(0, i); +- String right = target.substring(i+arg.length()); +- target = new String(left+source+right); +- i = target.indexOf(arg); +- } +- return target; +- } +- +- /* +- * Load a class and check that it is assignable to a given type. +- * @param className the class name. +- * @param remoteCodebase the codebase to use. May be null. +- * @param loader the class loader of last resort. May be null. +- * @param expectedType the expected type. May be null. +- * @return the loaded class. +- */ +- private Class loadClassOfType (String className, +- String remoteCodebase, +- ClassLoader loader, +- Class expectedType, +- ClassLoader expectedTypeClassLoader) +- throws ClassNotFoundException { +- +- Class loadedClass = null; +- +- try { +- //Sequence finding of the stubs according to spec +- try{ +- //If-else is put here for speed up of J2EE. +- //According to the OMG spec, the if clause is not dead code. +- //It can occur if some compiler has allowed generation +- //into org.omg.stub hierarchy for non-offending +- //classes. This will encourage people to +- //produce non-offending class stubs in their own hierarchy. +- if(!PackagePrefixChecker +- .hasOffendingPrefix(PackagePrefixChecker +- .withoutPackagePrefix(className))){ +- loadedClass = Util.loadClass +- (PackagePrefixChecker.withoutPackagePrefix(className), +- remoteCodebase, +- loader); +- } else { +- loadedClass = Util.loadClass +- (className, +- remoteCodebase, +- loader); +- } +- } catch (ClassNotFoundException cnfe) { +- loadedClass = Util.loadClass +- (className, +- remoteCodebase, +- loader); +- } +- if (expectedType == null) +- return loadedClass; +- } catch (ClassNotFoundException cnfe) { +- if (expectedType == null) +- throw cnfe; +- } +- +- // If no class was not loaded, or if the loaded class is not of the +- // correct type, make a further attempt to load the correct class +- // using the classloader of the expected type. +- // _REVISIT_ Is this step necessary, or should the Util,loadClass +- // algorithm always produce a valid class if the setup is correct? +- // Does the OMG standard algorithm need to be changed to include +- // this step? +- if (loadedClass == null || !expectedType.isAssignableFrom(loadedClass)) { +- if (expectedType.getClassLoader() != expectedTypeClassLoader) +- throw new IllegalArgumentException("expectedTypeClassLoader not class loader of expectedType."); +- +- if (expectedTypeClassLoader != null) +- loadedClass = expectedTypeClassLoader.loadClass(className); +- else +- loadedClass = ORBClassLoader.loadClass(className); +- } +- +- return loadedClass; +- } +- +- /** +- * Checks to see if the FullValueDescription should be retrieved. +- * @exception Throws IOException if suids do not match or if the repositoryID +- * is not an RMIValueType +- */ +- public static boolean useFullValueDescription(Class clazz, String repositoryID) +- throws IOException{ +- +- String clazzRepIDStr = createForAnyType(clazz); +- +- if (clazzRepIDStr.equals(repositoryID)) +- return false; +- +- RepositoryId_1_3 targetRepid; +- RepositoryId_1_3 clazzRepid; +- +- synchronized(cache) { +- // to avoid race condition where multiple threads could be +- // accessing this method, and their access to the cache may +- // be interleaved giving unexpected results +- +- targetRepid = cache.getId(repositoryID); +- clazzRepid = cache.getId(clazzRepIDStr); +- } +- +- if ((targetRepid.isRMIValueType()) && (clazzRepid.isRMIValueType())){ +- if (!targetRepid.getSerialVersionUID().equals(clazzRepid.getSerialVersionUID())) { +- +- String mssg = "Mismatched serialization UIDs : Source (Rep. ID" + +- clazzRepid + ") = " + +- clazzRepid.getSerialVersionUID() + " whereas Target (Rep. ID " + repositoryID + +- ") = " + targetRepid.getSerialVersionUID(); +- throw new IOException(mssg); +- } else { +- return true; +- } +- } else { +- +- throw new IOException("The repository ID is not of an RMI value type (Expected ID = " + clazzRepIDStr + "; Received ID = " + repositoryID +")"); +- } +- } +-} +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryId_1_3_1.java b/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryId_1_3_1.java +deleted file mode 100644 +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/RepositoryId_1_3_1.java ++++ /dev/null +@@ -1,1065 +0,0 @@ +-/* +- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. +- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License version 2 only, as +- * published by the Free Software Foundation. Oracle designates this +- * particular file as subject to the "Classpath" exception as provided +- * by Oracle in the LICENSE file that accompanied this code. +- * +- * This code is distributed in the hope that it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +- * version 2 for more details (a copy is included in the LICENSE file that +- * accompanied this code). +- * +- * You should have received a copy of the GNU General Public License version +- * 2 along with this work; if not, write to the Free Software Foundation, +- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +- * or visit www.oracle.com if you need additional information or have any +- * questions. +- */ +- +-/* +- */ +-package com.sun.corba.se.impl.orbutil; +- +-import java.util.StringTokenizer; +-import java.util.Hashtable; +-import java.io.IOException; +-import java.lang.reflect.Method; +-import java.net.MalformedURLException; +-import org.omg.CORBA.portable.ValueBase; +-import org.omg.CORBA.portable.IDLEntity; +- +-//d11638 files in the same package, therefore remove their reference +-//import com.sun.corba.se.impl.util.JDKBridge; +-//import com.sun.corba.se.impl.util.IdentityHashtable; +-import com.sun.corba.se.impl.util.JDKBridge; +-import com.sun.corba.se.impl.util.Utility; +-import com.sun.corba.se.impl.util.PackagePrefixChecker; +-import com.sun.corba.se.impl.util.IdentityHashtable; +- +-import javax.rmi.CORBA.Util; +- +-/** +- * Because all methods in RepositoryId are static, we have +- * to duplicate all of this code, freezing it in its 1.3.1 +- * form for backwards compatibility. +- * +- * For security reasons, we can't expose enough of +- * io/ObjectStreamClass, so it has to be duplicated in +- * orbutil. +- */ +-public class RepositoryId_1_3_1 { +- +- // Legal IDL Identifier characters (1 = legal). Note +- // that '.' (2E) is marked as legal even though it is +- // not legal in IDL. This allows us to treat a fully +- // qualified Java name with '.' package separators +- // uniformly, and is safe because that is the only +- // legal use of '.' in a Java name. +- +- private static final byte[] IDL_IDENTIFIER_CHARS = { +- +- // 0 1 2 3 4 5 6 7 8 9 a b c d e f +- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 00-0f +- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 10-1f +- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,0, // 20-2f +- 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, // 30-3f +- 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // 40-4f +- 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,1, // 50-5f +- 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // 60-6f +- 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, // 70-7f +- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 80-8f +- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 90-9f +- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // a0-af +- 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // b0-bf +- 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // c0-cf +- 0,1,1,1, 1,1,1,0, 1,1,1,1, 1,0,0,1, // d0-df +- 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, // e0-ef +- 0,1,1,1, 1,1,1,0, 1,1,1,1, 1,0,0,1, // f0-ff +- }; +- +- +- private static final long serialVersionUID = 123456789L; +- +- private static String defaultServerURL = null; +- private static boolean useCodebaseOnly = false; +- +- static { +- if (defaultServerURL == null) +- defaultServerURL = (String)JDKBridge.getLocalCodebase(); +- useCodebaseOnly = JDKBridge.useCodebaseOnly(); +- +- } +- +- private static IdentityHashtable classToRepStr = new IdentityHashtable(); +- private static IdentityHashtable classIDLToRepStr = new IdentityHashtable(); +- private static IdentityHashtable classSeqToRepStr = new IdentityHashtable(); +- +- private static IdentityHashtable repStrToByteArray = new IdentityHashtable(); +- private static Hashtable repStrToClass = new Hashtable(); +- +- private String repId = null; +- private boolean isSupportedFormat = true; +- private String typeString = null; +- private String versionString = null; +- private boolean isSequence = false; +- private boolean isRMIValueType = false; +- private boolean isIDLType = false; +- private String completeClassName = null; +- private String unqualifiedName = null; +- private String definedInId = null; +- private Class clazz = null; +- private String suid = null, actualSuid = null; +- private long suidLong = ObjectStreamClass_1_3_1.kDefaultUID, actualSuidLong = ObjectStreamClass_1_3_1.kDefaultUID; +- +- // Repository ID fragments +- private static final String kSequenceKeyword = "seq"; +- private static final String kValuePrefix = "RMI:"; +- private static final String kIDLPrefix = "IDL:"; +- private static final String kIDLNamePrefix = "omg.org/"; +- private static final String kIDLClassnamePrefix = "org.omg."; +- private static final String kSequencePrefix = "["; +- private static final String kCORBAPrefix = "CORBA/"; +- private static final String kArrayPrefix = kValuePrefix + kSequencePrefix + kCORBAPrefix; +- private static final int kValuePrefixLength = kValuePrefix.length(); +- private static final int kIDLPrefixLength = kIDLPrefix.length(); +- private static final int kSequencePrefixLength = kSequencePrefix.length(); +- private static final String kInterfaceHashCode = ":0000000000000000"; +- private static final String kInterfaceOnlyHashStr = "0000000000000000"; +- private static final String kExternalizableHashStr = "0000000000000001"; +- +- // Value tag utility methods and constants +- public static final int kInitialValueTag= 0x7fffff00; +- public static final int kNoTypeInfo = 0; +- public static final int kSingleRepTypeInfo = 0x02; +- public static final int kPartialListTypeInfo = 0x06; +- public static final int kChunkedMask = 0x08; +- public static final int kPreComputed_StandardRMIUnchunked = RepositoryId_1_3_1.computeValueTag(false, RepositoryId_1_3_1.kSingleRepTypeInfo, false); +- public static final int kPreComputed_CodeBaseRMIUnchunked = RepositoryId_1_3_1.computeValueTag(true, RepositoryId_1_3_1.kSingleRepTypeInfo, false); +- public static final int kPreComputed_StandardRMIChunked = RepositoryId_1_3_1.computeValueTag(false, RepositoryId_1_3_1.kSingleRepTypeInfo, true); +- public static final int kPreComputed_CodeBaseRMIChunked = RepositoryId_1_3_1.computeValueTag(true, RepositoryId_1_3_1.kSingleRepTypeInfo, true); +- +- public static final int kPreComputed_StandardRMIUnchunked_NoRep = RepositoryId_1_3_1.computeValueTag(false, RepositoryId_1_3_1.kNoTypeInfo, false); +- public static final int kPreComputed_CodeBaseRMIUnchunked_NoRep = RepositoryId_1_3_1.computeValueTag(true, RepositoryId_1_3_1.kNoTypeInfo, false); +- public static final int kPreComputed_StandardRMIChunked_NoRep = RepositoryId_1_3_1.computeValueTag(false, RepositoryId_1_3_1.kNoTypeInfo, true); +- public static final int kPreComputed_CodeBaseRMIChunked_NoRep = RepositoryId_1_3_1.computeValueTag(true, RepositoryId_1_3_1.kNoTypeInfo, true); +- +- // Public, well known repository IDs +- +- // _REVISIT_ : A table structure with a good search routine for all of this +- // would be more efficient and easier to maintain... +- +- // String +- public static final String kWStringValueVersion = "1.0"; +- public static final String kWStringValueHash = ":"+kWStringValueVersion; +- public static final String kWStringStubValue = "WStringValue"; +- public static final String kWStringTypeStr = "omg.org/CORBA/"+kWStringStubValue; +- public static final String kWStringValueRepID = kIDLPrefix + kWStringTypeStr + kWStringValueHash; +- +- // Any +- public static final String kAnyRepID = kIDLPrefix + "omg.org/CORBA/Any"; +- +- // Class +- // Anita4: convert to uppercase +- public static final String kClassDescValueHash = ":" + +- Long.toHexString( +- ObjectStreamClass_1_3_1.getActualSerialVersionUID(javax.rmi.CORBA.ClassDesc.class)).toUpperCase() + ":" + +- Long.toHexString( +- ObjectStreamClass_1_3_1.getSerialVersionUID(javax.rmi.CORBA.ClassDesc.class)).toUpperCase(); +- public static final String kClassDescStubValue = "ClassDesc"; +- public static final String kClassDescTypeStr = "javax.rmi.CORBA."+kClassDescStubValue; +- public static final String kClassDescValueRepID = kValuePrefix + kClassDescTypeStr + kClassDescValueHash; +- +- // Object +- public static final String kObjectValueHash = ":1.0"; +- public static final String kObjectStubValue = "Object"; +- +- // Sequence +- public static final String kSequenceValueHash = ":1.0"; +- public static final String kPrimitiveSequenceValueHash = ":0000000000000000"; +- +- // Serializable +- public static final String kSerializableValueHash = ":1.0"; +- public static final String kSerializableStubValue = "Serializable"; +- +- // Externalizable +- public static final String kExternalizableValueHash = ":1.0"; +- public static final String kExternalizableStubValue = "Externalizable"; +- +- // Remote (The empty string is used for java.rmi.Remote) +- public static final String kRemoteValueHash = ""; +- public static final String kRemoteStubValue = ""; +- public static final String kRemoteTypeStr = ""; +- public static final String kRemoteValueRepID = ""; +- +- private static final Hashtable kSpecialArrayTypeStrings = new Hashtable(); +- +- static { +- kSpecialArrayTypeStrings.put("CORBA.WStringValue", new StringBuffer(java.lang.String.class.getName())); +- kSpecialArrayTypeStrings.put("javax.rmi.CORBA.ClassDesc", new StringBuffer(java.lang.Class.class.getName())); +- kSpecialArrayTypeStrings.put("CORBA.Object", new StringBuffer(java.rmi.Remote.class.getName())); +- +- } +- +- private static final Hashtable kSpecialCasesRepIDs = new Hashtable(); +- +- static { +- kSpecialCasesRepIDs.put(java.lang.String.class, kWStringValueRepID); +- kSpecialCasesRepIDs.put(java.lang.Class.class, kClassDescValueRepID); +- kSpecialCasesRepIDs.put(java.rmi.Remote.class, kRemoteValueRepID); +- } +- +- private static final Hashtable kSpecialCasesStubValues = new Hashtable(); +- +- static { +- kSpecialCasesStubValues.put(java.lang.String.class, kWStringStubValue); +- kSpecialCasesStubValues.put(java.lang.Class.class, kClassDescStubValue); +- kSpecialCasesStubValues.put(java.lang.Object.class, kObjectStubValue); +- kSpecialCasesStubValues.put(java.io.Serializable.class, kSerializableStubValue); +- kSpecialCasesStubValues.put(java.io.Externalizable.class, kExternalizableStubValue); +- kSpecialCasesStubValues.put(java.rmi.Remote.class, kRemoteStubValue); +- } +- +- +- private static final Hashtable kSpecialCasesVersions = new Hashtable(); +- +- static { +- kSpecialCasesVersions.put(java.lang.String.class, kWStringValueHash); +- kSpecialCasesVersions.put(java.lang.Class.class, kClassDescValueHash); +- kSpecialCasesVersions.put(java.lang.Object.class, kObjectValueHash); +- kSpecialCasesVersions.put(java.io.Serializable.class, kSerializableValueHash); +- kSpecialCasesVersions.put(java.io.Externalizable.class, kExternalizableValueHash); +- kSpecialCasesVersions.put(java.rmi.Remote.class, kRemoteValueHash); +- } +- +- private static final Hashtable kSpecialCasesClasses = new Hashtable(); +- +- static { +- kSpecialCasesClasses.put(kWStringTypeStr, java.lang.String.class); +- kSpecialCasesClasses.put(kClassDescTypeStr, java.lang.Class.class); +- kSpecialCasesClasses.put(kRemoteTypeStr, java.rmi.Remote.class); +- +- kSpecialCasesClasses.put("org.omg.CORBA.WStringValue", java.lang.String.class); +- kSpecialCasesClasses.put("javax.rmi.CORBA.ClassDesc", java.lang.Class.class); +- //kSpecialCasesClasses.put(kRemoteTypeStr, java.rmi.Remote.class); +- } +- +- private static final Hashtable kSpecialCasesArrayPrefix = new Hashtable(); +- +- static { +- kSpecialCasesArrayPrefix.put(java.lang.String.class, kValuePrefix + kSequencePrefix + kCORBAPrefix); +- kSpecialCasesArrayPrefix.put(java.lang.Class.class, kValuePrefix + kSequencePrefix + "javax/rmi/CORBA/"); +- kSpecialCasesArrayPrefix.put(java.lang.Object.class, kValuePrefix + kSequencePrefix + "java/lang/"); +- kSpecialCasesArrayPrefix.put(java.io.Serializable.class, kValuePrefix + kSequencePrefix + "java/io/"); +- kSpecialCasesArrayPrefix.put(java.io.Externalizable.class, kValuePrefix + kSequencePrefix + "java/io/"); +- kSpecialCasesArrayPrefix.put(java.rmi.Remote.class, kValuePrefix + kSequencePrefix + kCORBAPrefix); +- } +- +- private static final Hashtable kSpecialPrimitives = new Hashtable(); +- +- static { +- kSpecialPrimitives.put("int","long"); +- kSpecialPrimitives.put("long","longlong"); +- kSpecialPrimitives.put("byte","octet"); +- } +- +- /** +- * Used to convert ascii to hex. +- */ +- private static final byte ASCII_HEX[] = { +- (byte)'0', +- (byte)'1', +- (byte)'2', +- (byte)'3', +- (byte)'4', +- (byte)'5', +- (byte)'6', +- (byte)'7', +- (byte)'8', +- (byte)'9', +- (byte)'A', +- (byte)'B', +- (byte)'C', +- (byte)'D', +- (byte)'E', +- (byte)'F', +- }; +- +- +- // bug fix for 4328952; to eliminate possibility of overriding this +- // in a subclass. +- public static final RepositoryIdCache_1_3_1 cache = new RepositoryIdCache_1_3_1(); +- +- // Interface Rep ID Strings +- public static final String kjava_rmi_Remote = createForAnyType(java.rmi.Remote.class); +- public static final String korg_omg_CORBA_Object = createForAnyType(org.omg.CORBA.Object.class); +- +- // Dummy arguments for getIdFromHelper method +- public static final Class kNoParamTypes[] ={}; +- public static final Object kNoArgs[] = {}; +- +- +- // To create a RepositoryID, use code similar to the following: +- // RepositoryId.cache.getId( id ); +- +- RepositoryId_1_3_1(){} +- +- RepositoryId_1_3_1(String aRepId){ +- init(aRepId); +- } +- +- RepositoryId_1_3_1 init(String aRepId){ +- +- this.repId = aRepId; +- +- // Special case for remote +- if (aRepId.length() == 0) { +- clazz = java.rmi.Remote.class; +- typeString = ""; +- isRMIValueType = true; +- suid = kInterfaceOnlyHashStr; +- return this; +- } +- else if (aRepId.equals(kWStringValueRepID)) { +- clazz = java.lang.String.class; +- typeString = kWStringTypeStr; +- isIDLType = true; +- // fix where Attempting to obtain a FullValueDescription +- // for an RMI value type with a String field causes an exception. +- completeClassName = "java.lang.String"; +- versionString = kWStringValueVersion; +- return this; +- } +- else { +- +- String repId = convertFromISOLatin1(aRepId); +- +- versionString = repId.substring(repId.indexOf(':', repId.indexOf(':')+1)); +- if (repId.startsWith(kIDLPrefix)) { +- typeString = +- repId.substring(kIDLPrefixLength, repId.indexOf(':', kIDLPrefixLength)); +- isIDLType = true; +- if (typeString.startsWith(kIDLNamePrefix)) +- completeClassName = kIDLClassnamePrefix + +- typeString.substring(kIDLNamePrefix.length()).replace('/','.'); +- else completeClassName = typeString.replace('/','.'); +- +- } +- else if (repId.startsWith(kValuePrefix)) { +- typeString = +- repId.substring(kValuePrefixLength, repId.indexOf(':', kValuePrefixLength)); +- isRMIValueType = true; +- +- if (versionString.indexOf('.') == -1) { +- actualSuid = versionString.substring(1); +- suid = actualSuid; // default if not explicitly specified +- +- if (actualSuid.indexOf(':') != -1){ +- // we have a declared hash also +- int pos = actualSuid.indexOf(':')+1; +- // actualSuid = suid.substring(pos); +- // suid = suid.substring(0, pos-1); +- suid = actualSuid.substring(pos); +- actualSuid = actualSuid.substring(0, pos-1); +- } +- +- } +- else { +- // _REVISIT_ : Special case version failure ? +- } +- } +- else isSupportedFormat = false; +- +- if (typeString.startsWith(kSequencePrefix)) { +- isSequence = true; +- } +- +- +- return this; +- } +- } +- +- public final String getUnqualifiedName() { +- if (unqualifiedName == null){ +- String className = getClassName(); +- int index = className.lastIndexOf('.'); +- if (index == -1){ +- unqualifiedName = className; +- definedInId = "IDL::1.0"; +- } +- else { +- unqualifiedName = className.substring(index); +- definedInId = "IDL:" + className.substring(0, index).replace('.','/') + ":1.0"; +- } +- } +- +- return unqualifiedName; +- } +- +- public final String getDefinedInId() { +- if (definedInId == null){ +- getUnqualifiedName(); +- } +- +- return definedInId; +- } +- +- public final String getTypeString() { +- return typeString; +- } +- +- public final String getVersionString() { +- return versionString; +- } +- +- public final String getSerialVersionUID() { +- return suid; +- } +- +- public final String getActualSerialVersionUID() { +- return actualSuid; +- } +- public final long getSerialVersionUIDAsLong() { +- return suidLong; +- } +- +- public final long getActualSerialVersionUIDAsLong() { +- return actualSuidLong; +- } +- +- public final boolean isRMIValueType() { +- return isRMIValueType; +- } +- +- public final boolean isIDLType() { +- return isIDLType; +- } +- +- public final String getRepositoryId() { +- return repId; +- } +- +- public static byte[] getByteArray(String repStr) { +- synchronized (repStrToByteArray){ +- return (byte[]) repStrToByteArray.get(repStr); +- } +- } +- +- public static void setByteArray(String repStr, byte[] repStrBytes) { +- synchronized (repStrToByteArray){ +- repStrToByteArray.put(repStr, repStrBytes); +- } +- } +- +- public final boolean isSequence() { +- return isSequence; +- } +- +- public final boolean isSupportedFormat() { +- return isSupportedFormat; +- } +- +- +- // This method will return the classname from the typestring OR if the classname turns out to be +- // a special class "pseudo" name, then the matching real classname is returned. +- public final String getClassName() { +- +- if (isRMIValueType) +- return typeString; +- else if (isIDLType) +- return completeClassName; +- else return null; +- +- } +- +- // This method calls getClazzFromType() and falls back to the repStrToClass +- // cache if no class was found. It's used where any class matching the +- // given repid is an acceptable result. +- public final Class getAnyClassFromType() throws ClassNotFoundException { +- try { +- return getClassFromType(); +- } catch (ClassNotFoundException cnfe) { +- Class clz = (Class)repStrToClass.get(repId); +- if (clz != null) +- return clz; +- else +- throw cnfe; +- } +- } +- +- public final Class getClassFromType() +- throws ClassNotFoundException { +- if (clazz != null) +- return clazz; +- +- Class specialCase = (Class)kSpecialCasesClasses.get(getClassName()); +- +- if (specialCase != null){ +- clazz = specialCase; +- return specialCase; +- } +- else +- { +- try{ +- return Util.loadClass(getClassName(), null, null); +- } +- catch(ClassNotFoundException cnfe){ +- if (defaultServerURL != null) { +- try{ +- return getClassFromType(defaultServerURL); +- } +- catch(MalformedURLException mue){ +- throw cnfe; +- } +- } +- else throw cnfe; +- } +- } +- +- } +- +- public final Class getClassFromType(Class expectedType, String codebase) +- throws ClassNotFoundException { +- if (clazz != null) +- return clazz; +- +- Class specialCase = (Class)kSpecialCasesClasses.get(getClassName()); +- +- if (specialCase != null){ +- clazz = specialCase; +- return specialCase; +- } else { +- ClassLoader expectedTypeClassLoader = (expectedType == null ? null : expectedType.getClassLoader()); +- return loadClassOfType(getClassName(), +- codebase, +- expectedTypeClassLoader, +- expectedType, +- expectedTypeClassLoader); +- } +- +- } +- +- public final Class getClassFromType(String url) +- throws ClassNotFoundException, MalformedURLException { +- return Util.loadClass(getClassName(), url, null); +- } +- +- public final String toString() { +- return repId; +- } +- +- /** +- * Checks to see if the FullValueDescription should be retrieved. +- * @exception Throws IOException if suids do not match or if the repositoryID +- * is not an RMIValueType +- */ +- public static boolean useFullValueDescription(Class clazz, String repositoryID) +- throws IOException{ +- +- String clazzRepIDStr = createForAnyType(clazz); +- +- if (clazzRepIDStr.equals(repositoryID)) +- return false; +- +- RepositoryId_1_3_1 targetRepid; +- RepositoryId_1_3_1 clazzRepid; +- +- synchronized(cache) { +- // to avoid race condition where multiple threads could be +- // accessing this method, and their access to the cache may +- // be interleaved giving unexpected results +- +- targetRepid = cache.getId(repositoryID); +- clazzRepid = cache.getId(clazzRepIDStr); +- } +- //ObjectStreamClass osc = ObjectStreamClass.lookup(clazz); +- +- if ((targetRepid.isRMIValueType()) && (clazzRepid.isRMIValueType())){ +- if (!targetRepid.getSerialVersionUID().equals(clazzRepid.getSerialVersionUID())) { +- +- String mssg = "Mismatched serialization UIDs : Source (Rep. ID" + +- clazzRepid + ") = " + +- clazzRepid.getSerialVersionUID() + " whereas Target (Rep. ID " + repositoryID + +- ") = " + targetRepid.getSerialVersionUID(); +- //com.sun.corba.se.impl.io.ValueUtility.log("RepositoryId",mssg); +- throw new IOException(mssg); +- } +- else { +- return true; +- } +- } +- else { +- +- throw new IOException("The repository ID is not of an RMI value type (Expected ID = " + clazzRepIDStr + "; Received ID = " + repositoryID +")"); +- } +- } +- +- private static String createHashString(java.io.Serializable ser) { +- +- return createHashString(ser.getClass()); +- } +- +- private static String createHashString(java.lang.Class clazz) { +- +- if (clazz.isInterface() || !java.io.Serializable.class.isAssignableFrom(clazz)) +- return kInterfaceHashCode; +- +- //ObjectStreamClass osc = ObjectStreamClass.lookup(clazz); +- +- long actualLong = ObjectStreamClass_1_3_1.getActualSerialVersionUID(clazz); +- String hash = null; +- if (actualLong == 0) +- hash = kInterfaceOnlyHashStr; +- else if (actualLong == 1) +- hash = kExternalizableHashStr; +- else +- hash = Long.toHexString(actualLong).toUpperCase(); +- while(hash.length() < 16){ +- hash = "0" + hash; +- } +- +- long declaredLong = ObjectStreamClass_1_3_1.getSerialVersionUID(clazz); +- String declared = null; +- if (declaredLong == 0) +- declared = kInterfaceOnlyHashStr; +- else if (declaredLong == 1) +- declared = kExternalizableHashStr; +- else +- declared = Long.toHexString(declaredLong).toUpperCase(); +- while (declared.length() < 16){ +- declared = "0" + declared; +- } +- hash = hash + ":" + declared; +- +- return ":" + hash; +- } +- +- /** +- * Creates a repository ID for a sequence. This is for expert users only as +- * this method assumes the object passed is an array. If passed an object +- * that is not an array, it will produce a rep id for a sequence of zero +- * length. This would be an error. +- * @param ser The Java object to create a repository ID for +- **/ +- public static String createSequenceRepID(java.lang.Object ser){ +- return createSequenceRepID(ser.getClass()); +- } +- +- /** +- * Creates a repository ID for a sequence. This is for expert users only as +- * this method assumes the object passed is an array. If passed an object +- * that is not an array, it will produce a malformed rep id. +- * @param clazz The Java class to create a repository ID for +- **/ +- public static String createSequenceRepID(java.lang.Class clazz){ +- synchronized (classSeqToRepStr){ +- +- String repid = (String)classSeqToRepStr.get(clazz); +- if (repid != null) +- return repid; +- +- Class originalClazz = clazz; +- +- Class type = null; +- int numOfDims = 0; +- +- while ((type = clazz.getComponentType()) != null) { +- numOfDims++; +- clazz = type; +- } +- +- if (clazz.isPrimitive()) +- repid = kValuePrefix + originalClazz.getName() + kPrimitiveSequenceValueHash; +- else { +- StringBuffer buf = new StringBuffer(); +- buf.append(kValuePrefix); +- while(numOfDims-- > 0) { +- buf.append("["); +- } +- buf.append("L"); +- buf.append(convertToISOLatin1(clazz.getName())); +- buf.append(";"); +- buf.append(createHashString(clazz)); +- repid = buf.toString(); +- } +- classSeqToRepStr.put(originalClazz,repid); +- return repid; +- } +- +- } +- +- +- public static String createForSpecialCase(java.lang.Class clazz){ +- if (clazz.isArray()){ +- return createSequenceRepID(clazz); +- } +- else { +- return (String)kSpecialCasesRepIDs.get(clazz); +- } +- } +- +- public static String createForSpecialCase(java.io.Serializable ser){ +- Class clazz = ser.getClass(); +- if (clazz.isArray()){ +- return createSequenceRepID(ser); +- } +- else +- return createForSpecialCase(clazz); +- } +- +- /** +- * Creates a repository ID for a normal Java Type. +- * @param ser The Java object to create a repository ID for +- * @exception com.sun.corba.se.impl.io.TypeMismatchException if ser implements the +- * org.omg.CORBA.portable.IDLEntity interface which indicates it is an IDL Value type. +- **/ +- public static String createForJavaType(java.io.Serializable ser) +- throws com.sun.corba.se.impl.io.TypeMismatchException +- { +- synchronized (classToRepStr) { +- String repid = createForSpecialCase(ser); +- if (repid != null) +- return repid; +- Class clazz = ser.getClass(); +- repid = (String)classToRepStr.get(clazz); +- +- if (repid != null) +- return repid; +- +- repid = kValuePrefix + convertToISOLatin1(clazz.getName()) + +- createHashString(clazz); +- +- classToRepStr.put(clazz, repid); +- repStrToClass.put(repid, clazz); +- return repid; +- } +- } +- +- /** +- * Creates a repository ID for a normal Java Type. +- * @param clz The Java class to create a repository ID for +- * @exception com.sun.corba.se.impl.io.TypeMismatchException if ser implements the +- * org.omg.CORBA.portable.IDLEntity interface which indicates it is an IDL Value type. +- **/ +- public static String createForJavaType(Class clz) +- throws com.sun.corba.se.impl.io.TypeMismatchException +- { +- synchronized (classToRepStr){ +- String repid = createForSpecialCase(clz); +- if (repid != null) +- return repid; +- +- repid = (String)classToRepStr.get(clz); +- if (repid != null) +- return repid; +- +- repid = kValuePrefix + convertToISOLatin1(clz.getName()) + +- createHashString(clz); +- +- classToRepStr.put(clz, repid); +- repStrToClass.put(repid, clz); +- return repid; +- } +- } +- +- /** +- * Creates a repository ID for an IDL Java Type. +- * @param ser The IDL Value object to create a repository ID for +- * @param major The major version number +- * @param minor The minor version number +- * @exception com.sun.corba.se.impl.io.TypeMismatchException if ser does not implement the +- * org.omg.CORBA.portable.IDLEntity interface which indicates it is an IDL Value type. +- **/ +- public static String createForIDLType(Class ser, int major, int minor) +- throws com.sun.corba.se.impl.io.TypeMismatchException +- { +- synchronized (classIDLToRepStr){ +- String repid = (String)classIDLToRepStr.get(ser); +- if (repid != null) +- return repid; +- +- repid = kIDLPrefix + convertToISOLatin1(ser.getName()).replace('.','/') + +- ":" + major + "." + minor; +- classIDLToRepStr.put(ser, repid); +- return repid; +- } +- } +- +- private static String getIdFromHelper(Class clazz){ +- try { +- Class helperClazz = Utility.loadClassForClass(clazz.getName()+"Helper", null, +- clazz.getClassLoader(), clazz, clazz.getClassLoader()); +- Method idMethod = helperClazz.getDeclaredMethod("id", kNoParamTypes); +- return (String)idMethod.invoke(null, kNoArgs); +- } +- catch(java.lang.ClassNotFoundException cnfe) +- { +- throw new org.omg.CORBA.MARSHAL(cnfe.toString()); +- } +- catch(java.lang.NoSuchMethodException nsme) +- { +- throw new org.omg.CORBA.MARSHAL(nsme.toString()); +- } +- catch(java.lang.reflect.InvocationTargetException ite) +- { +- throw new org.omg.CORBA.MARSHAL(ite.toString()); +- } +- catch(java.lang.IllegalAccessException iae) +- { +- throw new org.omg.CORBA.MARSHAL(iae.toString()); +- } +- } +- +- /** +- * Createa a repository ID for the type if it is either a java type +- * or an IDL type. +- * @param type The type to create rep. id for +- * @return The rep. id. +- **/ +- public static String createForAnyType(Class type) { +- try{ +- if (type.isArray()) +- return createSequenceRepID(type); +- else if (IDLEntity.class.isAssignableFrom(type)) +- { +- try{ +- return getIdFromHelper(type); +- } +- catch(Throwable t) { +- return createForIDLType(type, 1, 0); +- } +- } +- else return createForJavaType(type); +- } +- catch(com.sun.corba.se.impl.io.TypeMismatchException e){ +- return null; +- } +- +- } +- +- public static boolean isAbstractBase(Class clazz) { +- return (clazz.isInterface() && +- IDLEntity.class.isAssignableFrom(clazz) && +- (!ValueBase.class.isAssignableFrom(clazz)) && +- (!org.omg.CORBA.Object.class.isAssignableFrom(clazz))); +- +- } +- +- public static boolean isAnyRequired(Class clazz) { +- return ((clazz == java.lang.Object.class) || +- (clazz == java.io.Serializable.class) || +- (clazz == java.io.Externalizable.class)); +- } +- +- public static long fromHex(String hexNumber) { +- if (hexNumber.startsWith("0x")) +- return Long.valueOf(hexNumber.substring(2), 16).longValue(); +- else return Long.valueOf(hexNumber, 16).longValue(); +- } +- +- /** +- * Convert strings with illegal IDL identifier characters. +- * <p> +- * Section 5.5.7 of OBV spec. +- */ +- private static String convertToISOLatin1 (String name) { +- +- int length = name.length(); +- if (length == 0) { +- return name; +- } +- StringBuffer buffer = null; +- +- for (int i = 0; i < length; i++) { +- +- char c = name.charAt(i); +- +- if (c > 255 || IDL_IDENTIFIER_CHARS[c] == 0) { +- +- // We gotta convert. Have we already started? +- +- if (buffer == null) { +- +- // No, so get set up... +- +- buffer = new StringBuffer(name.substring(0,i)); +- } +- +- // Convert the character into the IDL escape syntax... +- buffer.append( +- "\\U" + +- (char)ASCII_HEX[(c & 0xF000) >>> 12] + +- (char)ASCII_HEX[(c & 0x0F00) >>> 8] + +- (char)ASCII_HEX[(c & 0x00F0) >>> 4] + +- (char)ASCII_HEX[(c & 0x000F)]); +- +- } else { +- if (buffer != null) { +- buffer.append(c); +- } +- } +- } +- +- if (buffer != null) { +- name = buffer.toString(); +- } +- +- return name; +- } +- +- /** +- * Convert strings with ISO Latin 1 escape sequences back to original strings. +- * <p> +- * Section 5.5.7 of OBV spec. +- */ +- private static String convertFromISOLatin1 (String name) { +- +- int index = -1; +- StringBuffer buf = new StringBuffer(name); +- +- while ((index = buf.toString().indexOf("\\U")) != -1){ +- String str = "0000" + buf.toString().substring(index+2, index+6); +- +- // Convert Hexadecimal +- byte[] buffer = new byte[(str.length() - 4) / 2]; +- for (int i=4, j=0; i < str.length(); i +=2, j++) { +- buffer[j] = (byte)((ORBUtility.hexOf(str.charAt(i)) << 4) & 0xF0); +- buffer[j] |= (byte)((ORBUtility.hexOf(str.charAt(i+1)) << 0) & 0x0F); +- } +- buf = new StringBuffer(delete(buf.toString(), index, index+6)); +- buf.insert(index, (char)buffer[1]); +- } +- +- return buf.toString(); +- +- +- } +- +- private static String delete(String str, int from, int to) +- { +- return str.substring(0, from) + str.substring(to, str.length()); +- } +- +- private static String replace(String target, String arg, String source) +- { +- int i = 0; +- i = target.indexOf(arg); +- +- while(i != -1) +- { +- String left = target.substring(0, i); +- String right = target.substring(i+arg.length()); +- target = new String(left+source+right); +- i = target.indexOf(arg); +- } +- return target; +- } +- +- public static int computeValueTag(boolean codeBasePresent, int typeInfo, boolean chunkedEncoding){ +- int value_tag = kInitialValueTag; +- +- if (codeBasePresent) +- value_tag = value_tag | 0x00000001; +- +- value_tag = value_tag | typeInfo; +- +- if (chunkedEncoding) +- value_tag = value_tag | kChunkedMask; +- +- return value_tag; +- } +- +- public static boolean isCodeBasePresent(int value_tag){ +- return ((value_tag & 0x00000001) == 1); +- } +- +- public static int getTypeInfo(int value_tag){ +- return (value_tag & 0x00000006); +- } +- +- public static boolean isChunkedEncoding(int value_tag){ +- return ((value_tag & kChunkedMask) != 0); +- } +- +- public static String getServerURL(){ +- return defaultServerURL; +- } +- +- /* +- * Load a class and check that it is assignable to a given type. +- * @param className the class name. +- * @param remoteCodebase the codebase to use. May be null. +- * @param loader the class loader of last resort. May be null. +- * @param expectedType the expected type. May be null. +- * @return the loaded class. +- */ +- private Class loadClassOfType (String className, +- String remoteCodebase, +- ClassLoader loader, +- Class expectedType, +- ClassLoader expectedTypeClassLoader) +- throws ClassNotFoundException { +- +- Class loadedClass = null; +- +- try { +- //Sequence finding of the stubs according to spec +- try{ +- //If-else is put here for speed up of J2EE. +- //According to the OMG spec, the if clause is not dead code. +- //It can occur if some compiler has allowed generation +- //into org.omg.stub hierarchy for non-offending +- //classes. This will encourage people to +- //produce non-offending class stubs in their own hierarchy. +- if(!PackagePrefixChecker +- .hasOffendingPrefix(PackagePrefixChecker +- .withoutPackagePrefix(className))){ +- loadedClass = Util.loadClass +- (PackagePrefixChecker.withoutPackagePrefix(className), +- remoteCodebase, +- loader); +- } else { +- loadedClass = Util.loadClass +- (className, +- remoteCodebase, +- loader); +- } +- } catch (ClassNotFoundException cnfe) { +- loadedClass = Util.loadClass +- (className, +- remoteCodebase, +- loader); +- } +- if (expectedType == null) +- return loadedClass; +- } catch (ClassNotFoundException cnfe) { +- if (expectedType == null) +- throw cnfe; +- } +- +- // If no class was not loaded, or if the loaded class is not of the +- // correct type, make a further attempt to load the correct class +- // using the classloader of the expected type. +- // _REVISIT_ Is this step necessary, or should the Util,loadClass +- // algorithm always produce a valid class if the setup is correct? +- // Does the OMG standard algorithm need to be changed to include +- // this step? +- if (loadedClass == null || !expectedType.isAssignableFrom(loadedClass)) { +- if (expectedType.getClassLoader() != expectedTypeClassLoader) +- throw new IllegalArgumentException("expectedTypeClassLoader not class loader of expectedType."); +- +- if (expectedTypeClassLoader != null) +- loadedClass = expectedTypeClassLoader.loadClass(className); +- else +- loadedClass = Class.forName(className); +- } +- +- return loadedClass; +- } +-} +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/ValueHandlerImpl_1_3.java b/src/share/classes/com/sun/corba/se/impl/orbutil/ValueHandlerImpl_1_3.java +deleted file mode 100644 +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/ValueHandlerImpl_1_3.java ++++ /dev/null +@@ -1,251 +0,0 @@ +-/* +- * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. +- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License version 2 only, as +- * published by the Free Software Foundation. Oracle designates this +- * particular file as subject to the "Classpath" exception as provided +- * by Oracle in the LICENSE file that accompanied this code. +- * +- * This code is distributed in the hope that it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +- * version 2 for more details (a copy is included in the LICENSE file that +- * accompanied this code). +- * +- * You should have received a copy of the GNU General Public License version +- * 2 along with this work; if not, write to the Free Software Foundation, +- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +- * or visit www.oracle.com if you need additional information or have any +- * questions. +- */ +-/* +- * Licensed Materials - Property of IBM +- * RMI-IIOP v1.0 +- * Copyright IBM Corp. 1998 1999 All Rights Reserved +- * +- */ +- +-package com.sun.corba.se.impl.orbutil; +- +-import javax.rmi.CORBA.Util; +-import javax.rmi.PortableRemoteObject; +- +-import java.util.Hashtable; +-import java.util.Stack; +-import java.io.IOException; +-import java.util.EmptyStackException; +- +-import com.sun.corba.se.impl.util.Utility; +-import com.sun.corba.se.impl.io.IIOPInputStream; +-import com.sun.corba.se.impl.io.IIOPOutputStream; +-import com.sun.corba.se.impl.util.RepositoryId; +-import com.sun.corba.se.impl.util.Utility; +- +-import org.omg.CORBA.TCKind; +-import org.omg.CORBA.MARSHAL; +-import org.omg.CORBA.CompletionStatus; +-import org.omg.CORBA.portable.IndirectionException; +-import com.sun.org.omg.SendingContext.CodeBase; +- +-import java.security.AccessController; +-import java.security.PrivilegedAction; +- +-/** +- * This class overrides behavior of our current ValueHandlerImpl to +- * provide backwards compatibility with JDK 1.3.0. +- */ +-public class ValueHandlerImpl_1_3 extends com.sun.corba.se.impl.io.ValueHandlerImpl { +- +- public ValueHandlerImpl_1_3(){ +- super(); +- } +- +- public ValueHandlerImpl_1_3(boolean isInputStream) { +- super(isInputStream); +- } +- +- /** +- * Writes the value to the stream using java semantics. +- * @param out The stream to write the value to +- * @param value The value to be written to the stream +- **/ +- public void writeValue(org.omg.CORBA.portable.OutputStream _out, java.io.Serializable value) { +- super.writeValue(_out, value); +- } +- +- /** +- * Reads a value from the stream using java semantics. +- * @param in The stream to read the value from +- * @param clazz The type of the value to be read in +- * @param sender The sending context runtime +- **/ +- public java.io.Serializable readValue(org.omg.CORBA.portable.InputStream _in, +- int offset, +- java.lang.Class clazz, +- String repositoryID, +- org.omg.SendingContext.RunTime _sender) +- { +- return super.readValue(_in, offset, clazz, repositoryID, _sender); +- } +- +- /** +- * Returns the repository ID for the given RMI value Class. +- * @param clz The class to return a repository ID for. +- * @return the repository ID of the Class. +- **/ +- public java.lang.String getRMIRepositoryID(java.lang.Class clz) { +- return RepositoryId_1_3.createForJavaType(clz); +- } +- +- /** +- * Indicates whether the given Class performs custom or +- * default marshaling. +- * @param clz The class to test for custom marshaling. +- * @return True if the class performs custom marshaling, false +- * if it does not. +- **/ +- public boolean isCustomMarshaled(java.lang.Class clz) { +- return super.isCustomMarshaled(clz); +- } +- +- /** +- * Returns the CodeBase for this ValueHandler. This is used by +- * the ORB runtime. The server sends the service context containing +- * the IOR for this CodeBase on the first GIOP reply. The clients +- * do the same on the first GIOP request. +- * @return the SendingContext.CodeBase of this ValueHandler. +- **/ +- public org.omg.SendingContext.RunTime getRunTimeCodeBase() { +- return super.getRunTimeCodeBase(); +- } +- +- /** +- * If the value contains a writeReplace method then the result +- * is returned. Otherwise, the value itself is returned. +- * @return the true value to marshal on the wire. +- **/ +- public java.io.Serializable writeReplace(java.io.Serializable value) { +- return super.writeReplace(value); +- } +- +- // methods supported for backward compatability so that the appropriate +- // Rep-id calculations take place based on the ORB version +- +- /** +- * Returns a boolean of whether or not RepositoryId indicates +- * FullValueDescriptor. +- * used for backward compatability +- */ +- +- public boolean useFullValueDescription(Class clazz, String repositoryID) +- throws IOException +- +- { +- return RepositoryId_1_3.useFullValueDescription(clazz, repositoryID); +- } +- +- public String getClassName(String id) +- { +- RepositoryId_1_3 repID = RepositoryId_1_3.cache.getId(id); +- return repID.getClassName(); +- } +- +- public Class getClassFromType(String id) +- throws ClassNotFoundException +- { +- RepositoryId_1_3 repId = RepositoryId_1_3.cache.getId(id); +- return repId.getClassFromType(); +- } +- +- public Class getAnyClassFromType(String id) +- throws ClassNotFoundException +- { +- RepositoryId_1_3 repId = RepositoryId_1_3.cache.getId(id); +- return repId.getAnyClassFromType(); +- } +- +- public String createForAnyType(Class cl) +- { +- return RepositoryId_1_3.createForAnyType(cl); +- } +- +- public String getDefinedInId(String id) +- { +- RepositoryId_1_3 repId = RepositoryId_1_3.cache.getId(id); +- return repId.getDefinedInId(); +- } +- +- public String getUnqualifiedName(String id) +- { +- RepositoryId_1_3 repId = RepositoryId_1_3.cache.getId(id); +- return repId.getUnqualifiedName(); +- } +- +- public String getSerialVersionUID(String id) +- { +- RepositoryId_1_3 repId = RepositoryId_1_3.cache.getId(id); +- return repId.getSerialVersionUID(); +- } +- +- public boolean isAbstractBase(Class clazz) +- { +- return RepositoryId_1_3.isAbstractBase(clazz); +- } +- +- public boolean isSequence(String id) +- { +- RepositoryId_1_3 repId = RepositoryId_1_3.cache.getId(id); +- return repId.isSequence(); +- } +- +- /** +- * Preserves the incorrect 1.3 behavior which truncates Java chars in +- * arrays to 8-bit CORBA chars. Bug 4367783. This enables us to +- * continue interoperating with our legacy ORBs. If this goes into +- * Ladybird, then Ladybird and Kestrel will interoperate as long as +- * people don't use chars greater than 8-bits. +- */ +- protected void writeCharArray(org.omg.CORBA_2_3.portable.OutputStream out, +- char[] array, +- int offset, +- int length) +- { +- out.write_char_array(array, offset, length); +- } +- +- /** +- * Preserves the incorrect 1.3 behavior which truncates Java chars in +- * arrays to 8-bit CORBA chars. Bug 4367783. This enables us to +- * continue interoperating with our legacy ORBs. If this goes into +- * Ladybird, then Ladybird and Kestrel will interoperate as long as +- * people don't use chars greater than 8-bits. +- */ +- protected void readCharArray(org.omg.CORBA_2_3.portable.InputStream in, +- char[] array, +- int offset, +- int length) +- { +- in.read_char_array(array, offset, length); +- } +- +- protected final String getOutputStreamClassName() { +- return "com.sun.corba.se.impl.orbutil.IIOPOutputStream_1_3"; +- } +- +- protected final String getInputStreamClassName() { +- return "com.sun.corba.se.impl.orbutil.IIOPInputStream_1_3"; +- } +- +- /** +- * Our JDK 1.3 and JDK 1.3.1 behavior subclasses override this. +- * The correct behavior is for a Java char to map to a CORBA wchar, +- * but our older code mapped it to a CORBA char. +- */ +- protected TCKind getJavaCharTCKind() { +- return TCKind.tk_char; +- } +-} +diff --git a/src/share/classes/com/sun/corba/se/impl/orbutil/ValueHandlerImpl_1_3_1.java b/src/share/classes/com/sun/corba/se/impl/orbutil/ValueHandlerImpl_1_3_1.java +deleted file mode 100644 +--- corba/src/share/classes/com/sun/corba/se/impl/orbutil/ValueHandlerImpl_1_3_1.java ++++ /dev/null +@@ -1,77 +0,0 @@ +-/* +- * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. +- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +- * +- * This code is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License version 2 only, as +- * published by the Free Software Foundation. Oracle designates this +- * particular file as subject to the "Classpath" exception as provided +- * by Oracle in the LICENSE file that accompanied this code. +- * +- * This code is distributed in the hope that it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +- * version 2 for more details (a copy is included in the LICENSE file that +- * accompanied this code). +- * +- * You should have received a copy of the GNU General Public License version +- * 2 along with this work; if not, write to the Free Software Foundation, +- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +- * or visit www.oracle.com if you need additional information or have any +- * questions. +- */ +-package com.sun.corba.se.impl.orbutil; +- +-import org.omg.CORBA.TCKind; +- +-/** +- * This class overrides behavior of our current ValueHandlerImpl to +- * provide backwards compatibility with JDK 1.3.1. +- */ +-public class ValueHandlerImpl_1_3_1 +- extends com.sun.corba.se.impl.io.ValueHandlerImpl +-{ +- public ValueHandlerImpl_1_3_1() {} +- +- public ValueHandlerImpl_1_3_1(boolean isInputStream) { +- super(isInputStream); +- } +- +- /** +- * Our JDK 1.3 and JDK 1.3.1 behavior subclasses override this. +- * The correct behavior is for a Java char to map to a CORBA wchar, +- * but our older code mapped it to a CORBA char. +- */ +- protected TCKind getJavaCharTCKind() { +- return TCKind.tk_char; +- } +- +- /** +- * RepositoryId_1_3_1 performs an incorrect repId calculation +- * when using serialPersistentFields and one of the fields no longer +- * exists on the class itself. +- */ +- public boolean useFullValueDescription(Class clazz, String repositoryID) +- throws java.io.IOException +- { +- return RepositoryId_1_3_1.useFullValueDescription(clazz, repositoryID); +- } +- +- /** +- * Installs the legacy IIOPOutputStream_1_3_1 which does +- * PutFields/GetFields incorrectly. Bug 4407244. +- */ +- protected final String getOutputStreamClassName() { +- return "com.sun.corba.se.impl.orbutil.IIOPOutputStream_1_3_1"; +- } +- +- /** +- * Installs the legacy IIOPInputStream_1_3_1 which does +- * PutFields/GetFields incorrectly. Bug 4407244. +- */ +- protected final String getInputStreamClassName() { +- return "com.sun.corba.se.impl.orbutil.IIOPInputStream_1_3_1"; +- } +-} +diff --git a/src/share/classes/sun/corba/JavaCorbaAccess.java b/src/share/classes/sun/corba/JavaCorbaAccess.java +new file mode 100644 +--- /dev/null ++++ corba/src/share/classes/sun/corba/JavaCorbaAccess.java +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package sun.corba; ++ ++import com.sun.corba.se.impl.io.ValueHandlerImpl; ++ ++public interface JavaCorbaAccess { ++ public ValueHandlerImpl newValueHandlerImpl(); ++} +diff --git a/src/share/classes/sun/corba/SharedSecrets.java b/src/share/classes/sun/corba/SharedSecrets.java +new file mode 100644 +--- /dev/null ++++ corba/src/share/classes/sun/corba/SharedSecrets.java +@@ -0,0 +1,60 @@ ++/* ++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. Oracle designates this ++ * particular file as subject to the "Classpath" exception as provided ++ * by Oracle in the LICENSE file that accompanied this code. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package sun.corba; ++ ++import com.sun.corba.se.impl.io.ValueUtility; ++import sun.misc.Unsafe; ++ ++import java.security.AccessController; ++ ++/** A repository of "shared secrets", which are a mechanism for ++ calling implementation-private methods in another package without ++ using reflection. A package-private class implements a public ++ interface and provides the ability to call package-private methods ++ within that package; the object implementing that interface is ++ provided through a third package to which access is restricted. ++ This framework avoids the primary disadvantage of using reflection ++ for this purpose, namely the loss of compile-time checking. */ ++ ++// SharedSecrets cloned in corba repo to avoid build issues ++public class SharedSecrets { ++ private static final Unsafe unsafe = Unsafe.getUnsafe(); ++ private static JavaCorbaAccess javaCorbaAccess; ++ ++ public static JavaCorbaAccess getJavaCorbaAccess() { ++ if (javaCorbaAccess == null) { ++ // Ensure ValueUtility is initialized; we know that that class ++ // provides the shared secret ++ unsafe.ensureClassInitialized(ValueUtility.class); ++ } ++ return javaCorbaAccess; ++ } ++ ++ public static void setJavaCorbaAccess(JavaCorbaAccess access) { ++ javaCorbaAccess = access; ++ } ++ ++} diff --git a/java/openjdk6/files/icedtea/security/20130201/8001235.patch b/java/openjdk6/files/icedtea/security/20130201/8001235.patch new file mode 100644 index 000000000000..73d700c3bc30 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/8001235.patch @@ -0,0 +1,37 @@ +diff -Nru jaxp.old/build.properties jaxp/build.properties +--- jaxp.old/build.properties 2013-02-01 21:59:17.360429006 +0000 ++++ jaxp/build.properties 2013-02-01 22:04:56.349681812 +0000 +@@ -77,6 +77,9 @@ + # Where patches to drop bundle sources live + patches.dir=patches + ++# Patches to apply ++jaxp_src.patch.list=8001235.patch ++ + # Sanity information + sanity.info= Sanity Settings:${line.separator}\ + ant.home=${ant.home}${line.separator}\ +diff -Nru jaxp.old/patches/jaxp_src/8001235.patch jaxp/patches/jaxp_src/8001235.patch +--- jaxp.old/patches/jaxp_src/8001235.patch 1970-01-01 01:00:00.000000000 +0100 ++++ jaxp/patches/jaxp_src/8001235.patch 2013-02-01 22:04:27.369232768 +0000 +@@ -0,0 +1,20 @@ ++# HG changeset patch ++# User joehw ++# Date 1351536837 25200 ++# Node ID 5df9207c4378b7f4b24d70b365714c5ee6318982 ++# Parent 5449d5396bd8deee90f18f29899343129e3cdc4e ++8001235: Improve JAXP HTTP handling ++Reviewed-by: lancea, skoivu ++ ++diff --git a/src/com/sun/org/apache/xpath/internal/functions/FuncSystemProperty.java b/src/com/sun/org/apache/xpath/internal/functions/FuncSystemProperty.java ++--- src/com/sun/org/apache/xpath/internal/functions/FuncSystemProperty.java +++++ src/com/sun/org/apache/xpath/internal/functions/FuncSystemProperty.java ++@@ -165,7 +165,7 @@ public class FuncSystemProperty extends ++ * should already be fully qualified as path/filename ++ * @param target The target property bag the file will be placed into. ++ */ ++- public void loadPropertyFile(String file, Properties target) +++ private void loadPropertyFile(String file, Properties target) ++ { ++ try ++ { diff --git a/java/openjdk6/files/icedtea/security/20130201/8001242.patch b/java/openjdk6/files/icedtea/security/20130201/8001242.patch new file mode 100644 index 000000000000..5c983c3dc11d --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/8001242.patch @@ -0,0 +1,61 @@ +# HG changeset patch +# User dmocek +# Date 1353367979 28800 +# Node ID 49a37df9e80fae205a7b70d862cd303a62049c2c +# Parent 2281f5670cc599f0fe97c880cdceb6a7db837dc3 +8001242: Improve RMI HTTP conformance +Reviewed-by: ahgross, mchung, smarks + +diff --git a/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java b/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java +--- jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java ++++ jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java +@@ -285,11 +285,14 @@ final class CGIForwardCommand implements + "unexpected EOF reading server response"); + + if (line.toLowerCase().startsWith(key)) { +- if (contentLengthFound) +- ; // what would we want to do in this case?? +- responseContentLength = +- Integer.parseInt(line.substring(key.length()).trim()); +- contentLengthFound = true; ++ if (contentLengthFound) { ++ throw new CGIServerException( ++ "Multiple Content-length entries found."); ++ } else { ++ responseContentLength = ++ Integer.parseInt(line.substring(key.length()).trim()); ++ contentLengthFound = true; ++ } + } + } while ((line.length() != 0) && + (line.charAt(0) != '\r') && (line.charAt(0) != '\n')); +diff --git a/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java b/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java +--- jdk/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java ++++ jdk/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2001, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -70,11 +70,14 @@ class HttpInputStream extends FilterInpu + throw new EOFException(); + + if (line.toLowerCase().startsWith(key)) { +- if (contentLengthFound) +- ; // what would we want to do in this case?? +- bytesLeft = +- Integer.parseInt(line.substring(key.length()).trim()); +- contentLengthFound = true; ++ if (contentLengthFound) { ++ throw new IOException( ++ "Multiple Content-length entries found."); ++ } else { ++ bytesLeft = ++ Integer.parseInt(line.substring(key.length()).trim()); ++ contentLengthFound = true; ++ } + } + + // The idea here is to go past the first blank line. diff --git a/java/openjdk6/files/icedtea/security/20130201/8001307.patch b/java/openjdk6/files/icedtea/security/20130201/8001307.patch new file mode 100644 index 000000000000..4794f95418a7 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/8001307.patch @@ -0,0 +1,27 @@ +diff -Nru openjdk.orig/hotspot/src/share/vm/interpreter/linkResolver.cpp openjdk/hotspot/src/share/vm/interpreter/linkResolver.cpp +--- openjdk.orig/hotspot/src/share/vm/interpreter/linkResolver.cpp 2011-11-14 22:07:35.000000000 +0000 ++++ hotspot/src/share/vm/interpreter/linkResolver.cpp 2013-02-01 21:46:24.084475305 +0000 +@@ -695,7 +695,7 @@ + + if (check_access && + // a) check if ACC_SUPER flag is set for the current class +- current_klass->is_super() && ++ (current_klass->is_super() || !AllowNonVirtualCalls) && + // b) check if the method class is a superclass of the current class (superclass relation is not reflexive!) + current_klass->is_subtype_of(method_klass()) && current_klass() != method_klass() && + // c) check if the method is not <init> +diff -Nru openjdk.orig/hotspot/src/share/vm/runtime/globals.hpp openjdk/hotspot/src/share/vm/runtime/globals.hpp +--- openjdk.orig/hotspot/src/share/vm/runtime/globals.hpp 2013-02-01 21:44:12.678449777 +0000 ++++ hotspot/src/share/vm/runtime/globals.hpp 2013-02-01 21:46:57.300987338 +0000 +@@ -3700,7 +3700,10 @@ + product(bool, UseVMInterruptibleIO, false, \ + "(Unstable, Solaris-specific) Thread interrupt before or with " \ + "EINTR for I/O operations results in OS_INTRPT. The default value"\ +- " of this flag is true for JDK 6 and earliers") ++ " of this flag is true for JDK 6 and earlier") \ ++ \ ++ product(bool, AllowNonVirtualCalls, false, \ ++ "Obey the ACC_SUPER flag and allow invokenonvirtual calls") + + /* + * Macros for factoring of globals diff --git a/java/openjdk6/files/icedtea/security/20130201/8001972.patch b/java/openjdk6/files/icedtea/security/20130201/8001972.patch new file mode 100644 index 000000000000..b379b7a6b9ec --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/8001972.patch @@ -0,0 +1,438 @@ +diff -Nru openjdk.orig/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java openjdk/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java +--- openjdk.orig/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java 2011-11-14 22:11:59.000000000 +0000 ++++ jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java 2013-02-01 21:49:28.911324533 +0000 +@@ -198,7 +198,7 @@ + } + this.bandOffset = this.dataOffsets[0]; + +- verify(false); ++ verify(); + } + + /** +@@ -857,38 +857,68 @@ + } + + /** +- * Verify that the layout parameters are consistent with +- * the data. If strictCheck +- * is false, this method will check for ArrayIndexOutOfBounds conditions. If +- * strictCheck is true, this method will check for additional error +- * conditions such as line wraparound (width of a line greater than +- * the scanline stride). +- * @return String Error string, if the layout is incompatible with +- * the data. Otherwise returns null. +- */ +- private void verify (boolean strictCheck) { +- // Make sure data for Raster is in a legal range +- for (int i=0; i < dataOffsets.length; i++) { ++ * Verify that the layout parameters are consistent with the data. ++ * ++ * The method verifies whether scanline stride and pixel stride do not ++ * cause an integer overflow during calculation of a position of the pixel ++ * in data buffer. It also verifies whether the data buffer has enough data ++ * to correspond the raster layout attributes. ++ * ++ * @throws RasterFormatException if an integer overflow is detected, ++ * or if data buffer has not enough capacity. ++ */ ++ protected final void verify() { ++ for (int i = 0; i < dataOffsets.length; i++) { + if (dataOffsets[i] < 0) { +- throw new RasterFormatException("Data offsets for band "+i+ +- "("+dataOffsets[i]+ +- ") must be >= 0"); ++ throw new RasterFormatException("Data offsets for band " + i ++ + "(" + dataOffsets[i] ++ + ") must be >= 0"); + } + } + + int maxSize = 0; + int size; + +- for (int i=0; i < numDataElements; i++) { +- size = (height-1)*scanlineStride + (width-1)*pixelStride + +- dataOffsets[i]; ++ // we can be sure that width and height are greater than 0 ++ if (scanlineStride < 0 || ++ scanlineStride > (Integer.MAX_VALUE / height)) ++ { ++ // integer overflow ++ throw new RasterFormatException("Incorrect scanline stride: " ++ + scanlineStride); ++ } ++ int lastScanOffset = (height - 1) * scanlineStride; ++ ++ if (pixelStride < 0 || ++ pixelStride > (Integer.MAX_VALUE / width)) ++ { ++ // integer overflow ++ throw new RasterFormatException("Incorrect pixel stride: " ++ + pixelStride); ++ } ++ int lastPixelOffset = (width - 1) * pixelStride; ++ ++ if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) { ++ // integer overflow ++ throw new RasterFormatException("Incorrect raster attributes"); ++ } ++ lastPixelOffset += lastScanOffset; ++ ++ for (int i = 0; i < numDataElements; i++) { ++ size = lastPixelOffset + dataOffsets[i]; ++ if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) { ++ throw new RasterFormatException("Incorrect band offset: " ++ + dataOffsets[i]); ++ ++ } ++ + if (size > maxSize) { + maxSize = size; + } + } + if (data.length < maxSize) { +- throw new RasterFormatException("Data array too small (should be "+ +- maxSize+" )"); ++ throw new RasterFormatException("Data array too small (should be " ++ + maxSize + " )"); + } + } + +diff -Nru openjdk.orig/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java openjdk/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java +--- openjdk.orig/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java 2011-11-14 22:11:59.000000000 +0000 ++++ jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java 2013-02-01 21:49:28.911324533 +0000 +@@ -250,7 +250,7 @@ + } + } + +- verify(false); ++ verify(); + } + + /** +@@ -1292,33 +1292,6 @@ + return createCompatibleWritableRaster(width,height); + } + +- /** +- * Verify that the layout parameters are consistent with +- * the data. If strictCheck +- * is false, this method will check for ArrayIndexOutOfBounds conditions. If +- * strictCheck is true, this method will check for additional error +- * conditions such as line wraparound (width of a line greater than +- * the scanline stride). +- * @return String Error string, if the layout is incompatible with +- * the data. Otherwise returns null. +- */ +- private void verify (boolean strictCheck) { +- int maxSize = 0; +- int size; +- +- for (int i=0; i < numDataElements; i++) { +- size = (height-1)*scanlineStride + (width-1)*pixelStride + +- dataOffsets[i]; +- if (size > maxSize) { +- maxSize = size; +- } +- } +- if (data.length < maxSize) { +- throw new RasterFormatException("Data array too small (should be "+ +- maxSize+" )"); +- } +- } +- + public String toString() { + return new String ("ByteInterleavedRaster: width = "+width+" height = " + + height +diff -Nru openjdk.orig/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java openjdk/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java +--- openjdk.orig/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java 2011-11-14 22:11:59.000000000 +0000 ++++ jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java 2013-02-01 21:49:28.911324533 +0000 +@@ -198,7 +198,7 @@ + } + this.bandOffset = this.dataOffsets[0]; + +- verify(false); ++ verify(); + } + + /** +@@ -791,38 +791,67 @@ + } + + /** +- * Verify that the layout parameters are consistent with +- * the data. If strictCheck +- * is false, this method will check for ArrayIndexOutOfBounds conditions. If +- * strictCheck is true, this method will check for additional error +- * conditions such as line wraparound (width of a line greater than +- * the scanline stride). +- * @return String Error string, if the layout is incompatible with +- * the data. Otherwise returns null. +- */ +- private void verify (boolean strictCheck) { +- // Make sure data for Raster is in a legal range +- for (int i=0; i < dataOffsets.length; i++) { ++ * Verify that the layout parameters are consistent with the data. ++ * ++ * The method verifies whether scanline stride and pixel stride do not ++ * cause an integer overflow during calculation of a position of the pixel ++ * in data buffer. It also verifies whether the data buffer has enough data ++ * to correspond the raster layout attributes. ++ * ++ * @throws RasterFormatException if an integer overflow is detected, ++ * or if data buffer has not enough capacity. ++ */ ++ protected final void verify() { ++ for (int i = 0; i < dataOffsets.length; i++) { + if (dataOffsets[i] < 0) { +- throw new RasterFormatException("Data offsets for band "+i+ +- "("+dataOffsets[i]+ +- ") must be >= 0"); ++ throw new RasterFormatException("Data offsets for band " + i ++ + "(" + dataOffsets[i] ++ + ") must be >= 0"); + } + } + + int maxSize = 0; + int size; + +- for (int i=0; i < numDataElements; i++) { +- size = (height-1)*scanlineStride + (width-1)*pixelStride + +- dataOffsets[i]; ++ // we can be sure that width and height are greater than 0 ++ if (scanlineStride < 0 || ++ scanlineStride > (Integer.MAX_VALUE / height)) ++ { ++ // integer overflow ++ throw new RasterFormatException("Incorrect scanline stride: " ++ + scanlineStride); ++ } ++ int lastScanOffset = (height - 1) * scanlineStride; ++ ++ if (pixelStride < 0 || ++ pixelStride > (Integer.MAX_VALUE / width)) ++ { ++ // integer overflow ++ throw new RasterFormatException("Incorrect pixel stride: " ++ + pixelStride); ++ } ++ int lastPixelOffset = (width - 1) * pixelStride; ++ ++ if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) { ++ // integer overflow ++ throw new RasterFormatException("Incorrect raster attributes"); ++ } ++ lastPixelOffset += lastScanOffset; ++ ++ for (int i = 0; i < numDataElements; i++) { ++ size = lastPixelOffset + dataOffsets[i]; ++ if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) { ++ throw new RasterFormatException("Incorrect band offset: " ++ + dataOffsets[i]); ++ } ++ + if (size > maxSize) { + maxSize = size; + } + } + if (data.length < maxSize) { +- throw new RasterFormatException("Data array too small (should be "+ +- maxSize+" )"); ++ throw new RasterFormatException("Data array too small (should be " ++ + maxSize + " )"); + } + } + +diff -Nru openjdk.orig/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java openjdk/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java +--- openjdk.orig/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java 2011-11-14 22:11:59.000000000 +0000 ++++ jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java 2013-02-01 21:49:28.911324533 +0000 +@@ -171,7 +171,7 @@ + sampleModel); + } + this.bandOffset = this.dataOffsets[0]; +- verify(false); ++ verify(); + } + + /** +@@ -762,33 +762,6 @@ + return createCompatibleWritableRaster(width,height); + } + +- /** +- * Verify that the layout parameters are consistent with +- * the data. If strictCheck +- * is false, this method will check for ArrayIndexOutOfBounds conditions. If +- * strictCheck is true, this method will check for additional error +- * conditions such as line wraparound (width of a line greater than +- * the scanline stride). +- * @return String Error string, if the layout is incompatible with +- * the data. Otherwise returns null. +- */ +- private void verify (boolean strictCheck) { +- int maxSize = 0; +- int size; +- +- for (int i=0; i < numDataElements; i++) { +- size = (height-1)*scanlineStride + (width-1)*pixelStride + +- dataOffsets[i]; +- if (size > maxSize) { +- maxSize = size; +- } +- } +- if (data.length < maxSize) { +- throw new RasterFormatException("Data array too small (should be "+ +- maxSize+" )"); +- } +- } +- + public String toString() { + return new String ("ShortInterleavedRaster: width = "+width + +" height = " + height +diff -Nru openjdk.orig/jdk/src/share/native/sun/awt/image/awt_parseImage.c openjdk/jdk/src/share/native/sun/awt/image/awt_parseImage.c +--- openjdk.orig/jdk/src/share/native/sun/awt/image/awt_parseImage.c 2011-11-14 22:12:11.000000000 +0000 ++++ jdk/src/share/native/sun/awt/image/awt_parseImage.c 2013-02-01 21:54:40.100132273 +0000 +@@ -114,6 +114,62 @@ + return status; + } + ++/* Verifies whether the channel offsets are sane and correspond to the type of ++ * the raster. ++ * ++ * Return value: ++ * 0: Failure: channel offsets are invalid ++ * 1: Success ++ */ ++static int checkChannelOffsets(RasterS_t *rasterP, int dataArrayLength) { ++ int i, lastPixelOffset, lastScanOffset; ++ switch (rasterP->rasterType) { ++ case COMPONENT_RASTER_TYPE: ++ if (!SAFE_TO_MULT(rasterP->height, rasterP->scanlineStride)) { ++ return 0; ++ } ++ if (!SAFE_TO_MULT(rasterP->width, rasterP->pixelStride)) { ++ return 0; ++ } ++ ++ lastScanOffset = (rasterP->height - 1) * rasterP->scanlineStride; ++ lastPixelOffset = (rasterP->width - 1) * rasterP->pixelStride; ++ ++ ++ if (!SAFE_TO_ADD(lastPixelOffset, lastScanOffset)) { ++ return 0; ++ } ++ ++ lastPixelOffset += lastScanOffset; ++ ++ for (i = 0; i < rasterP->numDataElements; i++) { ++ int off = rasterP->chanOffsets[i]; ++ int size = lastPixelOffset + off; ++ ++ if (off < 0 || !SAFE_TO_ADD(lastPixelOffset, off)) { ++ return 0; ++ } ++ ++ if (size < lastPixelOffset || size >= dataArrayLength) { ++ // an overflow, or insufficient buffer capacity ++ return 0; ++ } ++ } ++ return 1; ++ case BANDED_RASTER_TYPE: ++ // NB:caller does not support the banded rasters yet, ++ // so this branch of the code must be re-defined in ++ // order to provide valid criteria for the data offsets ++ // verification, when/if banded rasters will be supported. ++ // At the moment, we prohibit banded rasters as well. ++ return 0; ++ default: ++ // PACKED_RASTER_TYPE: does not support channel offsets ++ // UNKNOWN_RASTER_TYPE: should not be used, likely indicates an error ++ return 0; ++ } ++} ++ + /* Parse the raster. All of the raster information is returned in the + * rasterP structure. + * +@@ -125,7 +181,6 @@ + int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { + jobject joffs = NULL; + /* int status;*/ +- int isDiscrete = TRUE; + + if (JNU_IsNull(env, jraster)) { + JNU_ThrowNullPointerException(env, "null Raster object"); +@@ -155,6 +210,9 @@ + return -1; + } + ++ // make sure that the raster type is initialized ++ rasterP->rasterType = UNKNOWN_RASTER_TYPE; ++ + if (rasterP->numBands <= 0 || + rasterP->numBands > MAX_NUMBANDS) + { +@@ -254,7 +312,6 @@ + } + rasterP->chanOffsets[0] = (*env)->GetIntField(env, jraster, g_BPRdataBitOffsetID); + rasterP->dataType = BYTE_DATA_TYPE; +- isDiscrete = FALSE; + } + else { + rasterP->type = sun_awt_image_IntegerComponentRaster_TYPE_CUSTOM; +@@ -265,7 +322,19 @@ + return 0; + } + +- if (isDiscrete) { ++ // do basic validation of the raster structure ++ if (rasterP->width <= 0 || rasterP->height <= 0 || ++ rasterP->pixelStride <= 0 || rasterP->scanlineStride <= 0) ++ { ++ // invalid raster ++ return -1; ++ } ++ ++ // channel (data) offsets ++ switch (rasterP->rasterType) { ++ case COMPONENT_RASTER_TYPE: ++ case BANDED_RASTER_TYPE: // note that this routine does not support banded rasters at the moment ++ // get channel (data) offsets + rasterP->chanOffsets = NULL; + if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) { + rasterP->chanOffsets = +@@ -278,6 +347,17 @@ + } + (*env)->GetIntArrayRegion(env, joffs, 0, rasterP->numDataElements, + rasterP->chanOffsets); ++ if (rasterP->jdata == NULL) { ++ // unable to verify the raster ++ return -1; ++ } ++ // verify whether channel offsets look sane ++ if (!checkChannelOffsets(rasterP, (*env)->GetArrayLength(env, rasterP->jdata))) { ++ return -1; ++ } ++ break; ++ default: ++ ; // PACKED_RASTER_TYPE does not use the channel offsets. + } + + #if 0 +diff -Nru openjdk.orig/jdk/src/share/native/sun/awt/medialib/safe_alloc.h openjdk/jdk/src/share/native/sun/awt/medialib/safe_alloc.h +--- openjdk.orig/jdk/src/share/native/sun/awt/medialib/safe_alloc.h 2011-11-14 22:12:12.000000000 +0000 ++++ jdk/src/share/native/sun/awt/medialib/safe_alloc.h 2013-02-01 21:49:28.911324533 +0000 +@@ -41,5 +41,10 @@ + (((w) > 0) && ((h) > 0) && ((sz) > 0) && \ + (((0xffffffffu / ((juint)(w))) / ((juint)(h))) > ((juint)(sz)))) + ++#define SAFE_TO_MULT(a, b) \ ++ (((a) > 0) && ((b) >= 0) && ((0x7fffffff / (a)) > (b))) ++ ++#define SAFE_TO_ADD(a, b) \ ++ (((a) >= 0) && ((b) >= 0) && ((0x7fffffff - (a)) > (b))) + + #endif // __SAFE_ALLOC_H__ diff --git a/java/openjdk6/files/icedtea/security/20130201/8002325.patch b/java/openjdk6/files/icedtea/security/20130201/8002325.patch new file mode 100644 index 000000000000..9de38623270b --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130201/8002325.patch @@ -0,0 +1,59 @@ +# HG changeset patch +# User bae +# Date 1353162084 -14400 +# Node ID 6081ed9a6461360252572f79713b20c49caa59ad +# Parent 1e4909147511ffa8f2089c488df2435af4707283 +8002325: Improve management of images +Reviewed-by: prr, ahgross + +diff --git a/src/share/native/sun/awt/image/awt_parseImage.c b/src/share/native/sun/awt/image/awt_parseImage.c +--- jdk/src/share/native/sun/awt/image/awt_parseImage.c ++++ jdk/src/share/native/sun/awt/image/awt_parseImage.c +@@ -223,9 +223,14 @@ int awt_parseRaster(JNIEnv *env, jobject + return 0; + } + ++ rasterP->sppsm.isUsed = 0; ++ + if ((*env)->IsInstanceOf(env, rasterP->jsampleModel, + (*env)->FindClass(env,"java/awt/image/SinglePixelPackedSampleModel"))) { + jobject jmask, joffs, jnbits; ++ ++ rasterP->sppsm.isUsed = 1; ++ + rasterP->sppsm.maxBitSize = (*env)->GetIntField(env, + rasterP->jsampleModel, + g_SPPSMmaxBitID); +@@ -711,6 +716,21 @@ setHints(JNIEnv *env, BufImageS_t *image + } + else if (cmodelP->cmType == DIRECT_CM_TYPE || cmodelP->cmType == PACKED_CM_TYPE) { + int i; ++ ++ /* do some sanity check first: make sure that ++ * - sample model is SinglePixelPackedSampleModel ++ * - number of bands in the raster corresponds to the number ++ * of color components in the color model ++ */ ++ if (!rasterP->sppsm.isUsed || ++ rasterP->numBands != cmodelP->numComponents) ++ { ++ /* given raster is not compatible with the color model, ++ * so the operation has to be aborted. ++ */ ++ return -1; ++ } ++ + if (cmodelP->maxNbits > 8) { + hintP->needToExpand = TRUE; + hintP->expandToNbits = cmodelP->maxNbits; +diff --git a/src/share/native/sun/awt/image/awt_parseImage.h b/src/share/native/sun/awt/image/awt_parseImage.h +--- jdk/src/share/native/sun/awt/image/awt_parseImage.h ++++ jdk/src/share/native/sun/awt/image/awt_parseImage.h +@@ -95,6 +95,7 @@ typedef struct { + jint offsets[MAX_NUMBANDS]; + jint nBits[MAX_NUMBANDS]; + jint maxBitSize; ++ jint isUsed; // flag to indicate whether the raster sample model is SPPSM + } SPPSampleModelS_t; + + /* Struct that holds information for the Raster object */ diff --git a/java/openjdk6/files/icedtea/security/20130219/8006446.patch b/java/openjdk6/files/icedtea/security/20130219/8006446.patch new file mode 100644 index 000000000000..80501ea62890 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130219/8006446.patch @@ -0,0 +1,395 @@ +diff -Nru openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java openjdk/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java +--- openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java 2011-11-14 22:11:44.000000000 +0000 ++++ jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java 2013-02-15 03:40:40.511587149 +0000 +@@ -36,6 +36,7 @@ + + import javax.management.ObjectName; + import javax.management.loading.PrivateClassLoader; ++import sun.reflect.misc.ReflectUtil; + + /** + * This class keeps the list of Class Loaders registered in the MBean Server. +@@ -192,6 +193,7 @@ + final ClassLoader without, + final ClassLoader stop) + throws ClassNotFoundException { ++ ReflectUtil.checkPackageAccess(className); + final int size = list.length; + for(int i=0; i<size; i++) { + try { +diff -Nru openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java openjdk/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java +--- openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java 2011-11-14 22:11:44.000000000 +0000 ++++ jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java 2013-02-15 03:40:40.511587149 +0000 +@@ -57,6 +57,7 @@ + import javax.management.RuntimeOperationsException; + import javax.management.MBeanServer; + import javax.management.MBeanServerDelegate; ++import javax.management.MBeanServerPermission; + import javax.management.loading.ClassLoaderRepository; + + import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER; +@@ -1413,6 +1414,8 @@ + // Default is true. + final boolean fairLock = DEFAULT_FAIR_LOCK_POLICY; + ++ checkNewMBeanServerPermission(); ++ + // This constructor happens to disregard the value of the interceptors + // flag - that is, it always uses the default value - false. + // This is admitedly a bug, but we chose not to fix it for now +@@ -1499,4 +1502,11 @@ + } + } + ++ private static void checkNewMBeanServerPermission() { ++ SecurityManager sm = System.getSecurityManager(); ++ if (sm != null) { ++ Permission perm = new MBeanServerPermission("newMBeanServer"); ++ sm.checkPermission(perm); ++ } ++ } + } +diff -Nru openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java openjdk/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java +--- openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java 2011-11-14 22:11:44.000000000 +0000 ++++ jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java 2013-02-15 03:40:40.511587149 +0000 +@@ -32,11 +32,13 @@ + import java.io.ObjectInputStream; + import java.lang.reflect.Constructor; + import java.lang.reflect.InvocationTargetException; ++import java.security.Permission; + import java.util.Map; + import java.util.logging.Level; + + import javax.management.InstanceNotFoundException; + import javax.management.MBeanException; ++import javax.management.MBeanPermission; + import javax.management.NotCompliantMBeanException; + import javax.management.ObjectName; + import javax.management.OperationsException; +@@ -44,7 +46,7 @@ + import javax.management.RuntimeErrorException; + import javax.management.RuntimeMBeanException; + import javax.management.RuntimeOperationsException; +- ++import sun.reflect.misc.ConstructorUtil; + import sun.reflect.misc.ReflectUtil; + + /** +@@ -56,7 +58,6 @@ + * @since 1.5 + */ + public class MBeanInstantiator { +- + private final ModifiableClassLoaderRepository clr; + // private MetaData meta = null; + +@@ -88,6 +89,7 @@ + "Exception occurred during object instantiation"); + } + ++ ReflectUtil.checkPackageAccess(className); + try { + if (clr == null) throw new ClassNotFoundException(className); + theClass = clr.loadClass(className); +@@ -162,6 +164,7 @@ + continue; + } + ++ ReflectUtil.checkPackageAccess(signature[i]); + // Ok we do not have a primitive type ! We need to build + // the signature of the method + // +@@ -205,6 +208,9 @@ + */ + public Object instantiate(Class theClass) + throws ReflectionException, MBeanException { ++ ++ checkMBeanPermission(theClass, null, null, "instantiate"); ++ + Object moi = null; + + +@@ -260,6 +266,9 @@ + public Object instantiate(Class theClass, Object params[], + String signature[], ClassLoader loader) + throws ReflectionException, MBeanException { ++ ++ checkMBeanPermission(theClass, null, null, "instantiate"); ++ + // Instantiate the new object + + // ------------------------------ +@@ -408,6 +417,8 @@ + throw new RuntimeOperationsException(new + IllegalArgumentException(), "Null className passed in parameter"); + } ++ ++ ReflectUtil.checkPackageAccess(className); + Class theClass = null; + if (loaderName == null) { + // Load the class using the agent class loader +@@ -620,13 +631,13 @@ + **/ + static Class loadClass(String className, ClassLoader loader) + throws ReflectionException { +- + Class theClass = null; + if (className == null) { + throw new RuntimeOperationsException(new + IllegalArgumentException("The class name cannot be null"), + "Exception occurred during object instantiation"); + } ++ ReflectUtil.checkPackageAccess(className); + try { + if (loader == null) + loader = MBeanInstantiator.class.getClassLoader(); +@@ -677,6 +688,7 @@ + // We need to load the class through the class + // loader of the target object. + // ++ ReflectUtil.checkPackageAccess(signature[i]); + tab[i] = Class.forName(signature[i], false, aLoader); + } + } catch (ClassNotFoundException e) { +@@ -702,7 +714,7 @@ + + private Constructor<?> findConstructor(Class<?> c, Class<?>[] params) { + try { +- return c.getConstructor(params); ++ return ConstructorUtil.getConstructor(c, params); + } catch (Exception e) { + return null; + } +@@ -716,4 +728,18 @@ + char.class, boolean.class}) + primitiveClasses.put(c.getName(), c); + } ++ ++ private static void checkMBeanPermission(Class<?> clazz, ++ String member, ++ ObjectName objectName, ++ String actions) { ++ SecurityManager sm = System.getSecurityManager(); ++ if (clazz != null && sm != null) { ++ Permission perm = new MBeanPermission(clazz.getName(), ++ member, ++ objectName, ++ actions); ++ sm.checkPermission(perm); ++ } ++ } + } +diff -Nru openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java openjdk/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java +--- openjdk.orig/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java 2011-11-14 22:11:44.000000000 +0000 ++++ jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java 2013-02-15 03:40:40.511587149 +0000 +@@ -38,6 +38,7 @@ + import javax.management.NotCompliantMBeanException; + import javax.management.ObjectName; + import javax.management.ReflectionException; ++import sun.reflect.misc.ReflectUtil; + + /** + * Base class for MBeans. There is one instance of this class for +@@ -131,6 +132,7 @@ + " is not an instance of " + mbeanInterface.getName(); + throw new NotCompliantMBeanException(msg); + } ++ ReflectUtil.checkPackageAccess(mbeanInterface); + this.resource = resource; + MBeanIntrospector<M> introspector = getMBeanIntrospector(); + this.perInterface = introspector.getPerInterface(mbeanInterface); +diff -Nru openjdk.orig/jdk/src/share/classes/sun/management/LockDataConverter.java openjdk/jdk/src/share/classes/sun/management/LockDataConverter.java +--- openjdk.orig/jdk/src/share/classes/sun/management/LockDataConverter.java 2011-11-14 22:12:00.000000000 +0000 ++++ jdk/src/share/classes/sun/management/LockDataConverter.java 2013-02-15 03:40:40.511587149 +0000 +@@ -27,6 +27,8 @@ + + import java.lang.management.LockInfo; + import java.lang.management.ThreadInfo; ++import java.security.AccessController; ++import java.security.PrivilegedAction; + import javax.management.Attribute; + import javax.management.StandardMBean; + import javax.management.openmbean.CompositeData; +@@ -40,13 +42,13 @@ + private LockInfo lockInfo; + private LockInfo[] lockedSyncs; + +- LockDataConverter() { ++ private LockDataConverter() { + super(LockDataConverterMXBean.class, true); + this.lockInfo = null; + this.lockedSyncs = null; + } + +- LockDataConverter(ThreadInfo ti) { ++ private LockDataConverter(ThreadInfo ti) { + super(LockDataConverterMXBean.class, true); + this.lockInfo = ti.getLockInfo(); + this.lockedSyncs = ti.getLockedSynchronizers(); +@@ -104,8 +106,24 @@ + } + + static CompositeData toLockInfoCompositeData(LockInfo l) { +- LockDataConverter ldc = new LockDataConverter(); ++ LockDataConverter ldc = newLockDataConverter(); + ldc.setLockInfo(l); + return ldc.toLockInfoCompositeData(); + } ++ ++ static LockDataConverter newLockDataConverter() { ++ return AccessController.doPrivileged(new PrivilegedAction<LockDataConverter>() { ++ public LockDataConverter run() { ++ return new LockDataConverter(); ++ } ++ }); ++ } ++ ++ static LockDataConverter newLockDataConverter(final ThreadInfo ti) { ++ LockDataConverter result = newLockDataConverter(); ++ result.lockInfo = ti.getLockInfo(); ++ result.lockedSyncs = ti.getLockedSynchronizers(); ++ return result; ++ } + } ++ +diff -Nru openjdk.orig/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java openjdk/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java +--- openjdk.orig/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java 2011-11-14 22:12:01.000000000 +0000 ++++ jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java 2013-02-15 03:40:40.511587149 +0000 +@@ -85,7 +85,7 @@ + } + + // Convert MonitorInfo[] and LockInfo[] to CompositeData[] +- LockDataConverter converter = new LockDataConverter(threadInfo); ++ LockDataConverter converter = LockDataConverter.newLockDataConverter(threadInfo); + CompositeData lockInfoData = converter.toLockInfoCompositeData(); + CompositeData[] lockedSyncsData = converter.toLockedSynchronizersCompositeData(); + +@@ -315,7 +315,7 @@ + + // 6.0 new attributes + public LockInfo lockInfo() { +- LockDataConverter converter = new LockDataConverter(); ++ LockDataConverter converter = LockDataConverter.newLockDataConverter(); + CompositeData lockInfoData = (CompositeData) cdata.get(LOCK_INFO); + return converter.toLockInfo(lockInfoData); + } +@@ -336,7 +336,7 @@ + } + + public LockInfo[] lockedSynchronizers() { +- LockDataConverter converter = new LockDataConverter(); ++ LockDataConverter converter = LockDataConverter.newLockDataConverter(); + CompositeData[] lockedSyncsData = + (CompositeData[]) cdata.get(LOCKED_SYNCS); + +diff -Nru openjdk.orig/jdk/src/share/lib/security/java.security openjdk/jdk/src/share/lib/security/java.security +--- openjdk.orig/jdk/src/share/lib/security/java.security 2013-02-15 03:39:56.922892783 +0000 ++++ jdk/src/share/lib/security/java.security 2013-02-15 03:40:40.511587149 +0000 +@@ -131,8 +131,7 @@ + com.sun.xml.internal.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ +- com.sun.jmx.defaults.,\ +- com.sun.jmx.remote.util. ++ com.sun.jmx. + + # + # List of comma-separated packages that start with or equal this string +@@ -148,8 +147,7 @@ + com.sun.xml.internal.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ +- com.sun.jmx.defaults.,\ +- com.sun.jmx.remote.util. ++ com.sun.jmx. + + # + # Determines whether this properties file can be appended to +diff -Nru openjdk.orig/jdk/src/share/lib/security/java.security-solaris openjdk/jdk/src/share/lib/security/java.security-solaris +--- openjdk.orig/jdk/src/share/lib/security/java.security-solaris 2013-02-15 03:39:56.902892466 +0000 ++++ jdk/src/share/lib/security/java.security-solaris 2013-02-15 03:41:36.996489851 +0000 +@@ -131,6 +131,8 @@ + package.access=sun.,\ + com.sun.xml.internal.,\ + com.sun.imageio. ++ com.sun.istack.internal.,\ ++ com.sun.jmx. + + # + # List of comma-separated packages that start with or equal this string +@@ -145,6 +147,8 @@ + package.definition=sun.,\ + com.sun.xml.internal.,\ + com.sun.imageio. ++ com.sun.istack.internal.,\ ++ com.sun.jmx. + + # + # Determines whether this properties file can be appended to +diff -Nru openjdk.orig/jdk/src/share/lib/security/java.security-windows openjdk/jdk/src/share/lib/security/java.security-windows +--- openjdk.orig/jdk/src/share/lib/security/java.security-windows 2013-02-15 03:39:56.902892466 +0000 ++++ jdk/src/share/lib/security/java.security-windows 2013-02-15 03:42:05.304943135 +0000 +@@ -131,6 +131,8 @@ + package.access=sun.,\ + com.sun.xml.internal.,\ + com.sun.imageio. ++ com.sun.istack.internal.,\ ++ com.sun.jmx. + + # + # List of comma-separated packages that start with or equal this string +@@ -145,6 +147,8 @@ + package.definition=sun.,\ + com.sun.xml.internal.,\ + com.sun.imageio. ++ com.sun.istack.internal.,\ ++ com.sun.jmx. + + # + # Determines whether this properties file can be appended to +diff -Nru openjdk.orig/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java openjdk/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java +--- openjdk.orig/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java 2011-11-14 22:12:28.000000000 +0000 ++++ jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java 2013-02-15 03:40:40.511587149 +0000 +@@ -119,9 +119,6 @@ + System.out.println("Create SimpleStandard MBean"); + SimpleStandard s = new SimpleStandard("monitorRole"); + mbs.registerMBean(s, new ObjectName("MBeans:type=SimpleStandard")); +- // Set Security Manager +- // +- System.setSecurityManager(new SecurityManager()); + // Create Properties containing the username/password entries + // + Properties props = new Properties(); +@@ -132,6 +129,9 @@ + HashMap env = new HashMap(); + env.put("jmx.remote.authenticator", + new JMXPluggableAuthenticator(props)); ++ // Set Security Manager ++ // ++ System.setSecurityManager(new SecurityManager()); + // Create an RMI connector server + // + System.out.println("Create an RMI connector server"); +diff -Nru openjdk.orig/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java openjdk/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java +--- openjdk.orig/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java 2011-11-14 22:12:28.000000000 +0000 ++++ jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java 2013-02-15 03:40:40.511587149 +0000 +@@ -120,9 +120,6 @@ + System.out.println("Create SimpleStandard MBean"); + SimpleStandard s = new SimpleStandard("delegate"); + mbs.registerMBean(s, new ObjectName("MBeans:type=SimpleStandard")); +- // Set Security Manager +- // +- System.setSecurityManager(new SecurityManager()); + // Create Properties containing the username/password entries + // + Properties props = new Properties(); +@@ -133,6 +130,9 @@ + HashMap env = new HashMap(); + env.put("jmx.remote.authenticator", + new JMXPluggableAuthenticator(props)); ++ // Set Security Manager ++ // ++ System.setSecurityManager(new SecurityManager()); + // Create an RMI connector server + // + System.out.println("Create an RMI connector server"); diff --git a/java/openjdk6/files/icedtea/security/20130219/8006777.patch b/java/openjdk6/files/icedtea/security/20130219/8006777.patch new file mode 100644 index 000000000000..913617accfd5 --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130219/8006777.patch @@ -0,0 +1,1036 @@ +# HG changeset patch +# User coffeys +# Date 1360882104 0 +# Node ID 85b3b034fdecdc94f082efa8d74e014366502deb +# Parent 617e68a3948824283f15c36fcd8cf264c1dd0a99 +8006777: Improve TLS handling of invalid messages +Reviewed-by: wetmore + +diff --git a/src/share/classes/sun/security/ssl/CipherBox.java b/src/share/classes/sun/security/ssl/CipherBox.java +--- jdk/src/share/classes/sun/security/ssl/CipherBox.java ++++ jdk/src/share/classes/sun/security/ssl/CipherBox.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -244,7 +244,8 @@ final class CipherBox { + * Decrypts a block of data, returning the size of the + * resulting block if padding was required. + */ +- int decrypt(byte[] buf, int offset, int len) throws BadPaddingException { ++ int decrypt(byte[] buf, int offset, int len, ++ int tagLen) throws BadPaddingException { + if (cipher == null) { + return len; + } +@@ -268,8 +269,8 @@ final class CipherBox { + } catch (IOException e) { } + } + if (blockSize != 0) { +- newLen = removePadding(buf, offset, newLen, +- blockSize, protocolVersion); ++ newLen = removePadding( ++ buf, offset, newLen, tagLen, blockSize, protocolVersion); + } + return newLen; + } catch (ShortBufferException e) { +@@ -285,7 +286,7 @@ final class CipherBox { + * limit and new limit may be different, given we may + * have stripped off some padding bytes. + */ +- int decrypt(ByteBuffer bb) throws BadPaddingException { ++ int decrypt(ByteBuffer bb, int tagLen) throws BadPaddingException { + + int len = bb.remaining(); + +@@ -309,7 +310,6 @@ final class CipherBox { + } + + if (debug != null && Debug.isOn("plaintext")) { +- bb.position(pos); + try { + HexDumpEncoder hd = new HexDumpEncoder(); + +@@ -317,7 +317,8 @@ final class CipherBox { + "Padded plaintext after DECRYPTION: len = " + + newLen); + +- hd.encodeBuffer(bb, System.out); ++ hd.encodeBuffer( ++ (ByteBuffer)bb.duplicate().position(pos), System.out); + } catch (IOException e) { } + } + +@@ -326,7 +327,8 @@ final class CipherBox { + */ + if (blockSize != 0) { + bb.position(pos); +- newLen = removePadding(bb, blockSize, protocolVersion); ++ newLen = removePadding( ++ bb, tagLen, blockSize, protocolVersion); + } + return newLen; + } catch (ShortBufferException e) { +@@ -400,6 +402,65 @@ final class CipherBox { + return newlen; + } + ++ /* ++ * A constant-time check of the padding. ++ * ++ * NOTE that we are checking both the padding and the padLen bytes here. ++ * ++ * The caller MUST ensure that the len parameter is a positive number. ++ */ ++ private static int[] checkPadding( ++ byte[] buf, int offset, int len, byte pad) { ++ ++ if (len <= 0) { ++ throw new RuntimeException("padding len must be positive"); ++ } ++ ++ // An array of hits is used to prevent Hotspot optimization for ++ // the purpose of a constant-time check ++ int[] results = {0, 0}; // {missed #, matched #} ++ for (int i = 0; i <= 256;) { ++ for (int j = 0; j < len && i <= 256; j++, i++) { // j <= i ++ if (buf[offset + j] != pad) { ++ results[0]++; // mismatched padding data ++ } else { ++ results[1]++; // matched padding data ++ } ++ } ++ } ++ ++ return results; ++ } ++ ++ /* ++ * A constant-time check of the padding. ++ * ++ * NOTE that we are checking both the padding and the padLen bytes here. ++ * ++ * The caller MUST ensure that the bb parameter has remaining. ++ */ ++ private static int[] checkPadding(ByteBuffer bb, byte pad) { ++ ++ if (!bb.hasRemaining()) { ++ throw new RuntimeException("hasRemaining() must be positive"); ++ } ++ ++ // An array of hits is used to prevent Hotspot optimization for ++ // the purpose of a constant-time check. ++ int[] results = {0, 0}; // {missed #, matched #} ++ bb.mark(); ++ for (int i = 0; i <= 256; bb.reset()) { ++ for (; bb.hasRemaining() && i <= 256; i++) { ++ if (bb.get() != pad) { ++ results[0]++; // mismatched padding data ++ } else { ++ results[1]++; // matched padding data ++ } ++ } ++ } ++ ++ return results; ++ } + + /* + * Typical TLS padding format for a 64 bit block cipher is as follows: +@@ -412,86 +473,95 @@ final class CipherBox { + * as it makes the data a multiple of the block size + */ + private static int removePadding(byte[] buf, int offset, int len, +- int blockSize, ProtocolVersion protocolVersion) +- throws BadPaddingException { ++ int tagLen, int blockSize, ++ ProtocolVersion protocolVersion) throws BadPaddingException { ++ + // last byte is length byte (i.e. actual padding length - 1) + int padOffset = offset + len - 1; +- int pad = buf[padOffset] & 0x0ff; ++ int padLen = buf[padOffset] & 0xFF; + +- int newlen = len - (pad + 1); +- if (newlen < 0) { +- throw new BadPaddingException("Padding length invalid: " + pad); ++ int newLen = len - (padLen + 1); ++ if ((newLen - tagLen) < 0) { ++ // If the buffer is not long enough to contain the padding plus ++ // a MAC tag, do a dummy constant-time padding check. ++ // ++ // Note that it is a dummy check, so we won't care about what is ++ // the actual padding data. ++ checkPadding(buf, offset, len, (byte)(padLen & 0xFF)); ++ ++ throw new BadPaddingException("Invalid Padding length: " + padLen); + } + ++ // The padding data should be filled with the padding length value. ++ int[] results = checkPadding(buf, offset + newLen, ++ padLen + 1, (byte)(padLen & 0xFF)); + if (protocolVersion.v >= ProtocolVersion.TLS10.v) { +- for (int i = 1; i <= pad; i++) { +- int val = buf[padOffset - i] & 0xff; +- if (val != pad) { +- throw new BadPaddingException +- ("Invalid TLS padding: " + val); +- } ++ if (results[0] != 0) { // padding data has invalid bytes ++ throw new BadPaddingException("Invalid TLS padding data"); + } + } else { // SSLv3 + // SSLv3 requires 0 <= length byte < block size + // some implementations do 1 <= length byte <= block size, + // so accept that as well + // v3 does not require any particular value for the other bytes +- if (pad > blockSize) { +- throw new BadPaddingException("Invalid SSLv3 padding: " + pad); ++ if (padLen > blockSize) { ++ throw new BadPaddingException("Invalid SSLv3 padding"); + } + } +- return newlen; ++ return newLen; + } + + /* + * Position/limit is equal the removed padding. + */ + private static int removePadding(ByteBuffer bb, +- int blockSize, ProtocolVersion protocolVersion) +- throws BadPaddingException { ++ int tagLen, int blockSize, ++ ProtocolVersion protocolVersion) throws BadPaddingException { + + int len = bb.remaining(); + int offset = bb.position(); + + // last byte is length byte (i.e. actual padding length - 1) + int padOffset = offset + len - 1; +- int pad = bb.get(padOffset) & 0x0ff; ++ int padLen = bb.get(padOffset) & 0xFF; + +- int newlen = len - (pad + 1); +- if (newlen < 0) { +- throw new BadPaddingException("Padding length invalid: " + pad); ++ int newLen = len - (padLen + 1); ++ if ((newLen - tagLen) < 0) { ++ // If the buffer is not long enough to contain the padding plus ++ // a MAC tag, do a dummy constant-time padding check. ++ // ++ // Note that it is a dummy check, so we won't care about what is ++ // the actual padding data. ++ checkPadding(bb.duplicate(), (byte)(padLen & 0xFF)); ++ ++ throw new BadPaddingException("Invalid Padding length: " + padLen); + } + +- /* +- * We could zero the padding area, but not much useful +- * information there. +- */ ++ // The padding data should be filled with the padding length value. ++ int[] results = checkPadding( ++ (ByteBuffer)bb.duplicate().position(offset + newLen), ++ (byte)(padLen & 0xFF)); + if (protocolVersion.v >= ProtocolVersion.TLS10.v) { +- bb.put(padOffset, (byte)0); // zero the padding. +- for (int i = 1; i <= pad; i++) { +- int val = bb.get(padOffset - i) & 0xff; +- if (val != pad) { +- throw new BadPaddingException +- ("Invalid TLS padding: " + val); +- } ++ if (results[0] != 0) { // padding data has invalid bytes ++ throw new BadPaddingException("Invalid TLS padding data"); + } + } else { // SSLv3 + // SSLv3 requires 0 <= length byte < block size + // some implementations do 1 <= length byte <= block size, + // so accept that as well + // v3 does not require any particular value for the other bytes +- if (pad > blockSize) { +- throw new BadPaddingException("Invalid SSLv3 padding: " + pad); ++ if (padLen > blockSize) { ++ throw new BadPaddingException("Invalid SSLv3 padding"); + } + } + + /* + * Reset buffer limit to remove padding. + */ +- bb.position(offset + newlen); +- bb.limit(offset + newlen); ++ bb.position(offset + newLen); ++ bb.limit(offset + newLen); + +- return newlen; ++ return newLen; + } + + /* +@@ -502,4 +572,40 @@ final class CipherBox { + boolean isCBCMode() { + return isCBCMode; + } ++ ++ /** ++ * Is the cipher null? ++ * ++ * @return true if the cipher is null, false otherwise. ++ */ ++ boolean isNullCipher() { ++ return cipher == null; ++ } ++ ++ /** ++ * Sanity check the length of a fragment before decryption. ++ * ++ * In CBC mode, check that the fragment length is one or multiple times ++ * of the block size of the cipher suite, and is at least one (one is the ++ * smallest size of padding in CBC mode) bigger than the tag size of the ++ * MAC algorithm. ++ * ++ * In non-CBC mode, check that the fragment length is not less than the ++ * tag size of the MAC algorithm. ++ * ++ * @return true if the length of a fragment matches above requirements ++ */ ++ boolean sanityCheck(int tagLen, int fragmentLen) { ++ if (!isCBCMode) { ++ return fragmentLen >= tagLen; ++ } ++ ++ if ((fragmentLen % blockSize) == 0) { ++ int minimal = tagLen + 1; ++ minimal = (minimal >= blockSize) ? minimal : blockSize; ++ return (fragmentLen >= minimal); ++ } ++ ++ return false; ++ } + } +diff --git a/src/share/classes/sun/security/ssl/CipherSuite.java b/src/share/classes/sun/security/ssl/CipherSuite.java +--- jdk/src/share/classes/sun/security/ssl/CipherSuite.java ++++ jdk/src/share/classes/sun/security/ssl/CipherSuite.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -451,9 +451,18 @@ final class CipherSuite implements Compa + // size of the MAC value (and MAC key) in bytes + final int size; + +- MacAlg(String name, int size) { ++ // block size of the underlying hash algorithm ++ final int hashBlockSize; ++ ++ // minimal padding size of the underlying hash algorithm ++ final int minimalPaddingSize; ++ ++ MacAlg(String name, int size, ++ int hashBlockSize, int minimalPaddingSize) { + this.name = name; + this.size = size; ++ this.hashBlockSize = hashBlockSize; ++ this.minimalPaddingSize = minimalPaddingSize; + } + + /** +@@ -497,9 +506,9 @@ final class CipherSuite implements Compa + new BulkCipher(CIPHER_AES, 32, 16, true); + + // MACs +- final static MacAlg M_NULL = new MacAlg("NULL", 0); +- final static MacAlg M_MD5 = new MacAlg("MD5", 16); +- final static MacAlg M_SHA = new MacAlg("SHA", 20); ++ final static MacAlg M_NULL = new MacAlg("NULL", 0, 0, 0); ++ final static MacAlg M_MD5 = new MacAlg("MD5", 16, 64, 9); ++ final static MacAlg M_SHA = new MacAlg("SHA", 20, 64, 9); + + static { + idMap = new HashMap<Integer,CipherSuite>(); +diff --git a/src/share/classes/sun/security/ssl/EngineInputRecord.java b/src/share/classes/sun/security/ssl/EngineInputRecord.java +--- jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java ++++ jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -177,71 +177,6 @@ final class EngineInputRecord extends In + } + + /* +- * Verifies and removes the MAC value. Returns true if +- * the MAC checks out OK. +- * +- * On entry: +- * position = beginning of app/MAC data +- * limit = end of MAC data. +- * +- * On return: +- * position = beginning of app data +- * limit = end of app data +- */ +- boolean checkMAC(MAC signer, ByteBuffer bb) { +- if (internalData) { +- return checkMAC(signer); +- } +- +- int len = signer.MAClen(); +- if (len == 0) { // no mac +- return true; +- } +- +- /* +- * Grab the original limit +- */ +- int lim = bb.limit(); +- +- /* +- * Delineate the area to apply a MAC on. +- */ +- int macData = lim - len; +- bb.limit(macData); +- +- byte[] mac = signer.compute(contentType(), bb); +- +- if (len != mac.length) { +- throw new RuntimeException("Internal MAC error"); +- } +- +- /* +- * Delineate the MAC values, position was already set +- * by doing the compute above. +- * +- * We could zero the MAC area, but not much useful information +- * there anyway. +- */ +- bb.position(macData); +- bb.limit(lim); +- +- try { +- for (int i = 0; i < len; i++) { +- if (bb.get() != mac[i]) { // No BB.equals(byte []); ! +- return false; +- } +- } +- return true; +- } finally { +- /* +- * Position to the data. +- */ +- bb.rewind(); +- bb.limit(macData); +- } +- } +- +- /* + * Pass the data down if it's internally cached, otherwise + * do it here. + * +@@ -250,18 +185,161 @@ final class EngineInputRecord extends In + * If external data(app), return a new ByteBuffer with data to + * process. + */ +- ByteBuffer decrypt(CipherBox box, ByteBuffer bb) +- throws BadPaddingException { ++ ByteBuffer decrypt(MAC signer, ++ CipherBox box, ByteBuffer bb) throws BadPaddingException { + + if (internalData) { +- decrypt(box); ++ decrypt(signer, box); // MAC is checked during decryption + return tmpBB; + } + +- box.decrypt(bb); +- bb.rewind(); ++ BadPaddingException reservedBPE = null; ++ int tagLen = signer.MAClen(); ++ int cipheredLength = bb.remaining(); ++ ++ if (!box.isNullCipher()) { ++ // sanity check length of the ciphertext ++ if (!box.sanityCheck(tagLen, cipheredLength)) { ++ throw new BadPaddingException( ++ "ciphertext sanity check failed"); ++ } ++ ++ try { ++ // Note that the CipherBox.decrypt() does not change ++ // the capacity of the buffer. ++ box.decrypt(bb, tagLen); ++ } catch (BadPaddingException bpe) { ++ // RFC 2246 states that decryption_failed should be used ++ // for this purpose. However, that allows certain attacks, ++ // so we just send bad record MAC. We also need to make ++ // sure to always check the MAC to avoid a timing attack ++ // for the same issue. See paper by Vaudenay et al and the ++ // update in RFC 4346/5246. ++ // ++ // Failover to message authentication code checking. ++ reservedBPE = bpe; ++ } finally { ++ bb.rewind(); ++ } ++ } ++ ++ if (tagLen != 0) { ++ int macOffset = bb.limit() - tagLen; ++ ++ // Note that although it is not necessary, we run the same MAC ++ // computation and comparison on the payload for both stream ++ // cipher and CBC block cipher. ++ if (bb.remaining() < tagLen) { ++ // negative data length, something is wrong ++ if (reservedBPE == null) { ++ reservedBPE = new BadPaddingException("bad record"); ++ } ++ ++ // set offset of the dummy MAC ++ macOffset = cipheredLength - tagLen; ++ bb.limit(cipheredLength); ++ } ++ ++ // Run MAC computation and comparison on the payload. ++ if (checkMacTags(contentType(), bb, signer, false)) { ++ if (reservedBPE == null) { ++ reservedBPE = new BadPaddingException("bad record MAC"); ++ } ++ } ++ ++ // Run MAC computation and comparison on the remainder. ++ // ++ // It is only necessary for CBC block cipher. It is used to get a ++ // constant time of MAC computation and comparison on each record. ++ if (box.isCBCMode()) { ++ int remainingLen = calculateRemainingLen( ++ signer, cipheredLength, macOffset); ++ ++ // NOTE: here we use the InputRecord.buf because I did not find ++ // an effective way to work on ByteBuffer when its capacity is ++ // less than remainingLen. ++ ++ // NOTE: remainingLen may be bigger (less than 1 block of the ++ // hash algorithm of the MAC) than the cipheredLength. However, ++ // We won't need to worry about it because we always use a ++ // maximum buffer for every record. We need a change here if ++ // we use small buffer size in the future. ++ if (remainingLen > buf.length) { ++ // unlikely to happen, just a placehold ++ throw new RuntimeException( ++ "Internal buffer capacity error"); ++ } ++ ++ // Won't need to worry about the result on the remainder. And ++ // then we won't need to worry about what's actual data to ++ // check MAC tag on. We start the check from the header of the ++ // buffer so that we don't need to construct a new byte buffer. ++ checkMacTags(contentType(), buf, 0, remainingLen, signer, true); ++ } ++ ++ bb.limit(macOffset); ++ } ++ ++ // Is it a failover? ++ if (reservedBPE != null) { ++ throw reservedBPE; ++ } + + return bb.slice(); ++ } ++ ++ /* ++ * Run MAC computation and comparison ++ * ++ * Please DON'T change the content of the ByteBuffer parameter! ++ */ ++ private static boolean checkMacTags(byte contentType, ByteBuffer bb, ++ MAC signer, boolean isSimulated) { ++ ++ int tagLen = signer.MAClen(); ++ int lim = bb.limit(); ++ int macData = lim - tagLen; ++ ++ bb.limit(macData); ++ byte[] hash = signer.compute(contentType, bb, isSimulated); ++ if (hash == null || tagLen != hash.length) { ++ // Something is wrong with MAC implementation. ++ throw new RuntimeException("Internal MAC error"); ++ } ++ ++ bb.position(macData); ++ bb.limit(lim); ++ try { ++ int[] results = compareMacTags(bb, hash); ++ return (results[0] != 0); ++ } finally { ++ bb.rewind(); ++ bb.limit(macData); ++ } ++ } ++ ++ /* ++ * A constant-time comparison of the MAC tags. ++ * ++ * Please DON'T change the content of the ByteBuffer parameter! ++ */ ++ private static int[] compareMacTags(ByteBuffer bb, byte[] tag) { ++ ++ // An array of hits is used to prevent Hotspot optimization for ++ // the purpose of a constant-time check. ++ int[] results = {0, 0}; // {missed #, matched #} ++ ++ // The caller ensures there are enough bytes available in the buffer. ++ // So we won't need to check the remaining of the buffer. ++ for (int i = 0; i < tag.length; i++) { ++ if (bb.get() != tag[i]) { ++ results[0]++; // mismatched bytes ++ } else { ++ results[1]++; // matched bytes ++ } ++ } ++ ++ return results; + } + + /* +diff --git a/src/share/classes/sun/security/ssl/EngineOutputRecord.java b/src/share/classes/sun/security/ssl/EngineOutputRecord.java +--- jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java ++++ jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -120,7 +120,7 @@ final class EngineOutputRecord extends O + throws IOException { + + if (signer.MAClen() != 0) { +- byte[] hash = signer.compute(contentType(), bb); ++ byte[] hash = signer.compute(contentType(), bb, false); + + /* + * position was advanced to limit in compute above. +diff --git a/src/share/classes/sun/security/ssl/InputRecord.java b/src/share/classes/sun/security/ssl/InputRecord.java +--- jdk/src/share/classes/sun/security/ssl/InputRecord.java ++++ jdk/src/share/classes/sun/security/ssl/InputRecord.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -135,43 +135,173 @@ class InputRecord extends ByteArrayInput + return handshakeHash; + } + +- /* +- * Verify and remove the MAC ... used for all records. +- */ +- boolean checkMAC(MAC signer) { +- int len = signer.MAClen(); +- if (len == 0) { // no mac +- return true; ++ void decrypt(MAC signer, CipherBox box) throws BadPaddingException { ++ ++ BadPaddingException reservedBPE = null; ++ int tagLen = signer.MAClen(); ++ int cipheredLength = count - headerSize; ++ ++ if (!box.isNullCipher()) { ++ // sanity check length of the ciphertext ++ if (!box.sanityCheck(tagLen, cipheredLength)) { ++ throw new BadPaddingException( ++ "ciphertext sanity check failed"); ++ } ++ ++ try { ++ // Note that the CipherBox.decrypt() does not change ++ // the capacity of the buffer. ++ count = headerSize + ++ box.decrypt(buf, headerSize, cipheredLength, tagLen); ++ } catch (BadPaddingException bpe) { ++ // RFC 2246 states that decryption_failed should be used ++ // for this purpose. However, that allows certain attacks, ++ // so we just send bad record MAC. We also need to make ++ // sure to always check the MAC to avoid a timing attack ++ // for the same issue. See paper by Vaudenay et al and the ++ // update in RFC 4346/5246. ++ // ++ // Failover to message authentication code checking. ++ reservedBPE = bpe; ++ } + } + +- int offset = count - len; ++ if (tagLen != 0) { ++ int macOffset = count - tagLen; ++ int contentLen = macOffset - headerSize; + +- if (offset < headerSize) { +- // data length would be negative, something is wrong +- return false; ++ // Note that although it is not necessary, we run the same MAC ++ // computation and comparison on the payload for both stream ++ // cipher and CBC block cipher. ++ if (contentLen < 0) { ++ // negative data length, something is wrong ++ if (reservedBPE == null) { ++ reservedBPE = new BadPaddingException("bad record"); ++ } ++ ++ // set offset of the dummy MAC ++ macOffset = headerSize + cipheredLength - tagLen; ++ contentLen = macOffset - headerSize; ++ } ++ ++ count -= tagLen; // Set the count before any MAC checking ++ // exception occurs, so that the following ++ // process can read the actual decrypted ++ // content (minus the MAC) in the fragment ++ // if necessary. ++ ++ // Run MAC computation and comparison on the payload. ++ if (checkMacTags(contentType(), ++ buf, headerSize, contentLen, signer, false)) { ++ if (reservedBPE == null) { ++ reservedBPE = new BadPaddingException("bad record MAC"); ++ } ++ } ++ ++ // Run MAC computation and comparison on the remainder. ++ // ++ // It is only necessary for CBC block cipher. It is used to get a ++ // constant time of MAC computation and comparison on each record. ++ if (box.isCBCMode()) { ++ int remainingLen = calculateRemainingLen( ++ signer, cipheredLength, contentLen); ++ ++ // NOTE: remainingLen may be bigger (less than 1 block of the ++ // hash algorithm of the MAC) than the cipheredLength. However, ++ // We won't need to worry about it because we always use a ++ // maximum buffer for every record. We need a change here if ++ // we use small buffer size in the future. ++ if (remainingLen > buf.length) { ++ // unlikely to happen, just a placehold ++ throw new RuntimeException( ++ "Internal buffer capacity error"); ++ } ++ ++ // Won't need to worry about the result on the remainder. And ++ // then we won't need to worry about what's actual data to ++ // check MAC tag on. We start the check from the header of the ++ // buffer so that we don't need to construct a new byte buffer. ++ checkMacTags(contentType(), buf, 0, remainingLen, signer, true); ++ } + } + +- byte[] mac = signer.compute(contentType(), buf, +- headerSize, offset - headerSize); ++ // Is it a failover? ++ if (reservedBPE != null) { ++ throw reservedBPE; ++ } ++ } + +- if (len != mac.length) { ++ /* ++ * Run MAC computation and comparison ++ * ++ * Please DON'T change the content of the byte buffer parameter! ++ */ ++ static boolean checkMacTags(byte contentType, byte[] buffer, ++ int offset, int contentLen, MAC signer, boolean isSimulated) { ++ ++ int tagLen = signer.MAClen(); ++ byte[] hash = signer.compute( ++ contentType, buffer, offset, contentLen, isSimulated); ++ if (hash == null || tagLen != hash.length) { ++ // Something is wrong with MAC implementation. + throw new RuntimeException("Internal MAC error"); + } + +- for (int i = 0; i < len; i++) { +- if (buf[offset + i] != mac[i]) { +- return false; ++ int[] results = compareMacTags(buffer, offset + contentLen, hash); ++ return (results[0] != 0); ++ } ++ ++ /* ++ * A constant-time comparison of the MAC tags. ++ * ++ * Please DON'T change the content of the byte buffer parameter! ++ */ ++ private static int[] compareMacTags( ++ byte[] buffer, int offset, byte[] tag) { ++ ++ // An array of hits is used to prevent Hotspot optimization for ++ // the purpose of a constant-time check. ++ int[] results = {0, 0}; // {missed #, matched #} ++ ++ // The caller ensures there are enough bytes available in the buffer. ++ // So we won't need to check the length of the buffer. ++ for (int i = 0; i < tag.length; i++) { ++ if (buffer[offset + i] != tag[i]) { ++ results[0]++; // mismatched bytes ++ } else { ++ results[1]++; // matched bytes + } + } +- count -= len; +- return true; ++ ++ return results; + } + +- void decrypt(CipherBox box) throws BadPaddingException { +- int len = count - headerSize; +- count = headerSize + box.decrypt(buf, headerSize, len); ++ /* ++ * Calculate the length of a dummy buffer to run MAC computation ++ * and comparison on the remainder. ++ * ++ * The caller MUST ensure that the fullLen is not less than usedLen. ++ */ ++ static int calculateRemainingLen( ++ MAC signer, int fullLen, int usedLen) { ++ ++ int blockLen = signer.hashBlockLen(); ++ int minimalPaddingLen = signer.minimalPaddingLen(); ++ ++ // (blockLen - minimalPaddingLen) is the maximum message size of ++ // the last block of hash function operation. See FIPS 180-4, or ++ // MD5 specification. ++ fullLen += 13 - (blockLen - minimalPaddingLen); ++ usedLen += 13 - (blockLen - minimalPaddingLen); ++ ++ // Note: fullLen is always not less than usedLen, and blockLen ++ // is always bigger than minimalPaddingLen, so we don't worry ++ // about negative values. 0x01 is added to the result to ensure ++ // that the return value is positive. The extra one byte does ++ // not impact the overall MAC compression function evaluations. ++ return 0x01 + (int)(Math.ceil(fullLen/(1.0d * blockLen)) - ++ Math.ceil(usedLen/(1.0d * blockLen))) * signer.hashBlockLen(); + } +- + + /* + * Well ... hello_request messages are _never_ hashed since we can't +diff --git a/src/share/classes/sun/security/ssl/MAC.java b/src/share/classes/sun/security/ssl/MAC.java +--- jdk/src/share/classes/sun/security/ssl/MAC.java ++++ jdk/src/share/classes/sun/security/ssl/MAC.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -44,7 +44,8 @@ import static sun.security.ssl.CipherSui + * one of several keyed hashes, as associated with the cipher suite and + * protocol version. (SSL v3.0 uses one construct, TLS uses another.) + * +- * <P>NOTE: MAC computation is the only place in the SSL protocol that the ++ * <P> ++ * NOTE: MAC computation is the only place in the SSL protocol that the + * sequence number is used. It's also reset to zero with each change of + * a cipher spec, so this is the only place this state is needed. + * +@@ -129,15 +130,31 @@ final class MAC { + } + + /** ++ * Returns the hash function block length of the MAC alorithm. ++ */ ++ int hashBlockLen() { ++ return macAlg.hashBlockSize; ++ } ++ ++ /** ++ * Returns the hash function minimal padding length of the MAC alorithm. ++ */ ++ int minimalPaddingLen() { ++ return macAlg.minimalPaddingSize; ++ } ++ ++ /** + * Computes and returns the MAC for the data in this byte array. + * + * @param type record type + * @param buf compressed record on which the MAC is computed + * @param offset start of compressed record data + * @param len the size of the compressed record ++ * @param isSimulated if true, simulate the the MAC computation + */ +- final byte[] compute(byte type, byte buf[], int offset, int len) { +- return compute(type, null, buf, offset, len); ++ final byte[] compute(byte type, byte buf[], ++ int offset, int len, boolean isSimulated) { ++ return compute(type, null, buf, offset, len, isSimulated); + } + + /** +@@ -150,9 +167,10 @@ final class MAC { + * @param type record type + * @param bb a ByteBuffer in which the position and limit + * demarcate the data to be MAC'd. ++ * @param isSimulated if true, simulate the the MAC computation + */ +- final byte[] compute(byte type, ByteBuffer bb) { +- return compute(type, bb, null, 0, bb.remaining()); ++ final byte[] compute(byte type, ByteBuffer bb, boolean isSimulated) { ++ return compute(type, bb, null, 0, bb.remaining(), isSimulated); + } + + // increment the sequence number in the block array +@@ -168,18 +186,22 @@ final class MAC { + * Compute based on either buffer type, either bb.position/limit + * or buf/offset/len. + */ +- private byte[] compute(byte type, ByteBuffer bb, byte[] buf, int offset, int len) { ++ private byte[] compute(byte type, ByteBuffer bb, byte[] buf, ++ int offset, int len, boolean isSimulated) { + + if (macSize == 0) { + return nullMAC; + } + +- block[BLOCK_OFFSET_TYPE] = type; +- block[block.length - 2] = (byte)(len >> 8); +- block[block.length - 1] = (byte)(len ); ++ // MUST NOT increase the sequence number for a simulated computation. ++ if (!isSimulated) { ++ block[BLOCK_OFFSET_TYPE] = type; ++ block[block.length - 2] = (byte)(len >> 8); ++ block[block.length - 1] = (byte)(len ); + +- mac.update(block); +- incrementSequenceNumber(); ++ mac.update(block); ++ incrementSequenceNumber(); ++ } + + // content + if (bb != null) { +diff --git a/src/share/classes/sun/security/ssl/OutputRecord.java b/src/share/classes/sun/security/ssl/OutputRecord.java +--- jdk/src/share/classes/sun/security/ssl/OutputRecord.java ++++ jdk/src/share/classes/sun/security/ssl/OutputRecord.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -204,7 +204,7 @@ class OutputRecord extends ByteArrayOutp + } + if (signer.MAClen() != 0) { + byte[] hash = signer.compute(contentType, buf, +- headerSize, count - headerSize); ++ headerSize, count - headerSize, false); + write(hash); + } + } +diff --git a/src/share/classes/sun/security/ssl/SSLEngineImpl.java b/src/share/classes/sun/security/ssl/SSLEngineImpl.java +--- jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java ++++ jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -919,34 +919,13 @@ final public class SSLEngineImpl extends + * throw a fatal alert if the integrity check fails. + */ + try { +- decryptedBB = inputRecord.decrypt(readCipher, readBB); ++ decryptedBB = inputRecord.decrypt(readMAC, readCipher, readBB); + } catch (BadPaddingException e) { +- // RFC 2246 states that decryption_failed should be used +- // for this purpose. However, that allows certain attacks, +- // so we just send bad record MAC. We also need to make +- // sure to always check the MAC to avoid a timing attack +- // for the same issue. See paper by Vaudenay et al. +- // +- // rewind the BB if necessary. +- readBB.rewind(); +- +- inputRecord.checkMAC(readMAC, readBB); +- +- // use the same alert types as for MAC failure below + byte alertType = (inputRecord.contentType() == + Record.ct_handshake) ? + Alerts.alert_handshake_failure : + Alerts.alert_bad_record_mac; +- fatal(alertType, "Invalid padding", e); +- } +- +- if (!inputRecord.checkMAC(readMAC, decryptedBB)) { +- if (inputRecord.contentType() == Record.ct_handshake) { +- fatal(Alerts.alert_handshake_failure, +- "bad handshake record MAC"); +- } else { +- fatal(Alerts.alert_bad_record_mac, "bad record MAC"); +- } ++ fatal(alertType, e.getMessage(), e); + } + + // if (!inputRecord.decompress(c)) +diff --git a/src/share/classes/sun/security/ssl/SSLSocketImpl.java b/src/share/classes/sun/security/ssl/SSLSocketImpl.java +--- jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java ++++ jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -922,27 +922,12 @@ final public class SSLSocketImpl extends + * throw a fatal alert if the integrity check fails. + */ + try { +- r.decrypt(readCipher); ++ r.decrypt(readMAC, readCipher); + } catch (BadPaddingException e) { +- // RFC 2246 states that decryption_failed should be used +- // for this purpose. However, that allows certain attacks, +- // so we just send bad record MAC. We also need to make +- // sure to always check the MAC to avoid a timing attack +- // for the same issue. See paper by Vaudenay et al. +- r.checkMAC(readMAC); +- // use the same alert types as for MAC failure below + byte alertType = (r.contentType() == Record.ct_handshake) + ? Alerts.alert_handshake_failure + : Alerts.alert_bad_record_mac; +- fatal(alertType, "Invalid padding", e); +- } +- if (!r.checkMAC(readMAC)) { +- if (r.contentType() == Record.ct_handshake) { +- fatal(Alerts.alert_handshake_failure, +- "bad handshake record MAC"); +- } else { +- fatal(Alerts.alert_bad_record_mac, "bad record MAC"); +- } ++ fatal(alertType, e.getMessage(), e); + } + + // if (!r.decompress(c)) diff --git a/java/openjdk6/files/icedtea/security/20130219/8007688.patch b/java/openjdk6/files/icedtea/security/20130219/8007688.patch new file mode 100644 index 000000000000..bc13a982ab4f --- /dev/null +++ b/java/openjdk6/files/icedtea/security/20130219/8007688.patch @@ -0,0 +1,130 @@ +# HG changeset patch +# User coffeys +# Date 1360873966 0 +# Node ID 617e68a3948824283f15c36fcd8cf264c1dd0a99 +# Parent 25e83b78298b71abb46eb5a337ed7bddef418ca4 +8007688: Blacklist known bad certificate +Reviewed-by: mullan + +diff --git a/src/share/classes/sun/security/util/UntrustedCertificates.java b/src/share/classes/sun/security/util/UntrustedCertificates.java +--- jdk/src/share/classes/sun/security/util/UntrustedCertificates.java ++++ jdk/src/share/classes/sun/security/util/UntrustedCertificates.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -739,5 +739,111 @@ public final class UntrustedCertificates + "B8WfedLHjFW/TMcnXlEWKz4=\n" + + "-----END CERTIFICATE-----"); + ++ // ++ // Revoked DigiCert code signing certificates used to sign malware ++ // ++ ++ // Subject: CN=Buster Paper Comercial Ltda, ++ // O=Buster Paper Comercial Ltda, ++ // L=S?o Jos? Dos Campos, ++ // ST=S?o Paulo, ++ // C=BR ++ // Issuer: CN=DigiCert Assured ID Code Signing CA-1, ++ // OU=www.digicert.com, ++ // O=DigiCert Inc, ++ // C=US ++ // Serial: 07:b4:4c:db:ff:fb:78:de:05:f4:26:16:72:a6:73:12 ++ add("buster-paper-comercial-ltda-72A67312", ++ "-----BEGIN CERTIFICATE-----\n" + ++ "MIIGwzCCBaugAwIBAgIQB7RM2//7eN4F9CYWcqZzEjANBgkqhkiG9w0BAQUFADBv\n" + ++ "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" + ++ "d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv\n" + ++ "ZGUgU2lnbmluZyBDQS0xMB4XDTEzMDExNzAwMDAwMFoXDTE0MDEyMjEyMDAwMFow\n" + ++ "gY4xCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMR4wHAYDVQQHDBVT\n" + ++ "w6NvIEpvc8OpIERvcyBDYW1wb3MxJDAiBgNVBAoTG0J1c3RlciBQYXBlciBDb21l\n" + ++ "cmNpYWwgTHRkYTEkMCIGA1UEAxMbQnVzdGVyIFBhcGVyIENvbWVyY2lhbCBMdGRh\n" + ++ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzO0l6jWIpEfO2oUpVHpL\n" + ++ "HETj5lzivNb0S9jKHgGJax917czh81PnGTxwxFXd6gLJuy/XFHvmiSi8g8jzlymn\n" + ++ "2Ji5zQ3CPaz7nomJokSUDlMVJ2qYWtctw4jrdjuI4qtn+koXXUFkWjkf8h8251I4\n" + ++ "tUs7S49HE2Go5owCYP3byajj7fsFAYR/Xb7TdVtndkZsUB/YgOjHovyACjouaNCi\n" + ++ "mDiRyQ6zLLjZGiyeD65Yiseuhp5b8/BL5h1p7w76QYMYMVQNAdtDKut2R8MBpuWf\n" + ++ "Ny7Eoi0x/gm1p9X5Rcl5aN7K0G4UtTAJKbkuUfXddsyFoM0Nx8uo8SgNQ8Y/X5Jx\n" + ++ "BwIDAQABo4IDOTCCAzUwHwYDVR0jBBgwFoAUe2jOKarAF75JeuHlP9an90WPNTIw\n" + ++ "HQYDVR0OBBYEFFLZ3n5nt/Eer7n1bvtOqMb1qKO5MA4GA1UdDwEB/wQEAwIHgDAT\n" + ++ "BgNVHSUEDDAKBggrBgEFBQcDAzBzBgNVHR8EbDBqMDOgMaAvhi1odHRwOi8vY3Js\n" + ++ "My5kaWdpY2VydC5jb20vYXNzdXJlZC1jcy0yMDExYS5jcmwwM6AxoC+GLWh0dHA6\n" + ++ "Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9hc3N1cmVkLWNzLTIwMTFhLmNybDCCAcQGA1Ud\n" + ++ "IASCAbswggG3MIIBswYJYIZIAYb9bAMBMIIBpDA6BggrBgEFBQcCARYuaHR0cDov\n" + ++ "L3d3dy5kaWdpY2VydC5jb20vc3NsLWNwcy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsG\n" + ++ "AQUFBwICMIIBVh6CAVIAQQBuAHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABD\n" + ++ "AGUAcgB0AGkAZgBpAGMAYQB0AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABh\n" + ++ "AGMAYwBlAHAAdABhAG4AYwBlACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQBy\n" + ++ "AHQAIABDAFAALwBDAFAAUwAgAGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBn\n" + ++ "ACAAUABhAHIAdAB5ACAAQQBnAHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABs\n" + ++ "AGkAbQBpAHQAIABsAGkAYQBiAGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABp\n" + ++ "AG4AYwBvAHIAcABvAHIAYQB0AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBl\n" + ++ "AGYAZQByAGUAbgBjAGUALjCBggYIKwYBBQUHAQEEdjB0MCQGCCsGAQUFBzABhhho\n" + ++ "dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTAYIKwYBBQUHMAKGQGh0dHA6Ly9jYWNl\n" + ++ "cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENvZGVTaWduaW5nQ0Et\n" + ++ "MS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQUFAAOCAQEAPTTQvpOIikXI\n" + ++ "hTLnNbajaFRR5GhQpTzUNgBfF9VYSlNw/wMjpGsrh5RxaJCip52jbehmTgjMRhft\n" + ++ "jRYyml44PAVsCcR9uEoDpCZYpI1fHI1R+F8jd1C9rqprbSwwOG4xlg4SmvTHYs6e\n" + ++ "gBItQ/1p9XY+Sf4Wv1qOuOFL1qvV/5VyR2zdlOQCmKCeMgxt6a/tHLBDiAA67D44\n" + ++ "/vfdoNJl0CU2It0PO60jdCPFNWIRcxL+OSDqAoePeUC7xQ+JsTEIxuUE8+d6w6fc\n" + ++ "BV2mYb1flh22t46GLjh4gyo7xw3aL6L0L0jzlTT6IcEw6NIbaPbIKj/npQnHobYj\n" + ++ "XMuKLxbh7g==\n" + ++ "-----END CERTIFICATE-----"); ++ ++ // Subject: CN=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME, ++ // O=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME, ++ // L=S?o Paulo, ++ // ST=S?o Paulo, ++ // C=BR ++ // Issuer: CN=DigiCert Assured ID Code Signing CA-1, ++ // OU=www.digicert.com, ++ // O=DigiCert Inc, ++ // C=US ++ // Serial: 0a:38:9b:95:ee:73:6d:d1:3b:c0:ed:74:3f:d7:4d:2f ++ add("buster-assistencia-tecnica-electronica-ltda-3FD74D2F", ++ "-----BEGIN CERTIFICATE-----\n" + ++ "MIIG4DCCBcigAwIBAgIQCjible5zbdE7wO10P9dNLzANBgkqhkiG9w0BAQUFADBv\n" + ++ "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" + ++ "d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv\n" + ++ "ZGUgU2lnbmluZyBDQS0xMB4XDTEyMTEwOTAwMDAwMFoXDTEzMTExNDEyMDAwMFow\n" + ++ "gasxCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMRMwEQYDVQQHDApT\n" + ++ "w6NvIFBhdWxvMTgwNgYDVQQKEy9CVVNURVIgQVNTSVNURU5DSUEgVEVDTklDQSBF\n" + ++ "TEVUUk9OSUNBIExUREEgLSBNRTE4MDYGA1UEAxMvQlVTVEVSIEFTU0lTVEVOQ0lB\n" + ++ "IFRFQ05JQ0EgRUxFVFJPTklDQSBMVERBIC0gTUUwggEiMA0GCSqGSIb3DQEBAQUA\n" + ++ "A4IBDwAwggEKAoIBAQDAqNeEs5/B2CTXGjTOkUIdu6jV6qulOZwdw4sefHWYj1UR\n" + ++ "4z6zPk9kjpUgbnb402RFq88QtfInwddZ/wXn9OxMtDd/3TnC7HrhNS7ga79ZFL2V\n" + ++ "JnmzKHum2Yvh0q82QEJ9tHBR2X9VdKpUIH08Zs3k6cWWM1H0YX0cxA/HohhesQJW\n" + ++ "kwJ3urOIJiH/HeByDk8a1NS8safcCxk5vxvW4WvCg43iT09LeHY5Aa8abKw8lqVb\n" + ++ "0tD5ZSIjdmdj3TT1U37iAHLLRM2DXbxfdbhouUX1c5U1ZHAMA67HwjKiseOiDaHj\n" + ++ "NUGbC37C+cgbc9VVM/cURD8WvS0Kj6fQv7F2QtJDAgMBAAGjggM5MIIDNTAfBgNV\n" + ++ "HSMEGDAWgBR7aM4pqsAXvkl64eU/1qf3RY81MjAdBgNVHQ4EFgQU88EXKAyDsh30\n" + ++ "o9+Gu9a4xUy+FSMwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMD\n" + ++ "MHMGA1UdHwRsMGowM6AxoC+GLWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9hc3N1\n" + ++ "cmVkLWNzLTIwMTFhLmNybDAzoDGgL4YtaHR0cDovL2NybDQuZGlnaWNlcnQuY29t\n" + ++ "L2Fzc3VyZWQtY3MtMjAxMWEuY3JsMIIBxAYDVR0gBIIBuzCCAbcwggGzBglghkgB\n" + ++ "hv1sAwEwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9z\n" + ++ "c2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4A\n" + ++ "eQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQA\n" + ++ "ZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUA\n" + ++ "IABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAA\n" + ++ "YQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcA\n" + ++ "cgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIA\n" + ++ "aQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQA\n" + ++ "ZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMIGC\n" + ++ "BggrBgEFBQcBAQR2MHQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0\n" + ++ "LmNvbTBMBggrBgEFBQcwAoZAaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Rp\n" + ++ "Z2lDZXJ0QXNzdXJlZElEQ29kZVNpZ25pbmdDQS0xLmNydDAMBgNVHRMBAf8EAjAA\n" + ++ "MA0GCSqGSIb3DQEBBQUAA4IBAQAei1QmiXepje8OIfo/WonD4MIXgpPr2dfRaquQ\n" + ++ "A8q63OpTRSveyqdQDCSPpDRF/nvO1Y30yksZvIH1tNBsW5LBdxAKN3lFdBlqBwtE\n" + ++ "Q3jHc0KVVYRJ0FBaGE/PJHmRajscdAhYIcMPhTga0u0tDK+wOHEq3993dfl6yHjA\n" + ++ "XHU2iW5pnk75ZoE39zALD5eKXT8ZXrET5c3XUFJKWA+XuGmdmyzqo0Au49PanBv9\n" + ++ "UlZnabYfqoMArqMS0tGSX4cGgi9/2E+pHG9BX4sFW+ZDumroOA2pxyMWEKjxePEL\n" + ++ "zCOfhbsRWdMLYepauaNZOIMZXmFwcrIl0TGMkTAtATz+XmZc\n" + ++ "-----END CERTIFICATE-----"); ++ + } + } diff --git a/java/openjdk6/files/patch-set b/java/openjdk6/files/patch-set index ae59dafe8471..0fabe80c09e8 100644 --- a/java/openjdk6/files/patch-set +++ b/java/openjdk6/files/patch-set @@ -11233,9 +11233,9 @@ typedef unsigned long uLong; #endif +#endif - #ifdef _MSC_VER - typedef LONGLONG jlong; - typedef DWORDLONG julong; + #ifdef _MSC_VER + typedef LONGLONG jlong; + typedef DWORDLONG julong; --- jdk/src/share/native/com/sun/java/util/jar/pack/main.cpp +++ jdk/src/share/native/com/sun/java/util/jar/pack/main.cpp @@ -33,9 +33,14 @@ |