--- a/jdk/make/gendata/GendataBreakIterator.gmk Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/make/gendata/GendataBreakIterator.gmk Thu Oct 27 21:22:57 2016 +0000
@@ -55,7 +55,6 @@
$(eval $(call SetupJavaCompilation,BUILD_BREAKITERATOR_LD, \
SETUP := GENERATE_OLDBYTECODE, \
SRC := $(JDK_TOPDIR)/src/jdk.localedata/share/classes, \
- INCLUDES := $(TEXT_PKG_LD), \
INCLUDE_FILES := \
$(TEXT_PKG_LD)/BreakIteratorRules_th.java \
$(TEXT_PKG_LD)/BreakIteratorInfo_th.java, \
--- a/jdk/make/mapfiles/libsplashscreen/mapfile-vers Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/make/mapfiles/libsplashscreen/mapfile-vers Thu Oct 27 21:22:57 2016 +0000
@@ -44,6 +44,7 @@
SplashSetFileJarName;
SplashSetScaleFactor;
SplashGetScaledImageName;
+ SplashGetScaledImgNameMaxPstfixLen;
local:
*;
};
--- a/jdk/src/java.base/share/classes/java/io/FileInputStream.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/io/FileInputStream.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
package java.io;
import java.nio.channels.FileChannel;
-import java.util.concurrent.atomic.AtomicBoolean;
import sun.nio.ch.FileChannelImpl;
@@ -60,7 +59,9 @@
private volatile FileChannel channel;
- private final AtomicBoolean closed = new AtomicBoolean(false);
+ private final Object closeLock = new Object();
+
+ private volatile boolean closed;
/**
* Creates a <code>FileInputStream</code> by
@@ -313,14 +314,21 @@
* @spec JSR-51
*/
public void close() throws IOException {
- if (!closed.compareAndSet(false, true)) {
- // if compareAndSet() returns false closed was already true
+ if (closed) {
return;
}
+ synchronized (closeLock) {
+ if (closed) {
+ return;
+ }
+ closed = true;
+ }
FileChannel fc = channel;
if (fc != null) {
- fc.close();
+ // possible race with getChannel(), benign since
+ // FileChannel.close is final and idempotent
+ fc.close();
}
fd.closeAll(new Closeable() {
@@ -370,8 +378,10 @@
fc = this.channel;
if (fc == null) {
this.channel = fc = FileChannelImpl.open(fd, path, true, false, this);
- if (closed.get()) {
+ if (closed) {
try {
+ // possible race with close(), benign since
+ // FileChannel.close is final and idempotent
fc.close();
} catch (IOException ioe) {
throw new InternalError(ioe); // should not happen
--- a/jdk/src/java.base/share/classes/java/io/FileOutputStream.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/io/FileOutputStream.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
package java.io;
import java.nio.channels.FileChannel;
-import java.util.concurrent.atomic.AtomicBoolean;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.JavaIOFileDescriptorAccess;
import sun.nio.ch.FileChannelImpl;
@@ -77,7 +76,9 @@
*/
private final String path;
- private final AtomicBoolean closed = new AtomicBoolean(false);
+ private final Object closeLock = new Object();
+
+ private volatile boolean closed;
/**
* Creates a file output stream to write to the file with the
@@ -341,14 +342,21 @@
* @spec JSR-51
*/
public void close() throws IOException {
- if (!closed.compareAndSet(false, true)) {
- // if compareAndSet() returns false closed was already true
+ if (closed) {
return;
}
+ synchronized (closeLock) {
+ if (closed) {
+ return;
+ }
+ closed = true;
+ }
FileChannel fc = channel;
if (fc != null) {
- fc.close();
+ // possible race with getChannel(), benign since
+ // FileChannel.close is final and idempotent
+ fc.close();
}
fd.closeAll(new Closeable() {
@@ -399,8 +407,10 @@
fc = this.channel;
if (fc == null) {
this.channel = fc = FileChannelImpl.open(fd, path, false, true, this);
- if (closed.get()) {
+ if (closed) {
try {
+ // possible race with close(), benign since
+ // FileChannel.close is final and idempotent
fc.close();
} catch (IOException ioe) {
throw new InternalError(ioe); // should not happen
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Thu Oct 27 21:22:57 2016 +0000
@@ -104,9 +104,9 @@
* class or resource itself.
*
* <p> Class loaders that support concurrent loading of classes are known as
- * <em>parallel capable</em> class loaders and are required to register
- * themselves at their class initialization time by invoking the
- * {@link
+ * <em>{@linkplain #isParallelCapable() parallel capable}</em> class loaders and
+ * are required to register themselves at their class initialization time by
+ * invoking the {@link
* #registerAsParallelCapable <tt>ClassLoader.registerAsParallelCapable</tt>}
* method. Note that the <tt>ClassLoader</tt> class is registered as parallel
* capable by default. However, its subclasses still need to register themselves
@@ -1437,7 +1437,7 @@
}
/**
- * Registers the caller as parallel capable.
+ * Registers the caller as {@linkplain #isParallelCapable() parallel capable}.
* The registration succeeds if and only if all of the following
* conditions are met:
* <ol>
@@ -1448,8 +1448,10 @@
* <p>Note that once a class loader is registered as parallel capable, there
* is no way to change it back.</p>
*
- * @return true if the caller is successfully registered as
- * parallel capable and false if otherwise.
+ * @return {@code true} if the caller is successfully registered as
+ * parallel capable and {@code false} if otherwise.
+ *
+ * @see #isParallelCapable()
*
* @since 1.7
*/
@@ -1461,6 +1463,22 @@
}
/**
+ * Returns {@code true} if this class loader is
+ * {@linkplain #registerAsParallelCapable parallel capable}, otherwise
+ * {@code false}.
+ *
+ * @return {@code true} if this class loader is parallel capable,
+ * otherwise {@code false}.
+ *
+ * @see #registerAsParallelCapable()
+ *
+ * @since 9
+ */
+ public final boolean isParallelCapable() {
+ return ParallelLoaders.isRegistered(this.getClass());
+ }
+
+ /**
* Find a resource of the specified name from the search path used to load
* classes. This method locates the resource through the system class
* loader (see {@link #getSystemClassLoader()}).
@@ -1663,6 +1681,15 @@
* this method during startup should take care not to cache the return
* value until the system is fully initialized.
*
+ * <p> The class path used by the built-in system class loader is determined
+ * by the system property "{@code java.class.path}" during early
+ * initialization of the VM. If the system property is not defined,
+ * or its value is an empty string, then there is no class path
+ * when the initial module is a module on the application module path,
+ * i.e. <em>a named module</em>. If the initial module is not on
+ * the application module path then the class path defaults to
+ * the current working directory.
+ *
* @return The system <tt>ClassLoader</tt> for delegation
*
* @throws SecurityException
--- a/jdk/src/java.base/share/classes/java/net/InetAddress.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java Thu Oct 27 21:22:57 2016 +0000
@@ -201,13 +201,13 @@
* Specify the address family: Internet Protocol, Version 4
* @since 1.4
*/
- static final int IPv4 = 1;
+ @Native static final int IPv4 = 1;
/**
* Specify the address family: Internet Protocol, Version 6
* @since 1.4
*/
- static final int IPv6 = 2;
+ @Native static final int IPv6 = 2;
/* Specify address family preference */
static transient final int preferIPv6Address;
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java Thu Oct 27 21:22:57 2016 +0000
@@ -69,16 +69,17 @@
bcp = toURLClassPath(s);
// we have a class path if -cp is specified or -m is not specified.
- // If neither is specified then default to -cp <working directory>.
+ // If neither is specified then default to -cp <working directory>
+ // If -cp is not specified and -m is specified, the value of
+ // java.class.path is an empty string, then no class path.
URLClassPath ucp = null;
String mainMid = System.getProperty("jdk.module.main");
String cp = System.getProperty("java.class.path");
- if (mainMid == null && cp == null)
+ if (cp == null)
cp = "";
- if (cp != null)
+ if (mainMid == null || cp.length() > 0)
ucp = toURLClassPath(cp);
-
// create the class loaders
BOOT_LOADER = new BootClassLoader(bcp);
PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER);
--- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@
\ (to execute the main class in a module)\n\
where options include:\n
-java.launcher.opt.datamodel =\ -d{0}\t use a {0}-bit data model if available\n
+java.launcher.opt.datamodel =\ -d{0}\t Deprecated, will be removed in a future release\n
java.launcher.opt.vmselect =\ {0}\t to select the "{1}" VM\n
java.launcher.opt.hotspot =\ {0}\t is a synonym for the "{1}" VM [deprecated]\n
@@ -95,6 +95,12 @@
\ load Java programming language agent, see java.lang.instrument\n\
\ -splash:<imagepath>\n\
\ show splash screen with specified image\n\
+\ HiDPI scaled images are automatically supported and used\n\
+\ if available. The unscaled image filename, e.g. image.ext,\n\
+\ should always be passed as the argument to the -splash option.\n\
+\ The most appropriate scaled image provided will be picked up\n\
+\ automatically.\n\
+\ See the SplashScreen API documentation for more information.\n\
\ @<filepath> read options from the specified file\n\
\To specify an argument for a long option, you can use --<name>=<value> or\n\
\--<name> <value>.\n\
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/text/BreakDictionary.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+/*
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
+ *
+ * The original version of this source code and documentation
+ * is copyrighted and owned by Taligent, Inc., a wholly-owned
+ * subsidiary of IBM. These materials are provided under terms
+ * of a License Agreement between Taligent and Sun. This technology
+ * is protected by multiple US and International patents.
+ *
+ * This notice and attribution to Taligent may not be removed.
+ * Taligent is a registered trademark of Taligent, Inc.
+ */
+package sun.text;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.util.MissingResourceException;
+import sun.text.CompactByteArray;
+import sun.text.SupplementaryCharacterData;
+
+/**
+ * This is the class that represents the list of known words used by
+ * DictionaryBasedBreakIterator. The conceptual data structure used
+ * here is a trie: there is a node hanging off the root node for every
+ * letter that can start a word. Each of these nodes has a node hanging
+ * off of it for every letter that can be the second letter of a word
+ * if this node is the first letter, and so on. The trie is represented
+ * as a two-dimensional array that can be treated as a table of state
+ * transitions. Indexes are used to compress this array, taking
+ * advantage of the fact that this array will always be very sparse.
+ */
+class BreakDictionary {
+
+ //=========================================================================
+ // data members
+ //=========================================================================
+
+ /**
+ * The version of the dictionary that was read in.
+ */
+ private static int supportedVersion = 1;
+
+ /**
+ * Maps from characters to column numbers. The main use of this is to
+ * avoid making room in the array for empty columns.
+ */
+ private CompactByteArray columnMap = null;
+ private SupplementaryCharacterData supplementaryCharColumnMap = null;
+
+ /**
+ * The number of actual columns in the table
+ */
+ private int numCols;
+
+ /**
+ * Columns are organized into groups of 32. This says how many
+ * column groups. (We could calculate this, but we store the
+ * value to avoid having to repeatedly calculate it.)
+ */
+ private int numColGroups;
+
+ /**
+ * The actual compressed state table. Each conceptual row represents
+ * a state, and the cells in it contain the row numbers of the states
+ * to transition to for each possible letter. 0 is used to indicate
+ * an illegal combination of letters (i.e., the error state). The
+ * table is compressed by eliminating all the unpopulated (i.e., zero)
+ * cells. Multiple conceptual rows can then be doubled up in a single
+ * physical row by sliding them up and possibly shifting them to one
+ * side or the other so the populated cells don't collide. Indexes
+ * are used to identify unpopulated cells and to locate populated cells.
+ */
+ private short[] table = null;
+
+ /**
+ * This index maps logical row numbers to physical row numbers
+ */
+ private short[] rowIndex = null;
+
+ /**
+ * A bitmap is used to tell which cells in the comceptual table are
+ * populated. This array contains all the unique bit combinations
+ * in that bitmap. If the table is more than 32 columns wide,
+ * successive entries in this array are used for a single row.
+ */
+ private int[] rowIndexFlags = null;
+
+ /**
+ * This index maps from a logical row number into the bitmap table above.
+ * (This keeps us from storing duplicate bitmap combinations.) Since there
+ * are a lot of rows with only one populated cell, instead of wasting space
+ * in the bitmap table, we just store a negative number in this index for
+ * rows with one populated cell. The absolute value of that number is
+ * the column number of the populated cell.
+ */
+ private short[] rowIndexFlagsIndex = null;
+
+ /**
+ * For each logical row, this index contains a constant that is added to
+ * the logical column number to get the physical column number
+ */
+ private byte[] rowIndexShifts = null;
+
+ //=========================================================================
+ // deserialization
+ //=========================================================================
+
+ BreakDictionary(String dictionaryName, byte[] dictionaryData) {
+ try {
+ setupDictionary(dictionaryName, dictionaryData);
+ } catch (BufferUnderflowException bue) {
+ MissingResourceException e;
+ e = new MissingResourceException("Corrupted dictionary data",
+ dictionaryName, "");
+ e.initCause(bue);
+ throw e;
+ }
+ }
+
+ private void setupDictionary(String dictionaryName, byte[] dictionaryData) {
+ ByteBuffer bb = ByteBuffer.wrap(dictionaryData);
+
+ // check version
+ int version = bb.getInt();
+ if (version != supportedVersion) {
+ throw new MissingResourceException("Dictionary version(" + version + ") is unsupported",
+ dictionaryName, "");
+ }
+
+ // Check data size
+ int len = bb.getInt();
+ if (bb.position() + len != bb.limit()) {
+ throw new MissingResourceException("Dictionary size is wrong: " + bb.limit(),
+ dictionaryName, "");
+ }
+
+ // read in the column map for BMP characteres (this is serialized in
+ // its internal form: an index array followed by a data array)
+ len = bb.getInt();
+ short[] temp = new short[len];
+ for (int i = 0; i < len; i++) {
+ temp[i] = bb.getShort();
+ }
+ len = bb.getInt();
+ byte[] temp2 = new byte[len];
+ bb.get(temp2);
+ columnMap = new CompactByteArray(temp, temp2);
+
+ // read in numCols and numColGroups
+ numCols = bb.getInt();
+ numColGroups = bb.getInt();
+
+ // read in the row-number index
+ len = bb.getInt();
+ rowIndex = new short[len];
+ for (int i = 0; i < len; i++) {
+ rowIndex[i] = bb.getShort();
+ }
+
+ // load in the populated-cells bitmap: index first, then bitmap list
+ len = bb.getInt();
+ rowIndexFlagsIndex = new short[len];
+ for (int i = 0; i < len; i++) {
+ rowIndexFlagsIndex[i] = bb.getShort();
+ }
+ len = bb.getInt();
+ rowIndexFlags = new int[len];
+ for (int i = 0; i < len; i++) {
+ rowIndexFlags[i] = bb.getInt();
+ }
+
+ // load in the row-shift index
+ len = bb.getInt();
+ rowIndexShifts = new byte[len];
+ bb.get(rowIndexShifts);
+
+ // load in the actual state table
+ len = bb.getInt();
+ table = new short[len];
+ for (int i = 0; i < len; i++) {
+ table[i] = bb.getShort();
+ }
+
+ // finally, prepare the column map for supplementary characters
+ len = bb.getInt();
+ int[] temp3 = new int[len];
+ for (int i = 0; i < len; i++) {
+ temp3[i] = bb.getInt();
+ }
+ assert bb.position() == bb.limit();
+
+ supplementaryCharColumnMap = new SupplementaryCharacterData(temp3);
+ }
+
+ //=========================================================================
+ // access to the words
+ //=========================================================================
+
+ /**
+ * Uses the column map to map the character to a column number, then
+ * passes the row and column number to getNextState()
+ * @param row The current state
+ * @param ch The character whose column we're interested in
+ * @return The new state to transition to
+ */
+ public final short getNextStateFromCharacter(int row, int ch) {
+ int col;
+ if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+ col = columnMap.elementAt((char)ch);
+ } else {
+ col = supplementaryCharColumnMap.getValue(ch);
+ }
+ return getNextState(row, col);
+ }
+
+ /**
+ * Returns the value in the cell with the specified (logical) row and
+ * column numbers. In DictionaryBasedBreakIterator, the row number is
+ * a state number, the column number is an input, and the return value
+ * is the row number of the new state to transition to. (0 is the
+ * "error" state, and -1 is the "end of word" state in a dictionary)
+ * @param row The row number of the current state
+ * @param col The column number of the input character (0 means "not a
+ * dictionary character")
+ * @return The row number of the new state to transition to
+ */
+ public final short getNextState(int row, int col) {
+ if (cellIsPopulated(row, col)) {
+ // we map from logical to physical row number by looking up the
+ // mapping in rowIndex; we map from logical column number to
+ // physical column number by looking up a shift value for this
+ // logical row and offsetting the logical column number by
+ // the shift amount. Then we can use internalAt() to actually
+ // get the value out of the table.
+ return internalAt(rowIndex[row], col + rowIndexShifts[row]);
+ }
+ else {
+ return 0;
+ }
+ }
+
+ /**
+ * Given (logical) row and column numbers, returns true if the
+ * cell in that position is populated
+ */
+ private boolean cellIsPopulated(int row, int col) {
+ // look up the entry in the bitmap index for the specified row.
+ // If it's a negative number, it's the column number of the only
+ // populated cell in the row
+ if (rowIndexFlagsIndex[row] < 0) {
+ return col == -rowIndexFlagsIndex[row];
+ }
+
+ // if it's a positive number, it's the offset of an entry in the bitmap
+ // list. If the table is more than 32 columns wide, the bitmap is stored
+ // successive entries in the bitmap list, so we have to divide the column
+ // number by 32 and offset the number we got out of the index by the result.
+ // Once we have the appropriate piece of the bitmap, test the appropriate
+ // bit and return the result.
+ else {
+ int flags = rowIndexFlags[rowIndexFlagsIndex[row] + (col >> 5)];
+ return (flags & (1 << (col & 0x1f))) != 0;
+ }
+ }
+
+ /**
+ * Implementation of getNextState() when we know the specified cell is
+ * populated.
+ * @param row The PHYSICAL row number of the cell
+ * @param col The PHYSICAL column number of the cell
+ * @return The value stored in the cell
+ */
+ private short internalAt(int row, int col) {
+ // the table is a one-dimensional array, so this just does the math necessary
+ // to treat it as a two-dimensional array (we don't just use a two-dimensional
+ // array because two-dimensional arrays are inefficient in Java)
+ return table[row * numCols + col];
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/text/DictionaryBasedBreakIterator.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,526 @@
+/*
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+/*
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
+ *
+ * The original version of this source code and documentation
+ * is copyrighted and owned by Taligent, Inc., a wholly-owned
+ * subsidiary of IBM. These materials are provided under terms
+ * of a License Agreement between Taligent and Sun. This technology
+ * is protected by multiple US and International patents.
+ *
+ * This notice and attribution to Taligent may not be removed.
+ * Taligent is a registered trademark of Taligent, Inc.
+ */
+
+package sun.text;
+
+import java.text.CharacterIterator;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+/**
+ * A subclass of RuleBasedBreakIterator that adds the ability to use a dictionary
+ * to further subdivide ranges of text beyond what is possible using just the
+ * state-table-based algorithm. This is necessary, for example, to handle
+ * word and line breaking in Thai, which doesn't use spaces between words. The
+ * state-table-based algorithm used by RuleBasedBreakIterator is used to divide
+ * up text as far as possible, and then contiguous ranges of letters are
+ * repeatedly compared against a list of known words (i.e., the dictionary)
+ * to divide them up into words.
+ *
+ * DictionaryBasedBreakIterator uses the same rule language as RuleBasedBreakIterator,
+ * but adds one more special substitution name: <dictionary>. This substitution
+ * name is used to identify characters in words in the dictionary. The idea is that
+ * if the iterator passes over a chunk of text that includes two or more characters
+ * in a row that are included in <dictionary>, it goes back through that range and
+ * derives additional break positions (if possible) using the dictionary.
+ *
+ * DictionaryBasedBreakIterator is also constructed with the filename of a dictionary
+ * file. It follows a prescribed search path to locate the dictionary (right now,
+ * it looks for it in /com/ibm/text/resources in each directory in the classpath,
+ * and won't find it in JAR files, but this location is likely to change). The
+ * dictionary file is in a serialized binary format. We have a very primitive (and
+ * slow) BuildDictionaryFile utility for creating dictionary files, but aren't
+ * currently making it public. Contact us for help.
+ */
+public class DictionaryBasedBreakIterator extends RuleBasedBreakIterator {
+
+ /**
+ * a list of known words that is used to divide up contiguous ranges of letters,
+ * stored in a compressed, indexed, format that offers fast access
+ */
+ private BreakDictionary dictionary;
+
+ /**
+ * a list of flags indicating which character categories are contained in
+ * the dictionary file (this is used to determine which ranges of characters
+ * to apply the dictionary to)
+ */
+ private boolean[] categoryFlags;
+
+ /**
+ * a temporary hiding place for the number of dictionary characters in the
+ * last range passed over by next()
+ */
+ private int dictionaryCharCount;
+
+ /**
+ * when a range of characters is divided up using the dictionary, the break
+ * positions that are discovered are stored here, preventing us from having
+ * to use either the dictionary or the state table again until the iterator
+ * leaves this range of text
+ */
+ private int[] cachedBreakPositions;
+
+ /**
+ * if cachedBreakPositions is not null, this indicates which item in the
+ * cache the current iteration position refers to
+ */
+ private int positionInCache;
+
+ /**
+ * Constructs a DictionaryBasedBreakIterator.
+ *
+ * @param ruleFile the name of the rule data file
+ * @param ruleData the rule data loaded from the rule data file
+ * @param dictionaryFile the name of the dictionary file
+ * @param dictionartData the dictionary data loaded from the dictionary file
+ * @throws MissingResourceException if rule data or dictionary initialization failed
+ */
+ public DictionaryBasedBreakIterator(String ruleFile, byte[] ruleData,
+ String dictionaryFile, byte[] dictionaryData) {
+ super(ruleFile, ruleData);
+ byte[] tmp = super.getAdditionalData();
+ if (tmp != null) {
+ prepareCategoryFlags(tmp);
+ super.setAdditionalData(null);
+ }
+ dictionary = new BreakDictionary(dictionaryFile, dictionaryData);
+ }
+
+ private void prepareCategoryFlags(byte[] data) {
+ categoryFlags = new boolean[data.length];
+ for (int i = 0; i < data.length; i++) {
+ categoryFlags[i] = (data[i] == (byte)1) ? true : false;
+ }
+ }
+
+ @Override
+ public void setText(CharacterIterator newText) {
+ super.setText(newText);
+ cachedBreakPositions = null;
+ dictionaryCharCount = 0;
+ positionInCache = 0;
+ }
+
+ /**
+ * Sets the current iteration position to the beginning of the text.
+ * (i.e., the CharacterIterator's starting offset).
+ * @return The offset of the beginning of the text.
+ */
+ @Override
+ public int first() {
+ cachedBreakPositions = null;
+ dictionaryCharCount = 0;
+ positionInCache = 0;
+ return super.first();
+ }
+
+ /**
+ * Sets the current iteration position to the end of the text.
+ * (i.e., the CharacterIterator's ending offset).
+ * @return The text's past-the-end offset.
+ */
+ @Override
+ public int last() {
+ cachedBreakPositions = null;
+ dictionaryCharCount = 0;
+ positionInCache = 0;
+ return super.last();
+ }
+
+ /**
+ * Advances the iterator one step backwards.
+ * @return The position of the last boundary position before the
+ * current iteration position
+ */
+ @Override
+ public int previous() {
+ CharacterIterator text = getText();
+
+ // if we have cached break positions and we're still in the range
+ // covered by them, just move one step backward in the cache
+ if (cachedBreakPositions != null && positionInCache > 0) {
+ --positionInCache;
+ text.setIndex(cachedBreakPositions[positionInCache]);
+ return cachedBreakPositions[positionInCache];
+ }
+
+ // otherwise, dump the cache and use the inherited previous() method to move
+ // backward. This may fill up the cache with new break positions, in which
+ // case we have to mark our position in the cache
+ else {
+ cachedBreakPositions = null;
+ int result = super.previous();
+ if (cachedBreakPositions != null) {
+ positionInCache = cachedBreakPositions.length - 2;
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Sets the current iteration position to the last boundary position
+ * before the specified position.
+ * @param offset The position to begin searching from
+ * @return The position of the last boundary before "offset"
+ */
+ @Override
+ public int preceding(int offset) {
+ CharacterIterator text = getText();
+ checkOffset(offset, text);
+
+ // if we have no cached break positions, or "offset" is outside the
+ // range covered by the cache, we can just call the inherited routine
+ // (which will eventually call other routines in this class that may
+ // refresh the cache)
+ if (cachedBreakPositions == null || offset <= cachedBreakPositions[0] ||
+ offset > cachedBreakPositions[cachedBreakPositions.length - 1]) {
+ cachedBreakPositions = null;
+ return super.preceding(offset);
+ }
+
+ // on the other hand, if "offset" is within the range covered by the cache,
+ // then all we have to do is search the cache for the last break position
+ // before "offset"
+ else {
+ positionInCache = 0;
+ while (positionInCache < cachedBreakPositions.length
+ && offset > cachedBreakPositions[positionInCache]) {
+ ++positionInCache;
+ }
+ --positionInCache;
+ text.setIndex(cachedBreakPositions[positionInCache]);
+ return text.getIndex();
+ }
+ }
+
+ /**
+ * Sets the current iteration position to the first boundary position after
+ * the specified position.
+ * @param offset The position to begin searching forward from
+ * @return The position of the first boundary after "offset"
+ */
+ @Override
+ public int following(int offset) {
+ CharacterIterator text = getText();
+ checkOffset(offset, text);
+
+ // if we have no cached break positions, or if "offset" is outside the
+ // range covered by the cache, then dump the cache and call our
+ // inherited following() method. This will call other methods in this
+ // class that may refresh the cache.
+ if (cachedBreakPositions == null || offset < cachedBreakPositions[0] ||
+ offset >= cachedBreakPositions[cachedBreakPositions.length - 1]) {
+ cachedBreakPositions = null;
+ return super.following(offset);
+ }
+
+ // on the other hand, if "offset" is within the range covered by the
+ // cache, then just search the cache for the first break position
+ // after "offset"
+ else {
+ positionInCache = 0;
+ while (positionInCache < cachedBreakPositions.length
+ && offset >= cachedBreakPositions[positionInCache]) {
+ ++positionInCache;
+ }
+ text.setIndex(cachedBreakPositions[positionInCache]);
+ return text.getIndex();
+ }
+ }
+
+ /**
+ * This is the implementation function for next().
+ */
+ @Override
+ protected int handleNext() {
+ CharacterIterator text = getText();
+
+ // if there are no cached break positions, or if we've just moved
+ // off the end of the range covered by the cache, we have to dump
+ // and possibly regenerate the cache
+ if (cachedBreakPositions == null ||
+ positionInCache == cachedBreakPositions.length - 1) {
+
+ // start by using the inherited handleNext() to find a tentative return
+ // value. dictionaryCharCount tells us how many dictionary characters
+ // we passed over on our way to the tentative return value
+ int startPos = text.getIndex();
+ dictionaryCharCount = 0;
+ int result = super.handleNext();
+
+ // if we passed over more than one dictionary character, then we use
+ // divideUpDictionaryRange() to regenerate the cached break positions
+ // for the new range
+ if (dictionaryCharCount > 1 && result - startPos > 1) {
+ divideUpDictionaryRange(startPos, result);
+ }
+
+ // otherwise, the value we got back from the inherited fuction
+ // is our return value, and we can dump the cache
+ else {
+ cachedBreakPositions = null;
+ return result;
+ }
+ }
+
+ // if the cache of break positions has been regenerated (or existed all
+ // along), then just advance to the next break position in the cache
+ // and return it
+ if (cachedBreakPositions != null) {
+ ++positionInCache;
+ text.setIndex(cachedBreakPositions[positionInCache]);
+ return cachedBreakPositions[positionInCache];
+ }
+ return -9999; // SHOULD NEVER GET HERE!
+ }
+
+ /**
+ * Looks up a character category for a character.
+ */
+ @Override
+ protected int lookupCategory(int c) {
+ // this override of lookupCategory() exists only to keep track of whether we've
+ // passed over any dictionary characters. It calls the inherited lookupCategory()
+ // to do the real work, and then checks whether its return value is one of the
+ // categories represented in the dictionary. If it is, bump the dictionary-
+ // character count.
+ int result = super.lookupCategory(c);
+ if (result != RuleBasedBreakIterator.IGNORE && categoryFlags[result]) {
+ ++dictionaryCharCount;
+ }
+ return result;
+ }
+
+ /**
+ * This is the function that actually implements the dictionary-based
+ * algorithm. Given the endpoints of a range of text, it uses the
+ * dictionary to determine the positions of any boundaries in this
+ * range. It stores all the boundary positions it discovers in
+ * cachedBreakPositions so that we only have to do this work once
+ * for each time we enter the range.
+ */
+ @SuppressWarnings("unchecked")
+ private void divideUpDictionaryRange(int startPos, int endPos) {
+ CharacterIterator text = getText();
+
+ // the range we're dividing may begin or end with non-dictionary characters
+ // (i.e., for line breaking, we may have leading or trailing punctuation
+ // that needs to be kept with the word). Seek from the beginning of the
+ // range to the first dictionary character
+ text.setIndex(startPos);
+ int c = getCurrent();
+ int category = lookupCategory(c);
+ while (category == IGNORE || !categoryFlags[category]) {
+ c = getNext();
+ category = lookupCategory(c);
+ }
+
+ // initialize. We maintain two stacks: currentBreakPositions contains
+ // the list of break positions that will be returned if we successfully
+ // finish traversing the whole range now. possibleBreakPositions lists
+ // all other possible word ends we've passed along the way. (Whenever
+ // we reach an error [a sequence of characters that can't begin any word
+ // in the dictionary], we back up, possibly delete some breaks from
+ // currentBreakPositions, move a break from possibleBreakPositions
+ // to currentBreakPositions, and start over from there. This process
+ // continues in this way until we either successfully make it all the way
+ // across the range, or exhaust all of our combinations of break
+ // positions.)
+ Stack<Integer> currentBreakPositions = new Stack<>();
+ Stack<Integer> possibleBreakPositions = new Stack<>();
+ List<Integer> wrongBreakPositions = new ArrayList<>();
+
+ // the dictionary is implemented as a trie, which is treated as a state
+ // machine. -1 represents the end of a legal word. Every word in the
+ // dictionary is represented by a path from the root node to -1. A path
+ // that ends in state 0 is an illegal combination of characters.
+ int state = 0;
+
+ // these two variables are used for error handling. We keep track of the
+ // farthest we've gotten through the range being divided, and the combination
+ // of breaks that got us that far. If we use up all possible break
+ // combinations, the text contains an error or a word that's not in the
+ // dictionary. In this case, we "bless" the break positions that got us the
+ // farthest as real break positions, and then start over from scratch with
+ // the character where the error occurred.
+ int farthestEndPoint = text.getIndex();
+ Stack<Integer> bestBreakPositions = null;
+
+ // initialize (we always exit the loop with a break statement)
+ c = getCurrent();
+ while (true) {
+
+ // if we can transition to state "-1" from our current state, we're
+ // on the last character of a legal word. Push that position onto
+ // the possible-break-positions stack
+ if (dictionary.getNextState(state, 0) == -1) {
+ possibleBreakPositions.push(text.getIndex());
+ }
+
+ // look up the new state to transition to in the dictionary
+ state = dictionary.getNextStateFromCharacter(state, c);
+
+ // if the character we're sitting on causes us to transition to
+ // the "end of word" state, then it was a non-dictionary character
+ // and we've successfully traversed the whole range. Drop out
+ // of the loop.
+ if (state == -1) {
+ currentBreakPositions.push(text.getIndex());
+ break;
+ }
+
+ // if the character we're sitting on causes us to transition to
+ // the error state, or if we've gone off the end of the range
+ // without transitioning to the "end of word" state, we've hit
+ // an error...
+ else if (state == 0 || text.getIndex() >= endPos) {
+
+ // if this is the farthest we've gotten, take note of it in
+ // case there's an error in the text
+ if (text.getIndex() > farthestEndPoint) {
+ farthestEndPoint = text.getIndex();
+
+ @SuppressWarnings("unchecked")
+ Stack<Integer> currentBreakPositionsCopy = (Stack<Integer>) currentBreakPositions.clone();
+
+ bestBreakPositions = currentBreakPositionsCopy;
+ }
+
+ // wrongBreakPositions is a list of all break positions
+ // we've tried starting that didn't allow us to traverse
+ // all the way through the text. Every time we pop a
+ // break position off of currentBreakPositions, we put it
+ // into wrongBreakPositions to avoid trying it again later.
+ // If we make it to this spot, we're either going to back
+ // up to a break in possibleBreakPositions and try starting
+ // over from there, or we've exhausted all possible break
+ // positions and are going to do the fallback procedure.
+ // This loop prevents us from messing with anything in
+ // possibleBreakPositions that didn't work as a starting
+ // point the last time we tried it (this is to prevent a bunch of
+ // repetitive checks from slowing down some extreme cases)
+ while (!possibleBreakPositions.isEmpty()
+ && wrongBreakPositions.contains(possibleBreakPositions.peek())) {
+ possibleBreakPositions.pop();
+ }
+
+ // if we've used up all possible break-position combinations, there's
+ // an error or an unknown word in the text. In this case, we start
+ // over, treating the farthest character we've reached as the beginning
+ // of the range, and "blessing" the break positions that got us that
+ // far as real break positions
+ if (possibleBreakPositions.isEmpty()) {
+ if (bestBreakPositions != null) {
+ currentBreakPositions = bestBreakPositions;
+ if (farthestEndPoint < endPos) {
+ text.setIndex(farthestEndPoint + 1);
+ }
+ else {
+ break;
+ }
+ }
+ else {
+ if ((currentBreakPositions.size() == 0 ||
+ currentBreakPositions.peek().intValue() != text.getIndex())
+ && text.getIndex() != startPos) {
+ currentBreakPositions.push(text.getIndex());
+ }
+ getNext();
+ currentBreakPositions.push(text.getIndex());
+ }
+ }
+
+ // if we still have more break positions we can try, then promote the
+ // last break in possibleBreakPositions into currentBreakPositions,
+ // and get rid of all entries in currentBreakPositions that come after
+ // it. Then back up to that position and start over from there (i.e.,
+ // treat that position as the beginning of a new word)
+ else {
+ Integer temp = possibleBreakPositions.pop();
+ Integer temp2 = null;
+ while (!currentBreakPositions.isEmpty() && temp.intValue() <
+ currentBreakPositions.peek().intValue()) {
+ temp2 = currentBreakPositions.pop();
+ wrongBreakPositions.add(temp2);
+ }
+ currentBreakPositions.push(temp);
+ text.setIndex(currentBreakPositions.peek().intValue());
+ }
+
+ // re-sync "c" for the next go-round, and drop out of the loop if
+ // we've made it off the end of the range
+ c = getCurrent();
+ if (text.getIndex() >= endPos) {
+ break;
+ }
+ }
+
+ // if we didn't hit any exceptional conditions on this last iteration,
+ // just advance to the next character and loop
+ else {
+ c = getNext();
+ }
+ }
+
+ // dump the last break position in the list, and replace it with the actual
+ // end of the range (which may be the same character, or may be further on
+ // because the range actually ended with non-dictionary characters we want to
+ // keep with the word)
+ if (!currentBreakPositions.isEmpty()) {
+ currentBreakPositions.pop();
+ }
+ currentBreakPositions.push(endPos);
+
+ // create a regular array to hold the break positions and copy
+ // the break positions from the stack to the array (in addition,
+ // our starting position goes into this array as a break position).
+ // This array becomes the cache of break positions used by next()
+ // and previous(), so this is where we actually refresh the cache.
+ cachedBreakPositions = new int[currentBreakPositions.size() + 1];
+ cachedBreakPositions[0] = startPos;
+
+ for (int i = 0; i < currentBreakPositions.size(); i++) {
+ cachedBreakPositions[i + 1] = currentBreakPositions.elementAt(i).intValue();
+ }
+ positionInCache = 0;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/text/RuleBasedBreakIterator.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,1144 @@
+/*
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+/*
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
+ *
+ * The original version of this source code and documentation
+ * is copyrighted and owned by Taligent, Inc., a wholly-owned
+ * subsidiary of IBM. These materials are provided under terms
+ * of a License Agreement between Taligent and Sun. This technology
+ * is protected by multiple US and International patents.
+ *
+ * This notice and attribution to Taligent may not be removed.
+ * Taligent is a registered trademark of Taligent, Inc.
+ */
+
+package sun.text;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.text.BreakIterator;
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.MissingResourceException;
+import sun.text.CompactByteArray;
+import sun.text.SupplementaryCharacterData;
+
+/**
+ * <p>A subclass of BreakIterator whose behavior is specified using a list of rules.</p>
+ *
+ * <p>There are two kinds of rules, which are separated by semicolons: <i>substitutions</i>
+ * and <i>regular expressions.</i></p>
+ *
+ * <p>A substitution rule defines a name that can be used in place of an expression. It
+ * consists of a name, which is a string of characters contained in angle brackets, an equals
+ * sign, and an expression. (There can be no whitespace on either side of the equals sign.)
+ * To keep its syntactic meaning intact, the expression must be enclosed in parentheses or
+ * square brackets. A substitution is visible after its definition, and is filled in using
+ * simple textual substitution. Substitution definitions can contain other substitutions, as
+ * long as those substitutions have been defined first. Substitutions are generally used to
+ * make the regular expressions (which can get quite complex) shorted and easier to read.
+ * They typically define either character categories or commonly-used subexpressions.</p>
+ *
+ * <p>There is one special substitution. If the description defines a substitution
+ * called "<ignore>", the expression must be a [] expression, and the
+ * expression defines a set of characters (the "<em>ignore characters</em>") that
+ * will be transparent to the BreakIterator. A sequence of characters will break the
+ * same way it would if any ignore characters it contains are taken out. Break
+ * positions never occur befoer ignore characters.</p>
+ *
+ * <p>A regular expression uses a subset of the normal Unix regular-expression syntax, and
+ * defines a sequence of characters to be kept together. With one significant exception, the
+ * iterator uses a longest-possible-match algorithm when matching text to regular
+ * expressions. The iterator also treats descriptions containing multiple regular expressions
+ * as if they were ORed together (i.e., as if they were separated by |).</p>
+ *
+ * <p>The special characters recognized by the regular-expression parser are as follows:</p>
+ *
+ * <blockquote>
+ * <table border="1" width="100%">
+ * <tr>
+ * <td width="6%">*</td>
+ * <td width="94%">Specifies that the expression preceding the asterisk may occur any number
+ * of times (including not at all).</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">{}</td>
+ * <td width="94%">Encloses a sequence of characters that is optional.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">()</td>
+ * <td width="94%">Encloses a sequence of characters. If followed by *, the sequence
+ * repeats. Otherwise, the parentheses are just a grouping device and a way to delimit
+ * the ends of expressions containing |.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">|</td>
+ * <td width="94%">Separates two alternative sequences of characters. Either one
+ * sequence or the other, but not both, matches this expression. The | character can
+ * only occur inside ().</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">.</td>
+ * <td width="94%">Matches any character.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">*?</td>
+ * <td width="94%">Specifies a non-greedy asterisk. *? works the same way as *, except
+ * when there is overlap between the last group of characters in the expression preceding the
+ * * and the first group of characters following the *. When there is this kind of
+ * overlap, * will match the longest sequence of characters that match the expression before
+ * the *, and *? will match the shortest sequence of characters matching the expression
+ * before the *?. For example, if you have "xxyxyyyxyxyxxyxyxyy" in the text,
+ * "x[xy]*x" will match through to the last x (i.e., "<strong>xxyxyyyxyxyxxyxyx</strong>yy",
+ * but "x[xy]*?x" will only match the first two xes ("<strong>xx</strong>yxyyyxyxyxxyxyxyy").</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">[]</td>
+ * <td width="94%">Specifies a group of alternative characters. A [] expression will
+ * match any single character that is specified in the [] expression. For more on the
+ * syntax of [] expressions, see below.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">/</td>
+ * <td width="94%">Specifies where the break position should go if text matches this
+ * expression. (e.g., "[a-z]*/[:Zs:]*[1-0]" will match if the iterator sees a run
+ * of letters, followed by a run of whitespace, followed by a digit, but the break position
+ * will actually go before the whitespace). Expressions that don't contain / put the
+ * break position at the end of the matching text.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">\</td>
+ * <td width="94%">Escape character. The \ itself is ignored, but causes the next
+ * character to be treated as literal character. This has no effect for many
+ * characters, but for the characters listed above, this deprives them of their special
+ * meaning. (There are no special escape sequences for Unicode characters, or tabs and
+ * newlines; these are all handled by a higher-level protocol. In a Java string,
+ * "\n" will be converted to a literal newline character by the time the
+ * regular-expression parser sees it. Of course, this means that \ sequences that are
+ * visible to the regexp parser must be written as \\ when inside a Java string.) All
+ * characters in the ASCII range except for letters, digits, and control characters are
+ * reserved characters to the parser and must be preceded by \ even if they currently don't
+ * mean anything.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">!</td>
+ * <td width="94%">If ! appears at the beginning of a regular expression, it tells the regexp
+ * parser that this expression specifies the backwards-iteration behavior of the iterator,
+ * and not its normal iteration behavior. This is generally only used in situations
+ * where the automatically-generated backwards-iteration brhavior doesn't produce
+ * satisfactory results and must be supplemented with extra client-specified rules.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%"><em>(all others)</em></td>
+ * <td width="94%">All other characters are treated as literal characters, which must match
+ * the corresponding character(s) in the text exactly.</td>
+ * </tr>
+ * </table>
+ * </blockquote>
+ *
+ * <p>Within a [] expression, a number of other special characters can be used to specify
+ * groups of characters:</p>
+ *
+ * <blockquote>
+ * <table border="1" width="100%">
+ * <tr>
+ * <td width="6%">-</td>
+ * <td width="94%">Specifies a range of matching characters. For example
+ * "[a-p]" matches all lowercase Latin letters from a to p (inclusive). The -
+ * sign specifies ranges of continuous Unicode numeric values, not ranges of characters in a
+ * language's alphabetical order: "[a-z]" doesn't include capital letters, nor does
+ * it include accented letters such as a-umlaut.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">::</td>
+ * <td width="94%">A pair of colons containing a one- or two-letter code matches all
+ * characters in the corresponding Unicode category. The two-letter codes are the same
+ * as the two-letter codes in the Unicode database (for example, "[:Sc::Sm:]"
+ * matches all currency symbols and all math symbols). Specifying a one-letter code is
+ * the same as specifying all two-letter codes that begin with that letter (for example,
+ * "[:L:]" matches all letters, and is equivalent to
+ * "[:Lu::Ll::Lo::Lm::Lt:]"). Anything other than a valid two-letter Unicode
+ * category code or a single letter that begins a Unicode category code is illegal within
+ * colons.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">[]</td>
+ * <td width="94%">[] expressions can nest. This has no effect, except when used in
+ * conjunction with the ^ token.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">^</td>
+ * <td width="94%">Excludes the character (or the characters in the [] expression) following
+ * it from the group of characters. For example, "[a-z^p]" matches all Latin
+ * lowercase letters except p. "[:L:^[\u4e00-\u9fff]]" matches all letters
+ * except the Han ideographs.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%"><em>(all others)</em></td>
+ * <td width="94%">All other characters are treated as literal characters. (For
+ * example, "[aeiou]" specifies just the letters a, e, i, o, and u.)</td>
+ * </tr>
+ * </table>
+ * </blockquote>
+ *
+ * <p>For a more complete explanation, see <a
+ * href="http://www.ibm.com/java/education/boundaries/boundaries.html">http://www.ibm.com/java/education/boundaries/boundaries.html</a>.
+ * For examples, see the resource data (which is annotated).</p>
+ *
+ * @author Richard Gillam
+ */
+public class RuleBasedBreakIterator extends BreakIterator {
+
+ /**
+ * A token used as a character-category value to identify ignore characters
+ */
+ protected static final byte IGNORE = -1;
+
+ /**
+ * The state number of the starting state
+ */
+ private static final short START_STATE = 1;
+
+ /**
+ * The state-transition value indicating "stop"
+ */
+ private static final short STOP_STATE = 0;
+
+ /**
+ * Magic number for the BreakIterator data file format.
+ */
+ static final byte[] LABEL = {
+ (byte)'B', (byte)'I', (byte)'d', (byte)'a', (byte)'t', (byte)'a',
+ (byte)'\0'
+ };
+ static final int LABEL_LENGTH = LABEL.length;
+
+ /**
+ * Version number of the dictionary that was read in.
+ */
+ static final byte supportedVersion = 1;
+
+ /**
+ * An array length of indices for BMP characters
+ */
+ private static final int BMP_INDICES_LENGTH = 512;
+
+ /**
+ * Tables that indexes from character values to character category numbers
+ */
+ private CompactByteArray charCategoryTable = null;
+ private SupplementaryCharacterData supplementaryCharCategoryTable = null;
+
+ /**
+ * The table of state transitions used for forward iteration
+ */
+ private short[] stateTable = null;
+
+ /**
+ * The table of state transitions used to sync up the iterator with the
+ * text in backwards and random-access iteration
+ */
+ private short[] backwardsStateTable = null;
+
+ /**
+ * A list of flags indicating which states in the state table are accepting
+ * ("end") states
+ */
+ private boolean[] endStates = null;
+
+ /**
+ * A list of flags indicating which states in the state table are
+ * lookahead states (states which turn lookahead on and off)
+ */
+ private boolean[] lookaheadStates = null;
+
+ /**
+ * A table for additional data. May be used by a subclass of
+ * RuleBasedBreakIterator.
+ */
+ private byte[] additionalData = null;
+
+ /**
+ * The number of character categories (and, thus, the number of columns in
+ * the state tables)
+ */
+ private int numCategories;
+
+ /**
+ * The character iterator through which this BreakIterator accesses the text
+ */
+ private CharacterIterator text = null;
+
+ /**
+ * A CRC32 value of all data in datafile
+ */
+ private long checksum;
+
+ //=======================================================================
+ // constructors
+ //=======================================================================
+
+ /**
+ * Constructs a RuleBasedBreakIterator using the given rule data.
+ *
+ * @throws MissingResourceException if the rule data is invalid or corrupted
+ */
+ public RuleBasedBreakIterator(String ruleFile, byte[] ruleData) {
+ ByteBuffer bb = ByteBuffer.wrap(ruleData);
+ try {
+ validateRuleData(ruleFile, bb);
+ setupTables(ruleFile, bb);
+ } catch (BufferUnderflowException bue) {
+ MissingResourceException e;
+ e = new MissingResourceException("Corrupted rule data file", ruleFile, "");
+ e.initCause(bue);
+ throw e;
+ }
+ }
+
+ /**
+ * Initializes the fields with the given rule data.
+ * The data format is as follows:
+ * <pre>
+ * BreakIteratorData {
+ * u1 magic[7];
+ * u1 version;
+ * u4 totalDataSize;
+ * header_info header;
+ * body value;
+ * }
+ * </pre>
+ * <code>totalDataSize</code> is the summation of the size of
+ * <code>header_info</code> and <code>body</code> in byte count.
+ * <p>
+ * In <code>header</code>, each field except for checksum implies the
+ * length of each field. Since <code>BMPdataLength</code> is a fixed-length
+ * data(512 entries), its length isn't included in <code>header</code>.
+ * <code>checksum</code> is a CRC32 value of all in <code>body</code>.
+ * <pre>
+ * header_info {
+ * u4 stateTableLength;
+ * u4 backwardsStateTableLength;
+ * u4 endStatesLength;
+ * u4 lookaheadStatesLength;
+ * u4 BMPdataLength;
+ * u4 nonBMPdataLength;
+ * u4 additionalDataLength;
+ * u8 checksum;
+ * }
+ * </pre>
+ * <p>
+ *
+ * Finally, <code>BMPindices</code> and <code>BMPdata</code> are set to
+ * <code>charCategoryTable</code>. <code>nonBMPdata</code> is set to
+ * <code>supplementaryCharCategoryTable</code>.
+ * <pre>
+ * body {
+ * u2 stateTable[stateTableLength];
+ * u2 backwardsStateTable[backwardsStateTableLength];
+ * u1 endStates[endStatesLength];
+ * u1 lookaheadStates[lookaheadStatesLength];
+ * u2 BMPindices[512];
+ * u1 BMPdata[BMPdataLength];
+ * u4 nonBMPdata[numNonBMPdataLength];
+ * u1 additionalData[additionalDataLength];
+ * }
+ * </pre>
+ *
+ * @throws BufferUnderflowException if the end-of-data is reached before
+ * setting up all the tables
+ */
+ private void setupTables(String ruleFile, ByteBuffer bb) {
+ /* Read header_info. */
+ int stateTableLength = bb.getInt();
+ int backwardsStateTableLength = bb.getInt();
+ int endStatesLength = bb.getInt();
+ int lookaheadStatesLength = bb.getInt();
+ int BMPdataLength = bb.getInt();
+ int nonBMPdataLength = bb.getInt();
+ int additionalDataLength = bb.getInt();
+ checksum = bb.getLong();
+
+ /* Read stateTable[numCategories * numRows] */
+ stateTable = new short[stateTableLength];
+ for (int i = 0; i < stateTableLength; i++) {
+ stateTable[i] = bb.getShort();
+ }
+
+ /* Read backwardsStateTable[numCategories * numRows] */
+ backwardsStateTable = new short[backwardsStateTableLength];
+ for (int i = 0; i < backwardsStateTableLength; i++) {
+ backwardsStateTable[i] = bb.getShort();
+ }
+
+ /* Read endStates[numRows] */
+ endStates = new boolean[endStatesLength];
+ for (int i = 0; i < endStatesLength; i++) {
+ endStates[i] = bb.get() == 1;
+ }
+
+ /* Read lookaheadStates[numRows] */
+ lookaheadStates = new boolean[lookaheadStatesLength];
+ for (int i = 0; i < lookaheadStatesLength; i++) {
+ lookaheadStates[i] = bb.get() == 1;
+ }
+
+ /* Read a category table and indices for BMP characters. */
+ short[] temp1 = new short[BMP_INDICES_LENGTH]; // BMPindices
+ for (int i = 0; i < BMP_INDICES_LENGTH; i++) {
+ temp1[i] = bb.getShort();
+ }
+ byte[] temp2 = new byte[BMPdataLength]; // BMPdata
+ bb.get(temp2);
+ charCategoryTable = new CompactByteArray(temp1, temp2);
+
+ /* Read a category table for non-BMP characters. */
+ int[] temp3 = new int[nonBMPdataLength];
+ for (int i = 0; i < nonBMPdataLength; i++) {
+ temp3[i] = bb.getInt();
+ }
+ supplementaryCharCategoryTable = new SupplementaryCharacterData(temp3);
+
+ /* Read additional data */
+ if (additionalDataLength > 0) {
+ additionalData = new byte[additionalDataLength];
+ bb.get(additionalData);
+ }
+ assert bb.position() == bb.limit();
+
+ /* Set numCategories */
+ numCategories = stateTable.length / endStates.length;
+ }
+
+ /**
+ * Validates the magic number, version, and the length of the given data.
+ *
+ * @throws BufferUnderflowException if the end-of-data is reached while
+ * validating data
+ * @throws MissingResourceException if valification failed
+ */
+ void validateRuleData(String ruleFile, ByteBuffer bb) {
+ /* Verify the magic number. */
+ for (int i = 0; i < LABEL_LENGTH; i++) {
+ if (bb.get() != LABEL[i]) {
+ throw new MissingResourceException("Wrong magic number",
+ ruleFile, "");
+ }
+ }
+
+ /* Verify the version number. */
+ byte version = bb.get();
+ if (version != supportedVersion) {
+ throw new MissingResourceException("Unsupported version(" + version + ")",
+ ruleFile, "");
+ }
+
+ // Check the length of the rest of data
+ int len = bb.getInt();
+ if (bb.position() + len != bb.limit()) {
+ throw new MissingResourceException("Wrong data length",
+ ruleFile, "");
+ }
+ }
+
+ byte[] getAdditionalData() {
+ return additionalData;
+ }
+
+ void setAdditionalData(byte[] b) {
+ additionalData = b;
+ }
+
+ //=======================================================================
+ // boilerplate
+ //=======================================================================
+ /**
+ * Clones this iterator.
+ * @return A newly-constructed RuleBasedBreakIterator with the same
+ * behavior as this one.
+ */
+ @Override
+ public Object clone() {
+ RuleBasedBreakIterator result = (RuleBasedBreakIterator) super.clone();
+ if (text != null) {
+ result.text = (CharacterIterator) text.clone();
+ }
+ return result;
+ }
+
+ /**
+ * Returns true if both BreakIterators are of the same class, have the same
+ * rules, and iterate over the same text.
+ */
+ @Override
+ public boolean equals(Object that) {
+ try {
+ if (that == null) {
+ return false;
+ }
+
+ RuleBasedBreakIterator other = (RuleBasedBreakIterator) that;
+ if (checksum != other.checksum) {
+ return false;
+ }
+ if (text == null) {
+ return other.text == null;
+ } else {
+ return text.equals(other.text);
+ }
+ }
+ catch(ClassCastException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns text
+ */
+ @Override
+ public String toString() {
+ return "[checksum=0x" + Long.toHexString(checksum) + ']';
+ }
+
+ /**
+ * Compute a hashcode for this BreakIterator
+ * @return A hash code
+ */
+ @Override
+ public int hashCode() {
+ return (int)checksum;
+ }
+
+ //=======================================================================
+ // BreakIterator overrides
+ //=======================================================================
+
+ /**
+ * Sets the current iteration position to the beginning of the text.
+ * (i.e., the CharacterIterator's starting offset).
+ * @return The offset of the beginning of the text.
+ */
+ @Override
+ public int first() {
+ CharacterIterator t = getText();
+
+ t.first();
+ return t.getIndex();
+ }
+
+ /**
+ * Sets the current iteration position to the end of the text.
+ * (i.e., the CharacterIterator's ending offset).
+ * @return The text's past-the-end offset.
+ */
+ @Override
+ public int last() {
+ CharacterIterator t = getText();
+
+ // I'm not sure why, but t.last() returns the offset of the last character,
+ // rather than the past-the-end offset
+ t.setIndex(t.getEndIndex());
+ return t.getIndex();
+ }
+
+ /**
+ * Advances the iterator either forward or backward the specified number of steps.
+ * Negative values move backward, and positive values move forward. This is
+ * equivalent to repeatedly calling next() or previous().
+ * @param n The number of steps to move. The sign indicates the direction
+ * (negative is backwards, and positive is forwards).
+ * @return The character offset of the boundary position n boundaries away from
+ * the current one.
+ */
+ @Override
+ public int next(int n) {
+ int result = current();
+ while (n > 0) {
+ result = handleNext();
+ --n;
+ }
+ while (n < 0) {
+ result = previous();
+ ++n;
+ }
+ return result;
+ }
+
+ /**
+ * Advances the iterator to the next boundary position.
+ * @return The position of the first boundary after this one.
+ */
+ @Override
+ public int next() {
+ return handleNext();
+ }
+
+ private int cachedLastKnownBreak = BreakIterator.DONE;
+
+ /**
+ * Advances the iterator backwards, to the last boundary preceding this one.
+ * @return The position of the last boundary position preceding this one.
+ */
+ @Override
+ public int previous() {
+ // if we're already sitting at the beginning of the text, return DONE
+ CharacterIterator text = getText();
+ if (current() == text.getBeginIndex()) {
+ return BreakIterator.DONE;
+ }
+
+ // set things up. handlePrevious() will back us up to some valid
+ // break position before the current position (we back our internal
+ // iterator up one step to prevent handlePrevious() from returning
+ // the current position), but not necessarily the last one before
+ // where we started
+ int start = current();
+ int lastResult = cachedLastKnownBreak;
+ if (lastResult >= start || lastResult <= BreakIterator.DONE) {
+ getPrevious();
+ lastResult = handlePrevious();
+ } else {
+ //it might be better to check if handlePrevious() give us closer
+ //safe value but handlePrevious() is slow too
+ //So, this has to be done carefully
+ text.setIndex(lastResult);
+ }
+ int result = lastResult;
+
+ // iterate forward from the known break position until we pass our
+ // starting point. The last break position before the starting
+ // point is our return value
+ while (result != BreakIterator.DONE && result < start) {
+ lastResult = result;
+ result = handleNext();
+ }
+
+ // set the current iteration position to be the last break position
+ // before where we started, and then return that value
+ text.setIndex(lastResult);
+ cachedLastKnownBreak = lastResult;
+ return lastResult;
+ }
+
+ /**
+ * Returns previous character
+ */
+ private int getPrevious() {
+ char c2 = text.previous();
+ if (Character.isLowSurrogate(c2) &&
+ text.getIndex() > text.getBeginIndex()) {
+ char c1 = text.previous();
+ if (Character.isHighSurrogate(c1)) {
+ return Character.toCodePoint(c1, c2);
+ } else {
+ text.next();
+ }
+ }
+ return (int)c2;
+ }
+
+ /**
+ * Returns current character
+ */
+ int getCurrent() {
+ char c1 = text.current();
+ if (Character.isHighSurrogate(c1) &&
+ text.getIndex() < text.getEndIndex()) {
+ char c2 = text.next();
+ text.previous();
+ if (Character.isLowSurrogate(c2)) {
+ return Character.toCodePoint(c1, c2);
+ }
+ }
+ return (int)c1;
+ }
+
+ /**
+ * Returns the count of next character.
+ */
+ private int getCurrentCodePointCount() {
+ char c1 = text.current();
+ if (Character.isHighSurrogate(c1) &&
+ text.getIndex() < text.getEndIndex()) {
+ char c2 = text.next();
+ text.previous();
+ if (Character.isLowSurrogate(c2)) {
+ return 2;
+ }
+ }
+ return 1;
+ }
+
+ /**
+ * Returns next character
+ */
+ int getNext() {
+ int index = text.getIndex();
+ int endIndex = text.getEndIndex();
+ if (index == endIndex ||
+ (index += getCurrentCodePointCount()) >= endIndex) {
+ return CharacterIterator.DONE;
+ }
+ text.setIndex(index);
+ return getCurrent();
+ }
+
+ /**
+ * Returns the position of next character.
+ */
+ private int getNextIndex() {
+ int index = text.getIndex() + getCurrentCodePointCount();
+ int endIndex = text.getEndIndex();
+ if (index > endIndex) {
+ return endIndex;
+ } else {
+ return index;
+ }
+ }
+
+ /**
+ * Throw IllegalArgumentException unless begin <= offset < end.
+ */
+ protected static final void checkOffset(int offset, CharacterIterator text) {
+ if (offset < text.getBeginIndex() || offset > text.getEndIndex()) {
+ throw new IllegalArgumentException("offset out of bounds");
+ }
+ }
+
+ /**
+ * Sets the iterator to refer to the first boundary position following
+ * the specified position.
+ * @offset The position from which to begin searching for a break position.
+ * @return The position of the first break after the current position.
+ */
+ @Override
+ public int following(int offset) {
+
+ CharacterIterator text = getText();
+ checkOffset(offset, text);
+
+ // Set our internal iteration position (temporarily)
+ // to the position passed in. If this is the _beginning_ position,
+ // then we can just use next() to get our return value
+ text.setIndex(offset);
+ if (offset == text.getBeginIndex()) {
+ cachedLastKnownBreak = handleNext();
+ return cachedLastKnownBreak;
+ }
+
+ // otherwise, we have to sync up first. Use handlePrevious() to back
+ // us up to a known break position before the specified position (if
+ // we can determine that the specified position is a break position,
+ // we don't back up at all). This may or may not be the last break
+ // position at or before our starting position. Advance forward
+ // from here until we've passed the starting position. The position
+ // we stop on will be the first break position after the specified one.
+ int result = cachedLastKnownBreak;
+ if (result >= offset || result <= BreakIterator.DONE) {
+ result = handlePrevious();
+ } else {
+ //it might be better to check if handlePrevious() give us closer
+ //safe value but handlePrevious() is slow too
+ //So, this has to be done carefully
+ text.setIndex(result);
+ }
+ while (result != BreakIterator.DONE && result <= offset) {
+ result = handleNext();
+ }
+ cachedLastKnownBreak = result;
+ return result;
+ }
+
+ /**
+ * Sets the iterator to refer to the last boundary position before the
+ * specified position.
+ * @offset The position to begin searching for a break from.
+ * @return The position of the last boundary before the starting position.
+ */
+ @Override
+ public int preceding(int offset) {
+ // if we start by updating the current iteration position to the
+ // position specified by the caller, we can just use previous()
+ // to carry out this operation
+ CharacterIterator text = getText();
+ checkOffset(offset, text);
+ text.setIndex(offset);
+ return previous();
+ }
+
+ /**
+ * Returns true if the specified position is a boundary position. As a side
+ * effect, leaves the iterator pointing to the first boundary position at
+ * or after "offset".
+ * @param offset the offset to check.
+ * @return True if "offset" is a boundary position.
+ */
+ @Override
+ public boolean isBoundary(int offset) {
+ CharacterIterator text = getText();
+ checkOffset(offset, text);
+ if (offset == text.getBeginIndex()) {
+ return true;
+ }
+
+ // to check whether this is a boundary, we can use following() on the
+ // position before the specified one and return true if the position we
+ // get back is the one the user specified
+ else {
+ return following(offset - 1) == offset;
+ }
+ }
+
+ /**
+ * Returns the current iteration position.
+ * @return The current iteration position.
+ */
+ @Override
+ public int current() {
+ return getText().getIndex();
+ }
+
+ /**
+ * Return a CharacterIterator over the text being analyzed. This version
+ * of this method returns the actual CharacterIterator we're using internally.
+ * Changing the state of this iterator can have undefined consequences. If
+ * you need to change it, clone it first.
+ * @return An iterator over the text being analyzed.
+ */
+ @Override
+ public CharacterIterator getText() {
+ // The iterator is initialized pointing to no text at all, so if this
+ // function is called while we're in that state, we have to fudge an
+ // iterator to return.
+ if (text == null) {
+ text = new StringCharacterIterator("");
+ }
+ return text;
+ }
+
+ /**
+ * Set the iterator to analyze a new piece of text. This function resets
+ * the current iteration position to the beginning of the text.
+ * @param newText An iterator over the text to analyze.
+ */
+ @Override
+ public void setText(CharacterIterator newText) {
+ // Test iterator to see if we need to wrap it in a SafeCharIterator.
+ // The correct behavior for CharacterIterators is to allow the
+ // position to be set to the endpoint of the iterator. Many
+ // CharacterIterators do not uphold this, so this is a workaround
+ // to permit them to use this class.
+ int end = newText.getEndIndex();
+ boolean goodIterator;
+ try {
+ newText.setIndex(end); // some buggy iterators throw an exception here
+ goodIterator = newText.getIndex() == end;
+ }
+ catch(IllegalArgumentException e) {
+ goodIterator = false;
+ }
+
+ if (goodIterator) {
+ text = newText;
+ }
+ else {
+ text = new SafeCharIterator(newText);
+ }
+ text.first();
+
+ cachedLastKnownBreak = BreakIterator.DONE;
+ }
+
+
+ //=======================================================================
+ // implementation
+ //=======================================================================
+
+ /**
+ * This method is the actual implementation of the next() method. All iteration
+ * vectors through here. This method initializes the state machine to state 1
+ * and advances through the text character by character until we reach the end
+ * of the text or the state machine transitions to state 0. We update our return
+ * value every time the state machine passes through a possible end state.
+ */
+ protected int handleNext() {
+ // if we're already at the end of the text, return DONE.
+ CharacterIterator text = getText();
+ if (text.getIndex() == text.getEndIndex()) {
+ return BreakIterator.DONE;
+ }
+
+ // no matter what, we always advance at least one character forward
+ int result = getNextIndex();
+ int lookaheadResult = 0;
+
+ // begin in state 1
+ int state = START_STATE;
+ int category;
+ int c = getCurrent();
+
+ // loop until we reach the end of the text or transition to state 0
+ while (c != CharacterIterator.DONE && state != STOP_STATE) {
+
+ // look up the current character's character category (which tells us
+ // which column in the state table to look at)
+ category = lookupCategory(c);
+
+ // if the character isn't an ignore character, look up a state
+ // transition in the state table
+ if (category != IGNORE) {
+ state = lookupState(state, category);
+ }
+
+ // if the state we've just transitioned to is a lookahead state,
+ // (but not also an end state), save its position. If it's
+ // both a lookahead state and an end state, update the break position
+ // to the last saved lookup-state position
+ if (lookaheadStates[state]) {
+ if (endStates[state]) {
+ result = lookaheadResult;
+ }
+ else {
+ lookaheadResult = getNextIndex();
+ }
+ }
+
+ // otherwise, if the state we've just transitioned to is an accepting
+ // state, update the break position to be the current iteration position
+ else {
+ if (endStates[state]) {
+ result = getNextIndex();
+ }
+ }
+
+ c = getNext();
+ }
+
+ // if we've run off the end of the text, and the very last character took us into
+ // a lookahead state, advance the break position to the lookahead position
+ // (the theory here is that if there are no characters at all after the lookahead
+ // position, that always matches the lookahead criteria)
+ if (c == CharacterIterator.DONE && lookaheadResult == text.getEndIndex()) {
+ result = lookaheadResult;
+ }
+
+ text.setIndex(result);
+ return result;
+ }
+
+ /**
+ * This method backs the iterator back up to a "safe position" in the text.
+ * This is a position that we know, without any context, must be a break position.
+ * The various calling methods then iterate forward from this safe position to
+ * the appropriate position to return. (For more information, see the description
+ * of buildBackwardsStateTable() in RuleBasedBreakIterator.Builder.)
+ */
+ protected int handlePrevious() {
+ CharacterIterator text = getText();
+ int state = START_STATE;
+ int category = 0;
+ int lastCategory = 0;
+ int c = getCurrent();
+
+ // loop until we reach the beginning of the text or transition to state 0
+ while (c != CharacterIterator.DONE && state != STOP_STATE) {
+
+ // save the last character's category and look up the current
+ // character's category
+ lastCategory = category;
+ category = lookupCategory(c);
+
+ // if the current character isn't an ignore character, look up a
+ // state transition in the backwards state table
+ if (category != IGNORE) {
+ state = lookupBackwardState(state, category);
+ }
+
+ // then advance one character backwards
+ c = getPrevious();
+ }
+
+ // if we didn't march off the beginning of the text, we're either one or two
+ // positions away from the real break position. (One because of the call to
+ // previous() at the end of the loop above, and another because the character
+ // that takes us into the stop state will always be the character BEFORE
+ // the break position.)
+ if (c != CharacterIterator.DONE) {
+ if (lastCategory != IGNORE) {
+ getNext();
+ getNext();
+ }
+ else {
+ getNext();
+ }
+ }
+ return text.getIndex();
+ }
+
+ /**
+ * Looks up a character's category (i.e., its category for breaking purposes,
+ * not its Unicode category)
+ */
+ protected int lookupCategory(int c) {
+ if (c < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+ return charCategoryTable.elementAt((char)c);
+ } else {
+ return supplementaryCharCategoryTable.getValue(c);
+ }
+ }
+
+ /**
+ * Given a current state and a character category, looks up the
+ * next state to transition to in the state table.
+ */
+ protected int lookupState(int state, int category) {
+ return stateTable[state * numCategories + category];
+ }
+
+ /**
+ * Given a current state and a character category, looks up the
+ * next state to transition to in the backwards state table.
+ */
+ protected int lookupBackwardState(int state, int category) {
+ return backwardsStateTable[state * numCategories + category];
+ }
+
+ /*
+ * This class exists to work around a bug in incorrect implementations
+ * of CharacterIterator, which incorrectly handle setIndex(endIndex).
+ * This iterator relies only on base.setIndex(n) where n is less than
+ * endIndex.
+ *
+ * One caveat: if the base iterator's begin and end indices change
+ * the change will not be reflected by this wrapper. Does that matter?
+ */
+ // TODO: Review this class to see if it's still required.
+ private static final class SafeCharIterator implements CharacterIterator,
+ Cloneable {
+
+ private CharacterIterator base;
+ private int rangeStart;
+ private int rangeLimit;
+ private int currentIndex;
+
+ SafeCharIterator(CharacterIterator base) {
+ this.base = base;
+ this.rangeStart = base.getBeginIndex();
+ this.rangeLimit = base.getEndIndex();
+ this.currentIndex = base.getIndex();
+ }
+
+ @Override
+ public char first() {
+ return setIndex(rangeStart);
+ }
+
+ @Override
+ public char last() {
+ return setIndex(rangeLimit - 1);
+ }
+
+ @Override
+ public char current() {
+ if (currentIndex < rangeStart || currentIndex >= rangeLimit) {
+ return DONE;
+ }
+ else {
+ return base.setIndex(currentIndex);
+ }
+ }
+
+ @Override
+ public char next() {
+
+ currentIndex++;
+ if (currentIndex >= rangeLimit) {
+ currentIndex = rangeLimit;
+ return DONE;
+ }
+ else {
+ return base.setIndex(currentIndex);
+ }
+ }
+
+ @Override
+ public char previous() {
+
+ currentIndex--;
+ if (currentIndex < rangeStart) {
+ currentIndex = rangeStart;
+ return DONE;
+ }
+ else {
+ return base.setIndex(currentIndex);
+ }
+ }
+
+ @Override
+ public char setIndex(int i) {
+
+ if (i < rangeStart || i > rangeLimit) {
+ throw new IllegalArgumentException("Invalid position");
+ }
+ currentIndex = i;
+ return current();
+ }
+
+ @Override
+ public int getBeginIndex() {
+ return rangeStart;
+ }
+
+ @Override
+ public int getEndIndex() {
+ return rangeLimit;
+ }
+
+ @Override
+ public int getIndex() {
+ return currentIndex;
+ }
+
+ @Override
+ public Object clone() {
+
+ SafeCharIterator copy = null;
+ try {
+ copy = (SafeCharIterator) super.clone();
+ }
+ catch(CloneNotSupportedException e) {
+ throw new Error("Clone not supported: " + e);
+ }
+
+ CharacterIterator copyOfBase = (CharacterIterator) base.clone();
+ copy.base = copyOfBase;
+ return copy;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/text/resources/BreakIteratorResources.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.text.resources;
+
+import java.util.ResourceBundle;
+import sun.util.resources.BreakIteratorResourceBundle;
+
+public class BreakIteratorResources extends BreakIteratorResourceBundle {
+ @Override
+ protected ResourceBundle getBreakIteratorInfo() {
+ return new BreakIteratorInfo();
+ }
+}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakDictionary.java Thu Oct 27 16:29:00 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,352 +0,0 @@
-/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
- * 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.
- */
-
-/*
- *
- * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
- * (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
- *
- * The original version of this source code and documentation
- * is copyrighted and owned by Taligent, Inc., a wholly-owned
- * subsidiary of IBM. These materials are provided under terms
- * of a License Agreement between Taligent and Sun. This technology
- * is protected by multiple US and International patents.
- *
- * This notice and attribution to Taligent may not be removed.
- * Taligent is a registered trademark of Taligent, Inc.
- */
-package sun.util.locale.provider;
-
-import java.io.BufferedInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.lang.reflect.Module;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.MissingResourceException;
-import sun.text.CompactByteArray;
-import sun.text.SupplementaryCharacterData;
-
-/**
- * This is the class that represents the list of known words used by
- * DictionaryBasedBreakIterator. The conceptual data structure used
- * here is a trie: there is a node hanging off the root node for every
- * letter that can start a word. Each of these nodes has a node hanging
- * off of it for every letter that can be the second letter of a word
- * if this node is the first letter, and so on. The trie is represented
- * as a two-dimensional array that can be treated as a table of state
- * transitions. Indexes are used to compress this array, taking
- * advantage of the fact that this array will always be very sparse.
- */
-class BreakDictionary {
-
- //=========================================================================
- // data members
- //=========================================================================
-
- /**
- * The version of the dictionary that was read in.
- */
- private static int supportedVersion = 1;
-
- /**
- * Maps from characters to column numbers. The main use of this is to
- * avoid making room in the array for empty columns.
- */
- private CompactByteArray columnMap = null;
- private SupplementaryCharacterData supplementaryCharColumnMap = null;
-
- /**
- * The number of actual columns in the table
- */
- private int numCols;
-
- /**
- * Columns are organized into groups of 32. This says how many
- * column groups. (We could calculate this, but we store the
- * value to avoid having to repeatedly calculate it.)
- */
- private int numColGroups;
-
- /**
- * The actual compressed state table. Each conceptual row represents
- * a state, and the cells in it contain the row numbers of the states
- * to transition to for each possible letter. 0 is used to indicate
- * an illegal combination of letters (i.e., the error state). The
- * table is compressed by eliminating all the unpopulated (i.e., zero)
- * cells. Multiple conceptual rows can then be doubled up in a single
- * physical row by sliding them up and possibly shifting them to one
- * side or the other so the populated cells don't collide. Indexes
- * are used to identify unpopulated cells and to locate populated cells.
- */
- private short[] table = null;
-
- /**
- * This index maps logical row numbers to physical row numbers
- */
- private short[] rowIndex = null;
-
- /**
- * A bitmap is used to tell which cells in the comceptual table are
- * populated. This array contains all the unique bit combinations
- * in that bitmap. If the table is more than 32 columns wide,
- * successive entries in this array are used for a single row.
- */
- private int[] rowIndexFlags = null;
-
- /**
- * This index maps from a logical row number into the bitmap table above.
- * (This keeps us from storing duplicate bitmap combinations.) Since there
- * are a lot of rows with only one populated cell, instead of wasting space
- * in the bitmap table, we just store a negative number in this index for
- * rows with one populated cell. The absolute value of that number is
- * the column number of the populated cell.
- */
- private short[] rowIndexFlagsIndex = null;
-
- /**
- * For each logical row, this index contains a constant that is added to
- * the logical column number to get the physical column number
- */
- private byte[] rowIndexShifts = null;
-
- //=========================================================================
- // deserialization
- //=========================================================================
-
- BreakDictionary(Module module, String dictionaryName)
- throws IOException, MissingResourceException {
-
- readDictionaryFile(module, dictionaryName);
- }
-
- private void readDictionaryFile(final Module module, final String dictionaryName)
- throws IOException, MissingResourceException {
-
- BufferedInputStream in;
- try {
- PrivilegedExceptionAction<BufferedInputStream> pa = () -> {
- String pathName = "jdk.localedata".equals(module.getName()) ?
- "sun/text/resources/ext/" :
- "sun/text/resources/";
- InputStream is = module.getResourceAsStream(pathName + dictionaryName);
- if (is == null) {
- // Try to load the file with "java.base" module instance. Assumption
- // here is that the fall back data files to be read should reside in
- // java.base.
- is = BreakDictionary.class.getModule().getResourceAsStream("sun/text/resources/" + dictionaryName);
- }
-
- return new BufferedInputStream(is);
- };
- in = AccessController.doPrivileged(pa);
- }
- catch (PrivilegedActionException e) {
- throw new InternalError(e.toString(), e);
- }
-
- byte[] buf = new byte[8];
- if (in.read(buf) != 8) {
- throw new MissingResourceException("Wrong data length",
- dictionaryName, "");
- }
-
- // check version
- int version = RuleBasedBreakIterator.getInt(buf, 0);
- if (version != supportedVersion) {
- throw new MissingResourceException("Dictionary version(" + version + ") is unsupported",
- dictionaryName, "");
- }
-
- // get data size
- int len = RuleBasedBreakIterator.getInt(buf, 4);
- buf = new byte[len];
- if (in.read(buf) != len) {
- throw new MissingResourceException("Wrong data length",
- dictionaryName, "");
- }
-
- // close the stream
- in.close();
-
- int l;
- int offset = 0;
-
- // read in the column map for BMP characteres (this is serialized in
- // its internal form: an index array followed by a data array)
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- short[] temp = new short[l];
- for (int i = 0; i < l; i++, offset+=2) {
- temp[i] = RuleBasedBreakIterator.getShort(buf, offset);
- }
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- byte[] temp2 = new byte[l];
- for (int i = 0; i < l; i++, offset++) {
- temp2[i] = buf[offset];
- }
- columnMap = new CompactByteArray(temp, temp2);
-
- // read in numCols and numColGroups
- numCols = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- numColGroups = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
-
- // read in the row-number index
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- rowIndex = new short[l];
- for (int i = 0; i < l; i++, offset+=2) {
- rowIndex[i] = RuleBasedBreakIterator.getShort(buf, offset);
- }
-
- // load in the populated-cells bitmap: index first, then bitmap list
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- rowIndexFlagsIndex = new short[l];
- for (int i = 0; i < l; i++, offset+=2) {
- rowIndexFlagsIndex[i] = RuleBasedBreakIterator.getShort(buf, offset);
- }
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- rowIndexFlags = new int[l];
- for (int i = 0; i < l; i++, offset+=4) {
- rowIndexFlags[i] = RuleBasedBreakIterator.getInt(buf, offset);
- }
-
- // load in the row-shift index
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- rowIndexShifts = new byte[l];
- for (int i = 0; i < l; i++, offset++) {
- rowIndexShifts[i] = buf[offset];
- }
-
- // load in the actual state table
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- table = new short[l];
- for (int i = 0; i < l; i++, offset+=2) {
- table[i] = RuleBasedBreakIterator.getShort(buf, offset);
- }
-
- // finally, prepare the column map for supplementary characters
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- int[] temp3 = new int[l];
- for (int i = 0; i < l; i++, offset+=4) {
- temp3[i] = RuleBasedBreakIterator.getInt(buf, offset);
- }
- supplementaryCharColumnMap = new SupplementaryCharacterData(temp3);
- }
-
- //=========================================================================
- // access to the words
- //=========================================================================
-
- /**
- * Uses the column map to map the character to a column number, then
- * passes the row and column number to getNextState()
- * @param row The current state
- * @param ch The character whose column we're interested in
- * @return The new state to transition to
- */
- public final short getNextStateFromCharacter(int row, int ch) {
- int col;
- if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
- col = columnMap.elementAt((char)ch);
- } else {
- col = supplementaryCharColumnMap.getValue(ch);
- }
- return getNextState(row, col);
- }
-
- /**
- * Returns the value in the cell with the specified (logical) row and
- * column numbers. In DictionaryBasedBreakIterator, the row number is
- * a state number, the column number is an input, and the return value
- * is the row number of the new state to transition to. (0 is the
- * "error" state, and -1 is the "end of word" state in a dictionary)
- * @param row The row number of the current state
- * @param col The column number of the input character (0 means "not a
- * dictionary character")
- * @return The row number of the new state to transition to
- */
- public final short getNextState(int row, int col) {
- if (cellIsPopulated(row, col)) {
- // we map from logical to physical row number by looking up the
- // mapping in rowIndex; we map from logical column number to
- // physical column number by looking up a shift value for this
- // logical row and offsetting the logical column number by
- // the shift amount. Then we can use internalAt() to actually
- // get the value out of the table.
- return internalAt(rowIndex[row], col + rowIndexShifts[row]);
- }
- else {
- return 0;
- }
- }
-
- /**
- * Given (logical) row and column numbers, returns true if the
- * cell in that position is populated
- */
- private boolean cellIsPopulated(int row, int col) {
- // look up the entry in the bitmap index for the specified row.
- // If it's a negative number, it's the column number of the only
- // populated cell in the row
- if (rowIndexFlagsIndex[row] < 0) {
- return col == -rowIndexFlagsIndex[row];
- }
-
- // if it's a positive number, it's the offset of an entry in the bitmap
- // list. If the table is more than 32 columns wide, the bitmap is stored
- // successive entries in the bitmap list, so we have to divide the column
- // number by 32 and offset the number we got out of the index by the result.
- // Once we have the appropriate piece of the bitmap, test the appropriate
- // bit and return the result.
- else {
- int flags = rowIndexFlags[rowIndexFlagsIndex[row] + (col >> 5)];
- return (flags & (1 << (col & 0x1f))) != 0;
- }
- }
-
- /**
- * Implementation of getNextState() when we know the specified cell is
- * populated.
- * @param row The PHYSICAL row number of the cell
- * @param col The PHYSICAL column number of the cell
- * @return The value stored in the cell
- */
- private short internalAt(int row, int col) {
- // the table is a one-dimensional array, so this just does the math necessary
- // to treat it as a two-dimensional array (we don't just use a two-dimensional
- // array because two-dimensional arrays are inefficient in Java)
- return table[row * numCols + col];
- }
-}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakIteratorProviderImpl.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakIteratorProviderImpl.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,8 @@
import java.util.MissingResourceException;
import java.util.Objects;
import java.util.Set;
+import sun.text.DictionaryBasedBreakIterator;
+import sun.text.RuleBasedBreakIterator;
/**
* Concrete implementation of the {@link java.text.spi.BreakIteratorProvider
@@ -153,29 +155,31 @@
}
private BreakIterator getBreakInstance(Locale locale,
- int type,
- String dataName,
- String dictionaryName) {
+ int type,
+ String ruleName,
+ String dictionaryName) {
Objects.requireNonNull(locale);
LocaleResources lr = LocaleProviderAdapter.forJRE().getLocaleResources(locale);
String[] classNames = (String[]) lr.getBreakIteratorInfo("BreakIteratorClasses");
- String dataFile = (String) lr.getBreakIteratorInfo(dataName);
+ String ruleFile = (String) lr.getBreakIteratorInfo(ruleName);
+ byte[] ruleData = lr.getBreakIteratorResources(ruleName);
try {
switch (classNames[type]) {
case "RuleBasedBreakIterator":
- return new RuleBasedBreakIterator(
- lr.getBreakIteratorDataModule(), dataFile);
+ return new RuleBasedBreakIterator(ruleFile, ruleData);
+
case "DictionaryBasedBreakIterator":
String dictionaryFile = (String) lr.getBreakIteratorInfo(dictionaryName);
- return new DictionaryBasedBreakIterator(
- lr.getBreakIteratorDataModule(), dataFile, dictionaryFile);
+ byte[] dictionaryData = lr.getBreakIteratorResources(dictionaryName);
+ return new DictionaryBasedBreakIterator(ruleFile, ruleData,
+ dictionaryFile, dictionaryData);
default:
throw new IllegalArgumentException("Invalid break iterator class \"" +
classNames[type] + "\"");
}
- } catch (IOException | MissingResourceException | IllegalArgumentException e) {
+ } catch (MissingResourceException | IllegalArgumentException e) {
throw new InternalError(e.toString(), e);
}
}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/DictionaryBasedBreakIterator.java Thu Oct 27 16:29:00 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,524 +0,0 @@
-/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
- * 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.
- */
-
-/*
- *
- * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
- * (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
- *
- * The original version of this source code and documentation
- * is copyrighted and owned by Taligent, Inc., a wholly-owned
- * subsidiary of IBM. These materials are provided under terms
- * of a License Agreement between Taligent and Sun. This technology
- * is protected by multiple US and International patents.
- *
- * This notice and attribution to Taligent may not be removed.
- * Taligent is a registered trademark of Taligent, Inc.
- */
-
-package sun.util.locale.provider;
-
-import java.io.IOException;
-import java.lang.reflect.Module;
-import java.text.CharacterIterator;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Stack;
-
-/**
- * A subclass of RuleBasedBreakIterator that adds the ability to use a dictionary
- * to further subdivide ranges of text beyond what is possible using just the
- * state-table-based algorithm. This is necessary, for example, to handle
- * word and line breaking in Thai, which doesn't use spaces between words. The
- * state-table-based algorithm used by RuleBasedBreakIterator is used to divide
- * up text as far as possible, and then contiguous ranges of letters are
- * repeatedly compared against a list of known words (i.e., the dictionary)
- * to divide them up into words.
- *
- * DictionaryBasedBreakIterator uses the same rule language as RuleBasedBreakIterator,
- * but adds one more special substitution name: <dictionary>. This substitution
- * name is used to identify characters in words in the dictionary. The idea is that
- * if the iterator passes over a chunk of text that includes two or more characters
- * in a row that are included in <dictionary>, it goes back through that range and
- * derives additional break positions (if possible) using the dictionary.
- *
- * DictionaryBasedBreakIterator is also constructed with the filename of a dictionary
- * file. It follows a prescribed search path to locate the dictionary (right now,
- * it looks for it in /com/ibm/text/resources in each directory in the classpath,
- * and won't find it in JAR files, but this location is likely to change). The
- * dictionary file is in a serialized binary format. We have a very primitive (and
- * slow) BuildDictionaryFile utility for creating dictionary files, but aren't
- * currently making it public. Contact us for help.
- */
-class DictionaryBasedBreakIterator extends RuleBasedBreakIterator {
-
- /**
- * a list of known words that is used to divide up contiguous ranges of letters,
- * stored in a compressed, indexed, format that offers fast access
- */
- private BreakDictionary dictionary;
-
- /**
- * a list of flags indicating which character categories are contained in
- * the dictionary file (this is used to determine which ranges of characters
- * to apply the dictionary to)
- */
- private boolean[] categoryFlags;
-
- /**
- * a temporary hiding place for the number of dictionary characters in the
- * last range passed over by next()
- */
- private int dictionaryCharCount;
-
- /**
- * when a range of characters is divided up using the dictionary, the break
- * positions that are discovered are stored here, preventing us from having
- * to use either the dictionary or the state table again until the iterator
- * leaves this range of text
- */
- private int[] cachedBreakPositions;
-
- /**
- * if cachedBreakPositions is not null, this indicates which item in the
- * cache the current iteration position refers to
- */
- private int positionInCache;
-
- /**
- * Constructs a DictionaryBasedBreakIterator.
- * @param module The module where the dictionary file resides
- * @param dictionaryFilename The filename of the dictionary file to use
- */
- DictionaryBasedBreakIterator(Module module, String dataFile, String dictionaryFile)
- throws IOException {
- super(module, dataFile);
- byte[] tmp = super.getAdditionalData();
- if (tmp != null) {
- prepareCategoryFlags(tmp);
- super.setAdditionalData(null);
- }
- dictionary = new BreakDictionary(module, dictionaryFile);
- }
-
- private void prepareCategoryFlags(byte[] data) {
- categoryFlags = new boolean[data.length];
- for (int i = 0; i < data.length; i++) {
- categoryFlags[i] = (data[i] == (byte)1) ? true : false;
- }
- }
-
- @Override
- public void setText(CharacterIterator newText) {
- super.setText(newText);
- cachedBreakPositions = null;
- dictionaryCharCount = 0;
- positionInCache = 0;
- }
-
- /**
- * Sets the current iteration position to the beginning of the text.
- * (i.e., the CharacterIterator's starting offset).
- * @return The offset of the beginning of the text.
- */
- @Override
- public int first() {
- cachedBreakPositions = null;
- dictionaryCharCount = 0;
- positionInCache = 0;
- return super.first();
- }
-
- /**
- * Sets the current iteration position to the end of the text.
- * (i.e., the CharacterIterator's ending offset).
- * @return The text's past-the-end offset.
- */
- @Override
- public int last() {
- cachedBreakPositions = null;
- dictionaryCharCount = 0;
- positionInCache = 0;
- return super.last();
- }
-
- /**
- * Advances the iterator one step backwards.
- * @return The position of the last boundary position before the
- * current iteration position
- */
- @Override
- public int previous() {
- CharacterIterator text = getText();
-
- // if we have cached break positions and we're still in the range
- // covered by them, just move one step backward in the cache
- if (cachedBreakPositions != null && positionInCache > 0) {
- --positionInCache;
- text.setIndex(cachedBreakPositions[positionInCache]);
- return cachedBreakPositions[positionInCache];
- }
-
- // otherwise, dump the cache and use the inherited previous() method to move
- // backward. This may fill up the cache with new break positions, in which
- // case we have to mark our position in the cache
- else {
- cachedBreakPositions = null;
- int result = super.previous();
- if (cachedBreakPositions != null) {
- positionInCache = cachedBreakPositions.length - 2;
- }
- return result;
- }
- }
-
- /**
- * Sets the current iteration position to the last boundary position
- * before the specified position.
- * @param offset The position to begin searching from
- * @return The position of the last boundary before "offset"
- */
- @Override
- public int preceding(int offset) {
- CharacterIterator text = getText();
- checkOffset(offset, text);
-
- // if we have no cached break positions, or "offset" is outside the
- // range covered by the cache, we can just call the inherited routine
- // (which will eventually call other routines in this class that may
- // refresh the cache)
- if (cachedBreakPositions == null || offset <= cachedBreakPositions[0] ||
- offset > cachedBreakPositions[cachedBreakPositions.length - 1]) {
- cachedBreakPositions = null;
- return super.preceding(offset);
- }
-
- // on the other hand, if "offset" is within the range covered by the cache,
- // then all we have to do is search the cache for the last break position
- // before "offset"
- else {
- positionInCache = 0;
- while (positionInCache < cachedBreakPositions.length
- && offset > cachedBreakPositions[positionInCache]) {
- ++positionInCache;
- }
- --positionInCache;
- text.setIndex(cachedBreakPositions[positionInCache]);
- return text.getIndex();
- }
- }
-
- /**
- * Sets the current iteration position to the first boundary position after
- * the specified position.
- * @param offset The position to begin searching forward from
- * @return The position of the first boundary after "offset"
- */
- @Override
- public int following(int offset) {
- CharacterIterator text = getText();
- checkOffset(offset, text);
-
- // if we have no cached break positions, or if "offset" is outside the
- // range covered by the cache, then dump the cache and call our
- // inherited following() method. This will call other methods in this
- // class that may refresh the cache.
- if (cachedBreakPositions == null || offset < cachedBreakPositions[0] ||
- offset >= cachedBreakPositions[cachedBreakPositions.length - 1]) {
- cachedBreakPositions = null;
- return super.following(offset);
- }
-
- // on the other hand, if "offset" is within the range covered by the
- // cache, then just search the cache for the first break position
- // after "offset"
- else {
- positionInCache = 0;
- while (positionInCache < cachedBreakPositions.length
- && offset >= cachedBreakPositions[positionInCache]) {
- ++positionInCache;
- }
- text.setIndex(cachedBreakPositions[positionInCache]);
- return text.getIndex();
- }
- }
-
- /**
- * This is the implementation function for next().
- */
- @Override
- protected int handleNext() {
- CharacterIterator text = getText();
-
- // if there are no cached break positions, or if we've just moved
- // off the end of the range covered by the cache, we have to dump
- // and possibly regenerate the cache
- if (cachedBreakPositions == null ||
- positionInCache == cachedBreakPositions.length - 1) {
-
- // start by using the inherited handleNext() to find a tentative return
- // value. dictionaryCharCount tells us how many dictionary characters
- // we passed over on our way to the tentative return value
- int startPos = text.getIndex();
- dictionaryCharCount = 0;
- int result = super.handleNext();
-
- // if we passed over more than one dictionary character, then we use
- // divideUpDictionaryRange() to regenerate the cached break positions
- // for the new range
- if (dictionaryCharCount > 1 && result - startPos > 1) {
- divideUpDictionaryRange(startPos, result);
- }
-
- // otherwise, the value we got back from the inherited fuction
- // is our return value, and we can dump the cache
- else {
- cachedBreakPositions = null;
- return result;
- }
- }
-
- // if the cache of break positions has been regenerated (or existed all
- // along), then just advance to the next break position in the cache
- // and return it
- if (cachedBreakPositions != null) {
- ++positionInCache;
- text.setIndex(cachedBreakPositions[positionInCache]);
- return cachedBreakPositions[positionInCache];
- }
- return -9999; // SHOULD NEVER GET HERE!
- }
-
- /**
- * Looks up a character category for a character.
- */
- @Override
- protected int lookupCategory(int c) {
- // this override of lookupCategory() exists only to keep track of whether we've
- // passed over any dictionary characters. It calls the inherited lookupCategory()
- // to do the real work, and then checks whether its return value is one of the
- // categories represented in the dictionary. If it is, bump the dictionary-
- // character count.
- int result = super.lookupCategory(c);
- if (result != RuleBasedBreakIterator.IGNORE && categoryFlags[result]) {
- ++dictionaryCharCount;
- }
- return result;
- }
-
- /**
- * This is the function that actually implements the dictionary-based
- * algorithm. Given the endpoints of a range of text, it uses the
- * dictionary to determine the positions of any boundaries in this
- * range. It stores all the boundary positions it discovers in
- * cachedBreakPositions so that we only have to do this work once
- * for each time we enter the range.
- */
- @SuppressWarnings("unchecked")
- private void divideUpDictionaryRange(int startPos, int endPos) {
- CharacterIterator text = getText();
-
- // the range we're dividing may begin or end with non-dictionary characters
- // (i.e., for line breaking, we may have leading or trailing punctuation
- // that needs to be kept with the word). Seek from the beginning of the
- // range to the first dictionary character
- text.setIndex(startPos);
- int c = getCurrent();
- int category = lookupCategory(c);
- while (category == IGNORE || !categoryFlags[category]) {
- c = getNext();
- category = lookupCategory(c);
- }
-
- // initialize. We maintain two stacks: currentBreakPositions contains
- // the list of break positions that will be returned if we successfully
- // finish traversing the whole range now. possibleBreakPositions lists
- // all other possible word ends we've passed along the way. (Whenever
- // we reach an error [a sequence of characters that can't begin any word
- // in the dictionary], we back up, possibly delete some breaks from
- // currentBreakPositions, move a break from possibleBreakPositions
- // to currentBreakPositions, and start over from there. This process
- // continues in this way until we either successfully make it all the way
- // across the range, or exhaust all of our combinations of break
- // positions.)
- Stack<Integer> currentBreakPositions = new Stack<>();
- Stack<Integer> possibleBreakPositions = new Stack<>();
- List<Integer> wrongBreakPositions = new ArrayList<>();
-
- // the dictionary is implemented as a trie, which is treated as a state
- // machine. -1 represents the end of a legal word. Every word in the
- // dictionary is represented by a path from the root node to -1. A path
- // that ends in state 0 is an illegal combination of characters.
- int state = 0;
-
- // these two variables are used for error handling. We keep track of the
- // farthest we've gotten through the range being divided, and the combination
- // of breaks that got us that far. If we use up all possible break
- // combinations, the text contains an error or a word that's not in the
- // dictionary. In this case, we "bless" the break positions that got us the
- // farthest as real break positions, and then start over from scratch with
- // the character where the error occurred.
- int farthestEndPoint = text.getIndex();
- Stack<Integer> bestBreakPositions = null;
-
- // initialize (we always exit the loop with a break statement)
- c = getCurrent();
- while (true) {
-
- // if we can transition to state "-1" from our current state, we're
- // on the last character of a legal word. Push that position onto
- // the possible-break-positions stack
- if (dictionary.getNextState(state, 0) == -1) {
- possibleBreakPositions.push(text.getIndex());
- }
-
- // look up the new state to transition to in the dictionary
- state = dictionary.getNextStateFromCharacter(state, c);
-
- // if the character we're sitting on causes us to transition to
- // the "end of word" state, then it was a non-dictionary character
- // and we've successfully traversed the whole range. Drop out
- // of the loop.
- if (state == -1) {
- currentBreakPositions.push(text.getIndex());
- break;
- }
-
- // if the character we're sitting on causes us to transition to
- // the error state, or if we've gone off the end of the range
- // without transitioning to the "end of word" state, we've hit
- // an error...
- else if (state == 0 || text.getIndex() >= endPos) {
-
- // if this is the farthest we've gotten, take note of it in
- // case there's an error in the text
- if (text.getIndex() > farthestEndPoint) {
- farthestEndPoint = text.getIndex();
-
- @SuppressWarnings("unchecked")
- Stack<Integer> currentBreakPositionsCopy = (Stack<Integer>) currentBreakPositions.clone();
-
- bestBreakPositions = currentBreakPositionsCopy;
- }
-
- // wrongBreakPositions is a list of all break positions
- // we've tried starting that didn't allow us to traverse
- // all the way through the text. Every time we pop a
- // break position off of currentBreakPositions, we put it
- // into wrongBreakPositions to avoid trying it again later.
- // If we make it to this spot, we're either going to back
- // up to a break in possibleBreakPositions and try starting
- // over from there, or we've exhausted all possible break
- // positions and are going to do the fallback procedure.
- // This loop prevents us from messing with anything in
- // possibleBreakPositions that didn't work as a starting
- // point the last time we tried it (this is to prevent a bunch of
- // repetitive checks from slowing down some extreme cases)
- while (!possibleBreakPositions.isEmpty()
- && wrongBreakPositions.contains(possibleBreakPositions.peek())) {
- possibleBreakPositions.pop();
- }
-
- // if we've used up all possible break-position combinations, there's
- // an error or an unknown word in the text. In this case, we start
- // over, treating the farthest character we've reached as the beginning
- // of the range, and "blessing" the break positions that got us that
- // far as real break positions
- if (possibleBreakPositions.isEmpty()) {
- if (bestBreakPositions != null) {
- currentBreakPositions = bestBreakPositions;
- if (farthestEndPoint < endPos) {
- text.setIndex(farthestEndPoint + 1);
- }
- else {
- break;
- }
- }
- else {
- if ((currentBreakPositions.size() == 0 ||
- currentBreakPositions.peek().intValue() != text.getIndex())
- && text.getIndex() != startPos) {
- currentBreakPositions.push(text.getIndex());
- }
- getNext();
- currentBreakPositions.push(text.getIndex());
- }
- }
-
- // if we still have more break positions we can try, then promote the
- // last break in possibleBreakPositions into currentBreakPositions,
- // and get rid of all entries in currentBreakPositions that come after
- // it. Then back up to that position and start over from there (i.e.,
- // treat that position as the beginning of a new word)
- else {
- Integer temp = possibleBreakPositions.pop();
- Integer temp2 = null;
- while (!currentBreakPositions.isEmpty() && temp.intValue() <
- currentBreakPositions.peek().intValue()) {
- temp2 = currentBreakPositions.pop();
- wrongBreakPositions.add(temp2);
- }
- currentBreakPositions.push(temp);
- text.setIndex(currentBreakPositions.peek().intValue());
- }
-
- // re-sync "c" for the next go-round, and drop out of the loop if
- // we've made it off the end of the range
- c = getCurrent();
- if (text.getIndex() >= endPos) {
- break;
- }
- }
-
- // if we didn't hit any exceptional conditions on this last iteration,
- // just advance to the next character and loop
- else {
- c = getNext();
- }
- }
-
- // dump the last break position in the list, and replace it with the actual
- // end of the range (which may be the same character, or may be further on
- // because the range actually ended with non-dictionary characters we want to
- // keep with the word)
- if (!currentBreakPositions.isEmpty()) {
- currentBreakPositions.pop();
- }
- currentBreakPositions.push(endPos);
-
- // create a regular array to hold the break positions and copy
- // the break positions from the stack to the array (in addition,
- // our starting position goes into this array as a break position).
- // This array becomes the cache of break positions used by next()
- // and previous(), so this is where we actually refresh the cache.
- cachedBreakPositions = new int[currentBreakPositions.size() + 1];
- cachedBreakPositions[0] = startPos;
-
- for (int i = 0; i < currentBreakPositions.size(); i++) {
- cachedBreakPositions[i + 1] = currentBreakPositions.elementAt(i).intValue();
- }
- positionInCache = 0;
- }
-}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,6 @@
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
-import java.lang.reflect.Module;
import java.text.MessageFormat;
import java.util.Calendar;
import java.util.LinkedHashSet;
@@ -113,13 +112,14 @@
if (data == null || ((biInfo = data.get()) == null)) {
biInfo = localeData.getBreakIteratorInfo(locale).getObject(key);
cache.put(cacheKey, new ResourceReference(cacheKey, biInfo, referenceQueue));
- }
+ }
return biInfo;
}
- Module getBreakIteratorDataModule() {
- return localeData.getBreakIteratorInfo(locale).getClass().getModule();
+ @SuppressWarnings("unchecked")
+ byte[] getBreakIteratorResources(String key) {
+ return (byte[]) localeData.getBreakIteratorResources(locale).getObject(key);
}
int getCalendarData(String key) {
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java Thu Oct 27 16:29:00 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1198 +0,0 @@
-/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
- * 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.
- */
-
-/*
- *
- * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
- * (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
- *
- * The original version of this source code and documentation
- * is copyrighted and owned by Taligent, Inc., a wholly-owned
- * subsidiary of IBM. These materials are provided under terms
- * of a License Agreement between Taligent and Sun. This technology
- * is protected by multiple US and International patents.
- *
- * This notice and attribution to Taligent may not be removed.
- * Taligent is a registered trademark of Taligent, Inc.
- */
-
-package sun.util.locale.provider;
-
-import java.io.BufferedInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.lang.reflect.Module;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.text.BreakIterator;
-import java.text.CharacterIterator;
-import java.text.StringCharacterIterator;
-import java.util.MissingResourceException;
-import sun.text.CompactByteArray;
-import sun.text.SupplementaryCharacterData;
-
-/**
- * <p>A subclass of BreakIterator whose behavior is specified using a list of rules.</p>
- *
- * <p>There are two kinds of rules, which are separated by semicolons: <i>substitutions</i>
- * and <i>regular expressions.</i></p>
- *
- * <p>A substitution rule defines a name that can be used in place of an expression. It
- * consists of a name, which is a string of characters contained in angle brackets, an equals
- * sign, and an expression. (There can be no whitespace on either side of the equals sign.)
- * To keep its syntactic meaning intact, the expression must be enclosed in parentheses or
- * square brackets. A substitution is visible after its definition, and is filled in using
- * simple textual substitution. Substitution definitions can contain other substitutions, as
- * long as those substitutions have been defined first. Substitutions are generally used to
- * make the regular expressions (which can get quite complex) shorted and easier to read.
- * They typically define either character categories or commonly-used subexpressions.</p>
- *
- * <p>There is one special substitution. If the description defines a substitution
- * called "<ignore>", the expression must be a [] expression, and the
- * expression defines a set of characters (the "<em>ignore characters</em>") that
- * will be transparent to the BreakIterator. A sequence of characters will break the
- * same way it would if any ignore characters it contains are taken out. Break
- * positions never occur befoer ignore characters.</p>
- *
- * <p>A regular expression uses a subset of the normal Unix regular-expression syntax, and
- * defines a sequence of characters to be kept together. With one significant exception, the
- * iterator uses a longest-possible-match algorithm when matching text to regular
- * expressions. The iterator also treats descriptions containing multiple regular expressions
- * as if they were ORed together (i.e., as if they were separated by |).</p>
- *
- * <p>The special characters recognized by the regular-expression parser are as follows:</p>
- *
- * <blockquote>
- * <table border="1" width="100%">
- * <tr>
- * <td width="6%">*</td>
- * <td width="94%">Specifies that the expression preceding the asterisk may occur any number
- * of times (including not at all).</td>
- * </tr>
- * <tr>
- * <td width="6%">{}</td>
- * <td width="94%">Encloses a sequence of characters that is optional.</td>
- * </tr>
- * <tr>
- * <td width="6%">()</td>
- * <td width="94%">Encloses a sequence of characters. If followed by *, the sequence
- * repeats. Otherwise, the parentheses are just a grouping device and a way to delimit
- * the ends of expressions containing |.</td>
- * </tr>
- * <tr>
- * <td width="6%">|</td>
- * <td width="94%">Separates two alternative sequences of characters. Either one
- * sequence or the other, but not both, matches this expression. The | character can
- * only occur inside ().</td>
- * </tr>
- * <tr>
- * <td width="6%">.</td>
- * <td width="94%">Matches any character.</td>
- * </tr>
- * <tr>
- * <td width="6%">*?</td>
- * <td width="94%">Specifies a non-greedy asterisk. *? works the same way as *, except
- * when there is overlap between the last group of characters in the expression preceding the
- * * and the first group of characters following the *. When there is this kind of
- * overlap, * will match the longest sequence of characters that match the expression before
- * the *, and *? will match the shortest sequence of characters matching the expression
- * before the *?. For example, if you have "xxyxyyyxyxyxxyxyxyy" in the text,
- * "x[xy]*x" will match through to the last x (i.e., "<strong>xxyxyyyxyxyxxyxyx</strong>yy",
- * but "x[xy]*?x" will only match the first two xes ("<strong>xx</strong>yxyyyxyxyxxyxyxyy").</td>
- * </tr>
- * <tr>
- * <td width="6%">[]</td>
- * <td width="94%">Specifies a group of alternative characters. A [] expression will
- * match any single character that is specified in the [] expression. For more on the
- * syntax of [] expressions, see below.</td>
- * </tr>
- * <tr>
- * <td width="6%">/</td>
- * <td width="94%">Specifies where the break position should go if text matches this
- * expression. (e.g., "[a-z]*/[:Zs:]*[1-0]" will match if the iterator sees a run
- * of letters, followed by a run of whitespace, followed by a digit, but the break position
- * will actually go before the whitespace). Expressions that don't contain / put the
- * break position at the end of the matching text.</td>
- * </tr>
- * <tr>
- * <td width="6%">\</td>
- * <td width="94%">Escape character. The \ itself is ignored, but causes the next
- * character to be treated as literal character. This has no effect for many
- * characters, but for the characters listed above, this deprives them of their special
- * meaning. (There are no special escape sequences for Unicode characters, or tabs and
- * newlines; these are all handled by a higher-level protocol. In a Java string,
- * "\n" will be converted to a literal newline character by the time the
- * regular-expression parser sees it. Of course, this means that \ sequences that are
- * visible to the regexp parser must be written as \\ when inside a Java string.) All
- * characters in the ASCII range except for letters, digits, and control characters are
- * reserved characters to the parser and must be preceded by \ even if they currently don't
- * mean anything.</td>
- * </tr>
- * <tr>
- * <td width="6%">!</td>
- * <td width="94%">If ! appears at the beginning of a regular expression, it tells the regexp
- * parser that this expression specifies the backwards-iteration behavior of the iterator,
- * and not its normal iteration behavior. This is generally only used in situations
- * where the automatically-generated backwards-iteration brhavior doesn't produce
- * satisfactory results and must be supplemented with extra client-specified rules.</td>
- * </tr>
- * <tr>
- * <td width="6%"><em>(all others)</em></td>
- * <td width="94%">All other characters are treated as literal characters, which must match
- * the corresponding character(s) in the text exactly.</td>
- * </tr>
- * </table>
- * </blockquote>
- *
- * <p>Within a [] expression, a number of other special characters can be used to specify
- * groups of characters:</p>
- *
- * <blockquote>
- * <table border="1" width="100%">
- * <tr>
- * <td width="6%">-</td>
- * <td width="94%">Specifies a range of matching characters. For example
- * "[a-p]" matches all lowercase Latin letters from a to p (inclusive). The -
- * sign specifies ranges of continuous Unicode numeric values, not ranges of characters in a
- * language's alphabetical order: "[a-z]" doesn't include capital letters, nor does
- * it include accented letters such as a-umlaut.</td>
- * </tr>
- * <tr>
- * <td width="6%">::</td>
- * <td width="94%">A pair of colons containing a one- or two-letter code matches all
- * characters in the corresponding Unicode category. The two-letter codes are the same
- * as the two-letter codes in the Unicode database (for example, "[:Sc::Sm:]"
- * matches all currency symbols and all math symbols). Specifying a one-letter code is
- * the same as specifying all two-letter codes that begin with that letter (for example,
- * "[:L:]" matches all letters, and is equivalent to
- * "[:Lu::Ll::Lo::Lm::Lt:]"). Anything other than a valid two-letter Unicode
- * category code or a single letter that begins a Unicode category code is illegal within
- * colons.</td>
- * </tr>
- * <tr>
- * <td width="6%">[]</td>
- * <td width="94%">[] expressions can nest. This has no effect, except when used in
- * conjunction with the ^ token.</td>
- * </tr>
- * <tr>
- * <td width="6%">^</td>
- * <td width="94%">Excludes the character (or the characters in the [] expression) following
- * it from the group of characters. For example, "[a-z^p]" matches all Latin
- * lowercase letters except p. "[:L:^[\u4e00-\u9fff]]" matches all letters
- * except the Han ideographs.</td>
- * </tr>
- * <tr>
- * <td width="6%"><em>(all others)</em></td>
- * <td width="94%">All other characters are treated as literal characters. (For
- * example, "[aeiou]" specifies just the letters a, e, i, o, and u.)</td>
- * </tr>
- * </table>
- * </blockquote>
- *
- * <p>For a more complete explanation, see <a
- * href="http://www.ibm.com/java/education/boundaries/boundaries.html">http://www.ibm.com/java/education/boundaries/boundaries.html</a>.
- * For examples, see the resource data (which is annotated).</p>
- *
- * @author Richard Gillam
- */
-class RuleBasedBreakIterator extends BreakIterator {
-
- /**
- * A token used as a character-category value to identify ignore characters
- */
- protected static final byte IGNORE = -1;
-
- /**
- * The state number of the starting state
- */
- private static final short START_STATE = 1;
-
- /**
- * The state-transition value indicating "stop"
- */
- private static final short STOP_STATE = 0;
-
- /**
- * Magic number for the BreakIterator data file format.
- */
- static final byte[] LABEL = {
- (byte)'B', (byte)'I', (byte)'d', (byte)'a', (byte)'t', (byte)'a',
- (byte)'\0'
- };
- static final int LABEL_LENGTH = LABEL.length;
-
- /**
- * Version number of the dictionary that was read in.
- */
- static final byte supportedVersion = 1;
-
- /**
- * Header size in byte count
- */
- private static final int HEADER_LENGTH = 36;
-
- /**
- * An array length of indices for BMP characters
- */
- private static final int BMP_INDICES_LENGTH = 512;
-
- /**
- * Tables that indexes from character values to character category numbers
- */
- private CompactByteArray charCategoryTable = null;
- private SupplementaryCharacterData supplementaryCharCategoryTable = null;
-
- /**
- * The table of state transitions used for forward iteration
- */
- private short[] stateTable = null;
-
- /**
- * The table of state transitions used to sync up the iterator with the
- * text in backwards and random-access iteration
- */
- private short[] backwardsStateTable = null;
-
- /**
- * A list of flags indicating which states in the state table are accepting
- * ("end") states
- */
- private boolean[] endStates = null;
-
- /**
- * A list of flags indicating which states in the state table are
- * lookahead states (states which turn lookahead on and off)
- */
- private boolean[] lookaheadStates = null;
-
- /**
- * A table for additional data. May be used by a subclass of
- * RuleBasedBreakIterator.
- */
- private byte[] additionalData = null;
-
- /**
- * The number of character categories (and, thus, the number of columns in
- * the state tables)
- */
- private int numCategories;
-
- /**
- * The character iterator through which this BreakIterator accesses the text
- */
- private CharacterIterator text = null;
-
- /**
- * A CRC32 value of all data in datafile
- */
- private long checksum;
-
- //=======================================================================
- // constructors
- //=======================================================================
-
- /**
- * Constructs a RuleBasedBreakIterator according to the module and the datafile
- * provided.
- */
- RuleBasedBreakIterator(Module module, String datafile)
- throws IOException, MissingResourceException {
- readTables(module, datafile);
- }
-
- /**
- * Read datafile. The datafile's format is as follows:
- * <pre>
- * BreakIteratorData {
- * u1 magic[7];
- * u1 version;
- * u4 totalDataSize;
- * header_info header;
- * body value;
- * }
- * </pre>
- * <code>totalDataSize</code> is the summation of the size of
- * <code>header_info</code> and <code>body</code> in byte count.
- * <p>
- * In <code>header</code>, each field except for checksum implies the
- * length of each field. Since <code>BMPdataLength</code> is a fixed-length
- * data(512 entries), its length isn't included in <code>header</code>.
- * <code>checksum</code> is a CRC32 value of all in <code>body</code>.
- * <pre>
- * header_info {
- * u4 stateTableLength;
- * u4 backwardsStateTableLength;
- * u4 endStatesLength;
- * u4 lookaheadStatesLength;
- * u4 BMPdataLength;
- * u4 nonBMPdataLength;
- * u4 additionalDataLength;
- * u8 checksum;
- * }
- * </pre>
- * <p>
- *
- * Finally, <code>BMPindices</code> and <code>BMPdata</code> are set to
- * <code>charCategoryTable</code>. <code>nonBMPdata</code> is set to
- * <code>supplementaryCharCategoryTable</code>.
- * <pre>
- * body {
- * u2 stateTable[stateTableLength];
- * u2 backwardsStateTable[backwardsStateTableLength];
- * u1 endStates[endStatesLength];
- * u1 lookaheadStates[lookaheadStatesLength];
- * u2 BMPindices[512];
- * u1 BMPdata[BMPdataLength];
- * u4 nonBMPdata[numNonBMPdataLength];
- * u1 additionalData[additionalDataLength];
- * }
- * </pre>
- */
- protected final void readTables(Module module, String datafile)
- throws IOException, MissingResourceException {
-
- byte[] buffer = readFile(module, datafile);
-
- /* Read header_info. */
- int stateTableLength = getInt(buffer, 0);
- int backwardsStateTableLength = getInt(buffer, 4);
- int endStatesLength = getInt(buffer, 8);
- int lookaheadStatesLength = getInt(buffer, 12);
- int BMPdataLength = getInt(buffer, 16);
- int nonBMPdataLength = getInt(buffer, 20);
- int additionalDataLength = getInt(buffer, 24);
- checksum = getLong(buffer, 28);
-
- /* Read stateTable[numCategories * numRows] */
- stateTable = new short[stateTableLength];
- int offset = HEADER_LENGTH;
- for (int i = 0; i < stateTableLength; i++, offset+=2) {
- stateTable[i] = getShort(buffer, offset);
- }
-
- /* Read backwardsStateTable[numCategories * numRows] */
- backwardsStateTable = new short[backwardsStateTableLength];
- for (int i = 0; i < backwardsStateTableLength; i++, offset+=2) {
- backwardsStateTable[i] = getShort(buffer, offset);
- }
-
- /* Read endStates[numRows] */
- endStates = new boolean[endStatesLength];
- for (int i = 0; i < endStatesLength; i++, offset++) {
- endStates[i] = buffer[offset] == 1;
- }
-
- /* Read lookaheadStates[numRows] */
- lookaheadStates = new boolean[lookaheadStatesLength];
- for (int i = 0; i < lookaheadStatesLength; i++, offset++) {
- lookaheadStates[i] = buffer[offset] == 1;
- }
-
- /* Read a category table and indices for BMP characters. */
- short[] temp1 = new short[BMP_INDICES_LENGTH]; // BMPindices
- for (int i = 0; i < BMP_INDICES_LENGTH; i++, offset+=2) {
- temp1[i] = getShort(buffer, offset);
- }
- byte[] temp2 = new byte[BMPdataLength]; // BMPdata
- System.arraycopy(buffer, offset, temp2, 0, BMPdataLength);
- offset += BMPdataLength;
- charCategoryTable = new CompactByteArray(temp1, temp2);
-
- /* Read a category table for non-BMP characters. */
- int[] temp3 = new int[nonBMPdataLength];
- for (int i = 0; i < nonBMPdataLength; i++, offset+=4) {
- temp3[i] = getInt(buffer, offset);
- }
- supplementaryCharCategoryTable = new SupplementaryCharacterData(temp3);
-
- /* Read additional data */
- if (additionalDataLength > 0) {
- additionalData = new byte[additionalDataLength];
- System.arraycopy(buffer, offset, additionalData, 0, additionalDataLength);
- }
-
- /* Set numCategories */
- numCategories = stateTable.length / endStates.length;
- }
-
- protected byte[] readFile(final Module module, final String datafile)
- throws IOException, MissingResourceException {
-
- BufferedInputStream is;
- try {
- PrivilegedExceptionAction<BufferedInputStream> pa = () -> {
- String pathName = "jdk.localedata".equals(module.getName()) ?
- "sun/text/resources/ext/" :
- "sun/text/resources/";
- InputStream in = module.getResourceAsStream(pathName + datafile);
- if (in == null) {
- // Try to load the file with "java.base" module instance. Assumption
- // here is that the fall back data files to be read should reside in
- // java.base.
- in = RuleBasedBreakIterator.class.getModule().getResourceAsStream("sun/text/resources/" + datafile);
- }
-
- return new BufferedInputStream(in);
- };
- is = AccessController.doPrivileged(pa);
- } catch (PrivilegedActionException e) {
- throw new InternalError(e.toString(), e);
- }
-
- int offset = 0;
-
- /* First, read magic, version, and header_info. */
- int len = LABEL_LENGTH + 5;
- byte[] buf = new byte[len];
- if (is.read(buf) != len) {
- throw new MissingResourceException("Wrong header length",
- datafile, "");
- }
-
- /* Validate the magic number. */
- for (int i = 0; i < LABEL_LENGTH; i++, offset++) {
- if (buf[offset] != LABEL[offset]) {
- throw new MissingResourceException("Wrong magic number",
- datafile, "");
- }
- }
-
- /* Validate the version number. */
- if (buf[offset] != supportedVersion) {
- throw new MissingResourceException("Unsupported version(" + buf[offset] + ")",
- datafile, "");
- }
-
- /* Read data: totalDataSize + 8(for checksum) */
- len = getInt(buf, ++offset);
- buf = new byte[len];
- if (is.read(buf) != len) {
- throw new MissingResourceException("Wrong data length",
- datafile, "");
- }
-
- is.close();
-
- return buf;
- }
-
- byte[] getAdditionalData() {
- return additionalData;
- }
-
- void setAdditionalData(byte[] b) {
- additionalData = b;
- }
-
- //=======================================================================
- // boilerplate
- //=======================================================================
- /**
- * Clones this iterator.
- * @return A newly-constructed RuleBasedBreakIterator with the same
- * behavior as this one.
- */
- @Override
- public Object clone() {
- RuleBasedBreakIterator result = (RuleBasedBreakIterator) super.clone();
- if (text != null) {
- result.text = (CharacterIterator) text.clone();
- }
- return result;
- }
-
- /**
- * Returns true if both BreakIterators are of the same class, have the same
- * rules, and iterate over the same text.
- */
- @Override
- public boolean equals(Object that) {
- try {
- if (that == null) {
- return false;
- }
-
- RuleBasedBreakIterator other = (RuleBasedBreakIterator) that;
- if (checksum != other.checksum) {
- return false;
- }
- if (text == null) {
- return other.text == null;
- } else {
- return text.equals(other.text);
- }
- }
- catch(ClassCastException e) {
- return false;
- }
- }
-
- /**
- * Returns text
- */
- @Override
- public String toString() {
- return "[checksum=0x" + Long.toHexString(checksum) + ']';
- }
-
- /**
- * Compute a hashcode for this BreakIterator
- * @return A hash code
- */
- @Override
- public int hashCode() {
- return (int)checksum;
- }
-
- //=======================================================================
- // BreakIterator overrides
- //=======================================================================
-
- /**
- * Sets the current iteration position to the beginning of the text.
- * (i.e., the CharacterIterator's starting offset).
- * @return The offset of the beginning of the text.
- */
- @Override
- public int first() {
- CharacterIterator t = getText();
-
- t.first();
- return t.getIndex();
- }
-
- /**
- * Sets the current iteration position to the end of the text.
- * (i.e., the CharacterIterator's ending offset).
- * @return The text's past-the-end offset.
- */
- @Override
- public int last() {
- CharacterIterator t = getText();
-
- // I'm not sure why, but t.last() returns the offset of the last character,
- // rather than the past-the-end offset
- t.setIndex(t.getEndIndex());
- return t.getIndex();
- }
-
- /**
- * Advances the iterator either forward or backward the specified number of steps.
- * Negative values move backward, and positive values move forward. This is
- * equivalent to repeatedly calling next() or previous().
- * @param n The number of steps to move. The sign indicates the direction
- * (negative is backwards, and positive is forwards).
- * @return The character offset of the boundary position n boundaries away from
- * the current one.
- */
- @Override
- public int next(int n) {
- int result = current();
- while (n > 0) {
- result = handleNext();
- --n;
- }
- while (n < 0) {
- result = previous();
- ++n;
- }
- return result;
- }
-
- /**
- * Advances the iterator to the next boundary position.
- * @return The position of the first boundary after this one.
- */
- @Override
- public int next() {
- return handleNext();
- }
-
- private int cachedLastKnownBreak = BreakIterator.DONE;
-
- /**
- * Advances the iterator backwards, to the last boundary preceding this one.
- * @return The position of the last boundary position preceding this one.
- */
- @Override
- public int previous() {
- // if we're already sitting at the beginning of the text, return DONE
- CharacterIterator text = getText();
- if (current() == text.getBeginIndex()) {
- return BreakIterator.DONE;
- }
-
- // set things up. handlePrevious() will back us up to some valid
- // break position before the current position (we back our internal
- // iterator up one step to prevent handlePrevious() from returning
- // the current position), but not necessarily the last one before
- // where we started
- int start = current();
- int lastResult = cachedLastKnownBreak;
- if (lastResult >= start || lastResult <= BreakIterator.DONE) {
- getPrevious();
- lastResult = handlePrevious();
- } else {
- //it might be better to check if handlePrevious() give us closer
- //safe value but handlePrevious() is slow too
- //So, this has to be done carefully
- text.setIndex(lastResult);
- }
- int result = lastResult;
-
- // iterate forward from the known break position until we pass our
- // starting point. The last break position before the starting
- // point is our return value
- while (result != BreakIterator.DONE && result < start) {
- lastResult = result;
- result = handleNext();
- }
-
- // set the current iteration position to be the last break position
- // before where we started, and then return that value
- text.setIndex(lastResult);
- cachedLastKnownBreak = lastResult;
- return lastResult;
- }
-
- /**
- * Returns previous character
- */
- private int getPrevious() {
- char c2 = text.previous();
- if (Character.isLowSurrogate(c2) &&
- text.getIndex() > text.getBeginIndex()) {
- char c1 = text.previous();
- if (Character.isHighSurrogate(c1)) {
- return Character.toCodePoint(c1, c2);
- } else {
- text.next();
- }
- }
- return (int)c2;
- }
-
- /**
- * Returns current character
- */
- int getCurrent() {
- char c1 = text.current();
- if (Character.isHighSurrogate(c1) &&
- text.getIndex() < text.getEndIndex()) {
- char c2 = text.next();
- text.previous();
- if (Character.isLowSurrogate(c2)) {
- return Character.toCodePoint(c1, c2);
- }
- }
- return (int)c1;
- }
-
- /**
- * Returns the count of next character.
- */
- private int getCurrentCodePointCount() {
- char c1 = text.current();
- if (Character.isHighSurrogate(c1) &&
- text.getIndex() < text.getEndIndex()) {
- char c2 = text.next();
- text.previous();
- if (Character.isLowSurrogate(c2)) {
- return 2;
- }
- }
- return 1;
- }
-
- /**
- * Returns next character
- */
- int getNext() {
- int index = text.getIndex();
- int endIndex = text.getEndIndex();
- if (index == endIndex ||
- (index += getCurrentCodePointCount()) >= endIndex) {
- return CharacterIterator.DONE;
- }
- text.setIndex(index);
- return getCurrent();
- }
-
- /**
- * Returns the position of next character.
- */
- private int getNextIndex() {
- int index = text.getIndex() + getCurrentCodePointCount();
- int endIndex = text.getEndIndex();
- if (index > endIndex) {
- return endIndex;
- } else {
- return index;
- }
- }
-
- /**
- * Throw IllegalArgumentException unless begin <= offset < end.
- */
- protected static final void checkOffset(int offset, CharacterIterator text) {
- if (offset < text.getBeginIndex() || offset > text.getEndIndex()) {
- throw new IllegalArgumentException("offset out of bounds");
- }
- }
-
- /**
- * Sets the iterator to refer to the first boundary position following
- * the specified position.
- * @offset The position from which to begin searching for a break position.
- * @return The position of the first break after the current position.
- */
- @Override
- public int following(int offset) {
-
- CharacterIterator text = getText();
- checkOffset(offset, text);
-
- // Set our internal iteration position (temporarily)
- // to the position passed in. If this is the _beginning_ position,
- // then we can just use next() to get our return value
- text.setIndex(offset);
- if (offset == text.getBeginIndex()) {
- cachedLastKnownBreak = handleNext();
- return cachedLastKnownBreak;
- }
-
- // otherwise, we have to sync up first. Use handlePrevious() to back
- // us up to a known break position before the specified position (if
- // we can determine that the specified position is a break position,
- // we don't back up at all). This may or may not be the last break
- // position at or before our starting position. Advance forward
- // from here until we've passed the starting position. The position
- // we stop on will be the first break position after the specified one.
- int result = cachedLastKnownBreak;
- if (result >= offset || result <= BreakIterator.DONE) {
- result = handlePrevious();
- } else {
- //it might be better to check if handlePrevious() give us closer
- //safe value but handlePrevious() is slow too
- //So, this has to be done carefully
- text.setIndex(result);
- }
- while (result != BreakIterator.DONE && result <= offset) {
- result = handleNext();
- }
- cachedLastKnownBreak = result;
- return result;
- }
-
- /**
- * Sets the iterator to refer to the last boundary position before the
- * specified position.
- * @offset The position to begin searching for a break from.
- * @return The position of the last boundary before the starting position.
- */
- @Override
- public int preceding(int offset) {
- // if we start by updating the current iteration position to the
- // position specified by the caller, we can just use previous()
- // to carry out this operation
- CharacterIterator text = getText();
- checkOffset(offset, text);
- text.setIndex(offset);
- return previous();
- }
-
- /**
- * Returns true if the specified position is a boundary position. As a side
- * effect, leaves the iterator pointing to the first boundary position at
- * or after "offset".
- * @param offset the offset to check.
- * @return True if "offset" is a boundary position.
- */
- @Override
- public boolean isBoundary(int offset) {
- CharacterIterator text = getText();
- checkOffset(offset, text);
- if (offset == text.getBeginIndex()) {
- return true;
- }
-
- // to check whether this is a boundary, we can use following() on the
- // position before the specified one and return true if the position we
- // get back is the one the user specified
- else {
- return following(offset - 1) == offset;
- }
- }
-
- /**
- * Returns the current iteration position.
- * @return The current iteration position.
- */
- @Override
- public int current() {
- return getText().getIndex();
- }
-
- /**
- * Return a CharacterIterator over the text being analyzed. This version
- * of this method returns the actual CharacterIterator we're using internally.
- * Changing the state of this iterator can have undefined consequences. If
- * you need to change it, clone it first.
- * @return An iterator over the text being analyzed.
- */
- @Override
- public CharacterIterator getText() {
- // The iterator is initialized pointing to no text at all, so if this
- // function is called while we're in that state, we have to fudge an
- // iterator to return.
- if (text == null) {
- text = new StringCharacterIterator("");
- }
- return text;
- }
-
- /**
- * Set the iterator to analyze a new piece of text. This function resets
- * the current iteration position to the beginning of the text.
- * @param newText An iterator over the text to analyze.
- */
- @Override
- public void setText(CharacterIterator newText) {
- // Test iterator to see if we need to wrap it in a SafeCharIterator.
- // The correct behavior for CharacterIterators is to allow the
- // position to be set to the endpoint of the iterator. Many
- // CharacterIterators do not uphold this, so this is a workaround
- // to permit them to use this class.
- int end = newText.getEndIndex();
- boolean goodIterator;
- try {
- newText.setIndex(end); // some buggy iterators throw an exception here
- goodIterator = newText.getIndex() == end;
- }
- catch(IllegalArgumentException e) {
- goodIterator = false;
- }
-
- if (goodIterator) {
- text = newText;
- }
- else {
- text = new SafeCharIterator(newText);
- }
- text.first();
-
- cachedLastKnownBreak = BreakIterator.DONE;
- }
-
-
- //=======================================================================
- // implementation
- //=======================================================================
-
- /**
- * This method is the actual implementation of the next() method. All iteration
- * vectors through here. This method initializes the state machine to state 1
- * and advances through the text character by character until we reach the end
- * of the text or the state machine transitions to state 0. We update our return
- * value every time the state machine passes through a possible end state.
- */
- protected int handleNext() {
- // if we're already at the end of the text, return DONE.
- CharacterIterator text = getText();
- if (text.getIndex() == text.getEndIndex()) {
- return BreakIterator.DONE;
- }
-
- // no matter what, we always advance at least one character forward
- int result = getNextIndex();
- int lookaheadResult = 0;
-
- // begin in state 1
- int state = START_STATE;
- int category;
- int c = getCurrent();
-
- // loop until we reach the end of the text or transition to state 0
- while (c != CharacterIterator.DONE && state != STOP_STATE) {
-
- // look up the current character's character category (which tells us
- // which column in the state table to look at)
- category = lookupCategory(c);
-
- // if the character isn't an ignore character, look up a state
- // transition in the state table
- if (category != IGNORE) {
- state = lookupState(state, category);
- }
-
- // if the state we've just transitioned to is a lookahead state,
- // (but not also an end state), save its position. If it's
- // both a lookahead state and an end state, update the break position
- // to the last saved lookup-state position
- if (lookaheadStates[state]) {
- if (endStates[state]) {
- result = lookaheadResult;
- }
- else {
- lookaheadResult = getNextIndex();
- }
- }
-
- // otherwise, if the state we've just transitioned to is an accepting
- // state, update the break position to be the current iteration position
- else {
- if (endStates[state]) {
- result = getNextIndex();
- }
- }
-
- c = getNext();
- }
-
- // if we've run off the end of the text, and the very last character took us into
- // a lookahead state, advance the break position to the lookahead position
- // (the theory here is that if there are no characters at all after the lookahead
- // position, that always matches the lookahead criteria)
- if (c == CharacterIterator.DONE && lookaheadResult == text.getEndIndex()) {
- result = lookaheadResult;
- }
-
- text.setIndex(result);
- return result;
- }
-
- /**
- * This method backs the iterator back up to a "safe position" in the text.
- * This is a position that we know, without any context, must be a break position.
- * The various calling methods then iterate forward from this safe position to
- * the appropriate position to return. (For more information, see the description
- * of buildBackwardsStateTable() in RuleBasedBreakIterator.Builder.)
- */
- protected int handlePrevious() {
- CharacterIterator text = getText();
- int state = START_STATE;
- int category = 0;
- int lastCategory = 0;
- int c = getCurrent();
-
- // loop until we reach the beginning of the text or transition to state 0
- while (c != CharacterIterator.DONE && state != STOP_STATE) {
-
- // save the last character's category and look up the current
- // character's category
- lastCategory = category;
- category = lookupCategory(c);
-
- // if the current character isn't an ignore character, look up a
- // state transition in the backwards state table
- if (category != IGNORE) {
- state = lookupBackwardState(state, category);
- }
-
- // then advance one character backwards
- c = getPrevious();
- }
-
- // if we didn't march off the beginning of the text, we're either one or two
- // positions away from the real break position. (One because of the call to
- // previous() at the end of the loop above, and another because the character
- // that takes us into the stop state will always be the character BEFORE
- // the break position.)
- if (c != CharacterIterator.DONE) {
- if (lastCategory != IGNORE) {
- getNext();
- getNext();
- }
- else {
- getNext();
- }
- }
- return text.getIndex();
- }
-
- /**
- * Looks up a character's category (i.e., its category for breaking purposes,
- * not its Unicode category)
- */
- protected int lookupCategory(int c) {
- if (c < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
- return charCategoryTable.elementAt((char)c);
- } else {
- return supplementaryCharCategoryTable.getValue(c);
- }
- }
-
- /**
- * Given a current state and a character category, looks up the
- * next state to transition to in the state table.
- */
- protected int lookupState(int state, int category) {
- return stateTable[state * numCategories + category];
- }
-
- /**
- * Given a current state and a character category, looks up the
- * next state to transition to in the backwards state table.
- */
- protected int lookupBackwardState(int state, int category) {
- return backwardsStateTable[state * numCategories + category];
- }
-
- static long getLong(byte[] buf, int offset) {
- long num = buf[offset]&0xFF;
- for (int i = 1; i < 8; i++) {
- num = num<<8 | (buf[offset+i]&0xFF);
- }
- return num;
- }
-
- static int getInt(byte[] buf, int offset) {
- int num = buf[offset]&0xFF;
- for (int i = 1; i < 4; i++) {
- num = num<<8 | (buf[offset+i]&0xFF);
- }
- return num;
- }
-
- static short getShort(byte[] buf, int offset) {
- short num = (short)(buf[offset]&0xFF);
- num = (short)(num<<8 | (buf[offset+1]&0xFF));
- return num;
- }
-
- /*
- * This class exists to work around a bug in incorrect implementations
- * of CharacterIterator, which incorrectly handle setIndex(endIndex).
- * This iterator relies only on base.setIndex(n) where n is less than
- * endIndex.
- *
- * One caveat: if the base iterator's begin and end indices change
- * the change will not be reflected by this wrapper. Does that matter?
- */
- // TODO: Review this class to see if it's still required.
- private static final class SafeCharIterator implements CharacterIterator,
- Cloneable {
-
- private CharacterIterator base;
- private int rangeStart;
- private int rangeLimit;
- private int currentIndex;
-
- SafeCharIterator(CharacterIterator base) {
- this.base = base;
- this.rangeStart = base.getBeginIndex();
- this.rangeLimit = base.getEndIndex();
- this.currentIndex = base.getIndex();
- }
-
- @Override
- public char first() {
- return setIndex(rangeStart);
- }
-
- @Override
- public char last() {
- return setIndex(rangeLimit - 1);
- }
-
- @Override
- public char current() {
- if (currentIndex < rangeStart || currentIndex >= rangeLimit) {
- return DONE;
- }
- else {
- return base.setIndex(currentIndex);
- }
- }
-
- @Override
- public char next() {
-
- currentIndex++;
- if (currentIndex >= rangeLimit) {
- currentIndex = rangeLimit;
- return DONE;
- }
- else {
- return base.setIndex(currentIndex);
- }
- }
-
- @Override
- public char previous() {
-
- currentIndex--;
- if (currentIndex < rangeStart) {
- currentIndex = rangeStart;
- return DONE;
- }
- else {
- return base.setIndex(currentIndex);
- }
- }
-
- @Override
- public char setIndex(int i) {
-
- if (i < rangeStart || i > rangeLimit) {
- throw new IllegalArgumentException("Invalid position");
- }
- currentIndex = i;
- return current();
- }
-
- @Override
- public int getBeginIndex() {
- return rangeStart;
- }
-
- @Override
- public int getEndIndex() {
- return rangeLimit;
- }
-
- @Override
- public int getIndex() {
- return currentIndex;
- }
-
- @Override
- public Object clone() {
-
- SafeCharIterator copy = null;
- try {
- copy = (SafeCharIterator) super.clone();
- }
- catch(CloneNotSupportedException e) {
- throw new Error("Clone not supported: " + e);
- }
-
- CharacterIterator copyOfBase = (CharacterIterator) base.clone();
- copy.base = copyOfBase;
- return copy;
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/util/resources/BreakIteratorResourceBundle.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.util.resources;
+
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+/**
+ * BreakIteratorResourceBundle is an abstract class for loading BreakIterator
+ * data (rules or dictionary) from each module. An implementation class must
+ * implement getBreakIteratorInfo() that returns an instance of the
+ * corresponding BreakIteratorInfo (basename). The data name is taken from the
+ * BreakIteratorInfo instance.
+ *
+ * <p>For example, if the given key is "WordDictionary" and Locale is "th", the
+ * data name is taken from a BreakIteratorInfo_th and the key's value is
+ * "thai_dict". Its data thai_dict is loaded from the Module of the
+ * implementation class of this class.
+ */
+
+public abstract class BreakIteratorResourceBundle extends ResourceBundle {
+ // If any keys that are not for data names are added to BreakIteratorInfo*,
+ // those keys must be added to NON_DATA_KEYS.
+ private static final Set<String> NON_DATA_KEYS = Set.of("BreakIteratorClasses");
+
+ private volatile Set<String> keys;
+
+ /**
+ * Returns an instance of the corresponding {@code BreakIteratorInfo} (basename).
+ * The instance shouldn't have its parent.
+ */
+ protected abstract ResourceBundle getBreakIteratorInfo();
+
+ @Override
+ protected Object handleGetObject(String key) {
+ if (NON_DATA_KEYS.contains(key)) {
+ return null;
+ }
+ ResourceBundle info = getBreakIteratorInfo();
+ if (!info.containsKey(key)) {
+ return null;
+ }
+ String path = getClass().getPackage().getName().replace('.', '/')
+ + '/' + info.getString(key);
+ byte[] data;
+ try (InputStream is = getResourceAsStream(path)) {
+ data = is.readAllBytes();
+ } catch (Exception e) {
+ throw new InternalError("Can't load " + path, e);
+ }
+ return data;
+ }
+
+ private InputStream getResourceAsStream(String path) throws Exception {
+ PrivilegedExceptionAction<InputStream> pa;
+ pa = () -> getClass().getModule().getResourceAsStream(path);
+ InputStream is;
+ try {
+ is = AccessController.doPrivileged(pa);
+ } catch (PrivilegedActionException e) {
+ throw e.getException();
+ }
+ return is;
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ return Collections.enumeration(keySet());
+ }
+
+ @Override
+ protected Set<String> handleKeySet() {
+ if (keys == null) {
+ ResourceBundle info = getBreakIteratorInfo();
+ Set<String> k = info.keySet();
+ k.removeAll(NON_DATA_KEYS);
+ synchronized (this) {
+ if (keys == null) {
+ keys = k;
+ }
+ }
+ }
+ return keys;
+ }
+}
--- a/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java Thu Oct 27 21:22:57 2016 +0000
@@ -123,6 +123,14 @@
}
/**
+ * Gets a break iterator resources resource bundle, using
+ * privileges to allow accessing a sun.* package.
+ */
+ public ResourceBundle getBreakIteratorResources(Locale locale) {
+ return getBundle(type.getTextResourcesPackage() + ".BreakIteratorResources", locale);
+ }
+
+ /**
* Gets a collation data resource bundle, using privileges
* to allow accessing a sun.* package.
*/
--- a/jdk/src/java.base/share/lib/security/default.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/lib/security/default.policy Thu Oct 27 21:22:57 2016 +0000
@@ -32,8 +32,22 @@
permission javax.smartcardio.CardPermission "*", "*";
permission java.lang.RuntimePermission "loadLibrary.j2pcsc";
permission java.lang.RuntimePermission
- "accessClassInPackage.sun.security.*";
- permission java.util.PropertyPermission "*", "read";
+ "accessClassInPackage.sun.security.jca";
+ permission java.lang.RuntimePermission
+ "accessClassInPackage.sun.security.util";
+ permission java.util.PropertyPermission
+ "javax.smartcardio.TerminalFactory.DefaultType", "read";
+ permission java.util.PropertyPermission "os.name", "read";
+ permission java.util.PropertyPermission "os.arch", "read";
+ permission java.util.PropertyPermission "sun.arch.data.model", "read";
+ permission java.util.PropertyPermission
+ "sun.security.smartcardio.library", "read";
+ permission java.util.PropertyPermission
+ "sun.security.smartcardio.t0GetResponse", "read";
+ permission java.util.PropertyPermission
+ "sun.security.smartcardio.t1GetResponse", "read";
+ permission java.util.PropertyPermission
+ "sun.security.smartcardio.t1StripLe", "read";
// needed for looking up native PC/SC library
permission java.io.FilePermission "<<ALL FILES>>","read";
permission java.security.SecurityPermission "putProviderProperty.SunPCSC";
--- a/jdk/src/java.base/share/native/launcher/defines.h Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/native/launcher/defines.h Thu Oct 27 21:22:57 2016 +0000
@@ -51,16 +51,6 @@
static char* const_progname = NULL;
#endif
static const char* const_jargs[] = JAVA_ARGS;
-/*
- * ApplicationHome is prepended to each of these entries; the resulting
- * strings are concatenated (separated by PATH_SEPARATOR) and used as the
- * value of -cp option to the launcher.
- */
-#ifndef APP_CLASSPATH
-static const char* const_appclasspath[] = { NULL };
-#else
-static const char* const_appclasspath[] = APP_CLASSPATH;
-#endif /* APP_CLASSPATH */
#else /* !JAVA_ARGS */
#define HAS_JAVA_ARGS JNI_FALSE
static const char* const_progname = "java";
--- a/jdk/src/java.base/share/native/launcher/main.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/native/launcher/main.c Thu Oct 27 21:22:57 2016 +0000
@@ -83,7 +83,7 @@
int WINAPI
WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow)
{
- int margc, appclassc;
+ int margc;
char** margv;
const jboolean const_javaw = JNI_TRUE;
@@ -93,7 +93,7 @@
int
main(int argc, char **argv)
{
- int margc, appclassc;
+ int margc;
char** margv;
const jboolean const_javaw = JNI_FALSE;
#endif /* JAVAW */
@@ -148,14 +148,9 @@
margv = args->elements;
}
#endif /* WIN32 */
- if (const_appclasspath[0] == NULL) {
- appclassc = 0;
- } else {
- appclassc = sizeof(const_appclasspath) / sizeof(char *);
- }
return JLI_Launch(margc, margv,
sizeof(const_jargs) / sizeof(char *), const_jargs,
- appclassc, const_appclasspath,
+ 0, NULL,
VERSION_STRING,
DOT_VERSION,
(const_progname != NULL) ? const_progname : *margv,
--- a/jdk/src/java.base/share/native/libjli/java.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/native/libjli/java.c Thu Oct 27 21:22:57 2016 +0000
@@ -1664,19 +1664,21 @@
AddOption(apphome, NULL);
/* How big is the application's classpath? */
- size = 40; /* 40: "-Djava.class.path=" */
- for (i = 0; i < cpathc; i++) {
- size += (int)JLI_StrLen(home) + (int)JLI_StrLen(cpathv[i]) + 1; /* 1: separator */
+ if (cpathc > 0) {
+ size = 40; /* 40: "-Djava.class.path=" */
+ for (i = 0; i < cpathc; i++) {
+ size += (int)JLI_StrLen(home) + (int)JLI_StrLen(cpathv[i]) + 1; /* 1: separator */
+ }
+ appcp = (char *)JLI_MemAlloc(size + 1);
+ JLI_StrCpy(appcp, "-Djava.class.path=");
+ for (i = 0; i < cpathc; i++) {
+ JLI_StrCat(appcp, home); /* c:\program files\myapp */
+ JLI_StrCat(appcp, cpathv[i]); /* \lib\myapp.jar */
+ JLI_StrCat(appcp, separator); /* ; */
+ }
+ appcp[JLI_StrLen(appcp)-1] = '\0'; /* remove trailing path separator */
+ AddOption(appcp, NULL);
}
- appcp = (char *)JLI_MemAlloc(size + 1);
- JLI_StrCpy(appcp, "-Djava.class.path=");
- for (i = 0; i < cpathc; i++) {
- JLI_StrCat(appcp, home); /* c:\program files\myapp */
- JLI_StrCat(appcp, cpathv[i]); /* \lib\myapp.jar */
- JLI_StrCat(appcp, separator); /* ; */
- }
- appcp[JLI_StrLen(appcp)-1] = '\0'; /* remove trailing path separator */
- AddOption(appcp, NULL);
return JNI_TRUE;
}
--- a/jdk/src/java.base/share/native/libnet/net_util.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/native/libnet/net_util.c Thu Oct 27 21:22:57 2016 +0000
@@ -23,20 +23,19 @@
* questions.
*/
-#include "jni.h"
-#include "jvm.h"
-#include "jni_util.h"
#include "net_util.h"
-int IPv6_supported() ;
-int reuseport_supported() ;
+#include "java_net_InetAddress.h"
+
+int IPv6_supported();
+int reuseport_supported();
static int IPv6_available;
static int REUSEPORT_available;
JNIEXPORT jint JNICALL ipv6_available()
{
- return IPv6_available ;
+ return IPv6_available;
}
JNIEXPORT jint JNICALL reuseport_available()
@@ -206,11 +205,7 @@
jobject iaObj;
#ifdef AF_INET6
if (him->sa_family == AF_INET6) {
-#ifdef WIN32
- struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
-#else
struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
-#endif
jbyte *caddr = (jbyte *)&(him6->sin6_addr);
if (NET_IsIPv4Mapped(caddr)) {
int address;
@@ -218,7 +213,7 @@
CHECK_NULL_RETURN(iaObj, NULL);
address = NET_IPv4MappedToIPv4(caddr);
setInetAddress_addr(env, iaObj, address);
- setInetAddress_family(env, iaObj, IPv4);
+ setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);
} else {
jint scope;
jboolean ret;
@@ -227,7 +222,7 @@
ret = setInet6Address_ipaddress(env, iaObj, (char *)&(him6->sin6_addr));
if (ret == JNI_FALSE)
return NULL;
- setInetAddress_family(env, iaObj, IPv6);
+ setInetAddress_family(env, iaObj, java_net_InetAddress_IPv6);
scope = getScopeID(him);
setInet6Address_scopeid(env, iaObj, scope);
}
@@ -238,7 +233,7 @@
struct sockaddr_in *him4 = (struct sockaddr_in *)him;
iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
CHECK_NULL_RETURN(iaObj, NULL);
- setInetAddress_family(env, iaObj, IPv4);
+ setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);
setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr));
*port = ntohs(him4->sin_port);
}
@@ -251,13 +246,10 @@
jint family = AF_INET;
#ifdef AF_INET6
- family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
+ family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
+ AF_INET : AF_INET6;
if (him->sa_family == AF_INET6) {
-#ifdef WIN32
- struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
-#else
struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
-#endif
jbyte *caddrNew = (jbyte *)&(him6->sin6_addr);
if (NET_IsIPv4Mapped(caddrNew)) {
int addrNew;
--- a/jdk/src/java.base/share/native/libnet/net_util.h Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/share/native/libnet/net_util.h Thu Oct 27 21:22:57 2016 +0000
@@ -36,12 +36,6 @@
#define MAX_PACKET_LEN 65536
-#define IPv4 1
-#define IPv6 2
-
-#define NET_ERROR(env, ex, msg) \
-{ if (!(*env)->ExceptionOccurred(env)) JNU_ThrowByName(env, ex, msg); }
-
#define NET_WAIT_READ 0x01
#define NET_WAIT_WRITE 0x02
#define NET_WAIT_CONNECT 0x04
@@ -127,45 +121,43 @@
JNIEXPORT void JNICALL Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls);
JNIEXPORT void JNICALL NET_ThrowNew(JNIEnv *env, int errorNum, char *msg);
+
int NET_GetError();
void NET_ThrowCurrent(JNIEnv *env, char *msg);
jfieldID NET_GetFileDescriptorID(JNIEnv *env);
-JNIEXPORT jint JNICALL ipv6_available() ;
+JNIEXPORT jint JNICALL ipv6_available();
-JNIEXPORT jint JNICALL reuseport_available() ;
+JNIEXPORT jint JNICALL reuseport_available();
JNIEXPORT int JNICALL
-NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, int *len, jboolean v4MappedAddress);
+NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port,
+ struct sockaddr *him, int *len,
+ jboolean v4MappedAddress);
JNIEXPORT jobject JNICALL
NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port);
void platformInit();
+
void parseExclusiveBindProperty(JNIEnv *env);
-void
-NET_SetTrafficClass(struct sockaddr *him, int trafficClass);
+void NET_SetTrafficClass(struct sockaddr *him, int trafficClass);
-JNIEXPORT jint JNICALL
-NET_GetPortFromSockaddr(struct sockaddr *him);
+JNIEXPORT jint JNICALL NET_GetPortFromSockaddr(struct sockaddr *him);
JNIEXPORT jint JNICALL
NET_SockaddrEqualsInetAddress(JNIEnv *env,struct sockaddr *him, jobject iaObj);
-int
-NET_IsIPv4Mapped(jbyte* caddr);
+int NET_IsIPv4Mapped(jbyte* caddr);
-int
-NET_IPv4MappedToIPv4(jbyte* caddr);
+int NET_IPv4MappedToIPv4(jbyte* caddr);
-int
-NET_IsEqual(jbyte* caddr1, jbyte* caddr2);
+int NET_IsEqual(jbyte* caddr1, jbyte* caddr2);
-int
-NET_IsZeroAddr(jbyte* caddr);
+int NET_IsZeroAddr(jbyte* caddr);
/* Socket operations
*
@@ -191,9 +183,9 @@
JNIEXPORT jint JNICALL
NET_EnableFastTcpLoopback(int fd);
-int getScopeID (struct sockaddr *);
+int getScopeID(struct sockaddr *);
-int cmpScopeID (unsigned int, struct sockaddr *);
+int cmpScopeID(unsigned int, struct sockaddr *);
unsigned short in_cksum(unsigned short *addr, int len);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/unix/conf/s390x/jvm.cfg Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,34 @@
+# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# 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.
+#
+# List of JVMs that can be used as an option to java, javac, etc.
+# Order is important -- first in this list is the default JVM.
+# NOTE that this both this file and its format are UNSUPPORTED and
+# WILL GO AWAY in a future release.
+#
+# You may also select a JVM in an arbitrary location with the
+# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
+# and may not be available in a future release.
+#
+-server KNOWN
+-client IGNORE
--- a/jdk/src/java.base/unix/native/libnet/Inet4AddressImpl.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/Inet4AddressImpl.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,27 +22,17 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
+#include <ctype.h>
#include <errno.h>
-#include <sys/time.h>
#include <sys/types.h>
-#include <sys/socket.h>
+#include <netinet/in.h>
#include <netinet/in_systm.h>
-#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
-#include <netdb.h>
+#include <stdlib.h>
#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
+#include <sys/time.h>
-#ifdef _ALLBSD_SOURCE
-#include <unistd.h>
-#include <sys/param.h>
-#endif
-
-#include "jvm.h"
-#include "jni_util.h"
#include "net_util.h"
#include "java_net_Inet4AddressImpl.h"
@@ -293,13 +283,12 @@
addr |= ((caddr[2] <<8) & 0xff00);
addr |= (caddr[3] & 0xff);
memset((char *) &him4, 0, sizeof(him4));
- him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+ him4.sin_addr.s_addr = htonl(addr);
him4.sin_family = AF_INET;
sa = (struct sockaddr *) &him4;
len = sizeof(him4);
- error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
- NI_NAMEREQD);
+ error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
if (!error) {
ret = (*env)->NewStringUTF(env, host);
@@ -443,7 +432,7 @@
if (!skip) {
struct addrinfo *next
- = (struct addrinfo*) malloc(sizeof(struct addrinfo));
+ = (struct addrinfo *)malloc(sizeof(struct addrinfo));
if (!next) {
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
ret = NULL;
@@ -528,13 +517,12 @@
addr |= ((caddr[2] <<8) & 0xff00);
addr |= (caddr[3] & 0xff);
memset((void *) &him4, 0, sizeof(him4));
- him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+ him4.sin_addr.s_addr = htonl(addr);
him4.sin_family = AF_INET;
sa = (struct sockaddr *) &him4;
len = sizeof(him4);
- error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
- NI_NAMEREQD);
+ error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
if (!error) {
ret = (*env)->NewStringUTF(env, host);
--- a/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,29 +22,21 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
+#include <ctype.h>
#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
-#include <sys/socket.h>
#include <netinet/in.h>
-#include <netdb.h>
-#include <string.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <ctype.h>
-#ifdef MACOSX
+#include <netinet/icmp6.h>
+
+#if defined(_ALLBSD_SOURCE)
#include <ifaddrs.h>
#include <net/if.h>
-#include <unistd.h> /* gethostname */
#endif
-#include "jvm.h"
-#include "jni_util.h"
#include "net_util.h"
-#ifndef IPV6_DEFS_H
-#include <netinet/icmp6.h>
-#endif
#include "java_net_Inet4AddressImpl.h"
#include "java_net_Inet6AddressImpl.h"
@@ -504,24 +496,23 @@
addr |= ((caddr[2] <<8) & 0xff00);
addr |= (caddr[3] & 0xff);
memset((void *) &him4, 0, sizeof(him4));
- him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+ him4.sin_addr.s_addr = htonl(addr);
him4.sin_family = AF_INET;
- sa = (struct sockaddr *) &him4;
+ sa = (struct sockaddr *)&him4;
len = sizeof(him4);
} else {
/*
* For IPv6 address construct a sockaddr_in6 structure.
*/
(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
- memset((void *) &him6, 0, sizeof(him6));
- memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
+ memset((void *)&him6, 0, sizeof(him6));
+ memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr));
him6.sin6_family = AF_INET6;
- sa = (struct sockaddr *) &him6 ;
- len = sizeof(him6) ;
+ sa = (struct sockaddr *)&him6;
+ len = sizeof(him6);
}
- error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
- NI_NAMEREQD);
+ error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
if (!error) {
ret = (*env)->NewStringUTF(env, host);
--- a/jdk/src/java.base/unix/native/libnet/NetworkInterface.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/NetworkInterface.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,55 +22,36 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
+#include <arpa/inet.h>
#include <errno.h>
-#include <strings.h>
-#include <netinet/in.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_arp.h>
-
-#if defined(__solaris__)
-#include <sys/dlpi.h>
-#include <fcntl.h>
-#include <stropts.h>
-#include <sys/sockio.h>
-#endif
-
-#if defined(__linux__)
+#include <stdlib.h>
+#include <string.h>
#include <sys/ioctl.h>
-#include <sys/utsname.h>
-#include <stdio.h>
-#endif
#if defined(_AIX)
-#include <sys/ioctl.h>
#include <netinet/in6_var.h>
#include <sys/ndd_var.h>
#include <sys/kinfo.h>
#endif
-#if defined(_ALLBSD_SOURCE)
-#include <sys/param.h>
-#include <sys/ioctl.h>
+#if defined(__solaris__)
+#include <stropts.h>
+#include <sys/dlpi.h>
#include <sys/sockio.h>
-#if defined(__APPLE__)
+#endif
+
+#if defined(_ALLBSD_SOURCE)
#include <net/ethernet.h>
-#include <net/if_var.h>
#include <net/if_dl.h>
-#include <netinet/in_var.h>
#include <ifaddrs.h>
#endif
-#endif
-#include "jvm.h"
-#include "jni_util.h"
#include "net_util.h"
+#include "java_net_InetAddress.h"
+
#if defined(__linux__)
#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
#elif defined(__solaris__)
@@ -332,7 +313,7 @@
{
netif *ifs, *curr;
#if defined(AF_INET6)
- int family = (getInetAddress_family(env, iaObj) == IPv4) ? AF_INET : AF_INET6;
+ int family = (getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4) ? AF_INET : AF_INET6;
#else
int family = AF_INET;
#endif
--- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,29 +22,23 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
#include <errno.h>
-#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+#include <sys/ioctl.h>
-#ifdef __solaris__
-#include <fcntl.h>
-#include <unistd.h>
-#include <stropts.h>
+#if defined(__solaris__)
+#include <sys/filio.h>
+#endif
-#ifndef BSD_COMP
-#define BSD_COMP
-#endif
-#endif
+#include "net_util.h"
+
+#include "java_net_PlainDatagramSocketImpl.h"
+#include "java_net_InetAddress.h"
+#include "java_net_NetworkInterface.h"
+#include "java_net_SocketOptions.h"
+
#ifdef __linux__
-#include <unistd.h>
-#include <sys/sysctl.h>
-#include <sys/utsname.h>
-#include <netinet/ip.h>
-
#define IPV6_MULTICAST_IF 17
#ifndef SO_BSDCOMPAT
#define SO_BSDCOMPAT 14
@@ -58,7 +52,11 @@
#endif
#endif // __linux__
-#include <sys/ioctl.h>
+#ifdef __solaris__
+#ifndef BSD_COMP
+#define BSD_COMP
+#endif
+#endif
#ifndef IPTOS_TOS_MASK
#define IPTOS_TOS_MASK 0x1e
@@ -67,12 +65,6 @@
#define IPTOS_PREC_MASK 0xe0
#endif
-#include "jvm.h"
-#include "jni_util.h"
-#include "net_util.h"
-#include "java_net_SocketOptions.h"
-#include "java_net_PlainDatagramSocketImpl.h"
-#include "java_net_NetworkInterface.h"
/************************************************************************
* PlainDatagramSocketImpl
*/
@@ -151,9 +143,6 @@
JNIEXPORT void JNICALL
Java_java_net_PlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) {
-#ifdef __linux__
- struct utsname sysinfo;
-#endif
pdsi_fdID = (*env)->GetFieldID(env, cls, "fd",
"Ljava/io/FileDescriptor;");
CHECK_NULL(pdsi_fdID);
@@ -550,7 +539,8 @@
iaObj = NET_SockaddrToInetAddress(env, &rmtaddr.sa, &port);
#ifdef AF_INET6
- family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
+ family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
+ AF_INET : AF_INET6;
#else
family = AF_INET;
#endif
@@ -1071,7 +1061,7 @@
*/
for (i = 0; i < len; i++) {
addr = (*env)->GetObjectArrayElement(env, addrArray, i);
- if (getInetAddress_family(env, addr) == IPv4) {
+ if (getInetAddress_family(env, addr) == java_net_InetAddress_IPv4) {
in.s_addr = htonl(getInetAddress_addr(env, addr));
break;
}
@@ -1970,7 +1960,7 @@
ipv6_join_leave = ipv6_available();
#ifdef __linux__
- if (getInetAddress_family(env, iaObj) == IPv4) {
+ if (getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4) {
ipv6_join_leave = JNI_FALSE;
}
#endif
@@ -2162,7 +2152,8 @@
jbyte caddr[16];
jint family;
jint address;
- family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
+ family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
+ AF_INET : AF_INET6;
if (family == AF_INET) { /* will convert to IPv4-mapped address */
memset((char *) caddr, 0, 16);
address = getInetAddress_addr(env, iaObj);
--- a/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,32 +22,8 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#include <errno.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#if defined(__linux__)
-#include <sys/poll.h>
-#endif
-#include <netinet/tcp.h> /* Defines TCP_NODELAY, needed for 2.6 */
-#include <netinet/in.h>
-#ifdef __linux__
-#include <netinet/ip.h>
-#endif
-#include <netdb.h>
-#include <stdlib.h>
-
-#ifdef __solaris__
-#include <fcntl.h>
-#endif
-#ifdef __linux__
-#include <unistd.h>
-#include <sys/sysctl.h>
-#endif
-
-#include "jvm.h"
-#include "jni_util.h"
#include "net_util.h"
#include "java_net_SocketOptions.h"
--- a/jdk/src/java.base/unix/native/libnet/SocketInputStream.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/SocketInputStream.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,20 +22,15 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
+#include <errno.h>
#include <stdlib.h>
-#include <errno.h>
#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "jvm.h"
-#include "jni_util.h"
#include "net_util.h"
#include "java_net_SocketInputStream.h"
-/************************************************************************
+/*
* SocketInputStream
*/
--- a/jdk/src/java.base/unix/native/libnet/SocketOutputStream.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/SocketOutputStream.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,15 +22,10 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
+#include <errno.h>
#include <stdlib.h>
-#include <errno.h>
#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "jni_util.h"
-#include "jvm.h"
#include "net_util.h"
#include "java_net_SocketOutputStream.h"
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,60 +22,42 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
+#include <dlfcn.h>
#include <errno.h>
+#include <net/if.h>
+#include <netinet/tcp.h> // defines TCP_NODELAY
+#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/tcp.h> /* Defines TCP_NODELAY, needed for 2.6 */
-#include <netinet/in.h>
-#include <net/if.h>
-#include <netdb.h>
-#include <stdlib.h>
-#include <dlfcn.h>
+#include <sys/ioctl.h>
#include <sys/time.h>
-#ifndef _ALLBSD_SOURCE
-#include <values.h>
-#else
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/sysctl.h>
-#include <sys/ioctl.h>
-#ifndef MAXINT
-#define MAXINT INT_MAX
-#endif
-#endif
-
-#ifdef __solaris__
-#include <sys/filio.h>
-#include <sys/sockio.h>
-#include <stropts.h>
-#include <inet/nd.h>
-#endif
-
-#ifdef __linux__
-#include <sys/ioctl.h>
+#if defined(__linux__)
#include <arpa/inet.h>
#include <net/route.h>
#include <sys/utsname.h>
+#endif
-#ifndef IPV6_FLOWINFO_SEND
+#if defined(__solaris__)
+#include <inet/nd.h>
+#include <limits.h>
+#include <stropts.h>
+#include <sys/filio.h>
+#include <sys/sockio.h>
+#endif
+
+#include "net_util.h"
+
+#include "java_net_SocketOptions.h"
+#include "java_net_InetAddress.h"
+
+#if defined(__linux__) && !defined(IPV6_FLOWINFO_SEND)
#define IPV6_FLOWINFO_SEND 33
#endif
-#endif
-
-#ifdef _AIX
-#include <sys/ioctl.h>
+#if defined(__solaris__) && !defined(MAXINT)
+#define MAXINT INT_MAX
#endif
-#include "jni_util.h"
-#include "jvm.h"
-#include "net_util.h"
-
-#include "java_net_SocketOptions.h"
-
/*
* EXCLBIND socket options only on Solaris
*/
@@ -806,13 +788,15 @@
family = getInetAddress_family(env, iaObj);
#ifdef AF_INET6
/* needs work. 1. family 2. clean up him6 etc deallocate memory */
- if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) {
+ if (ipv6_available() && !(family == java_net_InetAddress_IPv4 &&
+ v4MappedAddress == JNI_FALSE)) {
struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
jbyte caddr[16];
jint address;
- if (family == IPv4) { /* will convert to IPv4-mapped address */
+ if (family == java_net_InetAddress_IPv4) {
+ // convert to IPv4-mapped address
memset((char *) caddr, 0, 16);
address = getInetAddress_addr(env, iaObj);
if (address == INADDR_ANY) {
@@ -906,7 +890,7 @@
#else
/* handle scope_id for solaris */
- if (family != IPv4) {
+ if (family != java_net_InetAddress_IPv4) {
if (ia6_scopeidID) {
him6->sin6_scope_id = getInet6Address_scopeid(env, iaObj);
}
@@ -917,14 +901,14 @@
{
struct sockaddr_in *him4 = (struct sockaddr_in*)him;
jint address;
- if (family == IPv6) {
+ if (family == java_net_InetAddress_IPv6) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");
return -1;
}
memset((char *) him4, 0, sizeof(struct sockaddr_in));
address = getInetAddress_addr(env, iaObj);
him4->sin_port = htons((short) port);
- him4->sin_addr.s_addr = (uint32_t) htonl(address);
+ him4->sin_addr.s_addr = htonl(address);
him4->sin_family = AF_INET;
*len = sizeof(struct sockaddr_in);
}
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.h Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h Thu Oct 27 21:22:57 2016 +0000
@@ -26,13 +26,9 @@
#ifndef NET_UTILS_MD_H
#define NET_UTILS_MD_H
+#include <netdb.h>
+#include <sys/poll.h>
#include <sys/socket.h>
-#include <sys/types.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <unistd.h>
-
-#include <sys/poll.h>
int NET_Timeout(int s, long timeout);
int NET_Timeout0(int s, long timeout, long currentTime);
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,10 +22,8 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-#include <windows.h>
-#include <winsock2.h>
-#include "jni.h"
#include "net_util.h"
+
#include "java_net_DualStackPlainDatagramSocketImpl.h"
/*
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,11 +22,10 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-#include <windows.h>
-#include <winsock2.h>
-#include "jni.h"
#include "net_util.h"
+
#include "java_net_DualStackPlainSocketImpl.h"
+#include "java_net_SocketOptions.h"
#define SET_BLOCKING 0
#define SET_NONBLOCKING 1
--- a/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* 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,24 +22,12 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#include <malloc.h>
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
-#include <process.h>
-#include <iphlpapi.h>
-#include <icmpapi.h>
-#include <WinError.h>
+#include "net_util.h"
#include "java_net_InetAddress.h"
#include "java_net_Inet4AddressImpl.h"
-#include "net_util.h"
-#include "icmp.h"
-
/*
* Returns true if hostname is in dotted IP address format. Note that this
--- a/jdk/src/java.base/windows/native/libnet/Inet6AddressImpl.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/Inet6AddressImpl.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,38 +22,13 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#include <malloc.h>
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
-#include <process.h>
-#include <iphlpapi.h>
-#include <icmpapi.h>
+#include "net_util.h"
#include "java_net_InetAddress.h"
#include "java_net_Inet4AddressImpl.h"
#include "java_net_Inet6AddressImpl.h"
-#include "net_util.h"
-#include "icmp.h"
-
-#ifdef WIN32
-#ifndef _WIN64
-
-/* Retain this code a little longer to support building in
- * old environments. _MSC_VER is defined as:
- * 1200 for MSVC++ 6.0
- * 1310 for Vc7
- */
-#if defined(_MSC_VER) && _MSC_VER < 1310
-#define sockaddr_in6 SOCKADDR_IN6
-#endif
-#endif
-#define uint32_t UINT32
-#endif
/*
* Inet6AddressImpl
@@ -300,7 +275,7 @@
addr |= ((caddr[2] <<8) & 0xff00);
addr |= (caddr[3] & 0xff);
memset((char *) &him4, 0, sizeof(him4));
- him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+ him4.sin_addr.s_addr = htonl(addr);
him4.sin_family = AF_INET;
sa = (struct sockaddr *) &him4;
len = sizeof(him4);
--- a/jdk/src/java.base/windows/native/libnet/NetworkInterface.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/NetworkInterface.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,17 +22,10 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
-#include <stdlib.h>
-#include <windows.h>
-#include <winsock2.h> /* needed for htonl */
-#include <iprtrmib.h>
-#include <assert.h>
+#include "net_util.h"
+#include "NetworkInterface.h"
#include "java_net_NetworkInterface.h"
-#include "jni_util.h"
-
-#include "NetworkInterface.h"
/*
* Windows implementation of the java.net.NetworkInterface native methods.
--- a/jdk/src/java.base/windows/native/libnet/NetworkInterface.h Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/NetworkInterface.h Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
#ifndef NETWORK_INTERFACE_H
#define NETWORK_INTERFACE_H
-#include <iphlpapi.h>
#include "net_util.h"
/*
--- a/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,19 +22,10 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
-#include <stdlib.h>
-#include <windows.h>
-#include <winsock2.h> /* needed for htonl */
-#include <iprtrmib.h>
-#include <assert.h>
-#include <limits.h>
+#include "net_util.h"
+#include "NetworkInterface.h"
#include "java_net_NetworkInterface.h"
-#include "jni_util.h"
-
-#include "NetworkInterface.h"
-#include "net_util.h"
/*
* Windows implementation of the java.net.NetworkInterface native methods.
--- a/jdk/src/java.base/windows/native/libnet/SocketInputStream.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/SocketInputStream.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,24 +22,15 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#include <malloc.h>
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
+#include "net_util.h"
#include "java_net_SocketInputStream.h"
-#include "net_util.h"
-#include "jni_util.h"
-
/*************************************************************************
* SocketInputStream
*/
-
static jfieldID IO_fd_fdID;
/*
--- a/jdk/src/java.base/windows/native/libnet/SocketOutputStream.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/SocketOutputStream.c Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* 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,20 +22,12 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#include <malloc.h>
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
+#include "net_util.h"
#include "java_net_SocketOutputStream.h"
-#include "net_util.h"
-#include "jni_util.h"
-
/************************************************************************
* SocketOutputStream
*/
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,15 +22,15 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#include <malloc.h>
-#include <windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
+#include "net_util.h"
+#include "NetworkInterface.h"
+
+#include "java_net_TwoStacksPlainDatagramSocketImpl.h"
+#include "java_net_SocketOptions.h"
+#include "java_net_NetworkInterface.h"
+#include "java_net_InetAddress.h"
#ifndef IPTOS_TOS_MASK
#define IPTOS_TOS_MASK 0x1e
@@ -39,14 +39,6 @@
#define IPTOS_PREC_MASK 0xe0
#endif
-#include "java_net_TwoStacksPlainDatagramSocketImpl.h"
-#include "java_net_SocketOptions.h"
-#include "java_net_NetworkInterface.h"
-
-#include "NetworkInterface.h"
-#include "jvm.h"
-#include "jni_util.h"
-#include "net_util.h"
#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000)
#define IN_MULTICAST(i) IN_CLASSD(i)
@@ -439,7 +431,7 @@
memset((char *)&lcladdr, 0, sizeof(lcladdr));
family = getInetAddress_family(env, addressObj);
- if (family == IPv6 && !ipv6_supported) {
+ if (family == java_net_InetAddress_IPv6 && !ipv6_supported) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported");
return;
@@ -561,13 +553,13 @@
addr = getInetAddress_addr(env, address);
family = getInetAddress_family(env, address);
- if (family == IPv6 && !ipv6_supported) {
+ if (family == java_net_InetAddress_IPv6 && !ipv6_supported) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported");
return;
}
- fdc = family == IPv4? fd: fd1;
+ fdc = family == java_net_InetAddress_IPv4 ? fd : fd1;
if (xp_or_later) {
/* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which
@@ -605,12 +597,12 @@
jint fd, len;
SOCKETADDRESS addr;
- if (family == IPv4) {
+ if (family == java_net_InetAddress_IPv4) {
fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
- len = sizeof (struct sockaddr_in);
+ len = sizeof(struct sockaddr_in);
} else {
fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
- len = sizeof (struct SOCKADDR_IN6);
+ len = sizeof(struct sockaddr_in6);
}
if (IS_NULL(fdObj)) {
@@ -678,7 +670,7 @@
}
family = getInetAddress_family(env, iaObj);
- if (family == IPv4) {
+ if (family == java_net_InetAddress_IPv4) {
fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
} else {
if (!ipv6_available()) {
@@ -906,7 +898,7 @@
return 0;
}
setInetAddress_addr(env, addressObj, ntohl(remote_addr.sa4.sin_addr.s_addr));
- setInetAddress_family(env, addressObj, IPv4);
+ setInetAddress_family(env, addressObj, java_net_InetAddress_IPv4);
/* return port */
return ntohs(remote_addr.sa4.sin_port);
@@ -1610,7 +1602,7 @@
{
jobject addr;
- int ret = getInetAddrFromIf (env, IPv4, nif, &addr);
+ int ret = getInetAddrFromIf(env, java_net_InetAddress_IPv4, nif, &addr);
if (ret == -1) {
return -1;
}
@@ -2285,9 +2277,9 @@
len = sizeof(struct sockaddr_in);
/* family==-1 when socket is not connected */
- if ((family == IPv6) || (family == -1 && fd == -1)) {
+ if ((family == java_net_InetAddress_IPv6) || (family == -1 && fd == -1)) {
fd = fd1; /* must be IPv6 only */
- len = sizeof (struct SOCKADDR_IN6);
+ len = sizeof(struct sockaddr_in6);
}
if (fd == -1) {
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,23 +22,13 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <malloc.h>
-#include <sys/types.h>
-
-#include "java_net_SocketOptions.h"
-#include "java_net_TwoStacksPlainSocketImpl.h"
-#include "java_net_InetAddress.h"
-#include "java_io_FileDescriptor.h"
-#include "java_lang_Integer.h"
#include "net_util.h"
-#include "jni_util.h"
+
+#include "java_net_TwoStacksPlainSocketImpl.h"
+#include "java_net_SocketOptions.h"
+#include "java_net_InetAddress.h"
/************************************************************************
* TwoStacksPlainSocketImpl
@@ -413,7 +403,7 @@
family = getInetAddress_family(env, iaObj);
- if (family == IPv6 && !ipv6_supported) {
+ if (family == java_net_InetAddress_IPv6 && !ipv6_supported) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported");
return;
@@ -655,18 +645,18 @@
return;
}
if (fd2 == fd) { /* v4 */
- len = sizeof (struct sockaddr_in);
+ len = sizeof(struct sockaddr_in);
} else {
- len = sizeof (struct SOCKADDR_IN6);
+ len = sizeof(struct sockaddr_in6);
}
fd = fd2;
} else {
int ret;
if (fd1 != -1) {
fd = fd1;
- len = sizeof (struct SOCKADDR_IN6);
+ len = sizeof(struct sockaddr_in6);
} else {
- len = sizeof (struct sockaddr_in);
+ len = sizeof(struct sockaddr_in);
}
if (timeout) {
ret = NET_Timeout(fd, timeout);
@@ -728,7 +718,7 @@
}
setInetAddress_addr(env, socketAddressObj, ntohl(him.sa4.sin_addr.s_addr));
- setInetAddress_family(env, socketAddressObj, IPv4);
+ setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv4);
(*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
} else {
/* AF_INET6 -> Inet6Address */
@@ -754,7 +744,7 @@
return;
}
setInet6Address_ipaddress(env, socketAddressObj, (char *)&him.sa6.sin6_addr);
- setInetAddress_family(env, socketAddressObj, IPv6);
+ setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv6);
setInet6Address_scopeid(env, socketAddressObj, him.sa6.sin6_scope_id);
}
--- a/jdk/src/java.base/windows/native/libnet/icmp.h Thu Oct 27 16:29:00 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * 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
- * 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.
- */
-
-#ifndef ICMP_H
-#define ICMP_H
-
-/*
- * Structure of an internet header, naked of options.
- *
- * We declare ip_len and ip_off to be short, rather than ushort_t
- * pragmatically since otherwise unsigned comparisons can result
- * against negative integers quite easily, and fail in subtle ways.
- */
-struct ip {
- unsigned char ip_hl:4, /* header length */
- ip_v:4; /* version */
- unsigned char ip_tos; /* type of service */
- short ip_len; /* total length */
- unsigned short ip_id; /* identification */
- short ip_off; /* fragment offset field */
-#define IP_DF 0x4000 /* don't fragment flag */
-#define IP_MF 0x2000 /* more fragments flag */
- unsigned char ip_ttl; /* time to live */
- unsigned char ip_p; /* protocol */
- unsigned short ip_sum; /* checksum */
- struct in_addr ip_src, ip_dst; /* source and dest address */
-};
-
-/*
- * Structure of an icmp header.
- */
-struct icmp {
- unsigned char icmp_type; /* type of message, see below */
- unsigned char icmp_code; /* type sub code */
- unsigned short icmp_cksum; /* ones complement cksum of struct */
- union {
- unsigned char ih_pptr; /* ICMP_PARAMPROB */
- struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
- struct ih_idseq {
- unsigned short icd_id;
- unsigned short icd_seq;
- } ih_idseq;
- int ih_void;
-
- /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
- struct ih_pmtu {
- unsigned short ipm_void;
- unsigned short ipm_nextmtu;
- } ih_pmtu;
-
- struct ih_rtradv {
- unsigned char irt_num_addrs;
- unsigned char irt_wpa;
- unsigned short irt_lifetime;
- } ih_rtradv;
- } icmp_hun;
-#define icmp_pptr icmp_hun.ih_pptr
-#define icmp_gwaddr icmp_hun.ih_gwaddr
-#define icmp_id icmp_hun.ih_idseq.icd_id
-#define icmp_seq icmp_hun.ih_idseq.icd_seq
-#define icmp_void icmp_hun.ih_void
-#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
-#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
- union {
- struct id_ts {
- unsigned int its_otime;
- unsigned int its_rtime;
- unsigned int its_ttime;
- } id_ts;
- struct id_ip {
- struct ip idi_ip;
- /* options and then 64 bits of data */
- } id_ip;
- unsigned int id_mask;
- char id_data[1];
- } icmp_dun;
-#define icmp_otime icmp_dun.id_ts.its_otime
-#define icmp_rtime icmp_dun.id_ts.its_rtime
-#define icmp_ttime icmp_dun.id_ts.its_ttime
-#define icmp_ip icmp_dun.id_ip.idi_ip
-#define icmp_mask icmp_dun.id_mask
-#define icmp_data icmp_dun.id_data
-};
-
-#define ICMP_ECHOREPLY 0 /* echo reply */
-#define ICMP_ECHO 8 /* echo service */
-
-/*
- * ICMPv6 structures & constants
- */
-
-typedef struct icmp6_hdr {
- u_char icmp6_type; /* type field */
- u_char icmp6_code; /* code field */
- u_short icmp6_cksum; /* checksum field */
- union {
- u_int icmp6_un_data32[1]; /* type-specific field */
- u_short icmp6_un_data16[2]; /* type-specific field */
- u_char icmp6_un_data8[4]; /* type-specific field */
- } icmp6_dataun;
-} icmp6_t;
-
-#define icmp6_data32 icmp6_dataun.icmp6_un_data32
-#define icmp6_data16 icmp6_dataun.icmp6_un_data16
-#define icmp6_data8 icmp6_dataun.icmp6_un_data8
-#define icmp6_pptr icmp6_data32[0] /* parameter prob */
-#define icmp6_mtu icmp6_data32[0] /* packet too big */
-#define icmp6_id icmp6_data16[0] /* echo request/reply */
-#define icmp6_seq icmp6_data16[1] /* echo request/reply */
-#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */
-
-struct ip6_pseudo_hdr /* for calculate the ICMPv6 checksum */
-{
- struct in6_addr ip6_src;
- struct in6_addr ip6_dst;
- u_int ip6_plen;
- u_int ip6_nxt;
-};
-
-#define ICMP6_ECHO_REQUEST 128
-#define ICMP6_ECHO_REPLY 129
-#define IPPROTO_ICMPV6 58
-#define IPV6_UNICAST_HOPS 4 /* Set/get IP unicast hop limit */
-
-
-#endif
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c Thu Oct 27 21:22:57 2016 +0000
@@ -22,12 +22,10 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#include "net_util.h"
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-#include "net_util.h"
-#include "jni.h"
+#include "java_net_InetAddress.h"
+#include "java_net_SocketOptions.h"
// Taken from mstcpip.h in Windows SDK 8.0 or newer.
#define SIO_LOOPBACK_FAST_PATH _WSAIOW(IOC_VENDOR,16)
@@ -593,7 +591,7 @@
void dumpAddr (char *str, void *addr) {
- struct SOCKADDR_IN6 *a = (struct SOCKADDR_IN6 *)addr;
+ struct sockaddr_in6 *a = (struct sockaddr_in6 *)addr;
int family = a->sin6_family;
printf ("%s\n", str);
if (family == AF_INET) {
@@ -812,7 +810,7 @@
* 0 if error
* > 0 interface index to use
*/
-jint getDefaultIPv6Interface(JNIEnv *env, struct SOCKADDR_IN6 *target_addr)
+jint getDefaultIPv6Interface(JNIEnv *env, struct sockaddr_in6 *target_addr)
{
int ret;
DWORD b;
@@ -866,9 +864,9 @@
int *len, jboolean v4MappedAddress) {
jint family, iafam;
iafam = getInetAddress_family(env, iaObj);
- family = (iafam == IPv4)? AF_INET : AF_INET6;
+ family = (iafam == java_net_InetAddress_IPv4)? AF_INET : AF_INET6;
if (ipv6_available() && !(family == AF_INET && v4MappedAddress == JNI_FALSE)) {
- struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
+ struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
jbyte caddr[16];
jint address, scopeid = 0;
jint cached_scope_id = 0;
@@ -894,7 +892,7 @@
cached_scope_id = (jint)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID);
}
- memset((char *)him6, 0, sizeof(struct SOCKADDR_IN6));
+ memset((char *)him6, 0, sizeof(struct sockaddr_in6));
him6->sin6_port = (u_short) htons((u_short)port);
memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );
him6->sin6_family = AF_INET6;
@@ -904,7 +902,7 @@
(*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
}
him6->sin6_scope_id = scopeid != 0 ? scopeid : cached_scope_id;
- *len = sizeof(struct SOCKADDR_IN6) ;
+ *len = sizeof(struct sockaddr_in6) ;
} else {
struct sockaddr_in *him4 = (struct sockaddr_in *)him;
jint address;
@@ -964,12 +962,12 @@
}
int getScopeID(struct sockaddr *him) {
- struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
+ struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
return him6->sin6_scope_id;
}
int cmpScopeID(unsigned int scope, struct sockaddr *him) {
- struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
+ struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
return him6->sin6_scope_id == scope;
}
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.h Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.h Thu Oct 27 21:22:57 2016 +0000
@@ -22,195 +22,10 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
#include <winsock2.h>
#include <WS2tcpip.h>
-
-/* typedefs that were defined correctly for the first time
- * in Nov. 2001 SDK, which we need to include here.
- * Specifically, in6_addr and sockaddr_in6 (which is defined but
- * not correctly). When moving to a later SDK remove following
- * code between START and END
- */
-
-/* --- START --- */
-
-/* WIN64 already uses newer SDK */
-#ifdef _WIN64
-
-#define SOCKADDR_IN6 sockaddr_in6
-
-#else
-
-#ifdef _MSC_VER
-#define WS2TCPIP_INLINE __inline
-#else
-#define WS2TCPIP_INLINE extern inline /* GNU style */
-#endif
-
-#if defined(_MSC_VER) && _MSC_VER >= 1310
-
-#define SOCKADDR_IN6 sockaddr_in6
-
-#else
-
-/*SO_REUSEPORT is not supported on Windows, define it to 0*/
-#define SO_REUSEPORT 0
-
-/* Retain this code a little longer to support building in
- * old environments. _MSC_VER is defined as:
- * 1200 for MSVC++ 6.0
- * 1310 for Vc7
- */
-
-#define IPPROTO_IPV6 41
-#define IPV6_MULTICAST_IF 9
-
-struct in6_addr {
- union {
- u_char Byte[16];
- u_short Word[8];
- } u;
-};
-
-/*
-** Defines to match RFC 2553.
-*/
-#define _S6_un u
-#define _S6_u8 Byte
-#define s6_addr _S6_un._S6_u8
-
-/*
-** Defines for our implementation.
-*/
-#define s6_bytes u.Byte
-#define s6_words u.Word
-
-/* IPv6 socket address structure, RFC 2553 */
-
-struct SOCKADDR_IN6 {
- short sin6_family; /* AF_INET6 */
- u_short sin6_port; /* Transport level port number */
- u_long sin6_flowinfo; /* IPv6 flow information */
- struct in6_addr sin6_addr; /* IPv6 address */
- u_long sin6_scope_id; /* set of interfaces for a scope */
-};
-
-
-/* Error codes from getaddrinfo() */
-
-#define EAI_AGAIN WSATRY_AGAIN
-#define EAI_BADFLAGS WSAEINVAL
-#define EAI_FAIL WSANO_RECOVERY
-#define EAI_FAMILY WSAEAFNOSUPPORT
-#define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY
-//#define EAI_NODATA WSANO_DATA
-#define EAI_NONAME WSAHOST_NOT_FOUND
-#define EAI_SERVICE WSATYPE_NOT_FOUND
-#define EAI_SOCKTYPE WSAESOCKTNOSUPPORT
-
-#define EAI_NODATA EAI_NONAME
-
-/* Structure used in getaddrinfo() call */
-
-typedef struct addrinfo {
- int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
- int ai_family; /* PF_xxx */
- int ai_socktype; /* SOCK_xxx */
- int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
- size_t ai_addrlen; /* Length of ai_addr */
- char *ai_canonname; /* Canonical name for nodename */
- struct sockaddr *ai_addr; /* Binary address */
- struct addrinfo *ai_next; /* Next structure in linked list */
-} ADDRINFO, FAR * LPADDRINFO;
-
-/* Flags used in "hints" argument to getaddrinfo() */
-
-#define AI_PASSIVE 0x1 /* Socket address will be used in bind() call */
-#define AI_CANONNAME 0x2 /* Return canonical name in first ai_canonname */
-#define AI_NUMERICHOST 0x4 /* Nodename must be a numeric address string */
-
-/* IPv6 Multicasting definitions */
-
-/* Argument structure for IPV6_JOIN_GROUP and IPV6_LEAVE_GROUP */
-
-typedef struct ipv6_mreq {
- struct in6_addr ipv6mr_multiaddr; /* IPv6 multicast address */
- unsigned int ipv6mr_interface; /* Interface index */
-} IPV6_MREQ;
-
-#define IPV6_ADD_MEMBERSHIP 12 /* Add an IP group membership */
-#define IPV6_DROP_MEMBERSHIP 13 /* Drop an IP group membership */
-#define IPV6_MULTICAST_LOOP 11 /* Set/get IP multicast loopback */
-
-WS2TCPIP_INLINE int
-IN6_IS_ADDR_MULTICAST(const struct in6_addr *a)
-{
- return (a->s6_bytes[0] == 0xff);
-}
-
-WS2TCPIP_INLINE int
-IN6_IS_ADDR_LINKLOCAL(const struct in6_addr *a)
-{
- return (a->s6_bytes[0] == 0xfe
- && a->s6_bytes[1] == 0x80);
-}
-
-#define NI_MAXHOST 1025 /* Max size of a fully-qualified domain name */
-#define NI_MAXSERV 32 /* Max size of a service name */
-
-#define INET_ADDRSTRLEN 16 /* Max size of numeric form of IPv4 address */
-#define INET6_ADDRSTRLEN 46 /* Max size of numeric form of IPv6 address */
-
-/* Flags for getnameinfo() */
-
-#define NI_NOFQDN 0x01 /* Only return nodename portion for local hosts */
-#define NI_NUMERICHOST 0x02 /* Return numeric form of the host's address */
-#define NI_NAMEREQD 0x04 /* Error if the host's name not in DNS */
-#define NI_NUMERICSERV 0x08 /* Return numeric form of the service (port #) */
-#define NI_DGRAM 0x10 /* Service is a datagram service */
-
-
-#define IN6_IS_ADDR_V4MAPPED(a) \
- (((a)->s6_words[0] == 0) && ((a)->s6_words[1] == 0) && \
- ((a)->s6_words[2] == 0) && ((a)->s6_words[3] == 0) && \
- ((a)->s6_words[4] == 0) && ((a)->s6_words[5] == 0xffff))
-
-
-/* --- END --- */
-#endif /* end 'else older build environment' */
-
-#endif
-
-#if !INCL_WINSOCK_API_TYPEDEFS
-
-typedef
-int
-(WSAAPI * LPFN_GETADDRINFO)(
- IN const char FAR * nodename,
- IN const char FAR * servname,
- IN const struct addrinfo FAR * hints,
- OUT struct addrinfo FAR * FAR * res
- );
-
-typedef
-void
-(WSAAPI * LPFN_FREEADDRINFO)(
- IN struct addrinfo FAR * ai
- );
-
-typedef
-int
-(WSAAPI * LPFN_GETNAMEINFO)(
- IN const struct sockaddr FAR * sa,
- IN int salen,
- OUT char FAR * host,
- IN DWORD hostlen,
- OUT char FAR * serv,
- IN DWORD servlen,
- IN int flags
- );
-#endif
+#include <iphlpapi.h>
+#include <icmpapi.h>
/* used to disable connection reset messages on Windows XP */
#ifndef SIO_UDP_CONNRESET
@@ -229,13 +44,9 @@
#define IPV6_V6ONLY 27 /* Treat wildcard bind as AF_INET6-only. */
#endif
-#include "java_io_FileDescriptor.h"
-#include "java_net_SocketOptions.h"
-
#define MAX_BUFFER_LEN 2048
#define MAX_HEAP_BUFFER_LEN 65536
-
/* true if SO_RCVTIMEO is supported by underlying provider */
extern jboolean isRcvTimeoutSupported;
@@ -249,7 +60,7 @@
typedef union {
struct sockaddr sa;
struct sockaddr_in sa4;
- struct SOCKADDR_IN6 sa6;
+ struct sockaddr_in6 sa6;
} SOCKETADDRESS;
/*
@@ -264,7 +75,7 @@
#define SOCKETADDRESS_COPY(DST,SRC) { \
if ((SRC)->sa_family == AF_INET6) { \
- memcpy ((DST), (SRC), sizeof (struct SOCKADDR_IN6)); \
+ memcpy ((DST), (SRC), sizeof (struct sockaddr_in6)); \
} else { \
memcpy ((DST), (SRC), sizeof (struct sockaddr_in)); \
} \
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java Thu Oct 27 21:22:57 2016 +0000
@@ -29,11 +29,9 @@
import java.awt.*;
import java.beans.*;
-import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.Callable;
-import sun.awt.AWTAccessor;
import javax.accessibility.*;
import javax.swing.*;
@@ -73,8 +71,20 @@
}
public void propertyChange(final PropertyChangeEvent evt) {
- if (evt.getNewValue() == null) return;
- focusChanged();
+ Object newValue = evt.getNewValue();
+ if (newValue == null) return;
+ // Don't post focus on things that don't matter, i.e. alert, colorchooser,
+ // desktoppane, dialog, directorypane, filechooser, filler, fontchoose,
+ // frame, glasspane, layeredpane, optionpane, panel, rootpane, separator,
+ // tooltip, viewport, window.
+ // List taken from initializeRoles() in JavaComponentUtilities.m.
+ if (newValue instanceof Accessible) {
+ AccessibleContext nvAC = ((Accessible) newValue).getAccessibleContext();
+ AccessibleRole nvRole = nvAC.getAccessibleRole();
+ if (!ignoredRoles.contains(roleKey(nvRole))) {
+ focusChanged();
+ }
+ }
}
private native void focusChanged();
@@ -683,9 +693,15 @@
if (context == null) continue;
if (whichChildren == JAVA_AX_VISIBLE_CHILDREN) {
- if (!context.getAccessibleComponent().isVisible()) continue;
+ AccessibleComponent acomp = context.getAccessibleComponent();
+ if (acomp == null || !acomp.isVisible()) {
+ continue;
+ }
} else if (whichChildren == JAVA_AX_SELECTED_CHILDREN) {
- if (!ac.getAccessibleSelection().isAccessibleChildSelected(i)) continue;
+ AccessibleSelection sel = ac.getAccessibleSelection();
+ if (sel == null || !sel.isAccessibleChildSelected(i)) {
+ continue;
+ }
}
if (!allowIgnored) {
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java Thu Oct 27 21:22:57 2016 +0000
@@ -39,7 +39,10 @@
import static javax.accessibility.AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY;
import static javax.accessibility.AccessibleContext.ACCESSIBLE_CARET_PROPERTY;
import static javax.accessibility.AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY;
+import static javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY;
import static javax.accessibility.AccessibleContext.ACCESSIBLE_TEXT_PROPERTY;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
import sun.awt.AWTAccessor;
@@ -63,6 +66,9 @@
private static native void valueChanged(long ptr);
private static native void selectedTextChanged(long ptr);
private static native void selectionChanged(long ptr);
+ private static native void menuOpened(long ptr);
+ private static native void menuClosed(long ptr);
+ private static native void menuItemSelected(long ptr);
private Accessible accessible;
@@ -111,16 +117,45 @@
public void propertyChange(PropertyChangeEvent e) {
String name = e.getPropertyName();
if ( ptr != 0 ) {
+ Object newValue = e.getNewValue();
+ Object oldValue = e.getOldValue();
if (name.compareTo(ACCESSIBLE_CARET_PROPERTY) == 0) {
selectedTextChanged(ptr);
} else if (name.compareTo(ACCESSIBLE_TEXT_PROPERTY) == 0 ) {
valueChanged(ptr);
} else if (name.compareTo(ACCESSIBLE_SELECTION_PROPERTY) == 0 ) {
selectionChanged(ptr);
- } else if (name.compareTo(ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY) == 0 ) {
- Object nv = e.getNewValue();
- if (nv instanceof AccessibleContext) {
- activeDescendant = (AccessibleContext)nv;
+ } else if (name.compareTo(ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY) == 0 ) {
+ if (newValue instanceof AccessibleContext) {
+ activeDescendant = (AccessibleContext)newValue;
+ }
+ } else if (name.compareTo(ACCESSIBLE_STATE_PROPERTY) == 0) {
+ AccessibleContext thisAC = accessible.getAccessibleContext();
+ AccessibleRole thisRole = thisAC.getAccessibleRole();
+ Accessible parentAccessible = thisAC.getAccessibleParent();
+ AccessibleRole parentRole = null;
+ if (parentAccessible != null) {
+ parentRole = parentAccessible.getAccessibleContext().getAccessibleRole();
+ }
+ // At least for now don't handle combo box menu state changes.
+ // This may change when later fixing issues which currently
+ // exist for combo boxes, but for now the following is only
+ // for JPopupMenus, not for combobox menus.
+ if (parentRole != AccessibleRole.COMBO_BOX) {
+ if (thisRole == AccessibleRole.POPUP_MENU) {
+ if ( newValue != null &&
+ ((AccessibleState)newValue) == AccessibleState.VISIBLE ) {
+ menuOpened(ptr);
+ } else if ( oldValue != null &&
+ ((AccessibleState)oldValue) == AccessibleState.VISIBLE ) {
+ menuClosed(ptr);
+ }
+ } else if (thisRole == AccessibleRole.MENU_ITEM) {
+ if ( newValue != null &&
+ ((AccessibleState)newValue) == AccessibleState.FOCUSED ) {
+ menuItemSelected(ptr);
+ }
+ }
}
}
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Thu Oct 27 21:22:57 2016 +0000
@@ -97,7 +97,7 @@
int absY = locationOnScreen.y + y;
responder.handleScrollEvent(x, y, absX, absY, modifierFlags, deltaX,
- deltaY);
+ deltaY, NSEvent.SCROLL_PHASE_UNSUPPORTED);
}
public void handleKeyEvent(int eventType, int modifierFlags, String characters,
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java Thu Oct 27 21:22:57 2016 +0000
@@ -44,6 +44,8 @@
private final PlatformEventNotifier eventNotifier;
private final boolean isNpapiCallback;
private int lastKeyPressCode = KeyEvent.VK_UNDEFINED;
+ private final DeltaAccumulator deltaAccumulatorX = new DeltaAccumulator();
+ private final DeltaAccumulator deltaAccumulatorY = new DeltaAccumulator();
CPlatformResponder(final PlatformEventNotifier eventNotifier,
final boolean isNpapiCallback) {
@@ -89,37 +91,37 @@
*/
void handleScrollEvent(final int x, final int y, final int absX,
final int absY, final int modifierFlags,
- final double deltaX, final double deltaY) {
+ final double deltaX, final double deltaY,
+ final int scrollPhase) {
int jmodifiers = NSEvent.nsToJavaModifiers(modifierFlags);
final boolean isShift = (jmodifiers & InputEvent.SHIFT_DOWN_MASK) != 0;
+ int roundDeltaX = deltaAccumulatorX.getRoundedDelta(deltaX, scrollPhase);
+ int roundDeltaY = deltaAccumulatorY.getRoundedDelta(deltaY, scrollPhase);
+
// Vertical scroll.
- if (!isShift && deltaY != 0.0) {
- dispatchScrollEvent(x, y, absX, absY, jmodifiers, deltaY);
+ if (!isShift && (deltaY != 0.0 || roundDeltaY != 0)) {
+ dispatchScrollEvent(x, y, absX, absY, jmodifiers, roundDeltaY, deltaY);
}
// Horizontal scroll or shirt+vertical scroll.
final double delta = isShift && deltaY != 0.0 ? deltaY : deltaX;
- if (delta != 0.0) {
+ final int roundDelta = isShift && roundDeltaY != 0 ? roundDeltaY : roundDeltaX;
+ if (delta != 0.0 || roundDelta != 0) {
jmodifiers |= InputEvent.SHIFT_DOWN_MASK;
- dispatchScrollEvent(x, y, absX, absY, jmodifiers, delta);
+ dispatchScrollEvent(x, y, absX, absY, jmodifiers, roundDelta, delta);
}
}
private void dispatchScrollEvent(final int x, final int y, final int absX,
final int absY, final int modifiers,
- final double delta) {
+ final int roundDelta, final double delta) {
final long when = System.currentTimeMillis();
final int scrollType = MouseWheelEvent.WHEEL_UNIT_SCROLL;
final int scrollAmount = 1;
- int wheelRotation = (int) delta;
- int signum = (int) Math.signum(delta);
- if (signum * delta < 1) {
- wheelRotation = signum;
- }
// invert the wheelRotation for the peer
eventNotifier.notifyMouseWheelEvent(when, x, y, absX, absY, modifiers,
scrollType, scrollAmount,
- -wheelRotation, -delta, null);
+ -roundDelta, -delta, null);
}
/**
@@ -260,4 +262,46 @@
void handleWindowFocusEvent(boolean gained, LWWindowPeer opposite) {
eventNotifier.notifyActivation(gained, opposite);
}
+
+ static class DeltaAccumulator {
+
+ static final double MIN_THRESHOLD = 0.1;
+ static final double MAX_THRESHOLD = 0.5;
+ double accumulatedDelta;
+
+ int getRoundedDelta(double delta, int scrollPhase) {
+
+ int roundDelta = (int) Math.round(delta);
+
+ if (scrollPhase == NSEvent.SCROLL_PHASE_UNSUPPORTED) { // mouse wheel
+ if (roundDelta == 0 && delta != 0) {
+ roundDelta = delta > 0 ? 1 : -1;
+ }
+ } else { // trackpad
+ boolean begin = scrollPhase == NSEvent.SCROLL_PHASE_BEGAN;
+ boolean end = scrollPhase == NSEvent.SCROLL_MASK_PHASE_ENDED
+ || scrollPhase == NSEvent.SCROLL_MASK_PHASE_CANCELLED;
+
+ if (begin) {
+ accumulatedDelta = 0;
+ }
+
+ accumulatedDelta += delta;
+
+ double absAccumulatedDelta = Math.abs(accumulatedDelta);
+ if (absAccumulatedDelta > MAX_THRESHOLD) {
+ roundDelta = (int) Math.round(accumulatedDelta);
+ accumulatedDelta -= roundDelta;
+ }
+
+ if (end) {
+ if (roundDelta == 0 && absAccumulatedDelta > MIN_THRESHOLD) {
+ roundDelta = accumulatedDelta > 0 ? 1 : -1;
+ }
+ }
+ }
+
+ return roundDelta;
+ }
+ }
}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformView.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformView.java Thu Oct 27 21:22:57 2016 +0000
@@ -194,7 +194,8 @@
if (event.getType() == CocoaConstants.NSScrollWheel) {
responder.handleScrollEvent(x, y, absX, absY, event.getModifierFlags(),
- event.getScrollDeltaX(), event.getScrollDeltaY());
+ event.getScrollDeltaX(), event.getScrollDeltaY(),
+ event.getScrollPhase());
} else {
responder.handleMouseEvent(event.getType(), event.getModifierFlags(), event.getButtonNumber(),
event.getClickCount(), x, y,
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java Thu Oct 27 21:22:57 2016 +0000
@@ -32,6 +32,13 @@
* JDK functionality.
*/
final class NSEvent {
+
+ static final int SCROLL_PHASE_UNSUPPORTED = 1;
+ static final int SCROLL_PHASE_BEGAN = 2;
+ static final int SCROLL_PHASE_CONTINUED = 3;
+ static final int SCROLL_MASK_PHASE_CANCELLED = 4;
+ static final int SCROLL_MASK_PHASE_ENDED = 5;
+
private int type;
private int modifierFlags;
@@ -42,6 +49,7 @@
private int y;
private double scrollDeltaY;
private double scrollDeltaX;
+ private int scrollPhase;
private int absX;
private int absY;
@@ -62,7 +70,7 @@
// Called from native
NSEvent(int type, int modifierFlags, int clickCount, int buttonNumber,
int x, int y, int absX, int absY,
- double scrollDeltaY, double scrollDeltaX) {
+ double scrollDeltaY, double scrollDeltaX, int scrollPhase) {
this.type = type;
this.modifierFlags = modifierFlags;
this.clickCount = clickCount;
@@ -73,6 +81,7 @@
this.absY = absY;
this.scrollDeltaY = scrollDeltaY;
this.scrollDeltaX = scrollDeltaX;
+ this.scrollPhase = scrollPhase;
}
int getType() {
@@ -107,6 +116,10 @@
return scrollDeltaX;
}
+ int getScrollPhase() {
+ return scrollPhase;
+ }
+
int getAbsX() {
return absX;
}
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m Thu Oct 27 21:22:57 2016 +0000
@@ -383,7 +383,7 @@
}
static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/NSEvent");
- static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDD)V");
+ static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDDI)V");
jobject jEvent = JNFNewObject(env, jctor_NSEvent,
[event type],
[event modifierFlags],
@@ -392,7 +392,8 @@
(jint)localPoint.x, (jint)localPoint.y,
(jint)absP.x, (jint)absP.y,
[event deltaY],
- [event deltaX]);
+ [event deltaX],
+ [AWTToolkit scrollStateWithEvent: event]);
CHECK_NULL(jEvent);
static JNF_CLASS_CACHE(jc_PlatformView, "sun/lwawt/macosx/CPlatformView");
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m Thu Oct 27 21:22:57 2016 +0000
@@ -317,7 +317,7 @@
[self setPropertiesForStyleBits:styleBits mask:MASK(_METHOD_PROP_BITMASK)];
if (IS(self.styleBits, IS_POPUP)) {
- [self.nsWindow setCollectionBehavior:(1 << 8) /*NSWindowCollectionBehaviorFullScreenAuxiliary*/];
+ [self.nsWindow setCollectionBehavior:(1 << 8) /*NSWindowCollectionBehaviorFullScreenAuxiliary*/];
}
return self;
@@ -330,7 +330,7 @@
// returns id for the topmost window under mouse
+ (NSInteger) getTopmostWindowUnderMouseID {
NSInteger result = -1;
-
+
NSRect screenRect = [[NSScreen mainScreen] frame];
NSPoint nsMouseLocation = [NSEvent mouseLocation];
CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y);
@@ -433,18 +433,18 @@
// Tests wheather the corresponding Java paltform window is visible or not
+ (BOOL) isJavaPlatformWindowVisible:(NSWindow *)window {
BOOL isVisible = NO;
-
+
if ([AWTWindow isAWTWindow:window] && [window delegate] != nil) {
AWTWindow *awtWindow = (AWTWindow *)[window delegate];
[AWTToolkit eventCountPlusPlus];
-
+
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject platformWindow = [awtWindow.javaPlatformWindow jObjectWithEnv:env];
if (platformWindow != NULL) {
static JNF_MEMBER_CACHE(jm_isVisible, jc_CPlatformWindow, "isVisible", "()Z");
isVisible = JNFCallBooleanMethod(env, platformWindow, jm_isVisible) == JNI_TRUE ? YES : NO;
(*env)->DeleteLocalRef(env, platformWindow);
-
+
}
}
return isVisible;
@@ -577,7 +577,9 @@
- (NSRect)windowWillUseStandardFrame:(NSWindow *)window
defaultFrame:(NSRect)newFrame {
- return [self standardFrame];
+ return NSEqualSizes(NSZeroSize, [self standardFrame].size)
+ ? newFrame
+ : [self standardFrame];
}
// Hides/shows window's childs during iconify/de-iconify operation
@@ -1085,17 +1087,17 @@
jdouble width, jdouble height)
{
JNF_COCOA_ENTER(env);
-
+
NSRect jrect = NSMakeRect(originX, originY, width, height);
-
+
NSWindow *nsWindow = OBJC(windowPtr);
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
-
+
NSRect rect = ConvertNSScreenRect(NULL, jrect);
AWTWindow *window = (AWTWindow*)[nsWindow delegate];
window.standardFrame = rect;
}];
-
+
JNF_COCOA_EXIT(env);
}
@@ -1366,7 +1368,7 @@
} else {
[JNFException raise:env as:kIllegalArgumentException reason:"unknown event type"];
}
-
+
JNF_COCOA_EXIT(env);
}
@@ -1476,7 +1478,7 @@
if (CGDisplayRelease(aID) == kCGErrorSuccess) {
NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:window.styleBits];
- [nsWindow setStyleMask:styleMask];
+ [nsWindow setStyleMask:styleMask];
[nsWindow setLevel: window.preFullScreenLevel];
// GraphicsDevice takes care of restoring pre full screen bounds
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobotKeyCode.m Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobotKeyCode.m Thu Oct 27 21:22:57 2016 +0000
@@ -45,7 +45,7 @@
self = [super init];
if (nil != self) {
- javaToMacKeyMap = [NSDictionary dictionaryWithObjectsAndKeys :
+ self.javaToMacKeyMap = [NSDictionary dictionaryWithObjectsAndKeys :
[NSNumber numberWithInt : OSX_Delete], [NSNumber numberWithInt : java_awt_event_KeyEvent_VK_BACK_SPACE],
[NSNumber numberWithInt : OSX_kVK_Tab], [NSNumber numberWithInt : java_awt_event_KeyEvent_VK_TAB],
[NSNumber numberWithInt : OSX_kVK_Return], [NSNumber numberWithInt : java_awt_event_KeyEvent_VK_ENTER],
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m Thu Oct 27 21:22:57 2016 +0000
@@ -139,9 +139,9 @@
jint clickCount;
clickCount = [event clickCount];
-
+
static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/NSEvent");
- static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDD)V");
+ static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDDI)V");
jobject jEvent = JNFNewObject(env, jctor_NSEvent,
[event type],
[event modifierFlags],
@@ -150,7 +150,8 @@
(jint)localPoint.x, (jint)localPoint.y,
(jint)absP.x, (jint)absP.y,
[event deltaY],
- [event deltaX]);
+ [event deltaX],
+ [AWTToolkit scrollStateWithEvent: event]);
CHECK_NULL(jEvent);
static JNF_CLASS_CACHE(jc_TrayIcon, "sun/lwawt/macosx/CTrayIcon");
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m Thu Oct 27 21:22:57 2016 +0000
@@ -66,7 +66,6 @@
static JNF_MEMBER_CACHE(jf_ptr, sjc_CAccessible, "ptr", "J");
static JNF_STATIC_MEMBER_CACHE(sjm_getCAccessible, sjc_CAccessible, "getCAccessible", "(Ljavax/accessibility/Accessible;)Lsun/lwawt/macosx/CAccessible;");
-
static jobject sAccessibilityClass = NULL;
// sAttributeNamesForRoleCache holds the names of the attributes to which each java
@@ -213,6 +212,24 @@
NSAccessibilityPostNotification(self, NSAccessibilitySelectedChildrenChangedNotification);
}
+- (void)postMenuOpened
+{
+ AWT_ASSERT_APPKIT_THREAD;
+ NSAccessibilityPostNotification(self, (NSString *)kAXMenuOpenedNotification);
+}
+
+- (void)postMenuClosed
+{
+ AWT_ASSERT_APPKIT_THREAD;
+ NSAccessibilityPostNotification(self, (NSString *)kAXMenuClosedNotification);
+}
+
+- (void)postMenuItemSelected
+{
+ AWT_ASSERT_APPKIT_THREAD;
+ NSAccessibilityPostNotification(self, (NSString *)kAXMenuItemSelectedNotification);
+}
+
- (BOOL)isEqual:(id)anObject
{
if (![anObject isKindOfClass:[self class]]) return NO;
@@ -278,8 +295,7 @@
+ (jobject) getCAccessible:(jobject)jaccessible withEnv:(JNIEnv *)env {
if (JNFIsInstanceOf(env, jaccessible, &sjc_CAccessible)) {
return jaccessible;
- }
- else if (JNFIsInstanceOf(env, jaccessible, &sjc_Accessible)) {
+ } else if (JNFIsInstanceOf(env, jaccessible, &sjc_Accessible)) {
return JNFCallStaticObjectMethod(env, sjm_getCAccessible, jaccessible);
}
return NULL;
@@ -368,6 +384,14 @@
// must init freshly -alloc'd object
[newChild initWithParent:parent withEnv:env withAccessible:jCAX withIndex:index withView:view withJavaRole:javaRole]; // must init new instance
+ // If creating a JPopupMenu (not a combobox popup list) need to fire menuOpened.
+ // This is the only way to know if the menu is opening; visible state change
+ // can't be caught because the listeners are not set up in time.
+ if ( [javaRole isEqualToString:@"popupmenu"] &&
+ ![[parent javaRole] isEqualToString:@"combobox"] ) {
+ [newChild postMenuOpened];
+ }
+
// must hard retain pointer poked into Java object
[newChild retain];
JNFSetLongField(env, jCAX, jf_ptr, ptr_to_jlong(newChild));
@@ -634,6 +658,15 @@
return moreNames;
}
}
+ // popupmenu's return values not selected children
+ if ( [javaRole isEqualToString:@"popupmenu"] &&
+ ![[[self parent] javaRole] isEqualToString:@"combobox"] ) {
+ NSMutableArray *moreNames =
+ [[NSMutableArray alloc] initWithCapacity: [names count] + 1];
+ [moreNames addObjectsFromArray: names];
+ [moreNames addObject:NSAccessibilityValueAttribute];
+ return moreNames;
+ }
return names;
} // end @synchronized
@@ -707,6 +740,7 @@
return value;
}
+
- (BOOL)accessibilityIsChildrenAttributeSettable
{
return NO;
@@ -939,6 +973,13 @@
if (fNSRole == nil) {
NSString *javaRole = [self javaRole];
fNSRole = [sRoles objectForKey:javaRole];
+ // The sRoles NSMutableDictionary maps popupmenu to Mac's popup button.
+ // JComboBox behavior currently relies on this. However this is not the
+ // proper mapping for a JPopupMenu so fix that.
+ if ( [javaRole isEqualToString:@"popupmenu"] &&
+ ![[[self parent] javaRole] isEqualToString:@"combobox"] ) {
+ fNSRole = NSAccessibilityMenuRole;
+ }
if (fNSRole == nil) {
// this component has assigned itself a custom AccessibleRole not in the sRoles array
fNSRole = javaRole;
@@ -947,6 +988,7 @@
}
return fNSRole;
}
+
- (BOOL)accessibilityIsRoleAttributeSettable
{
return NO;
@@ -1046,8 +1088,7 @@
- (NSString *)accessibilitySubroleAttribute
{
NSString *value = nil;
- if ([[self javaRole] isEqualToString:@"passwordtext"])
- {
+ if ([[self javaRole] isEqualToString:@"passwordtext"]) {
value = NSAccessibilitySecureTextFieldSubrole;
}
/*
@@ -1123,6 +1164,45 @@
JNIEnv* env = [ThreadUtilities getJNIEnv];
+ // Need to handle popupmenus differently.
+ //
+ // At least for now don't handle combo box menus.
+ // This may change when later fixing issues which currently
+ // exist for combo boxes, but for now the following is only
+ // for JPopupMenus, not for combobox menus.
+ id parent = [self parent];
+ if ( [[self javaRole] isEqualToString:@"popupmenu"] &&
+ ![[parent javaRole] isEqualToString:@"combobox"] ) {
+ NSArray *children =
+ [JavaComponentAccessibility childrenOfParent:self
+ withEnv:env
+ withChildrenCode:JAVA_AX_ALL_CHILDREN
+ allowIgnored:YES];
+ if ([children count] > 0) {
+ // handle case of AXMenuItem
+ // need to ask menu what is selected
+ NSArray *selectedChildrenOfMenu =
+ [self accessibilitySelectedChildrenAttribute];
+ JavaComponentAccessibility *selectedMenuItem =
+ [selectedChildrenOfMenu objectAtIndex:0];
+ if (selectedMenuItem != nil) {
+ jobject itemValue =
+ JNFCallStaticObjectMethod( env,
+ sjm_getAccessibleName,
+ selectedMenuItem->fAccessible,
+ selectedMenuItem->fComponent ); // AWT_THREADING Safe (AWTRunLoop)
+ if (itemValue == NULL) {
+ return nil;
+ }
+ NSString* itemString = JNFJavaToNSString(env, itemValue);
+ (*env)->DeleteLocalRef(env, itemValue);
+ return itemString;
+ } else {
+ return nil;
+ }
+ }
+ }
+
// ask Java for the component's accessibleValue. In java, the "accessibleValue" just means a numerical value
// a text value is taken care of in JavaTextAccessibility
@@ -1345,6 +1425,54 @@
/*
* Class: sun_lwawt_macosx_CAccessible
+ * Method: menuOpened
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_menuOpened
+(JNIEnv *env, jclass jklass, jlong element)
+{
+JNF_COCOA_ENTER(env);
+ [ThreadUtilities performOnMainThread:@selector(postMenuOpened)
+ on:(JavaComponentAccessibility *)jlong_to_ptr(element)
+ withObject:nil
+ waitUntilDone:NO];
+JNF_COCOA_EXIT(env);
+}
+
+/*
+ * Class: sun_lwawt_macosx_CAccessible
+ * Method: menuClosed
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_menuClosed
+(JNIEnv *env, jclass jklass, jlong element)
+{
+JNF_COCOA_ENTER(env);
+ [ThreadUtilities performOnMainThread:@selector(postMenuClosed)
+ on:(JavaComponentAccessibility *)jlong_to_ptr(element)
+ withObject:nil
+ waitUntilDone:NO];
+JNF_COCOA_EXIT(env);
+}
+
+/*
+ * Class: sun_lwawt_macosx_CAccessible
+ * Method: menuItemSelected
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_menuItemSelected
+(JNIEnv *env, jclass jklass, jlong element)
+{
+JNF_COCOA_ENTER(env);
+ [ThreadUtilities performOnMainThread:@selector(postMenuItemSelected)
+ on:(JavaComponentAccessibility *)jlong_to_ptr(element)
+ withObject:nil
+ waitUntilDone:NO];
+JNF_COCOA_EXIT(env);
+}
+
+/*
+ * Class: sun_lwawt_macosx_CAccessible
* Method: unregisterFromCocoaAXSystem
* Signature: (I)V
*/
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.h Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.h Thu Oct 27 21:22:57 2016 +0000
@@ -41,6 +41,7 @@
@interface AWTToolkit : NSObject { }
+ (long) getEventCount;
+ (void) eventCountPlusPlus;
++ (jint) scrollStateWithEvent: (NSEvent*) event;
@end
/*
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m Thu Oct 27 21:22:57 2016 +0000
@@ -43,6 +43,13 @@
#import <JavaRuntimeSupport/JavaRuntimeSupport.h>
+// SCROLL PHASE STATE
+#define SCROLL_PHASE_UNSUPPORTED 1
+#define SCROLL_PHASE_BEGAN 2
+#define SCROLL_PHASE_CONTINUED 3
+#define SCROLL_PHASE_CANCELLED 4
+#define SCROLL_PHASE_ENDED 5
+
int gNumberOfButtons;
jint* gButtonDownMasks;
@@ -72,6 +79,23 @@
eventCount++;
}
++ (jint) scrollStateWithEvent: (NSEvent*) event {
+
+ if ([event type] != NSScrollWheel) {
+ return 0;
+ }
+
+ NSEventPhase phase = [event phase];
+ NSEventPhase momentumPhase = [event momentumPhase];
+
+ if (!phase && !momentumPhase) return SCROLL_PHASE_UNSUPPORTED;
+ switch (phase) {
+ case NSEventPhaseBegan: return SCROLL_PHASE_BEGAN;
+ case NSEventPhaseCancelled: return SCROLL_PHASE_CANCELLED;
+ case NSEventPhaseEnded: return SCROLL_PHASE_ENDED;
+ default: return SCROLL_PHASE_CONTINUED;
+ }
+}
@end
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m Thu Oct 27 21:22:57 2016 +0000
@@ -193,6 +193,44 @@
return [sFontFamilyTable objectForKey:fontname];
}
+static void addFont(CTFontUIFontType uiType,
+ NSMutableArray *allFonts,
+ NSMutableDictionary* fontFamilyTable) {
+
+ CTFontRef font = CTFontCreateUIFontForLanguage(uiType, 0.0, NULL);
+ if (font == NULL) {
+ return;
+ }
+ CTFontDescriptorRef desc = CTFontCopyFontDescriptor(font);
+ if (desc == NULL) {
+ CFRelease(font);
+ return;
+ }
+ CFStringRef family = CTFontDescriptorCopyAttribute(desc, kCTFontFamilyNameAttribute);
+ if (family == NULL) {
+ CFRelease(desc);
+ CFRelease(font);
+ return;
+ }
+ CFStringRef name = CTFontDescriptorCopyAttribute(desc, kCTFontNameAttribute);
+ if (name == NULL) {
+ CFRelease(family);
+ CFRelease(desc);
+ CFRelease(font);
+ return;
+ }
+ [allFonts addObject:name];
+ [fontFamilyTable setObject:family forKey:name];
+#ifdef DEBUG
+ NSLog(@"name is : %@", (NSString*)name);
+ NSLog(@"family is : %@", (NSString*)family);
+#endif
+ CFRelease(family);
+ CFRelease(name);
+ CFRelease(desc);
+ CFRelease(font);
+}
+
static NSArray*
GetFilteredFonts()
{
@@ -227,6 +265,16 @@
}
}
+ /*
+ * JavaFX registers these fonts and so JDK needs to do so as well.
+ * If this isn't done we will have mis-matched rendering, since
+ * although these may include fonts that are enumerated normally
+ * they also demonstrably includes fonts that are not.
+ */
+ addFont(kCTFontUIFontSystem, allFonts, fontFamilyTable);
+ addFont(kCTFontUIFontEmphasizedSystem, allFonts, fontFamilyTable);
+ addFont(kCTFontUIFontUserFixedPitch, allFonts, fontFamilyTable);
+
sFilteredFonts = allFonts;
sFontFamilyTable = fontFamilyTable;
}
--- a/jdk/src/java.desktop/macosx/native/libsplashscreen/splashscreen_sys.m Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/macosx/native/libsplashscreen/splashscreen_sys.m Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,6 +47,10 @@
#include <sizecalc.h>
#import "ThreadUtilities.h"
+NSString* findScaledImageName(NSString *fileName,
+ NSUInteger dotIndex,
+ NSString *strToAppend);
+
static NSScreen* SplashNSScreen()
{
return [[NSScreen screens] objectAtIndex: 0];
@@ -134,8 +138,8 @@
}
jboolean SplashGetScaledImageName(const char* jar, const char* file,
- float *scaleFactor, char *scaledFile,
- const size_t scaledImageLength) {
+ float *scaleFactor, char *scaledFile,
+ const size_t scaledImageLength) {
*scaleFactor = 1;
if(isSWTRunning()){
@@ -158,18 +162,14 @@
options:NSBackwardsSearch];
NSUInteger dotIndex = range.location;
NSString *fileName2x = nil;
-
- if (dotIndex == NSNotFound) {
- fileName2x = [fileName stringByAppendingString: @"@2x"];
- } else {
- fileName2x = [fileName substringToIndex: dotIndex];
- fileName2x = [fileName2x stringByAppendingString: @"@2x"];
- fileName2x = [fileName2x stringByAppendingString:
- [fileName substringFromIndex: dotIndex]];
+
+ fileName2x = findScaledImageName(fileName, dotIndex, @"@2x");
+ if(![[NSFileManager defaultManager]
+ fileExistsAtPath: fileName2x]) {
+ fileName2x = findScaledImageName(fileName, dotIndex, @"@200pct");
}
-
- if ((fileName2x != nil) && (jar || [[NSFileManager defaultManager]
- fileExistsAtPath: fileName2x])){
+ if (jar || [[NSFileManager defaultManager]
+ fileExistsAtPath: fileName2x]){
if (strlen([fileName2x UTF8String]) > scaledImageLength) {
[pool drain];
return JNI_FALSE;
@@ -458,3 +458,16 @@
sendctl(splash, SPLASHCTL_RECONFIGURE);
}
+NSString* findScaledImageName(NSString *fileName, NSUInteger dotIndex, NSString *strToAppend) {
+ NSString *fileName2x = nil;
+ if (dotIndex == NSNotFound) {
+ fileName2x = [fileName stringByAppendingString: strToAppend];
+ } else {
+ fileName2x = [fileName substringToIndex: dotIndex];
+ fileName2x = [fileName2x stringByAppendingString: strToAppend];
+ fileName2x = [fileName2x stringByAppendingString:
+ [fileName substringFromIndex: dotIndex]];
+ }
+ return fileName2x;
+}
+
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java Thu Oct 27 21:22:57 2016 +0000
@@ -1314,7 +1314,7 @@
super(locale);
this.canWriteCompressed = true;
this.canWriteProgressive = true;
- this.compressionTypes = new String[] {"LZW", "lzw"};
+ this.compressionTypes = new String[] {"LZW"};
this.compressionType = compressionTypes[0];
}
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifComboBoxUI.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifComboBoxUI.java Thu Oct 27 21:22:57 2016 +0000
@@ -298,31 +298,24 @@
public void paintIcon(Component c, Graphics g, int xo, int yo) {
int w = getIconWidth();
int h = getIconHeight();
-
- g.setColor(lightShadow);
- g.drawLine(xo, yo, xo+w-1, yo);
- g.drawLine(xo, yo+1, xo+w-3, yo+1);
- g.setColor(darkShadow);
- g.drawLine(xo+w-2, yo+1, xo+w-1, yo+1);
+ int x1 = xo + w - 1;
+ int y1 = yo;
+ int x2 = xo + w / 2;
+ int y2 = yo + h - 1;
- for ( int x = xo+1, y = yo+2, dx = w-6; y+1 < yo+h; y += 2 ) {
- g.setColor(lightShadow);
- g.drawLine(x, y, x+1, y);
- g.drawLine(x, y+1, x+1, y+1);
- if ( dx > 0 ) {
- g.setColor(fill);
- g.drawLine(x+2, y, x+1+dx, y);
- g.drawLine(x+2, y+1, x+1+dx, y+1);
- }
- g.setColor(darkShadow);
- g.drawLine(x+dx+2, y, x+dx+3, y);
- g.drawLine(x+dx+2, y+1, x+dx+3, y+1);
- x += 1;
- dx -= 2;
- }
+ g.setColor(fill);
+ g.fillPolygon(new int[]{xo, x1, x2}, new int[]{yo, y1, y2}, 3);
+ g.setColor(lightShadow);
+ g.drawLine(xo, yo, x1, y1);
+ g.drawLine(xo, yo + 1, x2, y2);
+ g.drawLine(xo, yo + 1, x1, y1 + 1);
+ g.drawLine(xo + 1, yo + 1, x2, y2 - 1);
g.setColor(darkShadow);
- g.drawLine(xo+(w/2), yo+h-1, xo+(w/2), yo+h-1);
+ g.drawLine(x1, y1 + 1, x2, y2);
+ g.drawLine(x1 - 1, y1 + 1, x2, y2 - 1);
+ g.drawLine(x1 - 1, y1 + 1, x1, y1 + 1); // corner
+ g.drawLine(x2, y2, x2, y2); // corner
}
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifIconFactory.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifIconFactory.java Thu Oct 27 21:22:57 2016 +0000
@@ -249,17 +249,11 @@
if (check) {
// draw check
g.setColor(foreground);
- g.drawLine(csize-2,1,csize-2,2);
- g.drawLine(csize-3,2,csize-3,3);
- g.drawLine(csize-4,3,csize-4,4);
- g.drawLine(csize-5,4,csize-5,6);
- g.drawLine(csize-6,5,csize-6,8);
- g.drawLine(csize-7,6,csize-7,10);
- g.drawLine(csize-8,7,csize-8,10);
- g.drawLine(csize-9,6,csize-9,9);
- g.drawLine(csize-10,5,csize-10,8);
- g.drawLine(csize-11,5,csize-11,7);
- g.drawLine(csize-12,6,csize-12,6);
+ int[] xa = {csize - 12, csize - 8, csize - 7, csize - 4,
+ csize - 2, csize - 2, csize - 8, csize - 10,
+ csize - 11};
+ int[] ya = new int[]{6, 10, 10, 4, 2, 1, 7, 5, 5};
+ g.fillPolygon(xa, ya, 9);
}
g.translate(-x, -y);
g.setColor(oldColor);
@@ -301,50 +295,18 @@
if (checkIn){
g.setColor(shadow);
- g.drawLine(x+5,y+0,x+8,y+0);
- g.drawLine(x+3,y+1,x+4,y+1);
- g.drawLine(x+9,y+1,x+9,y+1);
- g.drawLine(x+2,y+2,x+2,y+2);
- g.drawLine(x+1,y+3,x+1,y+3);
- g.drawLine(x,y+4,x,y+9);
- g.drawLine(x+1,y+10,x+1,y+10);
- g.drawLine(x+2,y+11,x+2,y+11);
+ g.drawArc(x, y, w - 1, h - 1, 45, 180);
g.setColor(highlight);
- g.drawLine(x+3,y+12,x+4,y+12);
- g.drawLine(x+5,y+13,x+8,y+13);
- g.drawLine(x+9,y+12,x+10,y+12);
- g.drawLine(x+11,y+11,x+11,y+11);
- g.drawLine(x+12,y+10,x+12,y+10);
- g.drawLine(x+13,y+9,x+13,y+4);
- g.drawLine(x+12,y+3,x+12,y+3);
- g.drawLine(x+11,y+2,x+11,y+2);
- g.drawLine(x+10,y+1,x+10,y+1);
+ g.drawArc(x, y, w - 1, h - 1, 45, -180);
g.setColor(dot);
- g.fillRect(x+4,y+5,6,4);
- g.drawLine(x+5,y+4,x+8,y+4);
- g.drawLine(x+5,y+9,x+8,y+9);
+ g.fillOval(x + 3, y + 3, 7, 7);
}
else {
g.setColor(highlight);
- g.drawLine(x+5,y+0,x+8,y+0);
- g.drawLine(x+3,y+1,x+4,y+1);
- g.drawLine(x+9,y+1,x+9,y+1);
- g.drawLine(x+2,y+2,x+2,y+2);
- g.drawLine(x+1,y+3,x+1,y+3);
- g.drawLine(x,y+4,x,y+9);
- g.drawLine(x+1,y+10,x+1,y+10);
- g.drawLine(x+2,y+11,x+2,y+11);
+ g.drawArc(x, y, w - 1, h - 1, 45, 180);
g.setColor(shadow);
- g.drawLine(x+3,y+12,x+4,y+12);
- g.drawLine(x+5,y+13,x+8,y+13);
- g.drawLine(x+9,y+12,x+10,y+12);
- g.drawLine(x+11,y+11,x+11,y+11);
- g.drawLine(x+12,y+10,x+12,y+10);
- g.drawLine(x+13,y+9,x+13,y+4);
- g.drawLine(x+12,y+3,x+12,y+3);
- g.drawLine(x+11,y+2,x+11,y+2);
- g.drawLine(x+10,y+1,x+10,y+1);
+ g.drawArc(x, y, w - 1, h - 1, 45, -180);
}
}
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifScrollBarButton.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifScrollBarButton.java Thu Oct 27 21:22:57 2016 +0000
@@ -117,95 +117,57 @@
switch (direction) {
case NORTH:
+ g.setColor(fill);
+ g.fillPolygon(new int[]{cx, 0, s - 1}, new int[]{0, s - 1, s - 1}, 3);
+ g.setColor(trail);
+ g.drawLine(cx, 0, s - 1, s - 2);
+ g.drawLine(0, s - 1, s - 1, s - 1);
+ g.drawLine(s - 1, s - 2, s - 1, s - 1); // corner
g.setColor(lead);
- g.drawLine(cx, 0, cx, 0);
- for (int x = cx - 1, y = 1, dx = 1; y <= s - 2; y += 2) {
- g.setColor(lead);
- g.drawLine(x, y, x, y);
- if (y >= (s - 2)) {
- g.drawLine(x, y + 1, x, y + 1);
- }
- g.setColor(fill);
- g.drawLine(x + 1, y, x + dx, y);
- if (y < (s - 2)) {
- g.drawLine(x, y + 1, x + dx + 1, y + 1);
- }
- g.setColor(trail);
- g.drawLine(x + dx + 1, y, x + dx + 1, y);
- if (y >= (s - 2)) {
- g.drawLine(x + 1, y + 1, x + dx + 1, y + 1);
- }
- dx += 2;
- x -= 1;
- }
+ g.drawLine(cx, 0, 0, s - 2);
+ g.drawLine(cx, 0, cx, 0); // corner
+ g.drawLine(0, s - 1, 0, s - 1); // corner
break;
case SOUTH:
+ g.setColor(fill);
+ g.fillPolygon(new int[]{0, s - 1, cx}, new int[]{1, 1, s}, 3);
g.setColor(trail);
- g.drawLine(cx, s, cx, s);
- for (int x = cx - 1, y = s - 1, dx = 1; y >= 1; y -= 2) {
- g.setColor(lead);
- g.drawLine(x, y, x, y);
- if (y <= 2) {
- g.drawLine(x, y - 1, x + dx + 1, y - 1);
- }
- g.setColor(fill);
- g.drawLine(x + 1, y, x + dx, y);
- if (y > 2) {
- g.drawLine(x, y - 1, x + dx + 1, y - 1);
- }
- g.setColor(trail);
- g.drawLine(x + dx + 1, y, x + dx + 1, y);
-
- dx += 2;
- x -= 1;
- }
+ g.drawLine(s - 1, 2, cx, s);
+ g.drawLine(s - 1, 2, s - 1, 2); // corner
+ g.setColor(lead);
+ g.drawLine(0, 2, cx, s);
+ g.drawLine(0, 1, s - 1, 1);
+ g.drawLine(0, 1, 0, 2);
+ g.setColor(trail);
+ g.drawLine(cx, s, cx, s); // corner
break;
case EAST:
+ g.setColor(fill);
+ g.fillPolygon(new int[]{1, s, 1}, new int[]{0, cy, s}, 3);
+ g.setColor(trail);
+ g.drawLine(1, s, s, cy);
+ g.drawLine(2, s, 2, s); // corner
g.setColor(lead);
+ g.drawLine(1, 0, 1, s);
+ g.drawLine(2, 0, s, cy);
+ g.drawLine(2, 0, 2, 0); // corner
g.drawLine(s, cy, s, cy);
- for (int y = cy - 1, x = s - 1, dy = 1; x >= 1; x -= 2) {
- g.setColor(lead);
- g.drawLine(x, y, x, y);
- if (x <= 2) {
- g.drawLine(x - 1, y, x - 1, y + dy + 1);
- }
- g.setColor(fill);
- g.drawLine(x, y + 1, x, y + dy);
- if (x > 2) {
- g.drawLine(x - 1, y, x - 1, y + dy + 1);
- }
- g.setColor(trail);
- g.drawLine(x, y + dy + 1, x, y + dy + 1);
-
- dy += 2;
- y -= 1;
- }
break;
case WEST:
+ g.setColor(fill);
+ g.fillPolygon(new int[]{0, s - 1, s - 1}, new int[]{cy, 0, s}, 3);
+ g.drawLine(s - 1, 0, s - 1, s);
g.setColor(trail);
- g.drawLine(0, cy, 0, cy);
- for (int y = cy - 1, x = 1, dy = 1; x <= s - 2; x += 2) {
- g.setColor(lead);
- g.drawLine(x, y, x, y);
- if (x >= (s - 2)) {
- g.drawLine(x + 1, y, x + 1, y);
- }
- g.setColor(fill);
- g.drawLine(x, y + 1, x, y + dy);
- if (x < (s - 2)) {
- g.drawLine(x + 1, y, x + 1, y + dy + 1);
- }
- g.setColor(trail);
- g.drawLine(x, y + dy + 1, x, y + dy + 1);
- if (x >= (s - 2)) {
- g.drawLine(x + 1, y + 1, x + 1, y + dy + 1);
- }
- dy += 2;
- y -= 1;
- }
+ g.drawLine(0, cy, s - 1, s);
+ g.drawLine(s - 1, 0, s - 1, s);
+ g.setColor(lead);
+ g.drawLine(0, cy, s - 2, 0);
+ g.drawLine(s - 2, 0, s - 1, 0); // corner
+ g.setColor(trail);
+ g.drawLine(0, cy, 0, cy); // corner
break;
}
}
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AlawCodec.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AlawCodec.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* 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,25 +30,26 @@
import java.util.Vector;
import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.spi.FormatConversionProvider;
/**
* A-law encodes linear data, and decodes a-law data to linear data.
*
* @author Kara Kytle
*/
-public final class AlawCodec extends SunCodec {
+public final class AlawCodec extends FormatConversionProvider {
/* Tables used for A-law decoding */
private static final byte[] ALAW_TABH = new byte[256];
private static final byte[] ALAW_TABL = new byte[256];
- private static final AudioFormat.Encoding[] alawEncodings = { AudioFormat.Encoding.ALAW, AudioFormat.Encoding.PCM_SIGNED };
-
- private static final short seg_end [] = {0xFF, 0x1FF, 0x3FF,
- 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};
+ private static final short seg_end[] = {
+ 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
+ };
/**
* Initializes the decode tables.
@@ -73,13 +74,14 @@
}
}
+ @Override
+ public AudioFormat.Encoding[] getSourceEncodings() {
+ return new Encoding[]{Encoding.ALAW, Encoding.PCM_SIGNED};
+ }
- /**
- * Constructs a new ALAW codec object.
- */
- public AlawCodec() {
-
- super(alawEncodings, alawEncodings);
+ @Override
+ public AudioFormat.Encoding[] getTargetEncodings() {
+ return getSourceEncodings();
}
@Override
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -562,8 +562,7 @@
@Override
public Encoding[] getTargetEncodings() {
- return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
- Encoding.PCM_FLOAT };
+ return getSourceEncodings();
}
@Override
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/DirectAudioDevice.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/DirectAudioDevice.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1034,6 +1034,7 @@
// $$fb part of fix for 4679187: Clip.open() throws unexpected Exceptions
Toolkit.isFullySpecifiedAudioFormat(format);
+ Toolkit.validateBuffer(format.getFrameSize(), bufferSize);
byte[] newData = new byte[bufferSize];
System.arraycopy(data, offset, newData, 0, bufferSize);
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/PCMtoPCMCodec.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/PCMtoPCMCodec.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* 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,32 +30,26 @@
import java.util.Vector;
import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.spi.FormatConversionProvider;
/**
* Converts among signed/unsigned and little/big endianness of sampled.
*
* @author Jan Borgersen
*/
-public final class PCMtoPCMCodec extends SunCodec {
-
- private static final AudioFormat.Encoding[] inputEncodings = {
- AudioFormat.Encoding.PCM_SIGNED,
- AudioFormat.Encoding.PCM_UNSIGNED,
- };
+public final class PCMtoPCMCodec extends FormatConversionProvider {
- private static final AudioFormat.Encoding[] outputEncodings = {
- AudioFormat.Encoding.PCM_SIGNED,
- AudioFormat.Encoding.PCM_UNSIGNED,
- };
+ @Override
+ public AudioFormat.Encoding[] getSourceEncodings() {
+ return new Encoding[]{Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED};
+ }
- /**
- * Constructs a new PCMtoPCM codec object.
- */
- public PCMtoPCMCodec() {
-
- super( inputEncodings, outputEncodings);
+ @Override
+ public AudioFormat.Encoding[] getTargetEncodings() {
+ return getSourceEncodings();
}
@Override
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMixingClip.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMixingClip.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -363,9 +363,7 @@
if (AudioFloatConverter.getConverter(format) == null)
throw new IllegalArgumentException("Invalid format : "
+ format.toString());
- if (bufferSize % format.getFrameSize() != 0)
- throw new IllegalArgumentException(
- "Buffer size does not represent an integral number of sample frames!");
+ Toolkit.validateBuffer(format.getFrameSize(), bufferSize);
if (data != null) {
this.data = Arrays.copyOf(data, data.length);
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunCodec.java Thu Oct 27 16:29:00 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
- * 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.media.sound;
-
-import javax.sound.sampled.AudioFormat;
-import javax.sound.sampled.spi.FormatConversionProvider;
-
-/**
- * A codec can encode and/or decode audio data. It provides an
- * AudioInputStream from which processed data may be read.
- * <p>
- * Its input format represents the format of the incoming
- * audio data, or the format of the data in the underlying stream.
- * <p>
- * Its output format represents the format of the processed, outgoing
- * audio data. This is the format of the data which may be read from
- * the filtered stream.
- *
- * @author Kara Kytle
- */
-abstract class SunCodec extends FormatConversionProvider {
-
- private final AudioFormat.Encoding[] inputEncodings;
- private final AudioFormat.Encoding[] outputEncodings;
-
- /**
- * Constructs a new codec object.
- */
- SunCodec(final AudioFormat.Encoding[] inputEncodings,
- final AudioFormat.Encoding[] outputEncodings) {
- this.inputEncodings = inputEncodings;
- this.outputEncodings = outputEncodings;
- }
-
- @Override
- public final AudioFormat.Encoding[] getSourceEncodings() {
- AudioFormat.Encoding[] encodings = new AudioFormat.Encoding[inputEncodings.length];
- System.arraycopy(inputEncodings, 0, encodings, 0, inputEncodings.length);
- return encodings;
- }
-
- @Override
- public final AudioFormat.Encoding[] getTargetEncodings() {
- AudioFormat.Encoding[] encodings = new AudioFormat.Encoding[outputEncodings.length];
- System.arraycopy(outputEncodings, 0, encodings, 0, outputEncodings.length);
- return encodings;
- }
-}
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/Toolkit.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/Toolkit.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -149,6 +149,20 @@
return (long) (((double) frames) / format.getFrameRate() * 1000000.0d);
}
+ /**
+ * Throws an exception if the buffer size does not represent an integral
+ * number of sample frames.
+ */
+ static void validateBuffer(final int frameSize, final int bufferSize) {
+ if (bufferSize % frameSize == 0) {
+ return;
+ }
+ throw new IllegalArgumentException(String.format(
+ "Buffer size (%d) does not represent an integral number of "
+ + "sample frames (%d)", bufferSize, frameSize));
+ }
+
+
static void isFullySpecifiedAudioFormat(AudioFormat format) {
if (!format.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)
&& !format.getEncoding().equals(AudioFormat.Encoding.PCM_UNSIGNED)
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/UlawCodec.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/UlawCodec.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* 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,26 +30,26 @@
import java.util.Vector;
import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.spi.FormatConversionProvider;
/**
* U-law encodes linear data, and decodes u-law data to linear data.
*
* @author Kara Kytle
*/
-public final class UlawCodec extends SunCodec {
+public final class UlawCodec extends FormatConversionProvider {
/* Tables used for U-law decoding */
private static final byte[] ULAW_TABH = new byte[256];
private static final byte[] ULAW_TABL = new byte[256];
- private static final AudioFormat.Encoding[] ulawEncodings = {AudioFormat.Encoding.ULAW,
- AudioFormat.Encoding.PCM_SIGNED};
-
- private static final short seg_end [] = {0xFF, 0x1FF, 0x3FF,
- 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};
+ private static final short seg_end[] = {
+ 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
+ };
/**
* Initializes the decode tables.
@@ -69,11 +69,14 @@
}
}
- /**
- * Constructs a new ULAW codec object.
- */
- public UlawCodec() {
- super(ulawEncodings, ulawEncodings);
+ @Override
+ public AudioFormat.Encoding[] getSourceEncodings() {
+ return new Encoding[]{Encoding.ULAW, Encoding.PCM_SIGNED};
+ }
+
+ @Override
+ public AudioFormat.Encoding[] getTargetEncodings() {
+ return getSourceEncodings();
}
@Override
--- a/jdk/src/java.desktop/share/classes/java/awt/Component.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/java/awt/Component.java Thu Oct 27 21:22:57 2016 +0000
@@ -851,8 +851,8 @@
{
comp.setGraphicsConfiguration(gc);
}
- public boolean requestFocus(Component comp, FocusEvent.Cause cause) {
- return comp.requestFocus(cause);
+ public void requestFocus(Component comp, FocusEvent.Cause cause) {
+ comp.requestFocus(cause);
}
public boolean canBeFocusOwner(Component comp) {
return comp.canBeFocusOwner();
@@ -7511,8 +7511,51 @@
requestFocusHelper(false, true);
}
- boolean requestFocus(FocusEvent.Cause cause) {
- return requestFocusHelper(false, true, cause);
+
+ /**
+ * Requests by the reason of {@code cause} that this Component get the input
+ * focus, and that this Component's top-level ancestor become the
+ * focused Window. This component must be displayable, focusable, visible
+ * and all of its ancestors (with the exception of the top-level Window)
+ * must be visible for the request to be granted. Every effort will be
+ * made to honor the request; however, in some cases it may be
+ * impossible to do so. Developers must never assume that this
+ * Component is the focus owner until this Component receives a
+ * FOCUS_GAINED event.
+ * <p>
+ * The focus request effect may also depend on the provided
+ * cause value. If this request is succeed the {@code FocusEvent}
+ * generated in the result will receive the cause value specified as the
+ * argument of method. If this request is denied because this Component's
+ * top-level Window cannot become the focused Window, the request will be
+ * remembered and will be granted when the Window is later focused by the
+ * user.
+ * <p>
+ * This method cannot be used to set the focus owner to no Component at
+ * all. Use {@code KeyboardFocusManager.clearGlobalFocusOwner()}
+ * instead.
+ * <p>
+ * Because the focus behavior of this method is platform-dependent,
+ * developers are strongly encouraged to use
+ * {@code requestFocusInWindow(FocusEvent.Cause)} when possible.
+ *
+ * <p>Note: Not all focus transfers result from invoking this method. As
+ * such, a component may receive focus without this or any of the other
+ * {@code requestFocus} methods of {@code Component} being invoked.
+ *
+ * @param cause the cause why the focus is requested
+ * @see FocusEvent
+ * @see FocusEvent.Cause
+ * @see #requestFocusInWindow(FocusEvent.Cause)
+ * @see java.awt.event.FocusEvent
+ * @see #addFocusListener
+ * @see #isFocusable
+ * @see #isDisplayable
+ * @see KeyboardFocusManager#clearGlobalFocusOwner
+ * @since 9
+ */
+ public void requestFocus(FocusEvent.Cause cause) {
+ requestFocusHelper(false, true, cause);
}
/**
@@ -7578,9 +7621,77 @@
return requestFocusHelper(temporary, true);
}
- boolean requestFocus(boolean temporary, FocusEvent.Cause cause) {
+ /**
+ * Requests by the reason of {@code cause} that this {@code Component} get
+ * the input focus, and that this {@code Component}'s top-level ancestor
+ * become the focused {@code Window}. This component must be
+ * displayable, focusable, visible and all of its ancestors (with
+ * the exception of the top-level Window) must be visible for the
+ * request to be granted. Every effort will be made to honor the
+ * request; however, in some cases it may be impossible to do
+ * so. Developers must never assume that this component is the
+ * focus owner until this component receives a FOCUS_GAINED
+ * event. If this request is denied because this component's
+ * top-level window cannot become the focused window, the request
+ * will be remembered and will be granted when the window is later
+ * focused by the user.
+ * <p>
+ * This method returns a boolean value. If {@code false} is returned,
+ * the request is <b>guaranteed to fail</b>. If {@code true} is
+ * returned, the request will succeed <b>unless</b> it is vetoed, or an
+ * extraordinary event, such as disposal of the component's peer, occurs
+ * before the request can be granted by the native windowing system. Again,
+ * while a return value of {@code true} indicates that the request is
+ * likely to succeed, developers must never assume that this component is
+ * the focus owner until this component receives a FOCUS_GAINED event.
+ * <p>
+ * The focus request effect may also depend on the provided
+ * cause value. If this request is succeed the {FocusEvent}
+ * generated in the result will receive the cause value specified as the
+ * argument of the method.
+ * <p>
+ * This method cannot be used to set the focus owner to no component at
+ * all. Use {@code KeyboardFocusManager.clearGlobalFocusOwner}
+ * instead.
+ * <p>
+ * Because the focus behavior of this method is platform-dependent,
+ * developers are strongly encouraged to use
+ * {@code requestFocusInWindow} when possible.
+ * <p>
+ * Every effort will be made to ensure that {@code FocusEvent}s
+ * generated as a
+ * result of this request will have the specified temporary value. However,
+ * because specifying an arbitrary temporary state may not be implementable
+ * on all native windowing systems, correct behavior for this method can be
+ * guaranteed only for lightweight {@code Component}s.
+ * This method is not intended
+ * for general use, but exists instead as a hook for lightweight component
+ * libraries, such as Swing.
+ * <p>
+ * Note: Not all focus transfers result from invoking this method. As
+ * such, a component may receive focus without this or any of the other
+ * {@code requestFocus} methods of {@code Component} being invoked.
+ *
+ * @param temporary true if the focus change is temporary,
+ * such as when the window loses the focus; for
+ * more information on temporary focus changes see the
+ *<a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
+ *
+ * @param cause the cause why the focus is requested
+ * @return {@code false} if the focus change request is guaranteed to
+ * fail; {@code true} if it is likely to succeed
+ * @see FocusEvent
+ * @see FocusEvent.Cause
+ * @see #addFocusListener
+ * @see #isFocusable
+ * @see #isDisplayable
+ * @see KeyboardFocusManager#clearGlobalFocusOwner
+ * @since 9
+ */
+ protected boolean requestFocus(boolean temporary, FocusEvent.Cause cause) {
return requestFocusHelper(temporary, true, cause);
}
+
/**
* Requests that this Component get the input focus, if this
* Component's top-level ancestor is already the focused
@@ -7629,7 +7740,59 @@
return requestFocusHelper(false, false);
}
- boolean requestFocusInWindow(FocusEvent.Cause cause) {
+ /**
+ * Requests by the reason of {@code cause} that this Component get the input
+ * focus, if this Component's top-level ancestor is already the focused
+ * Window. This component must be displayable, focusable, visible
+ * and all of its ancestors (with the exception of the top-level
+ * Window) must be visible for the request to be granted. Every
+ * effort will be made to honor the request; however, in some
+ * cases it may be impossible to do so. Developers must never
+ * assume that this Component is the focus owner until this
+ * Component receives a FOCUS_GAINED event.
+ * <p>
+ * This method returns a boolean value. If {@code false} is returned,
+ * the request is <b>guaranteed to fail</b>. If {@code true} is
+ * returned, the request will succeed <b>unless</b> it is vetoed, or an
+ * extraordinary event, such as disposal of the Component's peer, occurs
+ * before the request can be granted by the native windowing system. Again,
+ * while a return value of {@code true} indicates that the request is
+ * likely to succeed, developers must never assume that this Component is
+ * the focus owner until this Component receives a FOCUS_GAINED event.
+ * <p>
+ * The focus request effect may also depend on the provided
+ * cause value. If this request is succeed the {@code FocusEvent}
+ * generated in the result will receive the cause value specified as the
+ * argument of the method.
+ * <p>
+ * This method cannot be used to set the focus owner to no Component at
+ * all. Use {@code KeyboardFocusManager.clearGlobalFocusOwner()}
+ * instead.
+ * <p>
+ * The focus behavior of this method can be implemented uniformly across
+ * platforms, and thus developers are strongly encouraged to use this
+ * method over {@code requestFocus(FocusEvent.Cause)} when possible.
+ * Code which relies on {@code requestFocus(FocusEvent.Cause)} may exhibit
+ * different focus behavior on different platforms.
+ *
+ * <p>Note: Not all focus transfers result from invoking this method. As
+ * such, a component may receive focus without this or any of the other
+ * {@code requestFocus} methods of {@code Component} being invoked.
+ *
+ * @param cause the cause why the focus is requested
+ * @return {@code false} if the focus change request is guaranteed to
+ * fail; {@code true} if it is likely to succeed
+ * @see #requestFocus(FocusEvent.Cause)
+ * @see FocusEvent
+ * @see FocusEvent.Cause
+ * @see java.awt.event.FocusEvent
+ * @see #addFocusListener
+ * @see #isFocusable
+ * @see #isDisplayable
+ * @see KeyboardFocusManager#clearGlobalFocusOwner
+ * @since 9
+ */
+ public boolean requestFocusInWindow(FocusEvent.Cause cause) {
return requestFocusHelper(false, false, cause);
}
--- a/jdk/src/java.desktop/share/classes/java/awt/DisplayMode.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/java/awt/DisplayMode.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -142,6 +142,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public boolean equals(Object dm) {
if (dm instanceof DisplayMode) {
return equals((DisplayMode)dm);
@@ -153,9 +154,20 @@
/**
* {@inheritDoc}
*/
+ @Override
public int hashCode() {
return getWidth() + getHeight() + getBitDepth() * 7
+ getRefreshRate() * 13;
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return getWidth() + "x" + getHeight() + "x" +
+ (getBitDepth() > 0 ? getBitDepth() + "bpp": "[Multi depth]")
+ + "@" + (getRefreshRate() > 0 ? getRefreshRate() + "Hz" :
+ "[Unknown refresh rate]");
+ }
}
--- a/jdk/src/java.desktop/share/classes/java/awt/Font.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/java/awt/Font.java Thu Oct 27 21:22:57 2016 +0000
@@ -154,6 +154,10 @@
* associated with a font face, each differing in size, style, transform
* and font features.
* <p>
+ * Glyphs may not always be rendered with the requested properties (e.g, font
+ * and style) due to platform limitations such as the absence of suitable
+ * platform fonts to implement a logical font.
+ * <p>
* The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method
* of the {@code GraphicsEnvironment} class returns an
* array of all font faces available in the system. These font faces are
--- a/jdk/src/java.desktop/share/classes/java/awt/SplashScreen.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/java/awt/SplashScreen.java Thu Oct 27 21:22:57 2016 +0000
@@ -65,6 +65,16 @@
* <PRE>
* java -splash:filename.gif Test
* </PRE>
+ * HiDPI scaled image is also supported.
+ * Unscaled image name i.e. filename.gif should be passed in
+ * {@code manifest.mf}/{@code -splash:} option for all image types irrespective of
+ * HiDPI and Non-HiDPI.
+ * Following is the naming convention for scaled images.
+ * Screen scale 1.25: filename@125pct.gif
+ * Screen scale 1.50: filename@150pct.gif
+ * Screen scale 2: filename@200pct.gif and filename@2x.gif both are supported
+ * Screen scale 2.50: filename@250pct.gif
+ * Screen scale 3: filename@300pct.gif and filename@3x.gif both are supported
* The command line interface has higher precedence over the manifest
* setting.
* <p>
--- a/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataNode.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataNode.java Thu Oct 27 21:22:57 2016 +0000
@@ -122,7 +122,7 @@
}
public Node item(int index) {
- if (index < 0 || index > nodes.size()) {
+ if (index < 0 || index >= nodes.size()) {
return null;
}
return nodes.get(index);
@@ -882,7 +882,7 @@
}
private void getElementsByTagName(String name, List<Node> l) {
- if (nodeName.equals(name)) {
+ if (nodeName.equals(name) || "*".equals(name)) {
l.add(this);
}
--- a/jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/FormatConversionProvider.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/FormatConversionProvider.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* 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 @@
package javax.sound.sampled.spi;
-import java.util.Objects;
+import java.util.stream.Stream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
@@ -81,16 +81,8 @@
* {@code false}
* @throws NullPointerException if {@code sourceEncoding} is {@code null}
*/
- public boolean isSourceEncodingSupported(Encoding sourceEncoding) {
- Objects.requireNonNull(sourceEncoding);
- Encoding sourceEncodings[] = getSourceEncodings();
-
- for(int i=0; i<sourceEncodings.length; i++) {
- if( sourceEncoding.equals( sourceEncodings[i]) ) {
- return true;
- }
- }
- return false;
+ public boolean isSourceEncodingSupported(final Encoding sourceEncoding) {
+ return Stream.of(getSourceEncodings()).anyMatch(sourceEncoding::equals);
}
/**
@@ -103,16 +95,8 @@
* {@code false}
* @throws NullPointerException if {@code targetEncoding} is {@code null}
*/
- public boolean isTargetEncodingSupported(Encoding targetEncoding) {
- Objects.requireNonNull(targetEncoding);
- Encoding targetEncodings[] = getTargetEncodings();
-
- for(int i=0; i<targetEncodings.length; i++) {
- if( targetEncoding.equals( targetEncodings[i]) ) {
- return true;
- }
- }
- return false;
+ public boolean isTargetEncodingSupported(final Encoding targetEncoding) {
+ return Stream.of(getTargetEncodings()).anyMatch(targetEncoding::equals);
}
/**
@@ -137,17 +121,10 @@
* @throws NullPointerException if {@code targetEncoding} or
* {@code sourceFormat} are {@code null}
*/
- public boolean isConversionSupported(Encoding targetEncoding,
- AudioFormat sourceFormat) {
- Objects.requireNonNull(targetEncoding);
- Encoding targetEncodings[] = getTargetEncodings(sourceFormat);
-
- for(int i=0; i<targetEncodings.length; i++) {
- if( targetEncoding.equals( targetEncodings[i]) ) {
- return true;
- }
- }
- return false;
+ public boolean isConversionSupported(final Encoding targetEncoding,
+ final AudioFormat sourceFormat) {
+ return Stream.of(getTargetEncodings(sourceFormat))
+ .anyMatch(targetEncoding::equals);
}
/**
@@ -175,17 +152,11 @@
* @throws NullPointerException if {@code targetFormat} or
* {@code sourceFormat} are {@code null}
*/
- public boolean isConversionSupported(AudioFormat targetFormat,
- AudioFormat sourceFormat) {
-
- AudioFormat targetFormats[] = getTargetFormats( targetFormat.getEncoding(), sourceFormat );
-
- for(int i=0; i<targetFormats.length; i++) {
- if( targetFormat.matches( targetFormats[i] ) ) {
- return true;
- }
- }
- return false;
+ public boolean isConversionSupported(final AudioFormat targetFormat,
+ final AudioFormat sourceFormat) {
+ final Encoding targetEncoding = targetFormat.getEncoding();
+ return Stream.of(getTargetFormats(targetEncoding, sourceFormat))
+ .anyMatch(targetFormat::matches);
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/TextUI.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/TextUI.java Thu Oct 27 21:22:57 2016 +0000
@@ -46,7 +46,11 @@
* @return the coordinates as a {@code Rectangle}
* @exception BadLocationException if the given position does not
* represent a valid location in the associated document
+ *
+ * @deprecated replaced by
+ * {@link #modelToView2D(JTextComponent, int, Position.Bias)}
*/
+ @Deprecated(since = "9")
public abstract Rectangle modelToView(JTextComponent t, int pos) throws BadLocationException;
/**
@@ -59,7 +63,11 @@
* @return the coordinates as a {@code Rectangle}
* @exception BadLocationException if the given position does not
* represent a valid location in the associated document
+ *
+ * @deprecated replaced by
+ * {@link #modelToView2D(JTextComponent, int, Position.Bias)}
*/
+ @Deprecated(since = "9")
public abstract Rectangle modelToView(JTextComponent t, int pos, Position.Bias bias) throws BadLocationException;
/**
@@ -92,7 +100,11 @@
* should be in the same coordinate system as the mouse
* events.
* @return the offset from the start of the document >= 0
+ *
+ * @deprecated replaced by
+ * {@link #viewToModel2D(JTextComponent, Point2D, Position.Bias[])}
*/
+ @Deprecated(since = "9")
public abstract int viewToModel(JTextComponent t, Point pt);
/**
@@ -110,7 +122,11 @@
*
* @return the location within the model that best represents the
* given point in the view >= 0
+ *
+ * @deprecated replaced by
+ * {@link #viewToModel2D(JTextComponent, Point2D, Position.Bias[])}
*/
+ @Deprecated(since = "9")
public abstract int viewToModel(JTextComponent t, Point pt,
Position.Bias[] biasReturn);
@@ -222,7 +238,11 @@
* @return a {@code String} containing the tooltip
* @see javax.swing.text.JTextComponent#getToolTipText
* @since 1.4
+ *
+ * @deprecated replaced by
+ * {@link #getToolTipText2D(JTextComponent, Point2D)}
*/
+ @Deprecated(since = "9")
public String getToolTipText(JTextComponent t, Point pt) {
return null;
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java Thu Oct 27 21:22:57 2016 +0000
@@ -28,6 +28,8 @@
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
import java.awt.im.InputContext;
import java.beans.*;
import java.io.*;
@@ -1047,7 +1049,12 @@
* @exception BadLocationException if the given position does not
* represent a valid location in the associated document
* @see TextUI#modelToView
+ *
+ * @deprecated replaced by
+ * {@link #modelToView2D(JTextComponent, int, Position.Bias)}
*/
+ @Deprecated(since = "9")
+ @Override
public Rectangle modelToView(JTextComponent tc, int pos) throws BadLocationException {
return modelToView(tc, pos, Position.Bias.Forward);
}
@@ -1064,8 +1071,30 @@
* @exception BadLocationException if the given position does not
* represent a valid location in the associated document
* @see TextUI#modelToView
+ *
+ * @deprecated replaced by
+ * {@link #modelToView2D(JTextComponent, int, Position.Bias)}
*/
- public Rectangle modelToView(JTextComponent tc, int pos, Position.Bias bias) throws BadLocationException {
+ @Deprecated(since = "9")
+ @Override
+ public Rectangle modelToView(JTextComponent tc, int pos, Position.Bias bias)
+ throws BadLocationException
+ {
+ return (Rectangle) modelToView(tc, pos, bias, false);
+ }
+
+ @Override
+ public Rectangle2D modelToView2D(JTextComponent tc, int pos,
+ Position.Bias bias)
+ throws BadLocationException
+ {
+ return modelToView(tc, pos, bias, true);
+ }
+
+ private Rectangle2D modelToView(JTextComponent tc, int pos,
+ Position.Bias bias, boolean useFPAPI)
+ throws BadLocationException
+ {
Document doc = editor.getDocument();
if (doc instanceof AbstractDocument) {
((AbstractDocument)doc).readLock();
@@ -1076,7 +1105,7 @@
rootView.setSize(alloc.width, alloc.height);
Shape s = rootView.modelToView(pos, alloc, bias);
if (s != null) {
- return s.getBounds();
+ return useFPAPI ? s.getBounds2D() : s.getBounds();
}
}
} finally {
@@ -1099,7 +1128,12 @@
* @return the offset from the start of the document >= 0,
* -1 if not painted
* @see TextUI#viewToModel
+ *
+ * @deprecated replaced by
+ * {@link #viewToModel2D(JTextComponent, Point2D, Position.Bias[])}
*/
+ @Deprecated(since = "9")
+ @Override
public int viewToModel(JTextComponent tc, Point pt) {
return viewToModel(tc, pt, discardBias);
}
@@ -1116,9 +1150,25 @@
* @return the offset from the start of the document >= 0,
* -1 if the component doesn't yet have a positive size.
* @see TextUI#viewToModel
+ *
+ * @deprecated replaced by
+ * {@link #viewToModel2D(JTextComponent, Point2D, Position.Bias[])}
*/
+ @Deprecated(since = "9")
+ @Override
public int viewToModel(JTextComponent tc, Point pt,
Position.Bias[] biasReturn) {
+ return viewToModel(tc, pt.x, pt.y, biasReturn);
+ }
+
+ @Override
+ public int viewToModel2D(JTextComponent tc, Point2D pt,
+ Position.Bias[] biasReturn) {
+ return viewToModel(tc, (float) pt.getX(), (float) pt.getY(), biasReturn);
+ }
+
+ private int viewToModel(JTextComponent tc, float x, float y,
+ Position.Bias[] biasReturn) {
int offs = -1;
Document doc = editor.getDocument();
if (doc instanceof AbstractDocument) {
@@ -1128,7 +1178,7 @@
Rectangle alloc = getVisibleEditorRect();
if (alloc != null) {
rootView.setSize(alloc.width, alloc.height);
- offs = rootView.viewToModel(pt.x, pt.y, alloc, biasReturn);
+ offs = rootView.viewToModel(x, y, alloc, biasReturn);
}
} finally {
if (doc instanceof AbstractDocument) {
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/multi/MultiTextUI.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/multi/MultiTextUI.java Thu Oct 27 21:22:57 2016 +0000
@@ -38,6 +38,8 @@
import javax.swing.JComponent;
import java.awt.Graphics;
import java.awt.Dimension;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
import javax.accessibility.Accessible;
/**
@@ -97,7 +99,11 @@
*
* @return the value obtained from the first UI, which is
* the UI obtained from the default <code>LookAndFeel</code>
+ *
+ * @deprecated replaced by
+ * {@link #modelToView2D(JTextComponent, int, Position.Bias)}
*/
+ @Deprecated(since = "9")
public Rectangle modelToView(JTextComponent a, int b)
throws BadLocationException {
Rectangle returnValue =
@@ -113,7 +119,12 @@
*
* @return the value obtained from the first UI, which is
* the UI obtained from the default <code>LookAndFeel</code>
+ *
+ * @deprecated replaced by
+ * {@link #modelToView2D(JTextComponent, int, Position.Bias)}
*/
+ @Deprecated(since = "9")
+ @Override
public Rectangle modelToView(JTextComponent a, int b, Position.Bias c)
throws BadLocationException {
Rectangle returnValue =
@@ -124,12 +135,24 @@
return returnValue;
}
+ @Override
+ public Rectangle2D modelToView2D(JTextComponent a, int b, Position.Bias c) throws BadLocationException {
+ Rectangle2D returnValue =
+ ((TextUI) (uis.elementAt(0))).modelToView2D(a,b,c);
+ for (int i = 1; i < uis.size(); i++) {
+ ((TextUI) (uis.elementAt(i))).modelToView2D(a,b,c);
+ }
+ return returnValue;
+ }
+
/**
* Invokes the <code>viewToModel</code> method on each UI handled by this object.
*
* @return the value obtained from the first UI, which is
* the UI obtained from the default <code>LookAndFeel</code>
*/
+ @Deprecated(since = "9")
+ @Override
public int viewToModel(JTextComponent a, Point b) {
int returnValue =
((TextUI) (uis.elementAt(0))).viewToModel(a,b);
@@ -145,6 +168,8 @@
* @return the value obtained from the first UI, which is
* the UI obtained from the default <code>LookAndFeel</code>
*/
+ @Deprecated(since = "9")
+ @Override
public int viewToModel(JTextComponent a, Point b, Position.Bias[] c) {
int returnValue =
((TextUI) (uis.elementAt(0))).viewToModel(a,b,c);
@@ -154,6 +179,16 @@
return returnValue;
}
+ @Override
+ public int viewToModel2D(JTextComponent a, Point2D b, Position.Bias[] c) {
+ int returnValue =
+ ((TextUI) (uis.elementAt(0))).viewToModel2D(a,b,c);
+ for (int i = 1; i < uis.size(); i++) {
+ ((TextUI) (uis.elementAt(i))).viewToModel2D(a,b,c);
+ }
+ return returnValue;
+ }
+
/**
* Invokes the <code>getNextVisualPositionFrom</code> method on each UI handled by this object.
*
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/GlyphPainter1.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/GlyphPainter1.java Thu Oct 27 21:22:57 2016 +0000
@@ -98,26 +98,27 @@
Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a : a.getBounds();
// determine the x coordinate to render the glyphs
- int x = alloc.x;
+ float x = alloc.x;
int p = v.getStartOffset();
int[] justificationData = getJustificationData(v);
if (p != p0) {
text = v.getText(p, p0);
- int width = Utilities.getTabbedTextWidth(v, text, metrics, x, expander, p,
- justificationData);
+ float width = Utilities.getTabbedTextWidth(v, text, metrics, x,
+ expander, p,
+ justificationData);
x += width;
SegmentCache.releaseSharedSegment(text);
}
// determine the y coordinate to render the glyphs
- int y = alloc.y + metrics.getHeight() - metrics.getDescent();
+ float y = alloc.y + metrics.getHeight() - metrics.getDescent();
// render the glyphs
text = v.getText(p0, p1);
g.setFont(metrics.getFont());
Utilities.drawTabbedText(v, text, x, y, g, expander,p0,
- justificationData);
+ justificationData, true);
SegmentCache.releaseSharedSegment(text);
}
@@ -210,9 +211,9 @@
TabExpander expander = v.getTabExpander();
Segment s = v.getText(p0, v.getEndOffset());
int[] justificationData = getJustificationData(v);
- int index = Utilities.getTabbedTextOffset(v, s, metrics, (int)x, (int)(x+len),
+ int index = Utilities.getTabbedTextOffset(v, s, metrics, x, (x+len),
expander, p0, false,
- justificationData);
+ justificationData, true);
SegmentCache.releaseSharedSegment(s);
int p1 = p0 + index;
return p1;
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/GlyphPainter2.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/GlyphPainter2.java Thu Oct 27 21:22:57 2016 +0000
@@ -145,8 +145,9 @@
// vertical at the baseline, should use slope and check if glyphs
// are being rendered vertically.
- alloc.setRect(alloc.getX() + locs[0], alloc.getY(), 1, alloc.getHeight());
- return alloc;
+ Rectangle2D rect = new Rectangle2D.Float();
+ rect.setRect(alloc.getX() + locs[0], alloc.getY(), 1, alloc.getHeight());
+ return rect;
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java Thu Oct 27 21:22:57 2016 +0000
@@ -49,6 +49,8 @@
import java.awt.im.InputMethodRequests;
import java.awt.font.TextHitInfo;
import java.awt.font.TextAttribute;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
@@ -1370,12 +1372,38 @@
* @exception BadLocationException if the given position does not
* represent a valid location in the associated document
* @see TextUI#modelToView
+ *
+ * @deprecated replaced by
+ * {@link #modelToView2D(int)}
*/
+ @Deprecated(since = "9")
public Rectangle modelToView(int pos) throws BadLocationException {
return getUI().modelToView(this, pos);
}
/**
+ * Converts the given location in the model to a place in
+ * the view coordinate system.
+ * The component must have a positive size for
+ * this translation to be computed (i.e. layout cannot
+ * be computed until the component has been sized). The
+ * component does not have to be visible or painted.
+ *
+ * @param pos the position {@code >= 0}
+ * @return the coordinates as a rectangle, with (r.x, r.y) as the location
+ * in the coordinate system, or null if the component does
+ * not yet have a positive size.
+ * @exception BadLocationException if the given position does not
+ * represent a valid location in the associated document
+ * @see TextUI#modelToView2D
+ *
+ * @since 9
+ */
+ public Rectangle2D modelToView2D(int pos) throws BadLocationException {
+ return getUI().modelToView2D(this, pos, Position.Bias.Forward);
+ }
+
+ /**
* Converts the given place in the view coordinate system
* to the nearest representative location in the model.
* The component must have a positive size for
@@ -1388,12 +1416,36 @@
* or -1 if the component does not yet have a positive
* size.
* @see TextUI#viewToModel
+ *
+ * @deprecated replaced by
+ * {@link #viewToModel2D(Point2D)}
*/
+ @Deprecated(since = "9")
public int viewToModel(Point pt) {
return getUI().viewToModel(this, pt);
}
/**
+ * Converts the given place in the view coordinate system
+ * to the nearest representative location in the model.
+ * The component must have a positive size for
+ * this translation to be computed (i.e. layout cannot
+ * be computed until the component has been sized). The
+ * component does not have to be visible or painted.
+ *
+ * @param pt the location in the view to translate
+ * @return the offset {@code >= 0} from the start of the document,
+ * or {@code -1} if the component does not yet have a positive
+ * size.
+ * @see TextUI#viewToModel2D
+ *
+ * @since 9
+ */
+ public int viewToModel2D(Point2D pt) {
+ return getUI().viewToModel2D(this, pt, new Position.Bias[1]);
+ }
+
+ /**
* Transfers the currently selected range in the associated
* text model to the system clipboard, removing the contents
* from the model. The current selection is reset. Does nothing
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/ParagraphView.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/ParagraphView.java Thu Oct 27 21:22:57 2016 +0000
@@ -27,6 +27,7 @@
import java.util.Arrays;
import java.awt.*;
import java.awt.font.TextAttribute;
+import java.awt.geom.Rectangle2D;
import javax.swing.event.*;
import javax.swing.SizeRequirements;
@@ -888,10 +889,9 @@
int height = r.height;
int y = r.y;
Shape loc = super.modelToView(pos, a, b);
- r = loc.getBounds();
- r.height = height;
- r.y = y;
- return r;
+ Rectangle2D bounds = loc.getBounds2D();
+ bounds.setRect(bounds.getX(), y, bounds.getWidth(), height);
+ return bounds;
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/PasswordView.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/PasswordView.java Thu Oct 27 21:22:57 2016 +0000
@@ -26,7 +26,11 @@
import sun.swing.SwingUtilities2;
import java.awt.*;
+import java.awt.font.FontRenderContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import javax.swing.JPasswordField;
+import static javax.swing.text.PlainView.isFPMethodOverriden;
/**
* Implements a View suitable for use in JPasswordField
@@ -61,15 +65,40 @@
* @param p1 the ending offset in the model >= p0
* @return the X location of the end of the range >= 0
* @exception BadLocationException if p0 or p1 are out of range
+ *
+ * @deprecated replaced by
+ * {@link #drawUnselectedText(Graphics2D, float, float, int, int)}
*/
+ @Deprecated(since = "9")
+ @Override
protected int drawUnselectedText(Graphics g, int x, int y,
int p0, int p1) throws BadLocationException {
+ return (int) drawUnselectedTextImpl(g, x, y, p0, p1, false);
+ }
+ @Override
+ protected float drawUnselectedText(Graphics2D g, float x, float y,
+ int p0, int p1)
+ throws BadLocationException
+ {
+ return drawUnselectedTextImpl(g, x, y, p0, p1, true);
+ }
+
+ private float drawUnselectedTextImpl(Graphics g, float x, float y,
+ int p0, int p1,
+ boolean useFPAPI)
+ throws BadLocationException
+ {
Container c = getContainer();
if (c instanceof JPasswordField) {
JPasswordField f = (JPasswordField) c;
- if (! f.echoCharIsSet()) {
- return super.drawUnselectedText(g, x, y, p0, p1);
+ if (!f.echoCharIsSet()) {
+ boolean useDrawUnselectedFPAPI = useFPAPI
+ && drawUnselectedTextOverridden
+ && g instanceof Graphics2D;
+ return (useDrawUnselectedFPAPI )
+ ? super.drawUnselectedText((Graphics2D) g, x, y, p0, p1)
+ : super.drawUnselectedText(g, (int) x, (int) y, p0, p1);
}
if (f.isEnabled()) {
g.setColor(f.getForeground());
@@ -79,8 +108,13 @@
}
char echoChar = f.getEchoChar();
int n = p1 - p0;
+ boolean useEchoCharFPAPI = useFPAPI
+ && drawEchoCharacterOverridden
+ && g instanceof Graphics2D;
for (int i = 0; i < n; i++) {
- x = drawEchoCharacter(g, x, y, echoChar);
+ x = (useEchoCharFPAPI)
+ ? drawEchoCharacter((Graphics2D) g, x, y, echoChar)
+ : drawEchoCharacter(g, (int) x, (int) y, echoChar);
}
}
return x;
@@ -100,20 +134,50 @@
* @param p1 the ending offset in the model >= p0
* @return the X location of the end of the range >= 0
* @exception BadLocationException if p0 or p1 are out of range
+ *
+ * @deprecated replaced by
+ * {@link #drawSelectedText(Graphics2D, float, float, int, int)}
*/
+ @Deprecated(since = "9")
+ @Override
protected int drawSelectedText(Graphics g, int x,
int y, int p0, int p1) throws BadLocationException {
+ return (int) drawSelectedTextImpl(g, x, y, p0, p1, false);
+ }
+
+ @Override
+ protected float drawSelectedText(Graphics2D g, float x, float y,
+ int p0, int p1) throws BadLocationException
+ {
+ return drawSelectedTextImpl(g, x, y, p0, p1, true);
+ }
+
+ private float drawSelectedTextImpl(Graphics g, float x, float y,
+ int p0, int p1,
+ boolean useFPAPI)
+ throws BadLocationException {
g.setColor(selected);
Container c = getContainer();
if (c instanceof JPasswordField) {
JPasswordField f = (JPasswordField) c;
- if (! f.echoCharIsSet()) {
- return super.drawSelectedText(g, x, y, p0, p1);
+ if (!f.echoCharIsSet()) {
+ boolean useDrawUnselectedFPAPI = useFPAPI
+ && drawSelectedTextOverridden
+ && g instanceof Graphics2D;
+ return (useFPAPI)
+ ? super.drawSelectedText((Graphics2D) g, x, y, p0, p1)
+ : super.drawSelectedText(g, (int) x, (int) y, p0, p1);
}
char echoChar = f.getEchoChar();
int n = p1 - p0;
+ boolean useEchoCharFPAPI = useFPAPI
+ && drawEchoCharacterOverridden
+ && g instanceof Graphics2D;
for (int i = 0; i < n; i++) {
- x = drawEchoCharacter(g, x, y, echoChar);
+ x = (useEchoCharFPAPI)
+ ? drawEchoCharacter((Graphics2D) g, x, y, echoChar)
+ : drawEchoCharacter(g, (int) x, (int) y, echoChar);
+
}
}
return x;
@@ -130,12 +194,13 @@
* @param y the starting Y coordinate >= 0
* @param c the echo character
* @return the updated X position >= 0
+ *
+ * @deprecated replaced by
+ * {@link #drawEchoCharacter(Graphics2D, float, float, char)}
*/
+ @Deprecated(since = "9")
protected int drawEchoCharacter(Graphics g, int x, int y, char c) {
- ONE[0] = c;
- SwingUtilities2.drawChars(Utilities.getJComponent(this),
- g, ONE, 0, 1, x, y);
- return x + g.getFontMetrics().charWidth(c);
+ return (int) drawEchoCharacterImpl(g, x, y, c, false);
}
/**
@@ -144,18 +209,29 @@
* object is set to the appropriate foreground color for selected
* or unselected text.
*
- * @implSpec This implementation calls
- * {@link #drawEchoCharacter(Graphics, int, int, char)
- * drawEchoCharacter((Graphics) g, (int) x, (int) y, c)}.
- *
* @param g the graphics context
* @param x the starting X coordinate {@code >= 0}
* @param y the starting Y coordinate {@code >= 0}
* @param c the echo character
* @return the updated X position {@code >= 0}
+ *
+ * @since 9
*/
protected float drawEchoCharacter(Graphics2D g, float x, float y, char c) {
- return drawEchoCharacter((Graphics) g, (int) x, (int) y, c);
+ return drawEchoCharacterImpl(g, x, y, c, true);
+ }
+
+ private float drawEchoCharacterImpl(Graphics g, float x, float y,
+ char c, boolean useFPAPI) {
+ ONE[0] = c;
+ SwingUtilities2.drawChars(Utilities.getJComponent(this),
+ g, ONE, 0, 1, x, y);
+ if (useFPAPI) {
+ return x + g.getFontMetrics().charWidth(c);
+ } else {
+ FontRenderContext frc = g.getFontMetrics().getFontRenderContext();
+ return x + (float) g.getFont().getStringBounds(ONE, 0, 1, frc).getWidth();
+ }
}
/**
@@ -253,4 +329,23 @@
}
static char[] ONE = new char[1];
+
+ private final boolean drawEchoCharacterOverridden;
+
+ {
+ final Class<?> CLS = getClass();
+ final Class<?> INT = Integer.TYPE;
+ final Class<?> FP = Float.TYPE;
+ final Class<?> CHAR = Character.TYPE;
+
+ drawEchoCharacterOverridden = AccessController
+ .doPrivileged(new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ Class<?>[] intTypes = {Graphics.class, INT, INT, CHAR};
+ Class<?>[] fpTypes = {Graphics2D.class, FP, FP, CHAR};
+ return isFPMethodOverriden("drawEchoCharacter", CLS, intTypes, fpTypes);
+ }
+ });
+ }
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/PlainView.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/PlainView.java Thu Oct 27 21:22:57 2016 +0000
@@ -24,11 +24,14 @@
*/
package javax.swing.text;
-import java.util.Vector;
-import java.util.Properties;
import java.awt.*;
+import java.awt.font.FontRenderContext;
+import java.awt.geom.Rectangle2D;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Objects;
import javax.swing.event.*;
+import java.lang.reflect.Module;
/**
* Implements View interface for a simple multi-line text view
@@ -61,17 +64,6 @@
}
/**
- * Returns the tab size set for the document, defaulting to 8.
- *
- * @implSpec This implementation calls {@link #getTabSize() getTabSize()}.
- *
- * @return the tab size
- */
- protected float getFractionalTabSize() {
- return getTabSize();
- }
-
- /**
* Renders a line of text, suppressing whitespace at the end
* and expanding any tabs. This is implemented to make calls
* to the methods <code>drawUnselectedText</code> and
@@ -84,8 +76,16 @@
* @param y the starting Y position >= 0
* @see #drawUnselectedText
* @see #drawSelectedText
+ *
+ * @deprecated replaced by
+ * {@link #drawLine(int, Graphics2D, float, float)}
*/
+ @Deprecated(since = "9")
protected void drawLine(int lineIndex, Graphics g, int x, int y) {
+ drawLineImpl(lineIndex, g, x, y);
+ }
+
+ private void drawLineImpl(int lineIndex, Graphics g, float x, float y) {
Element line = getElement().getElement(lineIndex);
Element elem;
@@ -112,22 +112,23 @@
* {@code drawSelectedText} so that the way selected and
* unselected text are rendered can be customized.
*
- * @implSpec This implementation calls
- * {@link #drawLine(int, Graphics, int, int)
- * drawLine(lineIndex, (Graphics)g, (int) x, (int) y)}.
- *
* @param lineIndex the line to draw {@code >= 0}
* @param g the {@code Graphics} context
* @param x the starting X position {@code >= 0}
* @param y the starting Y position {@code >= 0}
* @see #drawUnselectedText
* @see #drawSelectedText
+ *
+ * @since 9
*/
protected void drawLine(int lineIndex, Graphics2D g, float x, float y) {
- drawLine(lineIndex, (Graphics)g, (int) x, (int) y);
+ drawLineImpl(lineIndex, g, x, y);
}
- private int drawElement(int lineIndex, Element elem, Graphics g, int x, int y) throws BadLocationException {
+ private float drawElement(int lineIndex, Element elem, Graphics g,
+ float x, float y)
+ throws BadLocationException
+ {
int p0 = elem.getStartOffset();
int p1 = elem.getEndOffset();
p1 = Math.min(getDocument().getLength(), p1);
@@ -144,23 +145,23 @@
} else {
if (sel0 == sel1 || selected == unselected) {
// no selection, or it is invisible
- x = drawUnselectedText(g, x, y, p0, p1);
+ x = callDrawUnselectedText(g, x, y, p0, p1);
} else if ((p0 >= sel0 && p0 <= sel1) && (p1 >= sel0 && p1 <= sel1)) {
- x = drawSelectedText(g, x, y, p0, p1);
+ x = callDrawSelectedText(g, x, y, p0, p1);
} else if (sel0 >= p0 && sel0 <= p1) {
if (sel1 >= p0 && sel1 <= p1) {
- x = drawUnselectedText(g, x, y, p0, sel0);
- x = drawSelectedText(g, x, y, sel0, sel1);
- x = drawUnselectedText(g, x, y, sel1, p1);
+ x = callDrawUnselectedText(g, x, y, p0, sel0);
+ x = callDrawSelectedText(g, x, y, sel0, sel1);
+ x = callDrawUnselectedText(g, x, y, sel1, p1);
} else {
- x = drawUnselectedText(g, x, y, p0, sel0);
- x = drawSelectedText(g, x, y, sel0, p1);
+ x = callDrawUnselectedText(g, x, y, p0, sel0);
+ x = callDrawSelectedText(g, x, y, sel0, p1);
}
} else if (sel1 >= p0 && sel1 <= p1) {
- x = drawSelectedText(g, x, y, p0, sel1);
- x = drawUnselectedText(g, x, y, sel1, p1);
+ x = callDrawSelectedText(g, x, y, p0, sel1);
+ x = callDrawUnselectedText(g, x, y, sel1, p1);
} else {
- x = drawUnselectedText(g, x, y, p0, p1);
+ x = callDrawUnselectedText(g, x, y, p0, p1);
}
}
@@ -178,14 +179,36 @@
* @param p1 the ending position in the model >= 0
* @return the X location of the end of the range >= 0
* @exception BadLocationException if the range is invalid
+ *
+ * @deprecated replaced by
+ * {@link #drawUnselectedText(Graphics2D, float, float, int, int)}
*/
+ @Deprecated(since = "9")
protected int drawUnselectedText(Graphics g, int x, int y,
int p0, int p1) throws BadLocationException {
+ return (int) drawUnselectedTextImpl(g, x, y, p0, p1, false);
+ }
+
+ private float callDrawUnselectedText(Graphics g, float x, float y,
+ int p0, int p1)
+ throws BadLocationException
+ {
+ return drawUnselectedTextOverridden && (g instanceof Graphics2D)
+ ? drawUnselectedText((Graphics2D) g, x, y, p0, p1)
+ : drawUnselectedText(g, (int) x, (int) y, p0, p1);
+ }
+
+ private float drawUnselectedTextImpl(Graphics g, float x, float y,
+ int p0, int p1,
+ boolean useFPAPI)
+ throws BadLocationException
+ {
g.setColor(unselected);
Document doc = getDocument();
Segment s = SegmentCache.getSharedSegment();
doc.getText(p0, p1 - p0, s);
- int ret = Utilities.drawTabbedText(this, s, x, y, g, this, p0);
+ float ret = Utilities.drawTabbedText(this, s, x, y, g, this, p0, null,
+ useFPAPI);
SegmentCache.releaseSharedSegment(s);
return ret;
}
@@ -194,10 +217,6 @@
* Renders the given range in the model as normal unselected
* text. Uses the foreground or disabled color to render the text.
*
- * @implSpec This implementation calls
- * {@link #drawUnselectedText(Graphics, int, int, int, int)
- * drawUnselectedText((Graphics)g, (int) x, (int) y, p0, p1)}.
- *
* @param g the graphics context
* @param x the starting X coordinate {@code >= 0}
* @param y the starting Y coordinate {@code >= 0}
@@ -205,10 +224,12 @@
* @param p1 the ending position in the model {@code >= 0}
* @return the X location of the end of the range {@code >= 0}
* @exception BadLocationException if the range is invalid
+ *
+ * @since 9
*/
protected float drawUnselectedText(Graphics2D g, float x, float y,
int p0, int p1) throws BadLocationException {
- return drawUnselectedText((Graphics)g, (int) x, (int) y, p0, p1);
+ return drawUnselectedTextImpl(g, x, y, p0, p1, true);
}
/**
@@ -224,14 +245,38 @@
* @param p1 the ending position in the model >= 0
* @return the location of the end of the range
* @exception BadLocationException if the range is invalid
+ *
+ * @deprecated replaced by
+ * {@link #drawSelectedText(Graphics2D, float, float, int, int)}
*/
+ @Deprecated(since = "9")
protected int drawSelectedText(Graphics g, int x,
- int y, int p0, int p1) throws BadLocationException {
+ int y, int p0, int p1)
+ throws BadLocationException
+ {
+ return (int) drawSelectedTextImpl(g, x, y, p0, p1, false);
+ }
+
+ float callDrawSelectedText(Graphics g, float x, float y,
+ int p0, int p1)
+ throws BadLocationException
+ {
+ return drawSelectedTextOverridden && g instanceof Graphics2D
+ ? drawSelectedText((Graphics2D) g, x, y, p0, p1)
+ : drawSelectedText(g, (int) x, (int) y, p0, p1);
+ }
+
+ private float drawSelectedTextImpl(Graphics g, float x, float y,
+ int p0, int p1,
+ boolean useFPAPI)
+ throws BadLocationException
+ {
g.setColor(selected);
Document doc = getDocument();
Segment s = SegmentCache.getSharedSegment();
doc.getText(p0, p1 - p0, s);
- int ret = Utilities.drawTabbedText(this, s, x, y, g, this, p0);
+ float ret = Utilities.drawTabbedText(this, s, x, y, g, this, p0, null,
+ useFPAPI);
SegmentCache.releaseSharedSegment(s);
return ret;
}
@@ -242,10 +287,6 @@
* the hosting component. It assumes the highlighter will render
* the selected background.
*
- * @implSpec This implementation calls
- * {@link #drawSelectedText(Graphics, int, int, int, int)
- * drawSelectedText((Graphics)g, (int) x, (int) y, p0, p1)}.
- *
* @param g the graphics context
* @param x the starting X coordinate {@code >= 0}
* @param y the starting Y coordinate {@code >= 0}
@@ -253,11 +294,12 @@
* @param p1 the ending position in the model {@code >= 0}
* @return the location of the end of the range
* @exception BadLocationException if the range is invalid
+ *
+ * @since 9
*/
-
protected float drawSelectedText(Graphics2D g, float x,
float y, int p0, int p1) throws BadLocationException {
- return drawSelectedText((Graphics)g, (int) x, (int) y, p0, p1);
+ return drawSelectedTextImpl(g, x, y, p0, p1, true);
}
/**
@@ -287,7 +329,13 @@
// The font changed, we need to recalculate the
// longest line.
calculateLongestLine();
- tabSize = getTabSize() * metrics.charWidth('m');
+ if (useFloatingPointAPI) {
+ FontRenderContext frc = metrics.getFontRenderContext();
+ float tabWidth = (float) font.getStringBounds("m", frc).getWidth();
+ tabSize = getTabSize() * tabWidth;
+ } else {
+ tabSize = getTabSize() * metrics.charWidth('m');
+ }
}
}
@@ -388,7 +436,11 @@
originalA, host, this);
}
}
- drawLine(line, g, x, y);
+ if (drawLineOverridden && (g instanceof Graphics2D)) {
+ drawLine(line, (Graphics2D) g, (float) x, (float) y);
+ } else {
+ drawLine(line, g, x, y);
+ }
y += fontHeight;
if (line == 0) {
// This should never really happen, in so far as if
@@ -435,6 +487,13 @@
int p0 = line.getStartOffset();
Segment s = SegmentCache.getSharedSegment();
doc.getText(p0, pos - p0, s);
+
+ if (useFloatingPointAPI) {
+ float xOffs = Utilities.getTabbedTextWidth(s, metrics, (float) tabBase, this, p0);
+ SegmentCache.releaseSharedSegment(s);
+ return new Rectangle2D.Float(lineArea.x + xOffs, lineArea.y, 1, metrics.getHeight());
+ }
+
int xOffs = Utilities.getTabbedTextWidth(s, metrics, tabBase, this,p0);
SegmentCache.releaseSharedSegment(s);
@@ -456,14 +515,13 @@
* given point in the view >= 0
* @see View#viewToModel
*/
- public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias) {
+ public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) {
// PENDING(prinz) properly calculate bias
bias[0] = Position.Bias.Forward;
Rectangle alloc = a.getBounds();
Document doc = getDocument();
- int x = (int) fx;
- int y = (int) fy;
+
if (y < alloc.y) {
// above the area covered by this icon, so the position
// is assumed to be the start of the coverage for this view.
@@ -481,7 +539,7 @@
Element map = doc.getDefaultRootElement();
int fontHeight = metrics.getHeight();
int lineIndex = (fontHeight > 0 ?
- Math.abs((y - alloc.y) / fontHeight) :
+ (int)Math.abs((y - alloc.y) / fontHeight) :
map.getElementCount() - 1);
if (lineIndex >= map.getElementCount()) {
return getEndOffset() - 1;
@@ -507,7 +565,7 @@
doc.getText(p0, p1 - p0, s);
tabBase = alloc.x;
int offs = p0 + Utilities.getTabbedTextOffset(s, metrics,
- tabBase, x, this, p0);
+ tabBase, x, this, p0, true);
SegmentCache.releaseSharedSegment(s);
return offs;
} catch (BadLocationException e) {
@@ -586,7 +644,7 @@
if (tabSize == 0) {
return x;
}
- int ntabs = (((int) x) - tabBase) / tabSize;
+ float ntabs = (x - tabBase) / tabSize;
return tabBase + ((ntabs + 1) * tabSize);
}
@@ -758,6 +816,28 @@
return w;
}
+ static boolean isFPMethodOverriden(String method,
+ Class<?> cls,
+ Class<?>[] intTypes,
+ Class<?>[] fpTypes)
+ {
+ Module thisModule = PlainView.class.getModule();
+ while (!thisModule.equals(cls.getModule())) {
+ try {
+ cls.getDeclaredMethod(method, fpTypes);
+ return true;
+ } catch (Exception e1) {
+ try {
+ cls.getDeclaredMethod(method, intTypes);
+ return false;
+ } catch (Exception e2) {
+ cls = cls.getSuperclass();
+ }
+ }
+ }
+ return true;
+ }
+
// --- member variables -----------------------------------------------
/**
@@ -780,7 +860,7 @@
Font font;
Segment lineBuffer;
- int tabSize;
+ float tabSize;
int tabBase;
int sel0;
@@ -796,4 +876,46 @@
*/
int firstLineOffset;
+ final boolean drawLineOverridden;
+ final boolean drawSelectedTextOverridden;
+ final boolean drawUnselectedTextOverridden;
+ final boolean useFloatingPointAPI;
+
+ {
+ final Class<?> CLS = getClass();
+ final Class<?> INT = Integer.TYPE;
+ final Class<?> FP = Float.TYPE;
+
+ drawLineOverridden = AccessController
+ .doPrivileged(new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ Class<?>[] intTypes = {INT, Graphics.class, INT, INT};
+ Class<?>[] fpTypes = {INT, Graphics2D.class, FP, FP};
+ return isFPMethodOverriden("drawLine", CLS, intTypes, fpTypes);
+ }
+ });
+
+ drawUnselectedTextOverridden = AccessController
+ .doPrivileged(new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT};
+ Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT};
+ return isFPMethodOverriden("drawUnselectedText", CLS, intTypes, fpTypes);
+ }
+ });
+
+ drawSelectedTextOverridden = AccessController
+ .doPrivileged(new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT};
+ Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT};
+ return isFPMethodOverriden("drawSelectedText", CLS, intTypes, fpTypes);
+ }
+ });
+
+ useFloatingPointAPI = drawUnselectedTextOverridden || drawSelectedTextOverridden;
+ }
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/Utilities.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/Utilities.java Thu Oct 27 21:22:57 2016 +0000
@@ -24,24 +24,23 @@
*/
package javax.swing.text;
-import java.lang.reflect.Method;
-
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Shape;
-import java.awt.Toolkit;
import java.awt.Graphics2D;
-import java.awt.font.FontRenderContext;
-import java.awt.font.TextLayout;
import java.awt.font.TextAttribute;
+import java.awt.geom.Rectangle2D;
import java.text.*;
import javax.swing.JComponent;
import javax.swing.SwingConstants;
import javax.swing.text.ParagraphView.Row;
import sun.swing.SwingUtilities2;
+import static sun.swing.SwingUtilities2.drawChars;
+import static sun.swing.SwingUtilities2.getFontCharWidth;
+import static sun.swing.SwingUtilities2.getFontCharsWidth;
/**
* A collection of methods to deal with various text
@@ -78,7 +77,11 @@
* tabs will be expanded as a space character.
* @param startOffset starting offset of the text in the document >= 0
* @return the X location at the end of the rendered text
+ *
+ * @deprecated replaced by
+ * {@link #drawTabbedText(Segment, float, float, Graphics2D, TabExpander, int)}
*/
+ @Deprecated(since = "9")
public static final int drawTabbedText(Segment s, int x, int y, Graphics g,
TabExpander e, int startOffset) {
return drawTabbedText(null, s, x, y, g, e, startOffset);
@@ -96,6 +99,8 @@
* tabs will be expanded as a space character.
* @param startOffset starting offset of the text in the document {@code >= 0}
* @return the X location at the end of the rendered text
+ *
+ * @since 9
*/
public static final float drawTabbedText(Segment s, float x, float y,
Graphics2D g,
@@ -138,9 +143,19 @@
Segment s, int x, int y, Graphics g,
TabExpander e, int startOffset,
int [] justificationData) {
+ return (int) drawTabbedText(view, s, x, y, g, e, startOffset,
+ justificationData, false);
+ }
+
+ static final float drawTabbedText(View view,
+ Segment s, float x, float y, Graphics g,
+ TabExpander e, int startOffset,
+ int [] justificationData,
+ boolean useFPAPI)
+ {
JComponent component = getJComponent(view);
FontMetrics metrics = SwingUtilities2.getFontMetrics(component, g);
- int nextX = x;
+ float nextX = x;
char[] txt = s.array;
int txtOffset = s.offset;
int flushLen = 0;
@@ -174,19 +189,19 @@
&& i <= endJustifiableContent
)) {
if (flushLen > 0) {
- nextX = SwingUtilities2.drawChars(component, g, txt,
- flushIndex, flushLen, x, y);
+ nextX = drawChars(component, g, txt, flushIndex, flushLen, x, y);
flushLen = 0;
}
flushIndex = i + 1;
if (txt[i] == '\t') {
if (e != null) {
- nextX = (int) e.nextTabStop((float) nextX, startOffset + i - txtOffset);
+ nextX = e.nextTabStop(nextX, startOffset + i - txtOffset);
} else {
- nextX += metrics.charWidth(' ');
+ nextX += getFontCharWidth(' ', metrics, useFPAPI);
}
} else if (txt[i] == ' ') {
- nextX += metrics.charWidth(' ') + spaceAddon;
+ float spaceWidth = getFontCharWidth(' ', metrics, useFPAPI);
+ nextX += spaceWidth + spaceAddon;
if (i <= spaceAddonLeftoverEnd) {
nextX++;
}
@@ -194,8 +209,8 @@
x = nextX;
} else if ((txt[i] == '\n') || (txt[i] == '\r')) {
if (flushLen > 0) {
- nextX = SwingUtilities2.drawChars(component, g, txt,
- flushIndex, flushLen, x, y);
+ nextX = drawChars(component, g, txt, flushIndex, flushLen,
+ x, y, useFPAPI);
flushLen = 0;
}
flushIndex = i + 1;
@@ -205,8 +220,7 @@
}
}
if (flushLen > 0) {
- nextX = SwingUtilities2.drawChars(component, g,txt, flushIndex,
- flushLen, x, y);
+ nextX = drawChars(component, g,txt, flushIndex, flushLen, x, y, useFPAPI);
}
return nextX;
}
@@ -223,7 +237,11 @@
* tabs will be expanded as a space character.
* @param startOffset starting offset of the text in the document >= 0
* @return the width of the text
+ *
+ * @deprecated replaced by
+ * {@link #getTabbedTextWidth(Segment, FontMetrics, float, TabExpander, int)}
*/
+ @Deprecated(since = "9")
public static final int getTabbedTextWidth(Segment s, FontMetrics metrics, int x,
TabExpander e, int startOffset) {
return getTabbedTextWidth(null, s, metrics, x, e, startOffset, null);
@@ -240,11 +258,13 @@
* tabs will be expanded as a space character.
* @param startOffset starting offset of the text in the document {@code >= 0}
* @return the width of the text
+ *
+ * @since 9
*/
public static final float getTabbedTextWidth(Segment s, FontMetrics metrics,
float x, TabExpander e,
int startOffset) {
- return getTabbedTextWidth(s, metrics, (int) x, e, startOffset);
+ return getTabbedTextWidth(null, s, metrics, x, e, startOffset, null);
}
// In addition to the previous method it can extend spaces for
@@ -254,10 +274,32 @@
// one:
// @param justificationData justificationData for the row.
// if null not justification is needed
- static final int getTabbedTextWidth(View view, Segment s, FontMetrics metrics, int x,
+ static final int getTabbedTextWidth(View view, Segment s,
+ FontMetrics metrics, int x,
+ TabExpander e, int startOffset,
+ int[] justificationData)
+ {
+ return (int) getTabbedTextWidth(view, s, metrics, x, e, startOffset,
+ justificationData, false);
+
+ }
+
+ static final float getTabbedTextWidth(View view, Segment s,
+ FontMetrics metrics, float x,
TabExpander e, int startOffset,
- int[] justificationData) {
- int nextX = x;
+ int[] justificationData)
+ {
+ return getTabbedTextWidth(view, s, metrics, x, e, startOffset,
+ justificationData, true);
+
+ }
+
+ static final float getTabbedTextWidth(View view, Segment s,
+ FontMetrics metrics, float x,
+ TabExpander e, int startOffset,
+ int[] justificationData,
+ boolean useFPAPI) {
+ float nextX = x;
char[] txt = s.array;
int txtOffset = s.offset;
int n = s.offset + s.count;
@@ -294,13 +336,13 @@
charCount = 0;
if (txt[i] == '\t') {
if (e != null) {
- nextX = (int) e.nextTabStop((float) nextX,
- startOffset + i - txtOffset);
+ nextX = e.nextTabStop(nextX, startOffset + i - txtOffset);
} else {
- nextX += metrics.charWidth(' ');
+ nextX += getFontCharWidth(' ', metrics, useFPAPI);
}
} else if (txt[i] == ' ') {
- nextX += metrics.charWidth(' ') + spaceAddon;
+ float spaceWidth = getFontCharWidth(' ', metrics, useFPAPI);
+ nextX += spaceWidth + spaceAddon;
if (i <= spaceAddonLeftoverEnd) {
nextX++;
}
@@ -308,13 +350,15 @@
} else if(txt[i] == '\n') {
// Ignore newlines, they take up space and we shouldn't be
// counting them.
- nextX += metrics.charsWidth(txt, i - charCount, charCount);
+ nextX += getFontCharsWidth(txt, i - charCount, charCount,
+ metrics, useFPAPI);
charCount = 0;
} else {
charCount++;
}
}
- nextX += metrics.charsWidth(txt, n - charCount, charCount);
+ nextX += getFontCharsWidth(txt, n - charCount, charCount,
+ metrics, useFPAPI);
return nextX - x;
}
@@ -334,7 +378,12 @@
* tabs will be expanded as a space character.
* @param startOffset starting offset of the text in the document >= 0
* @return the offset into the text >= 0
+ *
+ * @deprecated replaced by
+ * {@link #getTabbedTextOffset(Segment, FontMetrics, float, float,
+ * TabExpander, int, boolean)}
*/
+ @Deprecated(since = "9")
public static final int getTabbedTextOffset(Segment s, FontMetrics metrics,
int x0, int x, TabExpander e,
int startOffset) {
@@ -346,7 +395,7 @@
int startOffset,
int[] justificationData) {
return getTabbedTextOffset(view, s, metrics, x0, x, e, startOffset, true,
- justificationData);
+ justificationData, false);
}
/**
@@ -365,13 +414,19 @@
* @param startOffset starting offset of the text in the document >= 0
* @param round whether or not to round
* @return the offset into the text >= 0
+ *
+ * @deprecated replaced by
+ * {@link #getTabbedTextOffset(Segment, FontMetrics, float, float,
+ * TabExpander, int, boolean)}
*/
+ @Deprecated(since = "9")
public static final int getTabbedTextOffset(Segment s,
FontMetrics metrics,
int x0, int x, TabExpander e,
int startOffset,
boolean round) {
- return getTabbedTextOffset(null, s, metrics, x0, x, e, startOffset, round, null);
+ return getTabbedTextOffset(null, s, metrics, x0, x, e, startOffset,
+ round, null, false);
}
/**
@@ -390,6 +445,8 @@
* @param startOffset starting offset of the text in the document {@code >= 0}
* @param round whether or not to round
* @return the offset into the text {@code >= 0}
+ *
+ * @since 9
*/
public static final int getTabbedTextOffset(Segment s,
FontMetrics metrics,
@@ -398,8 +455,8 @@
int startOffset,
boolean round)
{
- return getTabbedTextOffset(null, s, metrics, (int) x0, (int) x, e,
- startOffset, round, null);
+ return getTabbedTextOffset(null, s, metrics, x0, x, e,
+ startOffset, round, null, true);
}
// In addition to the previous method it can extend spaces for
@@ -412,15 +469,16 @@
static final int getTabbedTextOffset(View view,
Segment s,
FontMetrics metrics,
- int x0, int x, TabExpander e,
+ float x0, float x, TabExpander e,
int startOffset,
boolean round,
- int[] justificationData) {
+ int[] justificationData,
+ boolean useFPAPI) {
if (x0 >= x) {
// x before x0, return.
return 0;
}
- int nextX = x0;
+ float nextX = x0;
// s may be a shared segment, so it is copied prior to calling
// the tab expander
char[] txt = s.array;
@@ -456,19 +514,19 @@
)){
if (txt[i] == '\t') {
if (e != null) {
- nextX = (int) e.nextTabStop((float) nextX,
- startOffset + i - txtOffset);
+ nextX = e.nextTabStop(nextX, startOffset + i - txtOffset);
} else {
- nextX += metrics.charWidth(' ');
+ nextX += getFontCharWidth(' ', metrics, useFPAPI);
}
} else if (txt[i] == ' ') {
- nextX += metrics.charWidth(' ') + spaceAddon;
+ nextX += getFontCharWidth(' ', metrics, useFPAPI);
+ nextX += spaceAddon;
if (i <= spaceAddonLeftoverEnd) {
nextX++;
}
}
} else {
- nextX += metrics.charWidth(txt[i]);
+ nextX += getFontCharWidth(txt[i], metrics, useFPAPI);
}
if (x < nextX) {
// found the hit position... return the appropriate side
@@ -480,12 +538,15 @@
if (round) {
offset = i + 1 - txtOffset;
- int width = metrics.charsWidth(txt, txtOffset, offset);
- int span = x - x0;
+ float width = getFontCharsWidth(txt, txtOffset, offset,
+ metrics, useFPAPI);
+ float span = x - x0;
if (span < width) {
while (offset > 0) {
- int nextWidth = offset > 1 ? metrics.charsWidth(txt, txtOffset, offset - 1) : 0;
+ float charsWidth = getFontCharsWidth(txt, txtOffset,
+ offset - 1, metrics, useFPAPI);
+ float nextWidth = offset > 1 ? charsWidth : 0;
if (span >= nextWidth) {
if (span - nextWidth < width - span) {
@@ -502,7 +563,9 @@
} else {
offset = i - txtOffset;
- while (offset > 0 && metrics.charsWidth(txt, txtOffset, offset) > (x - x0)) {
+ while (offset > 0 && getFontCharsWidth(txt, txtOffset, offset,
+ metrics, useFPAPI)
+ > (x - x0)) {
offset--;
}
}
@@ -528,15 +591,26 @@
* tabs will be expanded as a space character.
* @param startOffset starting offset in the document of the text
* @return the offset into the given text
+ *
+ * @deprecated replaced by
+ * {@link #getBreakLocation(Segment, FontMetrics, float, float,
+ * TabExpander, int)}
*/
+ @Deprecated(since = "9")
public static final int getBreakLocation(Segment s, FontMetrics metrics,
int x0, int x, TabExpander e,
int startOffset) {
+ return getBreakLocation(s, metrics, x0, x, e, startOffset, false);
+ }
+
+ static final int getBreakLocation(Segment s, FontMetrics metrics,
+ float x0, float x, TabExpander e,
+ int startOffset, boolean useFPIAPI) {
char[] txt = s.array;
int txtOffset = s.offset;
int txtCount = s.count;
- int index = Utilities.getTabbedTextOffset(s, metrics, x0, x,
- e, startOffset, false);
+ int index = getTabbedTextOffset(null, s, metrics, x0, x, e, startOffset,
+ false, null, useFPIAPI);
if (index >= txtCount - 1) {
return txtCount;
@@ -577,11 +651,13 @@
* tabs will be expanded as a space character.
* @param startOffset starting offset in the document of the text
* @return the offset into the given text
+ *
+ * @since 9
*/
public static final int getBreakLocation(Segment s, FontMetrics metrics,
float x0, float x, TabExpander e,
int startOffset) {
- return getBreakLocation(s, metrics, (int) x0, (int) x, e, startOffset);
+ return getBreakLocation(s, metrics, x0, x, e, startOffset, false);
}
/**
@@ -627,16 +703,16 @@
* @exception BadLocationException if the offset is out of range
*/
public static final int getRowEnd(JTextComponent c, int offs) throws BadLocationException {
- Rectangle r = c.modelToView(offs);
+ Rectangle2D r = c.modelToView2D(offs);
if (r == null) {
return -1;
}
int n = c.getDocument().getLength();
int lastOffs = offs;
- int y = r.y;
- while ((r != null) && (y == r.y)) {
+ double y = r.getY();
+ while ((r != null) && (y == r.getY())) {
// Skip invisible elements
- if (r.height !=0) {
+ if (r.getHeight() !=0) {
offs = lastOffs;
}
lastOffs += 1;
@@ -657,27 +733,44 @@
* @return the position >= 0 if the request can be computed, otherwise
* a value of -1 will be returned.
* @exception BadLocationException if the offset is out of range
+ *
+ * @deprecated replaced by
+ * {@link #getPositionAbove(JTextComponent, int, float)}
*/
- public static final int getPositionAbove(JTextComponent c, int offs, int x) throws BadLocationException {
+ @Deprecated(since = "9")
+ public static final int getPositionAbove(JTextComponent c, int offs, int x)
+ throws BadLocationException
+ {
+ return getPositionAbove(c, offs, x, false);
+ }
+
+ static final int getPositionAbove(JTextComponent c, int offs, float x,
+ boolean useFPAPI) throws BadLocationException
+ {
int lastOffs = getRowStart(c, offs) - 1;
if (lastOffs < 0) {
return -1;
}
- int bestSpan = Integer.MAX_VALUE;
- int y = 0;
- Rectangle r = null;
+ double bestSpan = Integer.MAX_VALUE;
+ double y = 0;
+ Rectangle2D r = null;
if (lastOffs >= 0) {
- r = c.modelToView(lastOffs);
- y = r.y;
+ r = useFPAPI ? c.modelToView2D(lastOffs) : c.modelToView(lastOffs);
+ y = r.getY();
}
- while ((r != null) && (y == r.y)) {
- int span = Math.abs(r.x - x);
+ while ((r != null) && (y == r.getY())) {
+ double span = Math.abs(r.getX() - x);
if (span < bestSpan) {
offs = lastOffs;
bestSpan = span;
}
lastOffs -= 1;
- r = (lastOffs >= 0) ? c.modelToView(lastOffs) : null;
+
+ if ((lastOffs >= 0)) {
+ r = useFPAPI ? c.modelToView2D(lastOffs) : c.modelToView(lastOffs);
+ } else {
+ r = null;
+ }
}
return offs;
}
@@ -694,10 +787,12 @@
* @return the position {@code >= 0} if the request can be computed, otherwise
* a value of -1 will be returned.
* @exception BadLocationException if the offset is out of range
+ *
+ * @since 9
*/
public static final int getPositionAbove(JTextComponent c, int offs, float x)
throws BadLocationException {
- return getPositionAbove(c, offs, (int) x);
+ return getPositionAbove(c, offs, x, true);
}
/**
@@ -712,28 +807,45 @@
* @return the position >= 0 if the request can be computed, otherwise
* a value of -1 will be returned.
* @exception BadLocationException if the offset is out of range
+ *
+ * @deprecated replaced by
+ * {@link #getPositionBelow(JTextComponent, int, float)}
*/
- public static final int getPositionBelow(JTextComponent c, int offs, int x) throws BadLocationException {
+ @Deprecated(since = "9")
+ public static final int getPositionBelow(JTextComponent c, int offs, int x)
+ throws BadLocationException
+ {
+ return getPositionBelow(c, offs, x, false);
+ }
+
+ static final int getPositionBelow(JTextComponent c, int offs, float x,
+ boolean useFPAPI) throws BadLocationException
+ {
int lastOffs = getRowEnd(c, offs) + 1;
if (lastOffs <= 0) {
return -1;
}
- int bestSpan = Integer.MAX_VALUE;
+ double bestSpan = Integer.MAX_VALUE;
int n = c.getDocument().getLength();
- int y = 0;
- Rectangle r = null;
+ double y = 0;
+ Rectangle2D r = null;
if (lastOffs <= n) {
- r = c.modelToView(lastOffs);
- y = r.y;
+ r = useFPAPI ? c.modelToView2D(lastOffs) : c.modelToView(lastOffs);
+ y = r.getY();
}
- while ((r != null) && (y == r.y)) {
- int span = Math.abs(x - r.x);
+ while ((r != null) && (y == r.getY())) {
+ double span = Math.abs(x - r.getX());
if (span < bestSpan) {
offs = lastOffs;
bestSpan = span;
}
lastOffs += 1;
- r = (lastOffs <= n) ? c.modelToView(lastOffs) : null;
+
+ if (lastOffs <= n) {
+ r = useFPAPI ? c.modelToView2D(lastOffs) : c.modelToView(lastOffs);
+ } else {
+ r = null;
+ }
}
return offs;
}
@@ -750,10 +862,12 @@
* @return the position {@code >= 0} if the request can be computed, otherwise
* a value of -1 will be returned.
* @exception BadLocationException if the offset is out of range
+ *
+ * @since 9
*/
public static final int getPositionBelow(JTextComponent c, int offs, float x)
throws BadLocationException {
- return getPositionBelow(c, offs, (int) x);
+ return getPositionBelow(c, offs, x, true);
}
/**
@@ -1029,7 +1143,23 @@
*/
static int drawComposedText(View view, AttributeSet attr, Graphics g,
int x, int y, int p0, int p1)
- throws BadLocationException {
+ throws BadLocationException
+ {
+ return (int) drawComposedText(view, attr, g, x, y, p0, p1, false);
+ }
+
+ static float drawComposedText(View view, AttributeSet attr, Graphics g,
+ float x, float y, int p0, int p1)
+ throws BadLocationException
+ {
+ return drawComposedText(view, attr, g, x, y, p0, p1, true);
+ }
+
+ static float drawComposedText(View view, AttributeSet attr, Graphics g,
+ float x, float y, int p0, int p1,
+ boolean useFPAPI)
+ throws BadLocationException
+ {
Graphics2D g2d = (Graphics2D)g;
AttributedString as = (AttributedString)attr.getAttribute(
StyleConstants.ComposedTextAttribute);
@@ -1039,8 +1169,7 @@
return x;
AttributedCharacterIterator aci = as.getIterator(null, p0, p1);
- return x + (int)SwingUtilities2.drawString(
- getJComponent(view), g2d,aci,x,y);
+ return x + SwingUtilities2.drawString(getJComponent(view), g2d, aci, x, y);
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java Thu Oct 27 21:22:57 2016 +0000
@@ -25,8 +25,12 @@
package javax.swing.text;
import java.awt.*;
+import java.awt.font.FontRenderContext;
import java.lang.ref.SoftReference;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import javax.swing.event.*;
+import static javax.swing.text.PlainView.isFPMethodOverriden;
/**
* View of plain text (text with only one font and color)
@@ -87,17 +91,6 @@
}
/**
- * Returns the tab size set for the document, defaulting to 8.
- *
- * @implSpec This implementation calls {@link #getTabSize() getTabSize()}.
- *
- * @return the tab size
- */
- protected float getFractionalTabSize() {
- return getTabSize();
- }
-
- /**
* Renders a line of text, suppressing whitespace at the end
* and expanding any tabs. This is implemented to make calls
* to the methods <code>drawUnselectedText</code> and
@@ -111,8 +104,17 @@
* @param y the starting Y position >= 0
* @see #drawUnselectedText
* @see #drawSelectedText
+ *
+ * @deprecated replaced by
+ * {@link #drawLine(int, int, Graphics2D, float, float)}
*/
+ @Deprecated(since = "9")
protected void drawLine(int p0, int p1, Graphics g, int x, int y) {
+ drawLineImpl(p0, p1, g, x, y, false);
+ }
+
+ private void drawLineImpl(int p0, int p1, Graphics g, float x, float y,
+ boolean useFPAPI) {
Element lineMap = getElement();
Element line = lineMap.getElement(lineMap.getElementIndex(p0));
Element elem;
@@ -143,10 +145,6 @@
* <code>drawSelectedText</code> so that the way selected and
* unselected text are rendered can be customized.
*
- * @implSpec This implementation calls
- * {@link #drawLine(int, int, Graphics, int, int)
- * drawLine(p0, p1, (Graphics) g, (int) x, (int) y)}.
- *
* @param p0 the starting document location to use >= 0
* @param p1 the ending document location to use >= p1
* @param g the graphics context
@@ -154,12 +152,17 @@
* @param y the starting Y position >= 0
* @see #drawUnselectedText
* @see #drawSelectedText
+ *
+ * @since 9
*/
protected void drawLine(int p0, int p1, Graphics2D g, float x, float y) {
- drawLine(p0, p1, (Graphics) g, (int) x, (int) y);
+ drawLineImpl(p0, p1, g, x, y, true);
}
- private int drawText(Element elem, int p0, int p1, Graphics g, int x, int y) throws BadLocationException {
+ private float drawText(Element elem, int p0, int p1, Graphics g,
+ float x, float y)
+ throws BadLocationException
+ {
p1 = Math.min(getDocument().getLength(), p1);
AttributeSet attr = elem.getAttributes();
@@ -171,23 +174,23 @@
} else {
if (sel0 == sel1 || selected == unselected) {
// no selection, or it is invisible
- x = drawUnselectedText(g, x, y, p0, p1);
+ x = callDrawUnselectedText(g, x, y, p0, p1);
} else if ((p0 >= sel0 && p0 <= sel1) && (p1 >= sel0 && p1 <= sel1)) {
- x = drawSelectedText(g, x, y, p0, p1);
+ x = callDrawSelectedText(g, x, y, p0, p1);
} else if (sel0 >= p0 && sel0 <= p1) {
if (sel1 >= p0 && sel1 <= p1) {
- x = drawUnselectedText(g, x, y, p0, sel0);
- x = drawSelectedText(g, x, y, sel0, sel1);
- x = drawUnselectedText(g, x, y, sel1, p1);
+ x = callDrawUnselectedText(g, x, y, p0, sel0);
+ x = callDrawSelectedText(g, x, y, sel0, sel1);
+ x = callDrawUnselectedText(g, x, y, sel1, p1);
} else {
- x = drawUnselectedText(g, x, y, p0, sel0);
- x = drawSelectedText(g, x, y, sel0, p1);
+ x = callDrawUnselectedText(g, x, y, p0, sel0);
+ x = callDrawSelectedText(g, x, y, sel0, p1);
}
} else if (sel1 >= p0 && sel1 <= p1) {
- x = drawSelectedText(g, x, y, p0, sel1);
- x = drawUnselectedText(g, x, y, sel1, p1);
+ x = callDrawSelectedText(g, x, y, p0, sel1);
+ x = callDrawUnselectedText(g, x, y, sel1, p1);
} else {
- x = drawUnselectedText(g, x, y, p0, p1);
+ x = callDrawUnselectedText(g, x, y, p0, p1);
}
}
@@ -205,14 +208,36 @@
* @param p1 the ending position in the model >= p0
* @return the X location of the end of the range >= 0
* @exception BadLocationException if the range is invalid
+ *
+ * @deprecated replaced by
+ * {@link #drawUnselectedText(Graphics2D, float, float, int, int)}
*/
+ @Deprecated(since = "9")
protected int drawUnselectedText(Graphics g, int x, int y,
- int p0, int p1) throws BadLocationException {
+ int p0, int p1) throws BadLocationException
+ {
+ return (int) drawUnselectedTextImpl(g, x, y, p0, p1, false);
+ }
+
+ private float callDrawUnselectedText(Graphics g, float x, float y,
+ int p0, int p1)
+ throws BadLocationException
+ {
+ return drawUnselectedTextOverridden && g instanceof Graphics2D
+ ? drawUnselectedText((Graphics2D) g, x, y, p0, p1)
+ : drawUnselectedText(g, (int) x, (int) y, p0, p1);
+ }
+
+ private float drawUnselectedTextImpl(Graphics g, float x, float y,
+ int p0, int p1, boolean useFPAPI)
+ throws BadLocationException
+ {
g.setColor(unselected);
Document doc = getDocument();
Segment segment = SegmentCache.getSharedSegment();
doc.getText(p0, p1 - p0, segment);
- int ret = Utilities.drawTabbedText(this, segment, x, y, g, this, p0);
+ float ret = Utilities.drawTabbedText(this, segment, x, y, g, this, p0,
+ null, useFPAPI);
SegmentCache.releaseSharedSegment(segment);
return ret;
}
@@ -221,10 +246,6 @@
* Renders the given range in the model as normal unselected
* text.
*
- * @implSpec This implementation calls
- * {@link #drawUnselectedText(Graphics, int, int, int, int)
- * drawUnselectedText((Graphics)g, (int) x, (int) y, p0, p1)}.
- *
* @param g the graphics context
* @param x the starting X coordinate >= 0
* @param y the starting Y coordinate >= 0
@@ -232,10 +253,12 @@
* @param p1 the ending position in the model >= p0
* @return the X location of the end of the range >= 0
* @exception BadLocationException if the range is invalid
+ *
+ * @since 9
*/
protected float drawUnselectedText(Graphics2D g, float x, float y,
int p0, int p1) throws BadLocationException {
- return drawUnselectedText((Graphics) g, (int) x, (int) y, p0, p1);
+ return drawUnselectedTextImpl(g, x, y, p0, p1, true);
}
/**
* Renders the given range in the model as selected text. This
@@ -250,14 +273,37 @@
* @param p1 the ending position in the model >= p0
* @return the location of the end of the range.
* @exception BadLocationException if the range is invalid
+ *
+ * @deprecated replaced by
+ * {@link #drawSelectedText(Graphics2D, float, float, int, int)}
*/
- protected int drawSelectedText(Graphics g, int x,
- int y, int p0, int p1) throws BadLocationException {
+ @Deprecated(since = "9")
+ protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1)
+ throws BadLocationException
+ {
+ return (int) drawSelectedTextImpl(g, x, y, p0, p1, false);
+ }
+
+ private float callDrawSelectedText(Graphics g, float x, float y,
+ int p0, int p1)
+ throws BadLocationException
+ {
+ return drawSelectedTextOverridden && g instanceof Graphics2D
+ ? drawSelectedText((Graphics2D) g, x, y, p0, p1)
+ : drawSelectedText(g, (int) x, (int) y, p0, p1);
+ }
+
+ private float drawSelectedTextImpl(Graphics g, float x, float y,
+ int p0, int p1,
+ boolean useFPAPI)
+ throws BadLocationException
+ {
g.setColor(selected);
Document doc = getDocument();
Segment segment = SegmentCache.getSharedSegment();
doc.getText(p0, p1 - p0, segment);
- int ret = Utilities.drawTabbedText(this, segment, x, y, g, this, p0);
+ float ret = Utilities.drawTabbedText(this, segment, x, y, g, this, p0,
+ null, useFPAPI);
SegmentCache.releaseSharedSegment(segment);
return ret;
}
@@ -268,10 +314,6 @@
* the hosting component. It assumes the highlighter will render
* the selected background.
*
- * @implSpec This implementation calls
- * {@link #drawSelectedText(Graphics, int, int, int, int)
- * drawSelectedText((Graphics)g, (int) x, (int) y, p0, p1)}.
- *
* @param g the graphics context
* @param x the starting X coordinate >= 0
* @param y the starting Y coordinate >= 0
@@ -279,10 +321,12 @@
* @param p1 the ending position in the model >= p0
* @return the location of the end of the range.
* @exception BadLocationException if the range is invalid
+ *
+ * @since 9
*/
protected float drawSelectedText(Graphics2D g, float x, float y,
int p0, int p1) throws BadLocationException {
- return drawSelectedText((Graphics) g, (int) x, (int) y, p0, p1);
+ return drawSelectedTextImpl(g, x, y, p0, p1, true);
}
/**
* Gives access to a buffer that can be used to fetch
@@ -395,7 +439,13 @@
Component host = getContainer();
Font f = host.getFont();
metrics = host.getFontMetrics(f);
- tabSize = getTabSize() * metrics.charWidth('m');
+ if (useFloatingPointAPI) {
+ FontRenderContext frc = metrics.getFontRenderContext();
+ float tabWidth = (float) f.getStringBounds("m", frc).getWidth();
+ tabSize = getTabSize() * tabWidth;
+ } else {
+ tabSize = getTabSize() * metrics.charWidth('m');
+ }
}
// --- TabExpander methods ------------------------------------------
@@ -413,7 +463,7 @@
public float nextTabStop(float x, int tabOffset) {
if (tabSize == 0)
return x;
- int ntabs = ((int) x - tabBase) / tabSize;
+ float ntabs = (x - tabBase) / tabSize;
return tabBase + ((ntabs + 1) * tabSize);
}
@@ -591,7 +641,7 @@
Segment lineBuffer;
boolean widthChanging;
int tabBase;
- int tabSize;
+ float tabSize;
boolean wordWrap;
int sel0;
@@ -668,6 +718,7 @@
int end = getEndOffset();
int p0 = start;
int[] lineEnds = getLineEnds();
+ boolean useDrawLineFP = drawLineOverridden && g instanceof Graphics2D;
for (int i = 0; i < lineCount; i++) {
int p1 = (lineEnds == null) ? end :
start + lineEnds[i];
@@ -677,8 +728,11 @@
: p1;
dh.paintLayeredHighlights(g, p0, hOffset, a, host, this);
}
- drawLine(p0, p1, g, x, y);
-
+ if (useDrawLineFP) {
+ drawLine(p0, p1, (Graphics2D) g, (float) x, (float) y);
+ } else {
+ drawLine(p0, p1, g, x, y);
+ }
p0 = p1;
y += metrics.getHeight();
}
@@ -929,4 +983,47 @@
int lineCount;
SoftReference<int[]> lineCache = null;
}
+
+ private final boolean drawLineOverridden;
+ private final boolean drawSelectedTextOverridden;
+ private final boolean drawUnselectedTextOverridden;
+ private final boolean useFloatingPointAPI;
+
+ {
+ final Class<?> CLS = getClass();
+ final Class<?> INT = Integer.TYPE;
+ final Class<?> FP = Float.TYPE;
+
+ drawLineOverridden = AccessController
+ .doPrivileged(new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ Class<?>[] intTypes = {INT, INT, Graphics.class, INT, INT};
+ Class<?>[] fpTypes = {INT, INT, Graphics2D.class, FP, FP};
+ return isFPMethodOverriden("drawLine", CLS, intTypes, fpTypes);
+ }
+ });
+
+ drawUnselectedTextOverridden = AccessController
+ .doPrivileged(new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT};
+ Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT};
+ return isFPMethodOverriden("drawUnselectedText", CLS, intTypes, fpTypes);
+ }
+ });
+
+ drawSelectedTextOverridden = AccessController
+ .doPrivileged(new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT};
+ Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT};
+ return isFPMethodOverriden("drawSelectedText", CLS, intTypes, fpTypes);
+ }
+ });
+
+ useFloatingPointAPI = drawUnselectedTextOverridden || drawSelectedTextOverridden;
+ }
}
--- a/jdk/src/java.desktop/share/classes/module-info.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/module-info.java Thu Oct 27 21:22:57 2016 +0000
@@ -88,6 +88,9 @@
exports sun.awt to
jdk.accessibility;
+ exports com.sun.awt to
+ jdk.desktop;
+
uses java.awt.im.spi.InputMethodDescriptor;
uses javax.accessibility.AccessibilityProvider;
uses javax.imageio.spi.ImageInputStreamSpi;
--- a/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java Thu Oct 27 21:22:57 2016 +0000
@@ -107,7 +107,7 @@
/*
* Requests focus to the component.
*/
- boolean requestFocus(Component comp, Cause cause);
+ void requestFocus(Component comp, Cause cause);
/*
* Determines if the component can gain focus.
*/
@@ -1392,4 +1392,4 @@
AWTAccessor.dropTargetContextAccessor = accessor;
}
-}
\ No newline at end of file
+}
--- a/jdk/src/java.desktop/share/classes/sun/awt/IconInfo.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/sun/awt/IconInfo.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -103,7 +103,7 @@
}
this.scaledWidth = width;
this.scaledHeight = height;
- this.rawLength = getScaledRawLength();
+ this.rawLength = getScaledRawLength(width, height);
}
/*
@@ -112,14 +112,14 @@
public void setScaledSize(int width, int height) {
this.scaledWidth = width;
this.scaledHeight = height;
- this.rawLength = getScaledRawLength();
+ this.rawLength = getScaledRawLength(width, height);
}
/*
* returns scaled raw length.
*/
- private int getScaledRawLength() {
- int scaledWidthAndHeight[] = getScaledWidthAndHeight(width, height);
+ private int getScaledRawLength(int w, int h) {
+ int scaledWidthAndHeight[] = getScaledWidthAndHeight(w, h);
return scaledWidthAndHeight[0] * scaledWidthAndHeight[1] + 2;
}
--- a/jdk/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java Thu Oct 27 21:22:57 2016 +0000
@@ -142,8 +142,8 @@
}
// WARNING: Don't call it on the Toolkit thread.
- public static boolean requestFocusFor(Component target, FocusEvent.Cause cause) {
- return AWTAccessor.getComponentAccessor().requestFocus(target, cause);
+ public static void requestFocusFor(Component target, FocusEvent.Cause cause) {
+ AWTAccessor.getComponentAccessor().requestFocus(target, cause);
}
// WARNING: Don't call it on the Toolkit thread.
--- a/jdk/src/java.desktop/share/classes/sun/awt/SunToolkit.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/sun/awt/SunToolkit.java Thu Oct 27 21:22:57 2016 +0000
@@ -1512,9 +1512,9 @@
*/
protected abstract boolean syncNativeQueue(final long timeout);
- private boolean eventDispatched = false;
- private boolean queueEmpty = false;
- private final Object waitLock = "Wait Lock";
+ private boolean eventDispatched;
+ private boolean queueEmpty;
+ private final Object waitLock = new Object();
private boolean isEQEmpty() {
EventQueue queue = getSystemEventQueueImpl();
@@ -1531,10 +1531,11 @@
@SuppressWarnings("serial")
protected final boolean waitForIdle(final long timeout) {
flushPendingEvents();
- boolean queueWasEmpty = isEQEmpty();
- queueEmpty = false;
- eventDispatched = false;
- synchronized(waitLock) {
+ final boolean queueWasEmpty;
+ synchronized (waitLock) {
+ queueWasEmpty = isEQEmpty();
+ queueEmpty = false;
+ eventDispatched = false;
postEvent(AppContext.getAppContext(),
new PeerEvent(getSystemEventQueueImpl(), null, PeerEvent.LOW_PRIORITY_EVENT) {
@Override
--- a/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java Thu Oct 27 21:22:57 2016 +0000
@@ -1902,11 +1902,7 @@
clipRegion = devClip;
} else if (usrClip instanceof Rectangle2D) {
clipState = CLIP_RECTANGULAR;
- if (usrClip instanceof Rectangle) {
- clipRegion = devClip.getIntersection((Rectangle)usrClip);
- } else {
- clipRegion = devClip.getIntersection(usrClip.getBounds());
- }
+ clipRegion = devClip.getIntersection((Rectangle2D) usrClip);
} else {
PathIterator cpi = usrClip.getPathIterator(null);
int box[] = new int[4];
--- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/Region.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/Region.java Thu Oct 27 21:22:57 2016 +0000
@@ -28,10 +28,13 @@
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
import java.awt.geom.RectangularShape;
import sun.java2d.loops.TransformHelper;
+import static java.lang.Double.isNaN;
+
/**
* This class encapsulates a definition of a two dimensional region which
* consists of a number of Y ranges each containing multiple X bands.
@@ -118,6 +121,34 @@
}
/**
+ * Returns the closest {@code int} to the argument, with ties rounding to
+ * negative infinity.
+ * <p>
+ * Special cases:
+ * <ul><li>If the argument is NaN, the result is 0.
+ * <li>If the argument is negative infinity or any value less than or
+ * equal to the value of {@code Integer.MIN_VALUE}, the result is
+ * equal to the value of {@code Integer.MIN_VALUE}.
+ * <li>If the argument is positive infinity or any value greater than or
+ * equal to the value of {@code Integer.MAX_VALUE}, the result is
+ * equal to the value of {@code Integer.MAX_VALUE}.</ul>
+ *
+ * @param coordinate a floating-point value to be rounded to an integer
+ * @return the value of the argument rounded to the nearest
+ * {@code int} value.
+ */
+ public static int clipRound(final double coordinate) {
+ final double newv = coordinate - 0.5;
+ if (newv < Integer.MIN_VALUE) {
+ return Integer.MIN_VALUE;
+ }
+ if (newv > Integer.MAX_VALUE) {
+ return Integer.MAX_VALUE;
+ }
+ return (int) Math.ceil(newv);
+ }
+
+ /**
* Multiply the scale factor {@code sv} and the value {@code v} with
* appropriate clipping to the bounds of Integer resolution. If the answer
* would be greater than {@code Integer.MAX_VALUE} then {@code
@@ -559,6 +590,33 @@
/**
* Returns a Region object that represents the intersection of
+ * this object with the specified Rectangle2D. The return value
+ * may be this same object if no clipping occurs.
+ */
+ public Region getIntersection(final Rectangle2D r) {
+ if (r instanceof Rectangle) {
+ return getIntersection((Rectangle) r);
+ }
+ return getIntersectionXYXY(r.getMinX(), r.getMinY(), r.getMaxX(),
+ r.getMaxY());
+ }
+
+ /**
+ * Returns a Region object that represents the intersection of
+ * this object with the specified rectangular area. The return
+ * value may be this same object if no clipping occurs.
+ */
+ public Region getIntersectionXYXY(double lox, double loy, double hix,
+ double hiy) {
+ if (isNaN(lox) || isNaN(loy) || isNaN(hix) || isNaN(hiy)) {
+ return EMPTY_REGION;
+ }
+ return getIntersectionXYXY(clipRound(lox), clipRound(loy),
+ clipRound(hix), clipRound(hiy));
+ }
+
+ /**
+ * Returns a Region object that represents the intersection of
* this object with the specified rectangular area. The return
* value may be this same object if no clipping occurs.
*/
--- a/jdk/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java Thu Oct 27 21:22:57 2016 +0000
@@ -30,6 +30,7 @@
import static java.awt.RenderingHints.*;
import java.awt.event.*;
import java.awt.font.*;
+import java.awt.geom.Rectangle2D;
import java.awt.geom.AffineTransform;
import static java.awt.geom.AffineTransform.TYPE_FLIP;
import static java.awt.geom.AffineTransform.TYPE_TRANSLATION;
@@ -723,10 +724,31 @@
int length,
int x,
int y) {
+ return (int) drawChars(c, g, data, offset, length, x, y, false);
+ }
+
+ public static float drawChars(JComponent c, Graphics g,
+ char[] data,
+ int offset,
+ int length,
+ float x,
+ float y) {
+ return drawChars(c, g, data, offset, length, x, y, true);
+ }
+
+ public static float drawChars(JComponent c, Graphics g,
+ char[] data,
+ int offset,
+ int length,
+ float x,
+ float y,
+ boolean useFPAPI) {
if ( length <= 0 ) { //no need to paint empty strings
return x;
}
- int nextX = x + getFontMetrics(c, g).charsWidth(data, offset, length);
+ float nextX = x + getFontCharsWidth(data, offset, length,
+ getFontMetrics(c, g),
+ useFPAPI);
if (isPrinting(g)) {
Graphics2D g2d = getGraphics2D(g);
if (g2d != null) {
@@ -766,8 +788,14 @@
Object aaHint = (c == null)
? null
: c.getClientProperty(KEY_TEXT_ANTIALIASING);
- if (aaHint != null && (g instanceof Graphics2D)) {
- Graphics2D g2 = (Graphics2D)g;
+
+ if (!(g instanceof Graphics2D)) {
+ g.drawChars(data, offset, length, (int) x, (int) y);
+ return nextX;
+ }
+
+ Graphics2D g2 = (Graphics2D) g;
+ if (aaHint != null) {
Object oldContrast = null;
Object oldAAValue = g2.getRenderingHint(KEY_TEXT_ANTIALIASING);
@@ -788,7 +816,7 @@
}
}
- g.drawChars(data, offset, length, x, y);
+ g2.drawString(new String(data, offset, length), x, y);
if (oldAAValue != null) {
g2.setRenderingHint(KEY_TEXT_ANTIALIASING, oldAAValue);
@@ -798,19 +826,59 @@
}
}
else {
- g.drawChars(data, offset, length, x, y);
+ g2.drawString(new String(data, offset, length), x, y);
}
return nextX;
}
+ public static float getFontCharWidth(char c, FontMetrics fm,
+ boolean useFPAPI)
+ {
+ return getFontCharsWidth(new char[]{c}, 0, 1, fm, useFPAPI);
+ }
+
+ public static float getFontCharsWidth(char[] data, int offset, int len,
+ FontMetrics fm,
+ boolean useFPAPI)
+ {
+ return len == 0 ? 0 : getFontStringWidth(new String(data, offset, len),
+ fm, useFPAPI);
+ }
+
+ public static float getFontStringWidth(String data, FontMetrics fm,
+ boolean useFPAPI)
+ {
+ if (useFPAPI) {
+ Rectangle2D bounds = fm.getFont()
+ .getStringBounds(data, fm.getFontRenderContext());
+ return (float) bounds.getWidth();
+ } else {
+ return fm.stringWidth(data);
+ }
+ }
+
/*
* see documentation for drawChars
* returns the advance
*/
public static float drawString(JComponent c, Graphics g,
AttributedCharacterIterator iterator,
- int x,
- int y) {
+ int x, int y)
+ {
+ return drawStringImpl(c, g, iterator, x, y);
+ }
+
+ public static float drawString(JComponent c, Graphics g,
+ AttributedCharacterIterator iterator,
+ float x, float y)
+ {
+ return drawStringImpl(c, g, iterator, x, y);
+ }
+
+ private static float drawStringImpl(JComponent c, Graphics g,
+ AttributedCharacterIterator iterator,
+ float x, float y)
+ {
float retVal;
boolean isPrinting = isPrinting(g);
@@ -825,8 +893,8 @@
Graphics2D g2d = getGraphics2D(g);
if (g2d == null) {
- g.drawString(iterator,x,y); //for the cases where advance
- //matters it should not happen
+ g.drawString(iterator, (int)x, (int)y); //for the cases where advance
+ //matters it should not happen
retVal = x;
} else {
--- a/jdk/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.c Thu Oct 27 21:22:57 2016 +0000
@@ -25,7 +25,12 @@
#include "splashscreen_impl.h"
#include "splashscreen_gfx_impl.h"
-
+#define BUFF_SIZE 1024
+#ifdef _MSC_VER
+# ifndef snprintf
+# define snprintf _snprintf
+# endif
+#endif
int splashIsVisible = 0;
Splash *
@@ -392,5 +397,101 @@
SPLASHEXPORT int
SplashGetScaledImgNameMaxPstfixLen(const char *fileName){
- return strlen(fileName) + strlen(".java-scale-200") + 1;
+ return strlen(fileName) + strlen("@100pct") + 1;
}
+
+jboolean GetScaledImageName(const char *fileName, char *scaleImageName,
+ float *scaleFactor, const size_t scaledImageLength) {
+ if (*scaleFactor > 1.0) {
+ FILE *fp = NULL;
+ char scaledImgPct[BUFF_SIZE];
+ char scaledImgX[BUFF_SIZE];
+ char *scaledImageXName = NULL;
+ char *scaledImagePctName = malloc(scaledImageLength);
+ char *dupFileName = strdup(fileName);
+ char *fileExtension = strrchr(dupFileName, '.');
+ size_t lengthPct = 0;
+ size_t lengthX = 0;
+ int retValPct = 0;
+ int retValX = 0;
+ jboolean isPctScaledImage = (*scaleFactor * 100) != ((int) (*scaleFactor)) *100;
+ snprintf(scaledImgPct, BUFF_SIZE, "%s%d%s", "@",
+ (int) (*scaleFactor * 100), "pct");
+ if (!isPctScaledImage) {
+ scaledImageXName = malloc(scaledImageLength);
+ snprintf(scaledImgX, BUFF_SIZE, "%s%d%s", "@", (int) (*scaleFactor), "x");
+ }
+ /*File is missing extension */
+ if (fileExtension == NULL) {
+ lengthPct = strlen(dupFileName) +
+ strlen(scaledImgPct) + 1;
+ if (!isPctScaledImage) {
+ lengthX = strlen(dupFileName) +
+ strlen(scaledImgX) + 1;
+ }
+ if (lengthPct > scaledImageLength || lengthX > scaledImageLength) {
+ cleanUp(dupFileName, scaledImageXName, scaledImagePctName, scaleFactor);
+ return JNI_FALSE;
+ }
+ retValPct = snprintf(scaledImagePctName, lengthPct, "%s%s", dupFileName,
+ scaledImgPct);
+ if (!isPctScaledImage) {
+ retValX = snprintf(scaledImageXName, lengthX, "%s%s", dupFileName,
+ scaledImgX);
+ }
+ if ((retValPct < 0 || (retValPct > lengthPct - 1)) ||
+ (retValX < 0 || (retValX > lengthX - 1))) {
+ cleanUp(dupFileName, scaledImageXName, scaledImagePctName, scaleFactor);
+ return JNI_FALSE;
+ }
+ } else {
+ int length_Without_Ext = fileExtension - dupFileName;
+ lengthPct = length_Without_Ext + strlen(scaledImgPct) +
+ strlen(fileExtension) + 1;
+ if (!isPctScaledImage) {
+ lengthX = length_Without_Ext + strlen(scaledImgX) +
+ strlen(fileExtension) + 1;
+ }
+ if (lengthPct > scaledImageLength || lengthX > scaledImageLength) {
+ cleanUp(dupFileName, scaledImageXName, scaledImagePctName, scaleFactor);
+ return JNI_FALSE;
+ }
+ retValPct = snprintf(scaledImagePctName, lengthPct, "%.*s%s%s",
+ length_Without_Ext, dupFileName, scaledImgPct, fileExtension);
+ if (!isPctScaledImage) {
+ retValX = snprintf(scaledImageXName, lengthX, "%.*s%s%s",
+ length_Without_Ext, dupFileName, scaledImgX, fileExtension);
+ }
+ if ((retValPct < 0 || (retValPct > lengthPct - 1)) ||
+ (retValX < 0 || (retValX > lengthX - 1))) {
+ cleanUp(dupFileName, scaledImageXName, scaledImagePctName, scaleFactor);
+ return JNI_FALSE;
+ }
+ }
+ free(dupFileName);
+ if (!(fp = fopen(scaledImagePctName, "r"))) {
+ if (!isPctScaledImage && (fp = fopen(scaledImageXName, "r"))) {
+ fclose(fp);
+ strcpy(scaleImageName, scaledImageXName);
+ free(scaledImageXName);
+ free(scaledImagePctName);
+ return JNI_TRUE;
+ }
+ cleanUp(NULL, scaledImageXName, scaledImagePctName, scaleFactor);
+ return JNI_FALSE;
+ }
+ fclose(fp);
+ strcpy(scaleImageName, scaledImagePctName);
+ free(scaledImageXName);
+ free(scaledImagePctName);
+ return JNI_TRUE;
+ }
+ return JNI_FALSE;
+}
+
+void cleanUp(char *fName, char *xName, char *pctName, float *scaleFactor) {
+ *scaleFactor = 1;
+ free(fName);
+ free(xName);
+ free(pctName);
+}
--- a/jdk/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.h Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.h Thu Oct 27 21:22:57 2016 +0000
@@ -150,7 +150,9 @@
void SplashCleanup(Splash * splash);
void SplashSetScaleFactor(float scaleFactor);
int SplashGetScaledImgNameMaxPstfixLen(const char *fileName);
-
+void cleanUp(char *fName, char *xName, char *pctName, float *scaleFactor);
+jboolean GetScaledImageName(const char *fileName, char *scaledImgName,
+ float *scaleFactor, const size_t scaledImageLength);
typedef struct SplashStream {
int (*read)(void* pStream, void* pData, int nBytes);
int (*peek)(void* pStream);
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java Thu Oct 27 21:22:57 2016 +0000
@@ -301,7 +301,10 @@
}
private void resetWMSetInsets() {
- wm_set_insets = null;
+ if (XWM.getWMID() != XWM.UNITY_COMPIZ_WM) {
+ currentInsets = new Insets(0, 0, 0, 0);
+ wm_set_insets = null;
+ }
}
public void handlePropertyNotify(XEvent xev) {
@@ -352,7 +355,7 @@
// and the initially guessed insets were wrong
handleCorrectInsets(in);
}
- } else if (!dimensions.isClientSizeSet()) {
+ } else if (!insets_corrected || !dimensions.isClientSizeSet()) {
insets_corrected = true;
// initial insets were guessed correctly. Re-request
// frame bounds because they may be changed by WM if the
@@ -908,7 +911,6 @@
public void setResizable(boolean resizable) {
int fs = winAttr.functions;
if (!isResizable() && resizable) {
- currentInsets = new Insets(0, 0, 0, 0);
resetWMSetInsets();
if (!isEmbedded()) {
setReparented(false);
@@ -922,7 +924,6 @@
winAttr.functions = fs;
XWM.setShellResizable(this);
} else if (isResizable() && !resizable) {
- currentInsets = new Insets(0, 0, 0, 0);
resetWMSetInsets();
if (!isEmbedded()) {
setReparented(false);
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/Xrandr.h Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/Xrandr.h Thu Oct 27 21:22:57 2016 +0000
@@ -118,6 +118,19 @@
RRMode *modes;
} XRROutputInfo;
+typedef struct {
+ Time timestamp;
+ int x, y;
+ unsigned int width, height;
+ RRMode mode;
+ Rotation rotation;
+ int noutput;
+ RROutput *outputs;
+ Rotation rotations;
+ int npossible;
+ RROutput *possible;
+} XRRCrtcInfo;
+
XRRScreenResources *XRRGetScreenResources (Display *dpy, Window window);
void XRRFreeScreenResources (XRRScreenResources *resources);
@@ -126,6 +139,11 @@
RROutput output);
void XRRFreeOutputInfo (XRROutputInfo *outputInfo);
+XRRCrtcInfo *XRRGetCrtcInfo (Display *dpy, XRRScreenResources *resources,
+ RRCrtc crtc);
+void XRRFreeCrtcInfo (XRRCrtcInfo *crtcInfo);
+
+
/* internal representation is private to the library */
typedef struct _XRRScreenConfiguration XRRScreenConfiguration;
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c Thu Oct 27 21:22:57 2016 +0000
@@ -1667,6 +1667,11 @@
typedef void (*XRRFreeOutputInfoType)(XRROutputInfo *outputInfo);
+typedef XRRCrtcInfo* (*XRRGetCrtcInfoType)(Display *dpy,
+ XRRScreenResources *resources, RRCrtc crtc);
+
+typedef void (*XRRFreeCrtcInfoType)(XRRCrtcInfo *crtcInfo);
+
static XRRQueryVersionType awt_XRRQueryVersion;
static XRRGetScreenInfoType awt_XRRGetScreenInfo;
static XRRFreeScreenConfigInfoType awt_XRRFreeScreenConfigInfo;
@@ -1680,6 +1685,8 @@
static XRRFreeScreenResourcesType awt_XRRFreeScreenResources;
static XRRGetOutputInfoType awt_XRRGetOutputInfo;
static XRRFreeOutputInfoType awt_XRRFreeOutputInfo;
+static XRRGetCrtcInfoType awt_XRRGetCrtcInfo;
+static XRRFreeCrtcInfoType awt_XRRFreeCrtcInfo;
#define LOAD_XRANDR_FUNC(f) \
do { \
@@ -1755,6 +1762,8 @@
LOAD_XRANDR_FUNC(XRRFreeScreenResources);
LOAD_XRANDR_FUNC(XRRGetOutputInfo);
LOAD_XRANDR_FUNC(XRRFreeOutputInfo);
+ LOAD_XRANDR_FUNC(XRRGetCrtcInfo);
+ LOAD_XRANDR_FUNC(XRRFreeCrtcInfo);
return JNI_TRUE;
}
@@ -1895,7 +1904,49 @@
AWT_LOCK();
- if (screen < ScreenCount(awt_display)) {
+ if (usingXinerama && XScreenCount(awt_display) > 0) {
+ XRRScreenResources *res = awt_XRRGetScreenResources(awt_display,
+ RootWindow(awt_display, 0));
+ if (res) {
+ if (res->noutput > screen) {
+ XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display,
+ res, res->outputs[screen]);
+ if (output_info) {
+ if (output_info->crtc) {
+ XRRCrtcInfo *crtc_info =
+ awt_XRRGetCrtcInfo (awt_display, res,
+ output_info->crtc);
+ if (crtc_info) {
+ if (crtc_info->mode) {
+ int i;
+ for (i = 0; i < res->nmode; i++) {
+ XRRModeInfo *mode = &res->modes[i];
+ if (mode->id == crtc_info->mode) {
+ float rate = 0;
+ if (mode->hTotal && mode->vTotal) {
+ rate = ((float)mode->dotClock /
+ ((float)mode->hTotal *
+ (float)mode->vTotal));
+ }
+ displayMode = X11GD_CreateDisplayMode(
+ env,
+ mode->width,
+ mode->height,
+ BIT_DEPTH_MULTI,
+ (int)(rate +.2));
+ break;
+ }
+ }
+ }
+ awt_XRRFreeCrtcInfo(crtc_info);
+ }
+ }
+ awt_XRRFreeOutputInfo(output_info);
+ }
+ }
+ awt_XRRFreeScreenResources(res);
+ }
+ } else {
config = awt_XRRGetScreenInfo(awt_display,
RootWindow(awt_display, screen));
@@ -1954,7 +2005,7 @@
res, res->outputs[screen]);
if (output_info) {
int i;
- for (i = 0; i < res->nmode; i++) {
+ for (i = 0; i < output_info->nmode; i++) {
RRMode m = output_info->modes[i];
int j;
XRRModeInfo *mode;
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c Thu Oct 27 21:22:57 2016 +0000
@@ -35,9 +35,6 @@
#include <jni_util.h>
#include "awt.h"
-#define GTHREAD_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gthread-2.0", "0")
-#define GTHREAD_LIB JNI_LIB_NAME("gthread-2.0")
-
#define GTK_TYPE_BORDER ((*fp_gtk_border_get_type)())
#define G_TYPE_FUNDAMENTAL_SHIFT (2)
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h Thu Oct 27 21:22:57 2016 +0000
@@ -351,9 +351,6 @@
guint ellipsize : 3;
};
-
-typedef struct _GThreadFunctions GThreadFunctions;
-
/**
* Returns :
* NULL if the GLib library is compatible with the given version, or a string
@@ -449,17 +446,6 @@
static void (*fp_g_list_free) (GList *list);
static void (*fp_g_list_free_full) (GList *list, GDestroyNotify free_func);
-/**
- * This function is available for GLIB > 2.20, so it MUST be
- * called within GLIB_CHECK_VERSION(2, 20, 0) check.
- */
-static gboolean (*fp_g_thread_get_initialized)(void);
-
-static void (*fp_g_thread_init)(GThreadFunctions *vtable);
-static void (*fp_gdk_threads_init)(void);
-static void (*fp_gdk_threads_enter)(void);
-static void (*fp_gdk_threads_leave)(void);
-
static gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri,
guint32 timestamp, GError **error);
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c Thu Oct 27 21:22:57 2016 +0000
@@ -35,6 +35,7 @@
#include "awt.h"
static void *gtk3_libhandle = NULL;
+static void *gthread_libhandle = NULL;
static jmp_buf j;
@@ -87,6 +88,15 @@
return result;
}
+static void* dl_symbol_gthread(const char* name)
+{
+ void* result = dlsym(gthread_libhandle, name);
+ if (!result)
+ longjmp(j, NO_SYMBOL_EXCEPTION);
+
+ return result;
+}
+
gboolean gtk3_check(const char* lib_name, gboolean load)
{
if (gtk3_libhandle != NULL) {
@@ -261,6 +271,13 @@
return FALSE;
}
+ gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
+ if (gthread_libhandle == NULL) {
+ gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL);
+ if (gthread_libhandle == NULL)
+ return FALSE;
+ }
+
if (setjmp(j) == 0)
{
fp_gtk_check_version = dl_symbol("gtk_check_version");
@@ -530,8 +547,8 @@
fp_g_path_get_dirname = dl_symbol("g_path_get_dirname");
- fp_gdk_threads_enter = ∅
- fp_gdk_threads_leave = ∅
+ fp_gdk_threads_enter = dl_symbol("gdk_threads_enter");
+ fp_gdk_threads_leave = dl_symbol("gdk_threads_leave");
/**
* Functions for sun_awt_X11_GtkFileDialogPeer.c
@@ -556,6 +573,9 @@
dlclose(gtk3_libhandle);
gtk3_libhandle = NULL;
+ dlclose(gthread_libhandle);
+ gthread_libhandle = NULL;
+
return NULL;
}
@@ -651,6 +671,7 @@
dlerror();
dlclose(gtk3_libhandle);
+ dlclose(gthread_libhandle);
if ((gtk3_error = dlerror()) != NULL)
{
return FALSE;
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h Thu Oct 27 21:22:57 2016 +0000
@@ -33,6 +33,9 @@
#define TRUE (!FALSE)
#endif
+#define GTHREAD_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gthread-2.0", "0")
+#define GTHREAD_LIB JNI_LIB_NAME("gthread-2.0")
+
#define _G_TYPE_CIC(ip, gt, ct) ((ct*) ip)
#define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) \
(_G_TYPE_CIC ((instance), (g_type), c_type))
@@ -555,6 +558,13 @@
gboolean gtk_load(JNIEnv *env, GtkVersion version, gboolean verbose);
gboolean gtk_check_version(GtkVersion version);
+typedef struct _GThreadFunctions GThreadFunctions;
+static gboolean (*fp_g_thread_get_initialized)(void);
+static void (*fp_g_thread_init)(GThreadFunctions *vtable);
+static void (*fp_gdk_threads_init)(void);
+static void (*fp_gdk_threads_enter)(void);
+static void (*fp_gdk_threads_leave)(void);
+
extern GtkApi* gtk;
#endif /* !_GTK_INTERFACE_H */
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XWindow.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XWindow.c Thu Oct 27 21:22:57 2016 +0000
@@ -818,6 +818,32 @@
}
return awt_UseXKB;
}
+
+/*
+ * Map a keycode to the corresponding keysym.
+ * This replaces the deprecated X11 function XKeycodeToKeysym
+ */
+KeySym
+keycodeToKeysym(Display *display, KeyCode keycode, int index) {
+ static int min_kc = -1;
+ static int max_kc;
+ if (min_kc == -1) {
+ (void) XDisplayKeycodes(display, &min_kc, &max_kc);
+ }
+ if (keycode < min_kc || keycode > max_kc || index < 0) {
+ return NoSymbol;
+ }
+ int num_syms;
+ KeySym *key_syms = XGetKeyboardMapping(display, keycode, 1, &num_syms);
+ if (index >= num_syms) {
+ XFree(key_syms);
+ return NoSymbol;
+ }
+ KeySym ks = key_syms[index];
+ XFree(key_syms);
+ return ks;
+}
+
static Boolean
isKPevent(XEvent *event)
{
@@ -833,14 +859,14 @@
*/
Boolean bsun = isXsunServer( event );
Boolean bxkb = isXKBenabled( event->xkey.display );
- return IsKeypadKey( XKeycodeToKeysym(event->xkey.display, event->xkey.keycode,(bsun && !bxkb ? 2 : 1) ) );
+ return IsKeypadKey( keycodeToKeysym(event->xkey.display, event->xkey.keycode,(bsun && !bxkb ? 2 : 1) ) );
}
static void
dumpKeysymArray(XEvent *event) {
- printf(" 0x%X\n",XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 0));
- printf(" 0x%X\n",XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 1));
- printf(" 0x%X\n",XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 2));
- printf(" 0x%X\n",XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 3));
+ printf(" 0x%X\n",keycodeToKeysym(event->xkey.display, event->xkey.keycode, 0));
+ printf(" 0x%X\n",keycodeToKeysym(event->xkey.display, event->xkey.keycode, 1));
+ printf(" 0x%X\n",keycodeToKeysym(event->xkey.display, event->xkey.keycode, 2));
+ printf(" 0x%X\n",keycodeToKeysym(event->xkey.display, event->xkey.keycode, 3));
}
/*
* In a next redesign, get rid of this code altogether.
@@ -855,20 +881,20 @@
}
if( isXsunServer( event ) && !awt_UseXKB) {
if( (event->xkey.state & ShiftMask) ) { // shift modifier is on
- *keysym = XKeycodeToKeysym(event->xkey.display,
+ *keysym = keycodeToKeysym(event->xkey.display,
event->xkey.keycode, 3);
}else {
- *keysym = XKeycodeToKeysym(event->xkey.display,
+ *keysym = keycodeToKeysym(event->xkey.display,
event->xkey.keycode, 2);
}
} else {
if( (event->xkey.state & ShiftMask) || // shift modifier is on
((event->xkey.state & LockMask) && // lock modifier is on
(awt_ModLockIsShiftLock)) ) { // it is interpreted as ShiftLock
- *keysym = XKeycodeToKeysym(event->xkey.display,
+ *keysym = keycodeToKeysym(event->xkey.display,
event->xkey.keycode, 0);
}else{
- *keysym = XKeycodeToKeysym(event->xkey.display,
+ *keysym = keycodeToKeysym(event->xkey.display,
event->xkey.keycode, 1);
}
}
@@ -903,7 +929,7 @@
Perhaps using the index (modn in awt_MToolkit.c:setup_modifier_map)
would be more correct.
*/
- *keysym = XKeycodeToKeysym(event->xkey.display,
+ *keysym = keycodeToKeysym(event->xkey.display,
event->xkey.keycode, 2);
if (originalKeysym != *keysym) {
DTRACE_PRINTLN3("%s originalKeysym=0x%x, keysym=0x%x",
@@ -999,7 +1025,6 @@
}
}
-
/* This function is called as the keyChar parameter of a call to
* awt_post_java_key_event. It depends on being called after adjustKeySym.
*
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c Thu Oct 27 21:22:57 2016 +0000
@@ -49,6 +49,9 @@
#include <X11/XKBlib.h>
+// From XWindow.c
+extern KeySym keycodeToKeysym(Display *display, KeyCode keycode, int index);
+
#if defined(DEBUG)
static jmethodID lockIsHeldMID = NULL;
@@ -1286,7 +1289,7 @@
// report arbitrarily false.
return JNI_FALSE;
} else {
- long ks2 = XKeycodeToKeysym((Display*)jlong_to_ptr(display), kc7, 2);
+ long ks2 = keycodeToKeysym((Display*)jlong_to_ptr(display), kc7, 2);
if( ks2 == XK_KP_7 ) {
//XXX If some Xorg server would put XK_KP_7 in keysymarray[2] as well,
//XXX for yet unknown to me reason, the sniffer would lie.
@@ -1915,12 +1918,13 @@
XQueryKeymap( (Display *) jlong_to_ptr(display), (char *) jlong_to_ptr(vector));
}
+// XKeycodeToKeysym is deprecated but for compatibility we keep the API.
JNIEXPORT jlong JNICALL
Java_sun_awt_X11_XlibWrapper_XKeycodeToKeysym(JNIEnv *env, jclass clazz,
jlong display, jint keycode,
jint index) {
AWT_CHECK_HAVE_LOCK_RETURN(0);
- return XKeycodeToKeysym((Display*) jlong_to_ptr(display), (unsigned int)keycode, (int)index);
+ return keycodeToKeysym((Display*)jlong_to_ptr(display), (unsigned int)keycode, (int)index);
}
JNIEXPORT jint JNICALL
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c Thu Oct 27 21:22:57 2016 +0000
@@ -97,10 +97,7 @@
void callback(DbusmenuMenuitem* mi, guint ts, jobject data) {
JNIEnv* env = (JNIEnv*) JNU_GetEnv(jvm, JNI_VERSION_1_2);
- (*env)->CallStaticVoidMethod(env, jTaskbarCls, jTaskbarCallback, data,
- fp_dbusmenu_menuitem_property_get_int(mi, "toggle-state")
- ? JNI_FALSE
- : JNI_TRUE);
+ (*env)->CallStaticVoidMethod(env, jTaskbarCls, jTaskbarCallback, data);
}
/*
@@ -243,10 +240,9 @@
if (!menu) {
menu = fp_dbusmenu_menuitem_new();
+ fp_unity_launcher_entry_set_quicklist(entry, menu);
}
- fp_unity_launcher_entry_set_quicklist(entry, menu);
-
GList* list = fp_dbusmenu_menuitem_take_children(menu);
gtk->g_list_free_full(list, gtk->g_object_unref);
--- a/jdk/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c Thu Oct 27 21:22:57 2016 +0000
@@ -753,6 +753,9 @@
XMapRaised(splash->display, splash->window);
SplashUpdateShape(splash);
SplashRedrawWindow(splash);
+ //map the splash co-ordinates as per system scale
+ splash->x /= splash->scaleFactor;
+ splash->y /= splash->scaleFactor;
SplashEventLoop(splash);
}
SplashUnlock(splash);
@@ -807,50 +810,6 @@
return JNI_FALSE;
#endif
*scaleFactor = getNativeScaleFactor(NULL);
- if (*scaleFactor == 2.0) {
- size_t length = 0;
- char *stringToAppend = ".java-scale2x";
- char *dupFileName = strdup(fileName);
- char *fileExtension = strrchr(dupFileName, '.');
- if (fileExtension == NULL) {
- length = strlen(dupFileName) + strlen(stringToAppend) + 1;
- if (length > scaledImageNameLength) {
- *scaleFactor = 1;
- free(dupFileName);
- return JNI_FALSE;
- }
- int retVal = snprintf(scaledImgName, length, "%s%s",
- dupFileName, stringToAppend);
- if (retVal < 0 || (retVal != length - 1)) {
- free(dupFileName);
- *scaleFactor = 1;
- return JNI_FALSE;
- }
- } else {
- int length_without_ext = fileExtension - dupFileName;
- length = length_without_ext +
- strlen(stringToAppend) + strlen(fileExtension) + 1;
- if (length > scaledImageNameLength) {
- *scaleFactor = 1;
- free(dupFileName);
- return JNI_FALSE;
- }
- int retVal = snprintf(scaledImgName, length, "%.*s%s%s",
- length_without_ext, dupFileName, stringToAppend, fileExtension);
- if (retVal < 0 || retVal != length - 1) {
- free(dupFileName);
- *scaleFactor = 1;
- return JNI_FALSE;
- }
- }
- free(dupFileName);
- FILE *fp;
- if (!(fp = fopen(scaledImgName, "r"))) {
- *scaleFactor = 1;
- return JNI_FALSE;
- }
- fclose(fp);
- return JNI_TRUE;
- }
- return JNI_FALSE;
+ return GetScaledImageName(fileName, scaledImgName, scaleFactor, scaledImageNameLength);
}
+
--- a/jdk/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c Thu Oct 27 21:22:57 2016 +0000
@@ -535,6 +535,9 @@
splash->hWnd = SplashCreateWindow(splash);
if (splash->hWnd) {
SplashRedrawWindow(splash);
+ //map the splash co-ordinates as per system scale
+ splash->x /= splash->scaleFactor;
+ splash->y /= splash->scaleFactor;
SplashUnlock(splash);
SplashMessagePump();
SplashLock(splash);
@@ -582,55 +585,7 @@
*scaleFactor = 1.0;
GetScreenDpi(getPrimaryMonitor(), &dpiScaleX, &dpiScaleY);
*scaleFactor = dpiScaleX > 0 ? dpiScaleX / 96 : *scaleFactor;
- if (*scaleFactor > 1.0) {
- char strDpi[BUFF_SIZE];
- char *dupFileName = strdup(fileName);
- char *fileExtension = strrchr(dupFileName, '.');
- char *nameToAppend = ".scale-";
- size_t length = 0;
- int retVal = 0;
- _snprintf(strDpi, BUFF_SIZE, "%d", (int)dpiScaleX);
- /*File is missing extension */
- if (fileExtension == NULL) {
- length = strlen(dupFileName) + strlen(nameToAppend) +
- strlen(strDpi) + 1;
- if (length > scaledImageLength) {
- *scaleFactor = 1;
- free(dupFileName);
- return JNI_FALSE;
- }
- retVal = _snprintf(scaleImageName, length, "%s%s%s", dupFileName,
- nameToAppend, strDpi);
- if (retVal < 0 || (retVal != length - 1)) {
- *scaleFactor = 1;
- free(dupFileName);
- return JNI_FALSE;
- }
- }
- else {
- size_t length_Without_Ext = fileExtension - dupFileName;
- length = length_Without_Ext + strlen(nameToAppend) + strlen(strDpi) +
- strlen(fileExtension) + 1;
- if (length > scaledImageLength) {
- *scaleFactor = 1;
- free(dupFileName);
- return JNI_FALSE;
- }
- retVal = _snprintf(scaleImageName, length, "%.*s%s%s%s",
- length_Without_Ext, dupFileName, nameToAppend, strDpi, fileExtension);
- if (retVal < 0 || (retVal != length - 1)) {
- *scaleFactor = 1;
- free(dupFileName);
- return JNI_FALSE;
- }
- }
- free(dupFileName);
- if (!(fp = fopen(scaleImageName, "r"))) {
- *scaleFactor = 1;
- return JNI_FALSE;
- }
- fclose(fp);
- return JNI_TRUE;
- }
- return JNI_FALSE;
+ return GetScaledImageName(fileName, scaleImageName,
+ scaleFactor, scaledImageLength);
}
+
--- a/jdk/src/java.rmi/share/classes/sun/rmi/server/Activation.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/Activation.java Thu Oct 27 21:22:57 2016 +0000
@@ -1970,6 +1970,11 @@
AccessController.doPrivileged(
new PrivilegedExceptionAction<Void>() {
public Void run() throws IOException {
+ boolean disable = Boolean.getBoolean(
+ "sun.rmi.server.activation.disableErrRedirect");
+ if (disable)
+ return null;
+
File file =
Files.createTempFile("rmid-err", null).toFile();
PrintStream errStream =
--- a/jdk/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java Thu Oct 27 21:22:57 2016 +0000
@@ -41,13 +41,13 @@
import javax.accessibility.*;
import com.sun.java.accessibility.util.*;
+import java.awt.geom.Rectangle2D;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CountDownLatch;
/*
* Note: This class has to be public. It's loaded from the VM like this:
@@ -1754,7 +1754,7 @@
if (child instanceof JTextComponent) {
JTextComponent text = (JTextComponent) child;
try {
- r = text.modelToView(text.getCaretPosition());
+ r = text.modelToView2D(text.getCaretPosition()).getBounds();
if (r != null) {
Point p = text.getLocationOnScreen();
r.translate(p.x, p.y);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.desktop/share/classes/jdk/awt/AWTUtils.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.awt;
+
+import java.awt.Component;
+import java.awt.Shape;
+
+import com.sun.awt.AWTUtilities;
+
+/**
+ * A class to allow access to JDK-specific utility methods.
+ * Methods in this class are always deprecated since a caller
+ * should be aware they may be removed and replaced in the future.
+ * Access using reflection is highly recommended.
+ * @since 9
+ */
+public final class AWTUtils {
+
+ /**
+ * No-one should be creating instances of this class.
+ */
+ private AWTUtils() {
+ }
+
+ /**
+ * Sets a 'mixing-cutout' shape for the given component.
+ *
+ * By default a lightweight component is treated as an opaque rectangle for
+ * the purposes of the Heavyweight/Lightweight Components Mixing feature.
+ * This method enables developers to set an arbitrary shape to be cut out
+ * from heavyweight components positioned underneath the lightweight
+ * component in the z-order.
+ * <p>
+ * The {@code shape} argument may have the following values:
+ * <ul>
+ * <li>{@code null} - reverts the default cutout shape (the rectangle equal
+ * to the component's {@code getBounds()})
+ * <li><i>empty-shape</i> - does not cut out anything from heavyweight
+ * components. This makes the given lightweight component effectively
+ * transparent. Note that descendants of the lightweight component still
+ * affect the shapes of heavyweight components. An example of an
+ * <i>empty-shape</i> is {@code new Rectangle()}.
+ * <li><i>non-empty-shape</i> - the given shape will be cut out from
+ * heavyweight components.
+ * </ul>
+ * <p>
+ * The most common example when the 'mixing-cutout' shape is needed is a
+ * glass pane component. The {@link JRootPane#setGlassPane()} method
+ * automatically sets the <i>empty-shape</i> as the 'mixing-cutout' shape
+ * for the given glass pane component. If a developer needs some other
+ * 'mixing-cutout' shape for the glass pane (which is rare), this must be
+ * changed manually after installing the glass pane to the root pane.
+ * <p>
+ * Note that the 'mixing-cutout' shape neither affects painting, nor the
+ * mouse events handling for the given component. It is used exclusively
+ * for the purposes of the Heavyweight/Lightweight Components Mixing
+ * feature.
+ *
+ * @param component the component that needs non-default
+ * 'mixing-cutout' shape
+ * @param shape the new 'mixing-cutout' shape
+ * @throws NullPointerException if the component argument is {@code null}
+ * @deprecated This API may be removed or replaced.
+ */
+ @Deprecated
+ @SuppressWarnings("deprecation")
+ public static void setComponentMixingCutoutShape(Component component,
+ Shape shape) {
+
+ AWTUtilities.setComponentMixingCutoutShape(component, shape);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.desktop/share/classes/module-info.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+/*
+ * Provides non-SE desktop APIs.
+ */
+
+module jdk.desktop {
+ requires public java.desktop;
+
+ exports jdk.awt;
+}
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Thu Oct 27 21:22:57 2016 +0000
@@ -80,6 +80,7 @@
String fname, mname, ename;
String zname = "";
String rootjar = null;
+ Set<String> concealedPackages = new HashSet<>();
private static final int BASE_VERSION = 0;
@@ -821,22 +822,21 @@
return true;
}
- private static Set<String> findPackages(ZipFile zf) {
- return zf.stream()
- .filter(e -> e.getName().endsWith(".class"))
- .map(e -> toPackageName(e))
- .filter(pkg -> pkg.length() > 0)
- .distinct()
- .collect(Collectors.toSet());
- }
-
private static String toPackageName(ZipEntry entry) {
return toPackageName(entry.getName());
}
private static String toPackageName(String path) {
assert path.endsWith(".class");
- int index = path.lastIndexOf('/');
+ int index;
+ if (path.startsWith(VERSIONS_DIR)) {
+ index = path.indexOf('/', VERSIONS_DIR.length());
+ if (index <= 0) {
+ return "";
+ }
+ path = path.substring(index + 1);
+ }
+ index = path.lastIndexOf('/');
if (index != -1) {
return path.substring(0, index).replace('/', '.');
} else {
@@ -875,7 +875,7 @@
entryMap.put(entryName, entry);
} else if (entries.add(entry)) {
jarEntries.add(entryName);
- if (entry.basename.endsWith(".class") && !entryName.startsWith(VERSIONS_DIR))
+ if (entry.basename.endsWith(".class"))
packages.add(toPackageName(entry.basename));
if (isUpdate)
entryMap.put(entryName, entry);
@@ -1068,7 +1068,7 @@
}
jarEntries.add(name);
- if (name.endsWith(".class") && !(name.startsWith(VERSIONS_DIR)))
+ if (name.endsWith(".class"))
packages.add(toPackageName(name));
}
}
@@ -1762,6 +1762,13 @@
}
/**
+ * Print a warning message
+ */
+ void warn(String s) {
+ err.println(s);
+ }
+
+ /**
* Main routine to start program.
*/
public static void main(String args[]) {
@@ -1975,24 +1982,30 @@
ByteBuffer bb = ByteBuffer.wrap(moduleInfos.get(MODULE_INFO));
ModuleDescriptor rd = ModuleDescriptor.read(bb);
- Set<String> exports = rd.exports()
- .stream()
- .map(Exports::source)
- .collect(toSet());
-
- Set<String> conceals = packages.stream()
- .filter(p -> !exports.contains(p))
- .collect(toSet());
+ concealedPackages = findConcealedPackages(rd);
for (Map.Entry<String,byte[]> e: moduleInfos.entrySet()) {
ModuleDescriptor vd = ModuleDescriptor.read(ByteBuffer.wrap(e.getValue()));
if (!(isValidVersionedDescriptor(vd, rd)))
return false;
- e.setValue(extendedInfoBytes(rd, vd, e.getValue(), conceals));
+ e.setValue(extendedInfoBytes(rd, vd, e.getValue(), concealedPackages));
}
return true;
}
+ private Set<String> findConcealedPackages(ModuleDescriptor md){
+ Objects.requireNonNull(md);
+
+ Set<String> exports = md.exports()
+ .stream()
+ .map(Exports::source)
+ .collect(toSet());
+
+ return packages.stream()
+ .filter(p -> !exports.contains(p))
+ .collect(toSet());
+ }
+
private static boolean isPlatformModule(String name) {
return name.startsWith("java.") || name.startsWith("jdk.");
}
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java Thu Oct 27 21:22:57 2016 +0000
@@ -152,9 +152,13 @@
return;
}
if (fp.isPublicClass()) {
- main.error(Main.formatMsg("error.validator.new.public.class", entryName));
- isValid = false;
- return;
+ if (!isConcealed(internalName)) {
+ main.error(Main.formatMsg("error.validator.new.public.class", entryName));
+ isValid = false;
+ return;
+ }
+ main.warn(Main.formatMsg("warn.validator.concealed.public.class", entryName));
+ debug("%s is a public class entry in a concealed package", entryName);
}
debug("%s is a non-public class entry", entryName);
fps.put(internalName, fp);
@@ -169,7 +173,7 @@
// are the two classes/resources identical?
if (fp.isIdentical(matchFp)) {
- main.error(Main.formatMsg("error.validator.identical.entry", entryName));
+ main.warn(Main.formatMsg("warn.validator.identical.entry", entryName));
return; // it's okay, just takes up room
}
debug("sha1 not equal -- different bytes");
@@ -204,7 +208,7 @@
}
debug("%s is a resource", entryName);
- main.error(Main.formatMsg("error.validator.resources.with.same.name", entryName));
+ main.warn(Main.formatMsg("warn.validator.resources.with.same.name", entryName));
fps.put(internalName, fp);
return;
}
@@ -235,6 +239,15 @@
return entryName.endsWith(".class") ? entryName.substring(0, entryName.length() - 6) : null;
}
+ private boolean isConcealed(String internalName) {
+ if (main.concealedPackages.isEmpty()) {
+ return false;
+ }
+ int idx = internalName.lastIndexOf('/');
+ String pkgName = idx != -1 ? internalName.substring(0, idx).replace('/', '.') : "";
+ return main.concealedPackages.contains(pkgName);
+ }
+
private void debug(String fmt, Object... args) {
if (DEBUG) System.err.format(fmt, args);
}
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Thu Oct 27 21:22:57 2016 +0000
@@ -99,16 +99,19 @@
entry: {0}, is an isolated nested class
error.validator.new.public.class=\
entry: {0}, contains a new public class not found in base entries
-error.validator.identical.entry=\
- warning - entry: {0} contains a class that is identical to an entry already in the jar
error.validator.incompatible.class.version=\
entry: {0}, has a class version incompatible with an earlier version
error.validator.different.api=\
entry: {0}, contains a class with different api from earlier version
-error.validator.resources.with.same.name=\
- warning - entry: {0}, multiple resources with same name
error.validator.names.mismatch=\
entry: {0}, contains a class with internal name {1}, names do not match
+warn.validator.identical.entry=\
+ warning - entry: {0} contains a class that is identical to an entry already in the jar
+warn.validator.resources.with.same.name=\
+ warning - entry: {0}, multiple resources with same name
+warn.validator.concealed.public.class=\
+ warning - entry {0} is a public class in a concealed package, \n\
+ placing this jar on the class path will result in incompatible public interfaces
out.added.manifest=\
added manifest
out.added.module-info=\
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -246,9 +246,9 @@
* @throws java.lang.IllegalArgumentException if the method is not
* a member of this object's class, if the size of the argument list
* does not match the number of declared arguments for the method,
- * if the method is a constructor or static intializer, or
+ * if the method is a constructor or static initializer, or
* if {@link #INVOKE_NONVIRTUAL} is specified and the method is
- * either abstract or a non-default interface member.
+ * abstract.
* @throws {@link InvalidTypeException} if any argument in the
* argument list is not assignable to the corresponding method argument
* type.
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -347,10 +347,12 @@
throws InvalidTypeException,
InvocationException {
/*
- * Only default methods allowed for nonvirtual invokes
+ * For nonvirtual invokes, method must have a body
*/
- if (isNonVirtual(options) && !method.isDefault()) {
- throw new IllegalArgumentException("Not a default method");
+ if (isNonVirtual(options)) {
+ if (method.isAbstract()) {
+ throw new IllegalArgumentException("Abstract method");
+ }
}
}
--- a/jdk/src/jdk.jdi/share/classes/module-info.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/jdk.jdi/share/classes/module-info.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,6 @@
exports com.sun.jdi.connect.spi;
exports com.sun.jdi.event;
exports com.sun.jdi.request;
- exports com.sun.tools.jdi to jdk.hotspot.agent;
uses com.sun.jdi.connect.Connector;
uses com.sun.jdi.connect.spi.TransportService;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java Thu Oct 27 21:22:57 2016 +0000
@@ -186,7 +186,7 @@
new PrintWriter(System.err, true));
}
try {
- optionsHelper.handleOptions(this, args);
+ optionsHelper.handleOptionsNoUnhandled(this, args);
if (options.help) {
optionsHelper.showHelp(PROGNAME);
return EXIT_OK;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java Thu Oct 27 21:22:57 2016 +0000
@@ -466,7 +466,21 @@
return pp;
}
+ // used by jimage. Return unhandled arguments like "create", "describe".
public List<String> handleOptions(T task, String[] args) throws BadArgs {
+ return handleOptions(task, args, true);
+ }
+
+ // used by jlink. No unhandled arguments like "create", "describe".
+ void handleOptionsNoUnhandled(T task, String[] args) throws BadArgs {
+ handleOptions(task, args, false);
+ }
+
+ // shared code that handles options for both jlink and jimage. jimage uses arguments like
+ // "create", "describe" etc. as "task names". Those arguments are unhandled here and returned
+ // as "unhandled arguments list". jlink does not want such arguments. "collectUnhandled" flag
+ // tells whether to allow for unhandled arguments or not.
+ private List<String> handleOptions(T task, String[] args, boolean collectUnhandled) throws BadArgs {
// findbugs warning, copy instead of keeping a reference.
command = Arrays.copyOf(args, args.length);
@@ -499,10 +513,10 @@
String[] arr = new String[filteredArgs.size()];
args = filteredArgs.toArray(arr);
- List<String> rest = new ArrayList<>();
+ List<String> rest = collectUnhandled? new ArrayList<>() : null;
// process options
for (int i = 0; i < args.length; i++) {
- if (!args[i].isEmpty() && args[i].charAt(0) == '-') {
+ if (args[i].charAt(0) == '-') {
String name = args[i];
PlugOption pluginOption = null;
Option<T> option = getOption(name);
@@ -539,7 +553,12 @@
i = args.length;
}
} else {
- rest.add(args[i]);
+ if (collectUnhandled) {
+ rest.add(args[i]);
+ } else {
+ throw new BadArgs("err.orphan.argument", args[i]).
+ showUsage(true);
+ }
}
}
return rest;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties Thu Oct 27 21:22:57 2016 +0000
@@ -95,6 +95,7 @@
err.dir.exists={0} already exists
err.badpattern=bad pattern {0}
err.unknown.option=unknown option: {0}
+err.orphan.argument=orphan argument: {0}
err.missing.arg=no value given for {0}
err.internal.error=internal error: {0} {1} {2}
err.invalid.arg.for.option=invalid argument for option: {0}
--- a/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSObject.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSObject.java Thu Oct 27 21:22:57 2016 +0000
@@ -156,6 +156,7 @@
*/
@Deprecated(since = "9")
+ @SuppressWarnings("exports")
public static JSObject getWindow(Applet applet) throws JSException {
return ProviderLoader.callGetWindow(applet);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/BreakIteratorResources_th.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.text.resources.ext;
+
+import java.util.ResourceBundle;
+import sun.util.resources.BreakIteratorResourceBundle;
+
+public class BreakIteratorResources_th extends BreakIteratorResourceBundle {
+ @Override
+ protected ResourceBundle getBreakIteratorInfo() {
+ return new BreakIteratorInfo_th();
+ }
+}
--- a/jdk/test/ProblemList.txt Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/ProblemList.txt Thu Oct 27 21:22:57 2016 +0000
@@ -134,8 +134,6 @@
java/lang/instrument/BootClassPath/BootClassPathTest.sh 8072130 macosx-all
-java/lang/instrument/DaemonThread/TestDaemonThread.java 8167001 generic-all
-
java/lang/management/MemoryMXBean/Pending.java 8158837 generic-all
java/lang/management/MemoryMXBean/PendingAllGC.sh 8158760 generic-all
--- a/jdk/test/TEST.groups Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/TEST.groups Thu Oct 27 21:22:57 2016 +0000
@@ -158,6 +158,7 @@
jdk_net = \
java/net \
+ -java/net/httpclient \
com/sun/net/httpserver \
sun/net \
jdk/net
--- a/jdk/test/com/sun/corba/serialization/ObjectStreamTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/com/sun/corba/serialization/ObjectStreamTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -42,13 +42,8 @@
import java.util.Objects;
import java.util.PropertyPermission;
import java.util.Set;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder;
-import javax.naming.CommunicationException;
-import javax.naming.InitialContext;
-import javax.naming.Context;
-import javax.naming.NamingException;
import javax.rmi.CORBA.Util;
import javax.rmi.PortableRemoteObject;
@@ -56,11 +51,9 @@
import org.omg.CORBA_2_3.portable.OutputStream;
import org.omg.CORBA_2_3.portable.InputStream;
-import jdk.test.lib.JDKToolFinder;
-import jdk.test.lib.JDKToolLauncher;
-
import org.testng.Assert;
-import org.testng.annotations.AfterSuite;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;
import org.testng.TestNG;
@@ -69,15 +62,13 @@
* @test
* @library /test/lib
* @build jdk.test.lib.*
- * @compile ObjectStreamTest.java ObjectStreamTest$_Echo_Stub.java ObjectStreamTest$_Server_Tie.java
- * @modules java.corba/com.sun.corba.se.impl.io java.base/java.io java.corba/com.sun.corba.se.impl.activation
+ * @compile ObjectStreamTest.java ObjectStreamTest$_Echo_Stub.java
+ * ObjectStreamTest$_Server_Tie.java
+ * @modules java.corba/com.sun.corba.se.impl.io java.base/java.io
+ * java.corba/com.sun.corba.se.impl.activation
* @summary Tests of ReflectionFactory use in IIOP Serialization
- * @run testng/othervm
- * -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
- * -Djava.naming.provider.url=iiop://localhost:1050 ObjectStreamTest
- * @run testng/othervm/policy=security.policy
- * -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
- * -Djava.naming.provider.url=iiop://localhost:1050 ObjectStreamTest
+ * @run testng/othervm ObjectStreamTest
+ * @run testng/othervm/policy=security.policy ObjectStreamTest
*/
@Test
@@ -92,12 +83,6 @@
colorSet.add(Colors.GREEN);
}
- /**
- * The process spawned to run orbd.
- */
- static Process orbdProcess;
- static Thread orbThread;
-
@DataProvider(name = "Objects")
static Object[][] patterns() {
BigInteger bigInteger = new BigInteger("8943892002309239");
@@ -141,7 +126,7 @@
* @param value
*/
@Test(dataProvider = "Objects")
- static void factCheck(Serializable value) {
+ void factCheck(Serializable value) {
Class<?> clazz = value.getClass();
java.io.ObjectStreamClass sOSC = java.io.ObjectStreamClass.lookup(clazz);
java.io.ObjectStreamField[] sFields = sOSC.getFields();
@@ -150,25 +135,33 @@
Assert.assertEquals(sFields.length, cFields.length, "Different number of fields");
for (int i = 0; i < sFields.length; i++) {
- Assert.assertEquals(sFields[i].getName(), cFields[i].getName(), "different field names " + cFields[i].getName());
- Assert.assertEquals(sFields[i].getType(), cFields[i].getType(), "different field types " + cFields[i].getName());
- Assert.assertEquals(sFields[i].getTypeString(), cFields[i].getTypeString(), "different field typestrings " + cFields[i].getName());
+ Assert.assertEquals(sFields[i].getName(), cFields[i].getName(),
+ "different field names " + cFields[i].getName());
+ Assert.assertEquals(sFields[i].getType(), cFields[i].getType(),
+ "different field types " + cFields[i].getName());
+ Assert.assertEquals(sFields[i].getTypeString(), cFields[i].getTypeString(),
+ "different field typestrings " + cFields[i].getName());
}
Assert.assertEquals(baseMethod("hasReadObjectMethod", sOSC, (Class<?>[]) null),
- corbaMethod("hasReadObject", cOSC, (Class<?>[]) null), "hasReadObject: " + value.getClass());
+ corbaMethod("hasReadObject", cOSC, (Class<?>[]) null),
+ "hasReadObject: " + value.getClass());
Assert.assertEquals(baseMethod("hasWriteObjectMethod", sOSC, (Class<?>[]) null),
- corbaMethod("hasWriteObject", cOSC, (Class<?>[]) null), "hasWriteObject: " + value.getClass());
+ corbaMethod("hasWriteObject", cOSC, (Class<?>[]) null),
+ "hasWriteObject: " + value.getClass());
Assert.assertEquals(baseMethod("hasWriteReplaceMethod", sOSC, (Class<?>[]) null),
- corbaMethod("hasWriteReplaceMethod", cOSC, (Class<?>[]) null), "hasWriteReplace: " + value.getClass());
+ corbaMethod("hasWriteReplaceMethod", cOSC, (Class<?>[]) null),
+ "hasWriteReplace: " + value.getClass());
Assert.assertEquals(baseMethod("hasReadResolveMethod", sOSC, (Class<?>[]) null),
- corbaMethod("hasReadResolveMethod", cOSC, (Class<?>[]) null), "hasReadResolve: " + value.getClass());
+ corbaMethod("hasReadResolveMethod", cOSC, (Class<?>[]) null),
+ "hasReadResolve: " + value.getClass());
Assert.assertEquals(baseMethod("getSerialVersionUID", sOSC, (Class<?>[]) null),
- corbaMethod("getSerialVersionUID", cOSC, (Class<?>[]) null), "getSerialVersionUID: " + value.getClass());
+ corbaMethod("getSerialVersionUID", cOSC, (Class<?>[]) null),
+ "getSerialVersionUID: " + value.getClass());
}
@@ -178,7 +171,7 @@
* and deserialized using Util.readAny to equivalent objects.
*/
@Test(dataProvider = "Objects", enabled = true, dependsOnMethods = {"factCheck"})
- static void WriteValueObjectStreamTest01(Serializable value) throws Exception {
+ void WriteValueObjectStreamTest01(Serializable value) throws Exception {
ORB orb = (ORB) ORB.init(new String[0], null);
OutputStream out = (OutputStream) orb.create_output_stream();
@@ -193,15 +186,43 @@
/**
* Test that objects can be echoed to a server and come back equivalent.
*/
- @Test(dataProvider = "Objects", enabled = false, dependsOnMethods = {"factCheck"})
- static void echoObjects(Serializable value) throws Exception {
- Context initialNamingContext = Server.init();
- Echo echo = (Echo) PortableRemoteObject.narrow(
- initialNamingContext.lookup(Server.serverID), Echo.class);
+ @Test(dataProvider = "Objects", enabled = true, dependsOnMethods = {"factCheck"})
+ void echoObjects(Serializable value) throws Exception {
+ Echo echo = getEchoStub();
Object actual = echo.echo(value);
checkEquals(actual, value);
}
+
+ /**
+ * Initialize the ORB and the singleton Echo server stub.
+ * @return the stub for the Echo server.
+ * @throws RemoteException if an error occurs
+ */
+ synchronized Echo getEchoStub() throws RemoteException {
+ if (echoStub == null) {
+ ORB orb = (ORB) ORB.init(new String[0], null);
+ Echo server = new Server();
+ echoStub = (javax.rmi.CORBA.Stub) PortableRemoteObject.toStub(server);
+ echoStub.connect(orb);
+ }
+ return (Echo)echoStub;
+ }
+
+ /**
+ * The stub for the Echo Server class. Initialized on first use.
+ */
+ private javax.rmi.CORBA.Stub echoStub;
+
+ /**
+ * After all the tests run shutdown the orb.
+ */
+ @AfterClass
+ void shutdownOrb() {
+ ORB orb = (ORB) ORB.init(new String[0], null);
+ orb.shutdown(true);
+ }
+
/**
* Check if the value and result are equals, with some tests depending on the type.
* @param expected the expected value
@@ -209,15 +230,18 @@
*/
static void checkEquals(Object actual, Object expected) {
Class<?> cl = expected.getClass();
- Assert.assertEquals(actual.getClass(), cl, "type of value not equal to class of result");
+ Assert.assertEquals(actual.getClass(), cl,
+ "type of value not equal to class of result");
try {
if (cl.isArray() || !(cl.getDeclaredMethod("equals", cl) == null)) {
Assert.assertEquals(actual, expected, "echo'd object not equal");
} else {
- Assert.assertEquals(toString(actual), toString(expected), "toString values not equal");
+ Assert.assertEquals(toString(actual), toString(expected),
+ "toString values not equal");
}
} catch (NoSuchMethodException ex) {
- Assert.assertEquals(toString(actual), toString(expected), "toString values not equal");
+ Assert.assertEquals(toString(actual), toString(expected),
+ "toString values not equal");
}
}
@@ -301,7 +325,9 @@
* @param argClasses method arguments
* @return the value returned from invoking the method
*/
- static Object corbaMethod(String methodName, com.sun.corba.se.impl.io.ObjectStreamClass osc, Class<?>... argClasses) {
+ static Object corbaMethod(String methodName,
+ com.sun.corba.se.impl.io.ObjectStreamClass osc,
+ Class<?>... argClasses) {
Class<?> oscClass = com.sun.corba.se.impl.io.ObjectStreamClass.class;
try {
@@ -325,7 +351,8 @@
* @param argClasses method arguments
* @return the value returned from invoking the method
*/
- static Object baseMethod(String methodName, java.io.ObjectStreamClass osc, Class<?>... argClasses) {
+ static Object baseMethod(String methodName, java.io.ObjectStreamClass osc,
+ Class<?>... argClasses) {
Class<?> oscClass = java.io.ObjectStreamClass.class;
try {
@@ -342,7 +369,7 @@
}
/**
- * Simple echo interface to check serialization/deserialization.
+ * Simple echo interface to check IIOP serialization/deserialization.
*/
interface Echo extends Remote {
Object echo(Object obj) throws RemoteException;
@@ -350,12 +377,6 @@
static class Server extends PortableRemoteObject implements Echo {
- public static final String serverID = "ObjectStreamTestServer";
-
- private static Context initialNamingContext;
-
- private static Server server;
-
public Server() throws RemoteException {
super();
}
@@ -363,63 +384,8 @@
public Object echo(Object obj) {
return obj;
}
-
-
- public static Context init() {
- if (initialNamingContext == null) {
- try {
- startOrbd();
- Thread.sleep(5000L); // Give it 5 seconds
- } catch (Exception eex) {
- throw new RuntimeException("Orbd", eex);
- }
- for (int i = 0; i < 1; i++) {
- try {
- Thread.sleep(1L);
- initialNamingContext = new InitialContext();
- server = new Server();
- initialNamingContext.rebind(serverID, server);
- } catch (CommunicationException | InterruptedException cex) {
- System.out.printf("retry #%d sec: ex: %s%n", i, cex);
- } catch (NamingException ex) {
- throw new RuntimeException("can't initialize naming context", ex);
- } catch (RemoteException rex) {
- throw new RuntimeException("can't initialize server", rex);
- }
- }
- }
- if (initialNamingContext == null) {
- Assert.fail("Can't initialize the Orb, no naming context");
- }
- return initialNamingContext;
- }
}
- static void startOrbd() throws Exception {
- System.out.println("\nStarting orbd with NS port 1050 ");
- JDKToolLauncher orbdLauncher = JDKToolLauncher.create("orbd")
- .addToolArg("-ORBInitialHost").addToolArg("localhost")
- .addToolArg("-ORBInitialPort").addToolArg("1050");
-
- System.out.println("ObjectStreamTest: Executing: " + Arrays.asList(orbdLauncher.getCommand()));
- ProcessBuilder pb = new ProcessBuilder(orbdLauncher.getCommand());
-
- pb.redirectError(ProcessBuilder.Redirect.INHERIT);
- orbdProcess = pb.start();
- }
-
- @AfterSuite
- static void killOrbd() throws Exception {
- if (orbdProcess != null) {
- orbdProcess.destroyForcibly();
- orbdProcess.waitFor();
- System.out.printf("destroyed orbd, pid: %d, exitValue: %d%n",
- orbdProcess.getPid(), orbdProcess.exitValue());
- }
- }
-
-
-
// Main can be used to run the tests from the command line with only testng.jar.
@SuppressWarnings("raw_types")
@Test(enabled = false)
--- a/jdk/test/com/sun/jdi/InterfaceMethodsTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/com/sun/jdi/InterfaceMethodsTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -25,7 +25,8 @@
* @test
* @bug 8031195
* @bug 8071657
- * @summary JDI: Add support for static and default methods in interfaces
+ * @bug 8165827
+ * @summary JDI: Add support for static, private and default methods in interfaces
*
* @modules jdk.jdi
* @run build TestScaffold VMConnection TargetListener TargetAdapter
@@ -35,11 +36,13 @@
import com.sun.jdi.*;
import com.sun.jdi.event.*;
import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
public class InterfaceMethodsTest extends TestScaffold {
private static final int RESULT_A = 1;
- private static final int RESULT_B = 1;
- private static final int RESULT_TARGET = 1;
+ private static final int RESULT_B = 2;
+ private static final int RESULT_TARGET = 3;
static interface InterfaceA {
static int staticMethodA() {
@@ -62,7 +65,10 @@
System.out.println("-InterfaceA: default interface method C-");
return RESULT_A;
}
-
+ private int privateMethodA() {
+ System.out.println("-InterfaceA: private interface method A-");
+ return RESULT_A;
+ }
int implementedMethod();
}
@@ -76,16 +82,18 @@
System.out.println("-InterfaceB: default interface method D-");
return RESULT_B;
}
-
static int staticMethodB() {
System.out.println("-InterfaceB: overridden static interface method B-");
return RESULT_B;
}
-
static int staticMethodC() {
System.out.println("-InterfaceB: static interface method C-");
return RESULT_B;
}
+ private int privateMethodB() {
+ System.out.println("-InterfaceB: private interface method B-");
+ return RESULT_B;
+ }
}
final static class TargetClass implements InterfaceB {
@@ -102,7 +110,7 @@
@Override
public int defaultMethodB() {
- System.out.println("-TargetClass: overridden default interface method D");
+ System.out.println("-TargetClass: overridden default interface method B");
return RESULT_TARGET;
}
@@ -169,9 +177,18 @@
}
private void testInterfaceA(ObjectReference ref) {
+
+ ReferenceType ifaceClass = (ReferenceType)vm().classesByName(INTERFACEA_NAME).get(0);
+
+ /* Private method calls */
+
+ Method m = testLookup(ifaceClass, "privateMethodA", "()I", true, null); // should succeed
+
+ testInvokePos(m, ref, vm().mirrorOf(RESULT_A), false);
+ testInvokePos(m, ref, vm().mirrorOf(RESULT_A), true);
+
// Test non-virtual calls on InterfaceA
- ReferenceType ifaceClass = (ReferenceType)vm().classesByName(INTERFACEA_NAME).get(0);
/* Default method calls */
// invoke the InterfaceA's "defaultMethodA"
@@ -185,39 +202,48 @@
// "defaultMethodD" from InterfaceB is not accessible from here
testInvokeNeg(ifaceClass, ref, "defaultMethodD", "()I", vm().mirrorOf(RESULT_B),
- "Attempted to invoke non-existing method");
+ "Attempted to invoke non-existing method");
- // trying to invoke the asbtract method "implementedMethod"
+ // non-virtual invoke of the abstract method "implementedMethod" fails
testInvokeNeg(ifaceClass, ref, "implementedMethod", "()I", vm().mirrorOf(TARGET_CLASS_NAME),
- "Invocation of non-default methods is not supported");
-
+ "Invocation of abstract methods is not supported");
/* Static method calls */
- // invoke interface static method A
+ // invoke static interface method A
testInvokePos(ifaceClass, null, "staticMethodA", "()I", vm().mirrorOf(RESULT_A));
// invoking static method A on the instance fails because static method A is
// not inherited by TargetClass.
testInvokeNeg(ifaceClass, ref, "staticMethodA", "()I", vm().mirrorOf(RESULT_A),
- "Invalid MethodID");
+ "Invalid MethodID");
- // invoke interface static method B
+ // invoke static interface method B
testInvokePos(ifaceClass, null, "staticMethodB", "()I", vm().mirrorOf(RESULT_A));
// invoking static method B on the instance fails because static method B is
// not inherited by TargetClass.
testInvokeNeg(ifaceClass, ref, "staticMethodB", "()I", vm().mirrorOf(RESULT_A),
- "Invalid MethodID");
+ "Invalid MethodID");
// try to invoke a virtual method
- testInvokePos(ifaceClass, ref, "implementedMethod", "()I", vm().mirrorOf(RESULT_A), true);
+ testInvokePos(ifaceClass, ref, "implementedMethod", "()I", vm().mirrorOf(RESULT_TARGET), true);
}
private void testInterfaceB(ObjectReference ref) {
// Test non-virtual calls on InterfaceB
ReferenceType ifaceClass = (ReferenceType)vm().classesByName(INTERFACEB_NAME).get(0);
+ /* private method calls */
+
+ /* These should fail but won't because of JDK-8167416
+ testLookup(ifaceClass, "privateMethodA", "()I", true, NoSuchMethodError.class); // should fail
+ testLookup(ifaceClass, "privateMethodA", "()I", false, NoSuchMethodError.class); // should fail
+ */
+ Method m = testLookup(ifaceClass, "privateMethodB", "()I", true, null); // should succeed
+ testInvokePos(m, ref, vm().mirrorOf(RESULT_B), false);
+ testInvokePos(m, ref, vm().mirrorOf(RESULT_B), true);
+
/* Default method calls */
// invoke the inherited "defaultMethodA"
@@ -267,19 +293,21 @@
private void testImplementationClass(ReferenceType targetClass, ObjectReference thisObject) {
// Test invocations on the implementation object
+ // Note: private interface calls have already been tested
+
/* Default method calls */
// "defaultMethodA" is accessible and not overridden
- testInvokePos(targetClass, thisObject, "defaultMethodA", "()I", vm().mirrorOf(RESULT_TARGET));
+ testInvokePos(targetClass, thisObject, "defaultMethodA", "()I", vm().mirrorOf(RESULT_A));
// "defaultMethodB" is accessible and overridden in TargetClass
testInvokePos(targetClass, thisObject, "defaultMethodB", "()I", vm().mirrorOf(RESULT_TARGET));
// "defaultMethodC" is accessible and overridden in InterfaceB
- testInvokePos(targetClass, thisObject, "defaultMethodC", "()I", vm().mirrorOf(RESULT_TARGET));
+ testInvokePos(targetClass, thisObject, "defaultMethodC", "()I", vm().mirrorOf(RESULT_B));
// "defaultMethodD" is accessible
- testInvokePos(targetClass, thisObject, "defaultMethodD", "()I", vm().mirrorOf(RESULT_TARGET));
+ testInvokePos(targetClass, thisObject, "defaultMethodD", "()I", vm().mirrorOf(RESULT_B));
/* Non-default instance method calls */
@@ -314,11 +342,16 @@
"Static interface methods are not inheritable");
}
+ // Non-virtual invocation
private void testInvokePos(ReferenceType targetClass, ObjectReference ref, String methodName,
String methodSig, Value value) {
testInvokePos(targetClass, ref, methodName, methodSig, value, false);
}
+ // Lookup the named method in the targetClass and invoke on the given object (for instance methods)
+ // using virtual, or non-virtual, invocation mode as specified, for instance methods. Verify the
+ // expected return value.
+ // Should succeed.
private void testInvokePos(ReferenceType targetClass, ObjectReference ref, String methodName,
String methodSig, Value value, boolean virtual) {
logInvocation(ref, methodName, methodSig, targetClass);
@@ -331,11 +364,31 @@
}
}
+ // Invoke the given Method on the given object (for instance methods)
+ // using virtual, or non-virtual, invocation mode as specified, for instance methods. Verify the
+ // expected return value.
+ // Should succeed.
+ private void testInvokePos(Method method, ObjectReference ref, Value value, boolean virtual) {
+ logInvocation(ref, method.name(), method.signature(), method.declaringType());
+ try {
+ invoke(method.declaringType(), ref, method, value, virtual);
+ System.err.println("--- PASSED");
+ } catch (Exception e) {
+ System.err.println("--- FAILED");
+ failure("FAILED: Invocation failed with error message " + e.getLocalizedMessage());
+ }
+ }
+
+ // Non-virtual invocation - with lookup in targetClass
private void testInvokeNeg(ReferenceType targetClass, ObjectReference ref, String methodName,
String methodSig, Value value, String msg) {
testInvokeNeg(targetClass, ref, methodName, methodSig, value, msg, false);
}
+ // Lookup the named method in the targetClass and invoke on the given object (for instance methods)
+ // using virtual, or non-virtual, invocation mode as specified, for instance methods. Verify the
+ // expected return value.
+ // Should fail - with msg decribing why failure was expected
private void testInvokeNeg(ReferenceType targetClass, ObjectReference ref, String methodName,
String methodSig, Value value, String msg, boolean virtual) {
logInvocation(ref, methodName, methodSig, targetClass);
@@ -350,12 +403,17 @@
}
private void invoke(ReferenceType targetClass, ObjectReference ref, String methodName,
- String methodSig, Value value, boolean virtual)
- throws Exception {
+ String methodSig, Value value, boolean virtual) throws Exception {
+
Method method = getMethod(targetClass, methodName, methodSig);
if (method == null) {
throw new Exception("Can't find method: " + methodName + " for class = " + targetClass);
}
+ invoke(targetClass, ref, method, value, virtual);
+ }
+
+ private void invoke(ReferenceType targetClass, ObjectReference ref, Method method,
+ Value value, boolean virtual) throws Exception {
println("Invoking " + (method.isAbstract() ? "abstract " : " ") + "method: " + method);
println(method.declaringType().toString());
@@ -365,7 +423,7 @@
if (virtual) {
returnValue = invokeVirtual(ref, method);
} else {
- returnValue = invokeInstance(ref, method);
+ returnValue = invokeNonVirtual(ref, method);
}
} else {
returnValue = invokeStatic(targetClass, method);
@@ -387,7 +445,7 @@
}
}
- private Value invokeInstance(ObjectReference ref, Method method) throws Exception {
+ private Value invokeNonVirtual(ObjectReference ref, Method method) throws Exception {
return ref.invokeMethod(mainThread, method, Collections.emptyList(), ObjectReference.INVOKE_NONVIRTUAL);
}
@@ -449,4 +507,58 @@
methodName + methodSig);
}
}
+
+ private Method testLookup(ReferenceType targetClass, String methodName, String methodSig,
+ boolean declaredOnly, Class<?> expectedException) {
+
+ System.err.println("Looking up " + targetClass.name() + "." + methodName + methodSig);
+ try {
+ Method m = declaredOnly ?
+ lookupDeclaredMethod(targetClass, methodName, methodSig) :
+ lookupMethod(targetClass, methodName, methodSig);
+
+ if (expectedException == null) {
+ System.err.println("--- PASSED");
+ return m;
+ }
+ else {
+ System.err.println("--- FAILED");
+ failure("FAILED: lookup succeeded but expected exception "
+ + expectedException.getSimpleName());
+ return null;
+ }
+ }
+ catch (Throwable t) {
+ if (t.getClass() != expectedException) {
+ System.err.println("--- FAILED");
+ failure("FAILED: got exception " + t + " but expected exception "
+ + expectedException.getSimpleName());
+ return null;
+ }
+ else {
+ System.err.println("--- PASSED");
+ return null;
+ }
+ }
+ }
+
+ private Method lookupMethod(ReferenceType targetClass, String methodName, String methodSig) {
+ List methods = targetClass.allMethods();
+ Iterator iter = methods.iterator();
+ while (iter.hasNext()) {
+ Method method = (Method)iter.next();
+ if (method.name().equals(methodName) &&
+ method.signature().equals(methodSig)) {
+ return method;
+ }
+ }
+ throw new NoSuchMethodError();
+ }
+
+ private Method lookupDeclaredMethod(ReferenceType targetClass, String methodName, String methodSig) {
+ Method m = findMethod(targetClass, methodName, methodSig);
+ if (m == null)
+ throw new NoSuchMethodError();
+ return m;
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Focus/RequestFocusByCause/RequestFocusByCauseTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ @test
+ @bug 8154434
+ @summary Open the request focus methods of the java.awt.Component which accept
+ FocusEvent.Cause
+ @run main RequestFocusByCauseTest
+*/
+
+import java.awt.*;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+
+public class RequestFocusByCauseTest {
+ static boolean success;
+
+ public static void main(String[] args) throws Exception {
+ testRequestFocusCause();
+ testRequestFocusTemporaryCause();
+ testRequestFocusInWindowCause();
+ System.out.println("ok");
+ }
+
+ private static void testRequestFocusCause() throws AWTException {
+ Frame frame = new Frame();
+ Component c = new Button();
+ frame.add(new Button());
+ frame.add(c);
+ c.addFocusListener(new FocusListener() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ success = e.getCause() == FocusEvent.Cause.UNEXPECTED;
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {}
+ });
+ Robot robot = new Robot();
+
+ try {
+ frame.setVisible(true);
+ robot.waitForIdle();
+ robot.delay(200);
+ success = false;
+
+ c.requestFocus(FocusEvent.Cause.UNEXPECTED);
+ robot.waitForIdle();
+ robot.delay(200);
+ if(!success) {
+ throw new RuntimeException("request failed");
+ }
+ } finally {
+ frame.dispose();
+ }
+ }
+
+ private static void testRequestFocusTemporaryCause() throws AWTException {
+ Frame frame = new Frame();
+ frame.add(new Button() {
+ @Override
+ protected boolean requestFocus(boolean temporary,
+ FocusEvent.Cause cause) {
+ success = cause == FocusEvent.Cause.ROLLBACK;
+ return super.requestFocus(temporary, cause);
+ }
+ });
+ Component c = new Button() {
+ @Override
+ public void requestFocus() {
+ super.requestFocus();
+ setFocusable(false);
+ }
+ };
+ frame.add(c);
+ Robot robot = new Robot();
+
+ try {
+ frame.setVisible(true);
+ robot.waitForIdle();
+ robot.delay(200);
+
+ success = false;
+ c.requestFocus();
+ robot.waitForIdle();
+ robot.delay(200);
+
+
+ if(!success) {
+ throw new RuntimeException("rollback request is not triggered");
+ }
+ } finally {
+ frame.dispose();
+ }
+ }
+
+ private static void testRequestFocusInWindowCause() throws AWTException {
+ Frame frame = new Frame();
+ Component c = new Button();
+ frame.add(new Button());
+ frame.add(c);
+ c.addFocusListener(new FocusListener() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ success = e.getCause() == FocusEvent.Cause.UNEXPECTED;
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ }
+ });
+ Robot robot = new Robot();
+
+ try {
+ frame.setVisible(true);
+ robot.waitForIdle();
+ robot.delay(200);
+ success = false;
+
+ c.requestFocusInWindow(FocusEvent.Cause.UNEXPECTED);
+ robot.waitForIdle();
+ robot.delay(200);
+ if (!success) {
+ throw new RuntimeException("request in window failed");
+ }
+ } finally {
+ frame.dispose();
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Frame/SetIconImagesCrashTest/SetIconImagesCrashTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @key headful
+ * @bug 8166980
+ * @summary Test to check Window.setIconImages() does not result in crash when
+ * a frame is shown
+ * @run main/othervm SetIconImagesCrashTest
+ * @run main/othervm -Dsun.java2d.uiScale=2 SetIconImagesCrashTest
+ */
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Window;
+import java.awt.Frame;
+import java.util.List;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import javax.swing.SwingUtilities;
+
+public class SetIconImagesCrashTest {
+
+ public static void main(String[] args) throws Exception {
+
+ List<BufferedImage> imageList = new ArrayList<BufferedImage>();
+ imageList.add(new BufferedImage(200, 200,
+ BufferedImage.TYPE_BYTE_BINARY));
+
+ for (int i = 0; i < 10; i++) {
+ Frame f = new Frame();
+ test(f, imageList);
+ }
+ }
+
+ public static void test(final Window window,
+ final List<BufferedImage> imageList) throws Exception {
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ for (BufferedImage image : imageList) {
+ Graphics graphics = image.getGraphics();
+ graphics.setColor(Color.RED);
+ graphics.fillRect(
+ 0, 0, image.getWidth(), image.getHeight());
+ graphics.dispose();
+ }
+
+ window.setIconImages(imageList);
+ window.setSize(200, 200);
+ window.setVisible(true);
+ }
+ });
+
+ while (!window.isVisible()) {
+ Thread.sleep((long) (20));
+ }
+
+ Thread.sleep((long) (50));
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ window.setVisible(false);
+ window.dispose();
+ }
+ });
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/FullScreen/CurrentDisplayModeTest/CurrentDisplayModeTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8022810
+ * @summary Device.getDisplayMode() doesn't report refresh rate on Linux in case
+ * of dual screen
+ * @run main CurrentDisplayModeTest
+ */
+
+import java.awt.*;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public class CurrentDisplayModeTest {
+ public static void main(String[] args) {
+ GraphicsDevice[] screenDevices = GraphicsEnvironment.
+ getLocalGraphicsEnvironment().getScreenDevices();
+ for (GraphicsDevice screenDevice : screenDevices) {
+ DisplayMode currentMode = screenDevice.getDisplayMode();
+ System.out.println("current mode " + currentMode);
+ Set<DisplayMode> set = new HashSet<>(
+ Arrays.asList(screenDevice.getDisplayModes()));
+ if (!set.contains(currentMode)) {
+ throw new RuntimeException("Mode " + currentMode +
+ " is not found in the modes list " + set);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Graphics/IncorrectFractionalClip/IncorrectFractionalClip.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.Area;
+import java.awt.image.BufferedImage;
+import java.io.File;
+
+import javax.imageio.ImageIO;
+
+import static java.awt.RenderingHints.KEY_STROKE_CONTROL;
+import static java.awt.RenderingHints.VALUE_STROKE_PURE;
+import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
+
+/**
+ * @test
+ * @key headful
+ * @bug 8167310
+ * @summary The clip should be correct if the scale is fractional
+ */
+public final class IncorrectFractionalClip {
+
+ private static final int SIZE = 128;
+
+ public static final Color RED = new Color(255, 0, 0, 100);
+
+ public static final Color GREEN = new Color(0, 255, 0, 100);
+
+ public static final Color WHITE = new Color(0, 0, 0, 0);
+
+ public static final BasicStroke STROKE = new BasicStroke(2.01f);
+
+ private static final double[] SCALES = {
+ 0.1, 0.25, 0.4, 0.5, 0.6, 1, 1.4, 1.5, 1.6, 2.0, 2.4, 2.5, 2.6, 4
+ };
+
+ static BufferedImage bi;
+
+ static BufferedImage gold;
+
+ static BufferedImage redI;
+
+ static BufferedImage greenI;
+
+ public static void main(final String[] args) throws Exception {
+ bi = new BufferedImage(SIZE, SIZE, TYPE_INT_ARGB);
+ gold = new BufferedImage(SIZE, SIZE, TYPE_INT_ARGB);
+ redI = createImage(RED);
+ greenI = createImage(GREEN);
+
+ System.out.println("Will test fillRect");
+ test(0, true);
+ test(0, false);
+ System.out.println("Will test DrawImage");
+ test(1, true);
+ test(1, false);
+ System.out.println("Will test drawLine");
+ test(2, true);
+ test(2, false);
+ }
+
+ /**
+ * This method draws/fills a number of rectangle, images and lines. Each
+ * time the clip is set as one vertical/horizontal line. The resulted image
+ * should not have any overlapping of different colors. The clip is set via
+ * rectangle(test) and via shape(gold). Both images should be identical.
+ */
+ private static void test(final int testId, final boolean horiz)
+ throws Exception {
+ for (final double scale : SCALES) {
+ // Initialize the test and gold images
+ drawToImage(testId, horiz, scale, bi, /* Rectangle */ false);
+ drawToImage(testId, horiz, scale, gold, /* Shape */ true);
+ validate(bi, gold, testId);
+ }
+ }
+
+ private static void drawToImage(int testId, boolean horiz, double scale,
+ BufferedImage image, boolean shape) {
+ Graphics2D g = image.createGraphics();
+ g.setComposite(AlphaComposite.Src);
+ g.setColor(WHITE);
+ g.fillRect(0, 0, bi.getWidth(), bi.getHeight());
+ g.setComposite(AlphaComposite.SrcOver);
+ g.setRenderingHint(KEY_STROKE_CONTROL, VALUE_STROKE_PURE);
+
+ // set the scale in one direction
+ if (horiz) {
+ g.scale(scale, 1);
+ } else {
+ g.scale(1, scale);
+ }
+ // cover all units in the user space to touch all pixels in the
+ // image after transform
+ final int destSize = (int) Math.ceil(SIZE / scale);
+ final int destW;
+ final int destH;
+ if (horiz) {
+ destW = destSize;
+ destH = SIZE;
+ } else {
+ destW = SIZE;
+ destH = destSize;
+ }
+ for (int step = 0; step < destSize; ++step) {
+ if (horiz) {
+ if (!shape) {
+ g.setClip(step, 0, 1, SIZE);
+ } else{
+ g.setClip(new Area(new Rectangle(step, 0, 1, SIZE)));
+ }
+ } else {
+ if (!shape) {
+ g.setClip(0, step, SIZE, 1);
+ }else{
+ g.setClip(new Area(new Rectangle(0, step, SIZE, 1)));
+ }
+ }
+ switch (testId) {
+ case 0:
+ g.setColor(step % 2 == 0 ? RED : GREEN);
+ g.fillRect(0, 0, destW, destH);
+ break;
+ case 1:
+ g.drawImage(step % 2 == 0 ? redI : greenI, 0, 0,
+ destW, destH, null);
+ break;
+ case 2:
+ g.setColor(step % 2 == 0 ? RED : GREEN);
+ g.setStroke(STROKE);
+ if (horiz) {
+ g.drawLine(step, 0, step, SIZE);
+ } else {
+ g.drawLine(0, step, SIZE, step);
+ }
+ break;
+ default:
+ throw new RuntimeException();
+ }
+ }
+ g.dispose();
+ }
+
+ private static void validate(final BufferedImage bi, BufferedImage gold,
+ final int testID) throws Exception {
+ for (int x = 0; x < SIZE; ++x) {
+ for (int y = 0; y < SIZE; ++y) {
+ int rgb = bi.getRGB(x, y);
+ int goldRGB = gold.getRGB(x, y);
+ if ((rgb != GREEN.getRGB() && rgb != RED.getRGB())
+ || rgb != goldRGB) {
+ ImageIO.write(bi, "png", new File("image.png"));
+ ImageIO.write(gold, "png", new File("gold.png"));
+ throw new RuntimeException("Test failed.");
+ }
+ }
+ }
+ }
+
+ private static BufferedImage createImage(final Color color) {
+ BufferedImage bi = new BufferedImage(SIZE, SIZE, TYPE_INT_ARGB);
+ Graphics2D g = bi.createGraphics();
+ g.setComposite(AlphaComposite.Src);
+ g.setColor(color);
+ g.fillRect(0, 0, bi.getWidth(), bi.getHeight());
+ g.dispose();
+ return bi;
+ }
+}
--- a/jdk/test/java/awt/KeyboardFocusmanager/TypeAhead/SubMenuShowTest/SubMenuShowTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/awt/KeyboardFocusmanager/TypeAhead/SubMenuShowTest/SubMenuShowTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
test
- @bug 6380743
+ @bug 6380743 8158380
@summary Submenu should be shown by mnemonic key press.
@author anton.tarasov@...: area=awt.focus
@run applet SubMenuShowTest.html
@@ -55,6 +55,8 @@
public void init() {
robot = Util.createRobot();
+ robot.setAutoDelay(200);
+ robot.setAutoWaitForIdle(true);
// Create instructions for the user here, as well as set up
// the environment -- set the layout manager, add buttons,
@@ -85,35 +87,24 @@
});
frame.setVisible(true);
- Util.waitForIdle(robot);
boolean isMacOSX = (OSInfo.getOSType() == OSInfo.OSType.MACOSX);
if (isMacOSX) {
robot.keyPress(KeyEvent.VK_CONTROL);
- robot.delay(20);
}
robot.keyPress(KeyEvent.VK_ALT);
- robot.delay(20);
robot.keyPress(KeyEvent.VK_F);
- robot.delay(20);
robot.keyRelease(KeyEvent.VK_F);
- robot.delay(20);
robot.keyRelease(KeyEvent.VK_ALT);
+
if (isMacOSX) {
robot.keyRelease(KeyEvent.VK_CONTROL);
- robot.delay(20);
}
- Util.waitForIdle(robot);
robot.keyPress(KeyEvent.VK_M);
- robot.delay(20);
robot.keyRelease(KeyEvent.VK_M);
- Util.waitForIdle(robot);
-
robot.keyPress(KeyEvent.VK_SPACE);
- robot.delay(20);
robot.keyRelease(KeyEvent.VK_SPACE);
- Util.waitForIdle(robot);
if (!Util.waitForCondition(activated, 2000)) {
throw new TestFailedException("a submenu wasn't activated by mnemonic key press");
--- a/jdk/test/java/awt/List/ActionEventTest/ActionEventTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/awt/List/ActionEventTest/ActionEventTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* 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,7 +24,7 @@
/*
* @test
* @key headful
- * @bug 6191390
+ * @bug 6191390 8158380
* @summary Verify that ActionEvent is received with correct modifiers set.
* @run main ActionEventTest
*/
@@ -45,6 +45,8 @@
public ActionEventTest() {
try {
robot = new Robot();
+ robot.setAutoDelay(100);
+ robot.setAutoWaitForIdle(true);
} catch(AWTException e) {
throw new RuntimeException(e.getMessage());
}
@@ -56,7 +58,6 @@
setLayout(new FlowLayout());
pack();
setVisible(true);
- robot.waitForIdle();
}
void performTest() {
@@ -86,11 +87,9 @@
// Press Enter on list item, to generate action event.
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
- robot.waitForIdle();
robot.keyRelease(KeyEvent.VK_ALT);
robot.keyRelease(KeyEvent.VK_SHIFT);
robot.keyRelease(KeyEvent.VK_CONTROL);
- robot.waitForIdle();
}
public static void main(String args[]) {
--- a/jdk/test/java/awt/Modal/InvisibleParentTest/InvisibleParentTest.html Thu Oct 27 16:29:00 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-<!--
- Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
- This code is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License version 2 only, as
- published by the Free Software Foundation.
-
- This code is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- version 2 for more details (a copy is included in the LICENSE file that
- accompanied this code).
-
- You should have received a copy of the GNU General Public License version
- 2 along with this work; if not, write to the Free Software Foundation,
- Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
- Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- or visit www.oracle.com if you need additional information or have any
- questions.
--->
-
-<html>
-<!--
- @test
- @bug 6401700 6412803
- @requires (os.family != "windows")
- @summary Tests that modal dialog is shown on the screen and
-iconified/restored correctly if its parent window is invisible
- @author artem.ananiev: area=awt.modal
- @run applet/manual=yesno InvisibleParentTest.html
- -->
-<head>
-<title> InvisibleParentTest </title>
-</head>
-<body>
-
-<h1>InvisibleParentTest<br>Bug ID: 6401700, 6412803</h1>
-
-<p> See the dialog box (usually in upper left corner) for instructions</p>
-
-<APPLET CODE="InvisibleParentTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/jdk/test/java/awt/Modal/InvisibleParentTest/InvisibleParentTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/awt/Modal/InvisibleParentTest/InvisibleParentTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* 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,214 +22,187 @@
*/
/*
- test
- @bug 6401700 6412803
- @summary Tests that modal dialog is shown on the screen and
-iconified/restored correctly if some of its blocked windows are invisible
- @author artem.ananiev: area=awt.modal
- @run applet/manual=yesno InvisibleParentTest.html
-*/
-
-import java.applet.Applet;
-import java.awt.BorderLayout;
-import java.awt.Button;
-import java.awt.Component;
+ * @test
+ * @key headful
+ * @bug 6401700 6412803 8058950
+ * @summary Tests that modal dialog is shown on the screen and
+ * iconified/restored correctly if some of its blocked windows are invisible
+ * @requires (os.family == "linux" | os.family == "solaris")
+ * @run main/manual InvisibleParentTest
+ */
import java.awt.Dialog;
import java.awt.Frame;
-import java.awt.TextArea;
-import java.awt.Window;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+
+public class InvisibleParentTest {
-public class InvisibleParentTest extends Applet
-{
- public void init()
- {
- setLayout(new BorderLayout());
+ public static void main(String args[]) throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ TestUI test = new TestUI(latch);
+
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ test.createUI();
+ } catch (Exception ex) {
+ throw new RuntimeException("Exception while creating test UI");
+ }
+ }
+ });
+
+ boolean status = latch.await(5, TimeUnit.MINUTES);
- String[] instructions =
- {
- "If your system is Windows, press PASS button.",
- "When the test starts two windows should appear: frame G1 and",
- " dialog D1. Another one frame F1 should be minimized.",
- " If the dialog is not shown (minimizied), press FAIL button.",
- "Then minimize frame G1 and restore F1. If the dialog D1 is not",
- " restored together with F1, press FAIL, else PASS"
- };
- Sysout.createDialogWithInstructions( instructions );
+ if (!status) {
+ System.out.println("Test timed out.");
+ }
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ test.disposeUI();
+ } catch (Exception ex) {
+ throw new RuntimeException("Exception while disposing test UI");
+ }
+ }
+ });
+
+ if (test.testResult == false) {
+ throw new RuntimeException("Test Failed.");
+ }
+ }
+}
+
+class TestUI {
+
+ private static JFrame mainFrame;
+ private static JPanel mainControlPanel;
+
+ private static JTextArea instructionTextArea;
+
+ private static JPanel resultButtonPanel;
+ private static JButton passButton;
+ private static JButton failButton;
+
+ private static GridBagLayout layout;
+ private final CountDownLatch latch;
+ public boolean testResult = false;
+
+ public TestUI(CountDownLatch latch) throws Exception {
+ this.latch = latch;
}
- public void start ()
- {
- Button b;
+ public final void createUI() throws Exception {
+
+ mainFrame = new JFrame("InvisibleParentTest");
+ mainFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
+
+ layout = new GridBagLayout();
+ mainControlPanel = new JPanel(layout);
+ resultButtonPanel = new JPanel(layout);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ // Create Test instructions
+ String instructions
+ = "When the test starts two windows should appear: frame G1 and\n"
+ + " dialog D1. Another one frame F1 should be minimized.\n"
+ + " If the dialog is not shown (minimizied), press FAIL button.\n"
+ + "Then minimize frame G1 and restore F1. If the dialog D1 is not\n"
+ + " restored together with F1, press FAIL, else PASS";
- setSize (200,200);
- setVisible(true);
- validate();
+ instructionTextArea = new JTextArea();
+ instructionTextArea.setText(instructions);
+ instructionTextArea.setEditable(false);
+ instructionTextArea.setBorder(BorderFactory.
+ createTitledBorder("Test Instructions"));
+
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ mainControlPanel.add(instructionTextArea, gbc);
+
+ // Create resultButtonPanel with Pass, Fail buttons
+ passButton = new JButton("Pass");
+ passButton.setActionCommand("Pass");
+ passButton.addActionListener((ActionEvent e) -> {
+ System.out.println("Pass Button pressed!");
+ testResult = true;
+ latch.countDown();
- Component c = this;
- while ((c != null) && !(c instanceof Window))
- {
- c = c.getParent();
- }
- if (c != null)
- {
- ((Window)c).setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
- }
+ });
+
+ failButton = new JButton("Fail");
+ failButton.setActionCommand("Fail");
+ failButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ System.out.println("Fail Button pressed!");
+ testResult = false;
+ latch.countDown();
+ }
+ });
+
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ resultButtonPanel.add(passButton, gbc);
+ gbc.gridx = 1;
+ gbc.gridy = 0;
+ resultButtonPanel.add(failButton, gbc);
+ gbc.gridx = 0;
+ gbc.gridy = 1;
+ mainControlPanel.add(resultButtonPanel, gbc);
+
+ mainFrame.add(mainControlPanel);
+
+ mainFrame.pack();
+ mainFrame.setVisible(true);
+
+ // Create AWT frames and modal dialog
+ createAWTComponents();
+ }
+
+ public void disposeUI() {
+ mainFrame.setVisible(false);
+ mainFrame.dispose();
+ }
+
+ private void createAWTComponents() {
Frame f1 = new Frame("F1");
f1.setBounds(100, 300, 100, 100);
f1.setVisible(true);
+
+ try {
+ Thread.sleep(500);
+ } catch (Exception ex) {
+ }
+
f1.setExtendedState(Frame.ICONIFIED);
Frame g1 = new Frame("G1");
g1.setBounds(150, 350, 100, 100);
g1.setVisible(true);
- final Dialog d1 = new Dialog((Frame)null, "D1", Dialog.ModalityType.APPLICATION_MODAL);
+ final Dialog d1 = new Dialog((Frame) null, "D1", Dialog.ModalityType.APPLICATION_MODAL);
d1.setBounds(200, 400, 100, 100);
- new Thread(new Runnable()
- {
- public void run()
- {
+ new Thread(new Runnable() {
+ public void run() {
d1.setVisible(true);
}
}).start();
}
}
-/****************************************************
- Standard Test Machinery
- DO NOT modify anything below -- it's a standard
- chunk of code whose purpose is to make user
- interaction uniform, and thereby make it simpler
- to read and understand someone else's test.
- ****************************************************/
-
-/**
- This is part of the standard test machinery.
- It creates a dialog (with the instructions), and is the interface
- for sending text messages to the user.
- To print the instructions, send an array of strings to Sysout.createDialog
- WithInstructions method. Put one line of instructions per array entry.
- To display a message for the tester to see, simply call Sysout.println
- with the string to be displayed.
- This mimics System.out.println but works within the test harness as well
- as standalone.
- */
-
-class Sysout
-{
- private static TestDialog dialog;
-
- public static void createDialogWithInstructions( String[] instructions )
- {
- dialog = new TestDialog( new Frame(), "Instructions" );
- dialog.printInstructions( instructions );
- dialog.setVisible(true);
- println( "Any messages for the tester will display here." );
- }
-
- public static void createDialog( )
- {
- dialog = new TestDialog( new Frame(), "Instructions" );
- String[] defInstr = { "Instructions will appear here. ", "" } ;
- dialog.printInstructions( defInstr );
- dialog.setVisible(true);
- println( "Any messages for the tester will display here." );
- }
-
-
- public static void printInstructions( String[] instructions )
- {
- dialog.printInstructions( instructions );
- }
-
-
- public static void println( String messageIn )
- {
- dialog.displayMessage( messageIn );
- }
-
-}// Sysout class
-
-/**
- This is part of the standard test machinery. It provides a place for the
- test instructions to be displayed, and a place for interactive messages
- to the user to be displayed.
- To have the test instructions displayed, see Sysout.
- To have a message to the user be displayed, see Sysout.
- Do not call anything in this dialog directly.
- */
-class TestDialog extends Dialog
-{
-
- TextArea instructionsText;
- TextArea messageText;
- int maxStringLength = 80;
-
- //DO NOT call this directly, go through Sysout
- public TestDialog( Frame frame, String name )
- {
- super( frame, name );
- setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
- int scrollBoth = TextArea.SCROLLBARS_BOTH;
- instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
- add( "North", instructionsText );
-
- messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
- add("Center", messageText);
-
- pack();
-
- setVisible(true);
- }// TestDialog()
-
- //DO NOT call this directly, go through Sysout
- public void printInstructions( String[] instructions )
- {
- //Clear out any current instructions
- instructionsText.setText( "" );
-
- //Go down array of instruction strings
-
- String printStr, remainingStr;
- for( int i=0; i < instructions.length; i++ )
- {
- //chop up each into pieces maxSringLength long
- remainingStr = instructions[ i ];
- while( remainingStr.length() > 0 )
- {
- //if longer than max then chop off first max chars to print
- if( remainingStr.length() >= maxStringLength )
- {
- //Try to chop on a word boundary
- int posOfSpace = remainingStr.
- lastIndexOf( ' ', maxStringLength - 1 );
-
- if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
-
- printStr = remainingStr.substring( 0, posOfSpace + 1 );
- remainingStr = remainingStr.substring( posOfSpace + 1 );
- }
- //else just print
- else
- {
- printStr = remainingStr;
- remainingStr = "";
- }
-
- instructionsText.append( printStr + "\n" );
-
- }// while
-
- }// for
-
- }//printInstructions()
-
- //DO NOT call this directly, go through Sysout
- public void displayMessage( String messageIn )
- {
- messageText.append( messageIn + "\n" );
- System.out.println(messageIn);
- }
-
-}// TestDialog class
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Robot/WaitForIdleSyncroizedOnString/WaitForIdleSyncroizedOnString.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.Robot;
+import java.util.concurrent.CountDownLatch;
+
+import javax.swing.SwingUtilities;
+
+/**
+ * @test
+ * @key headful
+ * @bug 8166673
+ */
+public final class WaitForIdleSyncroizedOnString {
+
+ private static final String WAIT_LOCK = "Wait Lock";
+
+ private static volatile boolean passed = true;
+
+ public static void main(final String[] args) throws Exception {
+ CountDownLatch go = new CountDownLatch(1);
+ Robot r = new Robot();
+ SwingUtilities.invokeLater(() -> System.out.println("some work"));
+ Thread t = new Thread(() -> {
+ synchronized (WAIT_LOCK) {
+ go.countDown();
+ try {
+ Thread.sleep(30000);
+ passed = false;
+ } catch (InterruptedException e) {
+ System.out.println("e = " + e);
+ }
+ }
+ });
+ t.start();
+ go.await();
+ r.waitForIdle();
+ t.interrupt();
+ if (!passed) {
+ throw new RuntimeException("Test failed");
+ }
+ }
+}
--- a/jdk/test/java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -43,7 +43,7 @@
/**
* @test
* @key headful
- * @bug 8043869 8075244 8078082 8145173
+ * @bug 8043869 8075244 8078082 8145173 8151787
* @summary Tests the HiDPI splash screen support for windows and MAC
* @modules java.desktop/sun.java2d
* @run main MultiResolutionSplashTest GENERATE_IMAGES
@@ -56,27 +56,20 @@
private static final int IMAGE_WIDTH = 300;
private static final int IMAGE_HEIGHT = 200;
+ private static boolean isMac;
- private static final ImageInfo[] macTests = {
+ static {
+ isMac = System.getProperty("os.name").contains("OS X");
+ }
+ private static final ImageInfo[] tests = {
new ImageInfo("splash1.png", "splash1@2x.png", Color.BLUE, Color.GREEN),
new ImageInfo("splash2", "splash2@2x", Color.WHITE, Color.BLACK),
new ImageInfo("splash3.", "splash3@2x.", Color.YELLOW, Color.RED)
};
- private static final ImageInfo[] windowsTests = {
- new ImageInfo("splash1.png", "splash1.scale-120.png", Color.BLUE, Color.GREEN),
- new ImageInfo("splash2", "splash2.scale-120", Color.WHITE, Color.BLACK),
- new ImageInfo("splash3.", "splash3.scale-120.", Color.YELLOW, Color.RED)
- };
- private static ImageInfo[] tests;
public static void main(String[] args) throws Exception {
String test = args[0];
- tests = windowsTests;
- String osName = System.getProperty("os.name");
- if (osName.contains("OS X")) {
- tests = macTests;
- }
switch (test) {
case "GENERATE_IMAGES":
generateImages();
@@ -104,12 +97,10 @@
Rectangle splashBounds = splashScreen.getBounds();
int screenX = (int) splashBounds.getCenterX();
int screenY = (int) splashBounds.getCenterY();
-
if (splashBounds.width != IMAGE_WIDTH) {
throw new RuntimeException(
"SplashScreen#getBounds has wrong width");
}
-
if (splashBounds.height != IMAGE_HEIGHT) {
throw new RuntimeException(
"SplashScreen#getBounds has wrong height");
@@ -117,7 +108,6 @@
Robot robot = new Robot();
Color splashScreenColor = robot.getPixelColor(screenX, screenY);
-
float scaleFactor = getScaleFactor();
Color testColor = (1 < scaleFactor) ? test.color2x : test.color1x;
@@ -129,7 +119,6 @@
static void testFocus() throws Exception {
- System.out.println("Focus Test!");
Robot robot = new Robot();
robot.setAutoDelay(50);
@@ -150,18 +139,18 @@
frame.dispose();
- if(!textField.getText().equals("ab")){
+ if (!textField.getText().equals("ab")) {
throw new RuntimeException("Focus is lost!");
}
}
- static boolean compare(Color c1, Color c2){
+ static boolean compare(Color c1, Color c2) {
return compare(c1.getRed(), c2.getRed())
&& compare(c1.getGreen(), c2.getGreen())
&& compare(c1.getBlue(), c2.getBlue());
}
- static boolean compare(int n, int m){
+ static boolean compare(int n, int m) {
return Math.abs(n - m) <= 50;
}
@@ -177,10 +166,7 @@
public void paint(Graphics g) {
float scaleFactor = 1;
if (g instanceof SunGraphics2D) {
- scaleFactor = (float)GraphicsEnvironment.
- getLocalGraphicsEnvironment().
- getDefaultScreenDevice().getDefaultConfiguration().
- getDefaultTransform().getScaleX();
+ scaleFactor = getScreenScaleFactor();
}
scaleFactors[0] = scaleFactor;
dialog.setVisible(false);
@@ -197,23 +183,30 @@
static void generateImages() throws Exception {
for (ImageInfo test : tests) {
generateImage(test.name1x, test.color1x, 1);
- generateImage(test.name2x, test.color2x, 2);
+ generateImage(test.name2x, test.color2x, getScreenScaleFactor());
}
}
- static void generateImage(String name, Color color, int scale) throws Exception {
+ static void generateImage(String name, Color color, float scale) throws Exception {
File file = new File(name);
if (file.exists()) {
return;
}
- BufferedImage image = new BufferedImage(scale * IMAGE_WIDTH, scale * IMAGE_HEIGHT,
- BufferedImage.TYPE_INT_RGB);
+ BufferedImage image = new BufferedImage((int) (scale * IMAGE_WIDTH),
+ (int) (scale * IMAGE_HEIGHT), BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.setColor(color);
- g.fillRect(0, 0, scale * IMAGE_WIDTH, scale * IMAGE_HEIGHT);
+ g.fillRect(0, 0, (int) (scale * IMAGE_WIDTH), (int) (scale * IMAGE_HEIGHT));
ImageIO.write(image, "png", file);
}
+ static float getScreenScaleFactor() {
+ return (float) GraphicsEnvironment.
+ getLocalGraphicsEnvironment().
+ getDefaultScreenDevice().getDefaultConfiguration().
+ getDefaultTransform().getScaleX();
+ }
+
static class ImageInfo {
final String name1x;
@@ -223,9 +216,32 @@
public ImageInfo(String name1x, String name2x, Color color1x, Color color2x) {
this.name1x = name1x;
- this.name2x = name2x;
+ if (!isMac) {
+ float scale = getScreenScaleFactor();
+ StringBuffer buff = new StringBuffer();
+ if (scale - (int) scale > 0) {
+ buff.append("@").append((int) (scale * 100)).append("pct");
+ } else {
+ buff.append("@").append((int) scale).append("x");
+ }
+ StringBuffer buffer = new StringBuffer();
+ String[] splitStr = name1x.split("\\.");
+ if (splitStr.length == 2) {
+ this.name2x = buffer.append(splitStr[0]).append(buff)
+ .append(".").append(splitStr[1]).toString();
+ } else {
+ if (name1x.indexOf(".") > 0) {
+ this.name2x = buffer.append(splitStr[0]).append(buff).append(".").toString();
+ } else {
+ this.name2x = buffer.append(splitStr[0]).append(buff).toString();
+ }
+ }
+ } else {
+ this.name2x = name2x;
+ }
this.color1x = color1x;
this.color2x = color2x;
}
}
}
+
--- a/jdk/test/java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -44,7 +44,7 @@
import javax.imageio.ImageIO;
/**
- * @test @bug 8145174
+ * @test @bug 8145174 8151787
* @summary HiDPI splash screen support on Linux
* @modules java.desktop/sun.java2d
* @run main UnixMultiResolutionSplashTest
@@ -55,9 +55,9 @@
private static final int IMAGE_HEIGHT = 200;
private static int inx = 0;
private static final ImageInfo[] tests = {
- new ImageInfo("splash1.png", "splash1.java-scale2x.png", Color.BLUE, Color.GREEN),
- new ImageInfo("splash2", "splash2.java-scale2x", Color.WHITE, Color.BLACK),
- new ImageInfo("splash3.", "splash3.java-scale2x.", Color.YELLOW, Color.RED)
+ new ImageInfo("splash1.png", "splash1@200pct.png", Color.BLUE, Color.GREEN),
+ new ImageInfo("splash2", "splash2@2x", Color.WHITE, Color.BLACK),
+ new ImageInfo("splash3.", "splash3@200pct.", Color.YELLOW, Color.RED)
};
public static void main(String[] args) throws Exception {
@@ -96,8 +96,6 @@
Rectangle splashBounds = splashScreen.getBounds();
int screenX = (int) splashBounds.getCenterX();
int screenY = (int) splashBounds.getCenterY();
- System.out.println(screenX);
- System.out.println(screenY);
Robot robot = new Robot();
Color splashScreenColor = robot.getPixelColor(screenX, screenY);
--- a/jdk/test/java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,7 +21,11 @@
* questions.
*/
-import java.awt.*;
+import java.awt.EventQueue;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.SystemTray;
+import java.awt.TrayIcon;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
@@ -31,9 +35,10 @@
/*
* @test
+ * @bug 8161473
+ * @key headful
* @summary Check if MouseEvent has the proper modifiers when
* TrayIcon is clicked pressing the modifier keys
- * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
* @library /java/awt/patchlib
* @library ../../../../lib/testlibrary ../
* @build java.desktop/java.awt.Helper
@@ -213,6 +218,7 @@
mousePressed = false;
robot.keyPress(keyTypes[j]);
+ robot.waitForIdle();
robot.mousePress(buttonTypes[i]);
if (! mousePressed) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Window/ChangeWindowResizabilty/ChangeWindowResizabiltyTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @bug 8166897
+ @summary Some font overlap in the Optionpane dialog.
+ @run main ChangeWindowResizabiltyTest
+*/
+
+import java.awt.*;
+
+public class ChangeWindowResizabiltyTest {
+ public static void main(String[] args) throws Exception {
+ Robot robot = new Robot();
+ for(int i = 0; i < 10; i++) {
+ Dialog dialog = new Dialog((Frame) null);
+ Component panel = new Panel();
+ panel.setPreferredSize(new Dimension(200, 100));
+ dialog.add(panel);
+ dialog.pack();
+ dialog.setVisible(true);
+
+ dialog.setResizable(false);
+ robot.waitForIdle();
+ robot.delay(200);
+
+ System.out.println(panel.getLocationOnScreen());
+ System.out.println(dialog.getLocationOnScreen());
+ if (panel.getLocationOnScreen().y <
+ dialog.getLocationOnScreen().y + dialog.getInsets().top) {
+ dialog.dispose();
+ throw new RuntimeException(
+ "Wrong content position after setResizable(false)");
+ }
+
+ dialog.setResizable(true);
+ robot.waitForIdle();
+ robot.delay(200);
+ System.out.println(panel.getLocationOnScreen());
+ System.out.println(dialog.getLocationOnScreen());
+ if (panel.getLocationOnScreen().y <
+ dialog.getLocationOnScreen().y + dialog.getInsets().top) {
+ dialog.dispose();
+ throw new RuntimeException(
+ "Wrong content position after setResizable(true)");
+ }
+
+ dialog.dispose();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/KeyEvent/RobotCrash/RobotCrash.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @key headful
+ * @bug 8165555
+ * @summary VM crash after creating Robot second time and accessing key codes in
+ * single JVM mode.
+ * @run main RobotCrash
+ */
+import java.awt.Frame;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import javax.swing.SwingUtilities;
+
+public class RobotCrash implements Runnable {
+
+ private Frame frame;
+
+ public void robotKeyPressTest() throws Exception {
+
+ SwingUtilities.invokeAndWait(() -> {
+ frame = new Frame();
+ frame.setSize(300, 300);
+ frame.setVisible(true);
+ });
+
+ Robot robot = new Robot();
+ robot.waitForIdle();
+ Point pt = frame.getLocationOnScreen();
+ robot.mouseMove(((int) pt.getX() + frame.getWidth()) / 2,
+ ((int) pt.getY() + frame.getHeight()) / 2);
+ robot.waitForIdle();
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.waitForIdle();
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ robot.waitForIdle();
+ robot.keyPress(KeyEvent.VK_ENTER);
+ robot.waitForIdle();
+ robot.keyRelease(KeyEvent.VK_ENTER);
+ robot.waitForIdle();
+
+ SwingUtilities.invokeAndWait(() -> {
+ frame.dispose();
+ });
+ }
+
+ @Override
+ public void run() {
+ try {
+ robotKeyPressTest();
+ } catch (Exception e) {
+ throw new RuntimeException("Test Failed" + e.getMessage());
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ for (int i = 0; i < 10; i++) {
+ Thread t1 = new Thread(new RobotCrash());
+ t1.start();
+ t1.join();
+ Thread t2 = new Thread(new RobotCrash());
+ t2.start();
+ t2.join();
+ Thread.sleep(1000);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/jdk/TestJDKAWTUtils.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8167126
+ */
+import java.awt.BorderLayout;
+import java.awt.Font;
+import java.awt.Rectangle;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+public class TestJDKAWTUtils {
+
+ static JFrame f;
+ public static void main(String[] args) throws Exception {
+
+ SwingUtilities.invokeAndWait(() -> {
+ f = new JFrame("test");
+ JPanel p = new JPanel();
+ JButton b = new JButton("Hello");
+ b.setFont(new Font(Font.DIALOG, Font.PLAIN, 80));
+ p.setLayout(new BorderLayout());
+ p.add("Center", b);
+ f.getContentPane().add(p);
+ f.pack();
+ f.setVisible(true);
+ Rectangle r = new Rectangle(0, 0, 50, 50);
+ jdk.awt.AWTUtils.setComponentMixingCutoutShape(b, r);
+ });
+ Thread.sleep(2000);
+ SwingUtilities.invokeAndWait(() -> f.dispose());
+ }
+}
--- a/jdk/test/java/awt/security/WarningWindowDisposeTest/WarningWindowDisposeTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/awt/security/WarningWindowDisposeTest/WarningWindowDisposeTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,9 +23,9 @@
/*
@test
- @bug 8037776
+ @key headful
+ @bug 8037776 8167288
@summary tests that the WarningWindow is properly disposed
- @author Petr Pchelko
@library ../../regtesthelpers/process
@build ProcessResults ProcessCommunicator
@run main WarningWindowDisposeTest
@@ -45,13 +45,17 @@
public static void main(String[] args) {
final AtomicBoolean passed = new AtomicBoolean(false);
new Thread(() -> {
- try {
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- throw new RuntimeException("Test FAILED!", e);
- }
- if (!passed.get()) {
- throw new RuntimeException("Test FAILED! The child process never exits");
+ for (int trial = 0; trial < 5; ++trial) {
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Test FAILED!", e);
+ }
+ if (passed.get()) {
+ break;
+ } else if (trial == 4) {
+ throw new RuntimeException("Child process never exits");
+ }
}
}, "TimeoutThread").start();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/ClassLoader/IsParallelCapable.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8165793
+ * @summary Test ClassLoader.isParallelCapable() method
+ * @run main IsParallelCapable
+ */
+
+import java.util.stream.Stream;
+
+public class IsParallelCapable {
+ public abstract static class TestCL extends ClassLoader {
+ static {
+ ClassLoader.registerAsParallelCapable();
+ }
+ public abstract boolean expectCapable();
+ public Class findClass(String name) throws ClassNotFoundException {
+ throw new ClassNotFoundException("Why are you using this?");
+ }
+ }
+
+ public static class ParaCL extends TestCL {
+ static {
+ ClassLoader.registerAsParallelCapable();
+ }
+ @Override
+ public boolean expectCapable() { return true; }
+ }
+
+ public static class NonParaCL extends TestCL {
+ @Override
+ public boolean expectCapable() {
+ // Doesn't call registerAsParallelCapable()
+ return false;
+ }
+ }
+
+ public static class NonParaSubCL1 extends ParaCL {
+ @Override
+ public boolean expectCapable() {
+ // Doesn't call registerAsParallelCapable()
+ return false;
+ }
+ }
+
+ public static class NonParaSubCL2 extends NonParaCL {
+ static {
+ ClassLoader.registerAsParallelCapable();
+ }
+ @Override
+ public boolean expectCapable() {
+ // Superclass is not parallel capable
+ return false;
+ }
+ }
+
+ public static class ParaSubCL extends ParaCL {
+ static {
+ ClassLoader.registerAsParallelCapable();
+ }
+ @Override
+ public boolean expectCapable() { return true; }
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (!ClassLoader.getSystemClassLoader().isParallelCapable()) {
+ throw new RuntimeException("System classloader not parallel capable!?");
+ }
+
+ Stream.of(ParaCL.class,
+ NonParaCL.class,
+ NonParaSubCL1.class,
+ NonParaSubCL2.class,
+ ParaSubCL.class)
+ .forEach(IsParallelCapable::testClassLoaderClass);
+ }
+
+ private static void testClassLoaderClass(Class<? extends TestCL> klazz) {
+ try {
+ TestCL cl = (TestCL)klazz.newInstance();
+ if (cl.expectCapable() != cl.isParallelCapable()) {
+ throw new RuntimeException(klazz + " expectCapable: " +
+ cl.expectCapable() + ", isParallelCapable: " +
+ cl.isParallelCapable());
+ } else {
+ System.out.println(klazz + " passed");
+ }
+ } catch (InstantiationException | IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
--- a/jdk/test/java/lang/instrument/DaemonThread/TestDaemonThreadLauncher.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/lang/instrument/DaemonThread/TestDaemonThreadLauncher.java Thu Oct 27 21:22:57 2016 +0000
@@ -29,7 +29,7 @@
public class TestDaemonThreadLauncher {
public static void main(String args[]) throws Exception {
for(int i=0; i<50; i++) {
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-javaagent:DummyAgent.jar", "TestDaemonThread", ".");
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-javaagent:DummyAgent.jar", "TestDaemonThread", ".");
OutputAnalyzer analyzer = ProcessTools.executeProcess(pb);
analyzer.shouldNotContain("ASSERTION FAILED");
analyzer.shouldHaveExitValue(0);
--- a/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,7 @@
* @modules java.management
* @build jdk.testlibrary.* LowMemoryTest MemoryUtil RunUtil
* @run main/timeout=600 LowMemoryTest
+ * @requires vm.gc == "null"
* @requires vm.opt.ExplicitGCInvokesConcurrent != "true"
* @requires vm.opt.ExplicitGCInvokesConcurrentAndUnloadsClasses != "true"
* @requires vm.opt.DisableExplicitGC != "true"
--- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java Thu Oct 27 21:22:57 2016 +0000
@@ -40,7 +40,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivateMe CheckActivateRef_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivateMe CheckActivateRef_Stub
* @run main/othervm/policy=security.policy/timeout=240 -Djava.rmi.server.ignoreStubClasses=true CheckActivateRef
* @run main/othervm/policy=security.policy/timeout=240 -Djava.rmi.server.ignoreStubClasses=false CheckActivateRef
* @key intermittent
@@ -118,7 +119,7 @@
// start an rmid.
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -2,4 +2,6 @@
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.rmi.server.useDynamicProxies=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -38,4 +38,6 @@
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
permission java.lang.RuntimePermission "getClassLoader";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/CheckAnnotations.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/CheckAnnotations.java Thu Oct 27 21:22:57 2016 +0000
@@ -32,7 +32,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID MyRMI CheckAnnotations_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider MyRMI CheckAnnotations_Stub
* @run main/othervm/policy=security.policy/timeout=480 CheckAnnotations
*/
@@ -77,7 +78,7 @@
// start an rmid.
RMID.removeLog();
- rmid = RMID.createRMID(rmidOut, rmidErr, false);
+ rmid = RMID.createRMIDOnEphemeralPort(rmidOut, rmidErr, false);
rmid.start();
/* Cause activation groups to have a security policy that will
@@ -228,6 +229,7 @@
return false;
}
+
// just make sure that last two strings are what we expect.
if (execOut.equals("ExecGroup-" + iteration)
&& (new String(destOut.substring(0,4)).equals("out" +
--- a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -28,4 +28,7 @@
// test needs to export rmid and communicate with objects on arbitrary ports
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/CheckImplClassLoader.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/CheckImplClassLoader.java Thu Oct 27 21:22:57 2016 +0000
@@ -31,7 +31,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider
* MyRMI ActivatableImpl ActivatableImpl ActivatableImpl_Stub
* @run main/othervm/policy=security.policy/timeout=150 CheckImplClassLoader
*/
@@ -80,7 +81,7 @@
TestParams.defaultSecurityManager);
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
System.err.println("Create activation group in this VM");
--- a/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -39,4 +39,7 @@
// test needs to export rmid and communicate with objects on arbitrary ports
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/CheckRegisterInLog.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/CheckRegisterInLog.java Thu Oct 27 21:22:57 2016 +0000
@@ -31,7 +31,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
* ActivateMe CheckRegisterInLog_Stub
* @run main/othervm/policy=security.policy/timeout=240 CheckRegisterInLog
*/
@@ -99,7 +100,7 @@
* Start up activation system daemon "rmid".
*/
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -31,4 +31,7 @@
// allow exporting object with non-public remote interface
permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/CreatePrivateActivatable.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/CreatePrivateActivatable.java Thu Oct 27 21:22:57 2016 +0000
@@ -31,7 +31,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivateMe
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivateMe
* @run main/othervm/policy=security.policy/timeout=240 CreatePrivateActivatable
*/
@@ -103,7 +104,7 @@
// start an rmid.
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -31,4 +31,7 @@
// allow exporting object with non-public remote interface
permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/DownloadParameterClass.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/DownloadParameterClass.java Thu Oct 27 21:22:57 2016 +0000
@@ -35,7 +35,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
* Foo FooReceiverImpl FooReceiverImpl_Stub Bar
* @run main/othervm/policy=security.policy/timeout=240 DownloadParameterClass
*/
@@ -90,7 +91,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/manual.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/manual.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -34,4 +34,7 @@
// allow exporting of remote objects on an arbitrary port.
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -35,4 +35,7 @@
// allow exporting of remote objects on an arbitrary port.
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java Thu Oct 27 21:22:57 2016 +0000
@@ -31,7 +31,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivateMe ElucidateNoSuchMethod_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivateMe ElucidateNoSuchMethod_Stub
* @run main/othervm/policy=security.policy/timeout=240 ElucidateNoSuchMethod
*/
@@ -91,7 +92,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,7 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -37,4 +37,7 @@
// allow exporting of remote objects on an arbitrary port.
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ExtLoadedImplTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ExtLoadedImplTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -37,7 +37,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
Properties p = new Properties();
p.put("java.security.policy",
--- a/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh Thu Oct 27 21:22:57 2016 +0000
@@ -27,7 +27,7 @@
# loader, the context class loader should remain unchanged (i.e., not be
# set to the impl's class loader) when the impl is activated.
# @library ../../../testlibrary
-# @build TestLibrary RMID ActivationLibrary
+# @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
# @build ExtLoadedImplTest ExtLoadedImpl ExtLoadedImpl_Stub CheckLoader
# @run shell ext.sh
--- a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java Thu Oct 27 21:22:57 2016 +0000
@@ -31,7 +31,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
* ActivateMe ForceLogSnapshot_Stub
* @run main/othervm/policy=security.policy/timeout=640 ForceLogSnapshot
*/
@@ -129,7 +130,7 @@
SNAPSHOT_INTERVAL;
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.addOptions(new String[] {option, "-Djava.compiler="});
rmid.start();
--- a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -31,4 +31,7 @@
// allow exporting object with non-public remote interface
permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/InactiveGroup.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/InactiveGroup.java Thu Oct 27 21:22:57 2016 +0000
@@ -33,7 +33,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary ActivateMe InactiveGroup_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary ActivateMe InactiveGroup_Stub
* @run main/othervm/policy=security.policy/timeout=240 InactiveGroup
*/
@@ -101,7 +102,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -31,4 +31,7 @@
// allow exporting object with non-public remote interface
permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/LookupActivationSystem.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/LookupActivationSystem.java Thu Oct 27 21:22:57 2016 +0000
@@ -33,7 +33,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
* @run main/othervm/timeout=240 LookupActivationSystem
*/
@@ -55,7 +56,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
System.err.println("look up activation system");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,4 @@
+grant {
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
+};
--- a/jdk/test/java/rmi/activation/Activatable/nestedActivate/NestedActivate.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/NestedActivate.java Thu Oct 27 21:22:57 2016 +0000
@@ -31,7 +31,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary ActivateMe NestedActivate_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary ActivateMe NestedActivate_Stub
* @run main/othervm/policy=security.policy/timeout=240 NestedActivate
*/
@@ -101,7 +102,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/nestedActivate/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/nestedActivate/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -31,4 +31,7 @@
// allow exporting of non-public remote interface
permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/NonExistentActivatable.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/NonExistentActivatable.java Thu Oct 27 21:22:57 2016 +0000
@@ -32,7 +32,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
* ActivateMe NonExistentActivatable_Stub
* @run main/othervm/policy=security.policy/timeout=240 NonExistentActivatable
*/
@@ -91,7 +92,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -32,4 +32,6 @@
// allow exporting object with non-public remote interface
permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/RestartCrashedService.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/RestartCrashedService.java Thu Oct 27 21:22:57 2016 +0000
@@ -32,7 +32,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivateMe RestartCrashedService_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivateMe RestartCrashedService_Stub
* @run main/othervm/policy=security.policy/timeout=240 RestartCrashedService
*/
@@ -119,7 +120,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -28,4 +28,7 @@
// test needs to export rmid and communicate with objects on arbitrary ports
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/RestartLatecomer.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/RestartLatecomer.java Thu Oct 27 21:22:57 2016 +0000
@@ -31,7 +31,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
* RestartLatecomer RestartLatecomer_Stub
* @run main/othervm/policy=security.policy/timeout=240 RestartLatecomer
*/
@@ -166,7 +167,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -33,4 +33,7 @@
// allow exporting of remote objects on an arbitrary port.
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/restartService/RestartService.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/restartService/RestartService.java Thu Oct 27 21:22:57 2016 +0000
@@ -32,7 +32,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary ActivateMe RestartService_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary ActivateMe RestartService_Stub
* @run main/othervm/policy=security.policy/timeout=240 RestartService
*/
@@ -129,7 +130,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/restartService/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/restartService/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/restartService/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/restartService/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -33,4 +33,7 @@
// allow exporting of remote objects on an arbitrary port.
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java Thu Oct 27 21:22:57 2016 +0000
@@ -32,7 +32,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider
* TestSecurityManager RegisteringActivatable ShutdownGracefully_Stub
* @run main/othervm/policy=security.policy/timeout=700 ShutdownGracefully
*/
@@ -76,7 +77,7 @@
// start an rmid.
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
// rmid needs to run with a security manager that
// simulates a log problem; rmid should also snapshot
--- a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -2,4 +2,6 @@
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=java.lang.SecurityManager";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
permission com.sun.rmi.rmid.ExecOptionPermission "-Ddummyname=dummyvalue";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -25,4 +25,7 @@
// allow exporting of remote objects on an arbitrary port.
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/UnregisterInactive.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/UnregisterInactive.java Thu Oct 27 21:22:57 2016 +0000
@@ -32,7 +32,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary ActivateMe UnregisterInactive_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary ActivateMe UnregisterInactive_Stub
* @run main/othervm/policy=security.policy/timeout=240 UnregisterInactive
*/
@@ -89,7 +90,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
System.err.println("Creating descriptor");
--- a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -28,4 +28,7 @@
// allow exporting of remote objects on an arbitrary port.
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/ActivateFails.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/ActivateFails.java Thu Oct 27 21:22:57 2016 +0000
@@ -35,7 +35,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
* ActivateMe ActivateFails_Stub ShutdownThread
* @run main/othervm/java.security.policy=security.policy/timeout=240 ActivateFails
*/
@@ -93,7 +94,7 @@
* First run "rmid" and wait for it to start up.
*/
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/rmid.security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/rmid.security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/security.policy Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/security.policy Thu Oct 27 21:22:57 2016 +0000
@@ -28,4 +28,7 @@
// test needs to export rmid and communicate with objects on arbitrary ports
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java Thu Oct 27 21:22:57 2016 +0000
@@ -51,6 +51,8 @@
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
+import static java.net.StandardSocketOptions.SO_REUSEADDR;
+import static java.net.StandardSocketOptions.SO_REUSEPORT;
public class RmidViaInheritedChannel implements Callback {
private static final Object lock = new Object();
@@ -185,6 +187,15 @@
*/
channel = ServerSocketChannel.open();
ServerSocket serverSocket = channel.socket();
+
+ // Enable SO_REUSEADDR before binding
+ serverSocket.setOption(SO_REUSEADDR, true);
+
+ // Enable SO_REUSEPORT, if supported, before binding
+ if (serverSocket.supportedOptions().contains(SO_REUSEPORT)) {
+ serverSocket.setOption(SO_REUSEPORT, true);
+ }
+
serverSocket.bind(
new InetSocketAddress(InetAddress.getLocalHost(),
TestLibrary.RMIDVIAINHERITEDCHANNEL_ACTIVATION_PORT));
--- a/jdk/test/java/rmi/testlibrary/JavaVM.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/testlibrary/JavaVM.java Thu Oct 27 21:22:57 2016 +0000
@@ -21,8 +21,11 @@
* questions.
*/
+import java.io.BufferedReader;
+import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
+import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.StringTokenizer;
@@ -39,8 +42,8 @@
protected Process vm = null;
private String classname = "";
- private String args = "";
- private String options = "";
+ protected String args = "";
+ protected String options = "";
private OutputStream outputStream = System.out;
private OutputStream errorStream = System.err;
private String policyFileName = null;
@@ -113,7 +116,7 @@
/**
* Exec the VM as specified in this object's constructor.
*/
- public void start() throws IOException {
+ private void start0() throws IOException {
if (vm != null)
throw new IllegalStateException("JavaVM already started");
@@ -152,12 +155,50 @@
mesg("command = " + Arrays.asList(javaCommand).toString());
vm = Runtime.getRuntime().exec(javaCommand);
+ }
- /* output from the execed process may optionally be captured. */
+ public void start() throws IOException {
+ start0();
+
+ /* output from the exec'ed process may optionally be captured. */
outPipe = StreamPipe.plugTogether(vm.getInputStream(), this.outputStream);
errPipe = StreamPipe.plugTogether(vm.getErrorStream(), this.errorStream);
}
+ public int startAndGetPort() throws IOException {
+ start0();
+
+ int port = -1;
+ if (options.contains("java.nio.channels.spi.SelectorProvider=RMIDSelectorProvider")) {
+ // Obtain the server socket channel's ephemeral port number of the
+ // child rmid process.
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(vm.getInputStream()));
+ String s;
+ while ((s = reader.readLine()) != null) {
+ System.out.println(s);
+ int i = s.indexOf(RMID.EPHEMERAL_MSG);
+ if (i != -1) {
+ String v = s.substring(RMID.EPHEMERAL_MSG.length());
+ port = Integer.valueOf(v);
+ break;
+ }
+ }
+ if (port == -1) {
+ // something failed
+ reader = new BufferedReader(new InputStreamReader(vm.getErrorStream()));
+ while ((s = reader.readLine()) != null)
+ System.err.println(s);
+ }
+ }
+
+ /* output from the exec'ed process may optionally be captured. */
+ outPipe = StreamPipe.plugTogether(vm.getInputStream(), this.outputStream);
+ errPipe = StreamPipe.plugTogether(vm.getErrorStream(), this.errorStream);
+
+ return port;
+ }
+
public void destroy() {
if (vm != null) {
vm.destroy();
--- a/jdk/test/java/rmi/testlibrary/RMID.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/testlibrary/RMID.java Thu Oct 27 21:22:57 2016 +0000
@@ -49,20 +49,31 @@
public static String MANAGER_OPTION="-Djava.security.manager=";
- /** Test port for rmid */
- private final int port;
+ /**
+ * Test port for rmid.
+ *
+ * May initially be 0, which means that the child rmid process will choose
+ * an ephemeral port and report it back to the parent process. This field
+ * will then be set to the child rmid's ephemeral port value.
+ */
+ private volatile int port;
+ //private final boolean ephemeralPort
/** Initial log name */
protected static String log = "log";
/** rmid's logfile directory; currently must be "." */
protected static String LOGDIR = ".";
+ /** The output message from the child rmid process that directly precedes
+ * the ephemeral port number.*/
+ public static final String EPHEMERAL_MSG = "RmidSelectorProvider-listening-On:";
+
private static void mesg(Object mesg) {
System.err.println("RMID: " + mesg.toString());
}
/** make test options and arguments */
- private static String makeOptions(boolean debugExec) {
+ private static String makeOptions(int port, boolean debugExec) {
String options = " -Dsun.rmi.server.activation.debugExec=" +
debugExec;
@@ -87,6 +98,17 @@
// to avoid spurious timeouts on slow machines.
options += " -Dsun.rmi.activation.execTimeout=60000";
+ if (port == 0) {
+ // Ephemeral port, so have the rmid child process create the
+ // server socket channel and report its port number, over stdin.
+ options += " -classpath " + TestParams.testClassPath;
+ options += " --add-exports=java.base/sun.nio.ch=ALL-UNNAMED";
+ options += " -Djava.nio.channels.spi.SelectorProvider=RMIDSelectorProvider";
+
+ // Disable redirection of System.err to /tmp
+ options += " -Dsun.rmi.server.activation.disableErrRedirect=true";
+ }
+
return options;
}
@@ -107,7 +129,8 @@
String args =
" -log " + (new File(LOGDIR, log)).getAbsolutePath();
- if (includePortArg) {
+ // 0 = ephemeral port, do not include an explicit port number
+ if (includePortArg && port != 0) {
args += " -port " + port;
}
@@ -160,7 +183,7 @@
boolean debugExec, boolean includePortArg,
int port)
{
- String options = makeOptions(debugExec);
+ String options = makeOptions(port, debugExec);
String args = makeArgs(includePortArg, port);
RMID rmid = new RMID("sun.rmi.server.Activation", options, args,
out, err, port);
@@ -169,6 +192,17 @@
return rmid;
}
+ public static RMID createRMIDOnEphemeralPort() {
+ return createRMID(System.out, System.err, true, true, 0);
+ }
+
+ public static RMID createRMIDOnEphemeralPort(OutputStream out,
+ OutputStream err,
+ boolean debugExec)
+ {
+ return createRMID(out, err, debugExec, true, 0);
+ }
+
/**
* Private constructor. RMID instances should be created
@@ -247,7 +281,10 @@
// a well recognized exception (port already in use...).
mesg("Starting rmid on port " + port + ".");
- super.start();
+ int p = super.startAndGetPort();
+ if (p != -1)
+ port = p;
+ mesg("Started rmid on port " + port + ".");
// int slopFactor = 1;
// try {
@@ -271,8 +308,11 @@
try {
int status = vm.exitValue();
+ waitFor(TIMEOUT_SHUTDOWN_MS);
TestLibrary.bomb("Rmid process exited with status " + status + " after " +
(System.currentTimeMillis() - startTime) + "ms.");
+ } catch (InterruptedException | TimeoutException e) {
+ mesg(e);
} catch (IllegalThreadStateException ignore) { }
// The rmid process is alive; check to see whether
@@ -307,6 +347,8 @@
*/
public void restart() throws IOException {
destroy();
+ options = makeOptions(port, true);
+ args = makeArgs(true, port);
start();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/testlibrary/RMIDSelectorProvider.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.*;
+import java.net.InetSocketAddress;
+import java.net.ProtocolFamily;
+import java.nio.channels.Channel;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.Pipe;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+import static java.net.StandardSocketOptions.SO_REUSEADDR;
+import static java.net.StandardSocketOptions.SO_REUSEPORT;
+
+/**
+ * A SelectorProvider, that can be loaded by the child rmid process, whose
+ * inheritedChannel method will create a new server socket channel and report
+ * it back to the parent process, over stdout.
+ */
+public class RMIDSelectorProvider extends SelectorProvider {
+
+ private final SelectorProvider provider;
+ private ServerSocketChannel channel;
+
+ public RMIDSelectorProvider() {
+ provider = sun.nio.ch.DefaultSelectorProvider.create();
+ }
+
+ public DatagramChannel openDatagramChannel()
+ throws IOException
+ {
+ return provider.openDatagramChannel();
+ }
+
+ public DatagramChannel openDatagramChannel(ProtocolFamily family)
+ throws IOException
+ {
+ return provider.openDatagramChannel(family);
+ }
+
+ public Pipe openPipe()
+ throws IOException
+ {
+ return provider.openPipe();
+ }
+
+ public AbstractSelector openSelector()
+ throws IOException
+ {
+ return provider.openSelector();
+ }
+
+ public ServerSocketChannel openServerSocketChannel()
+ throws IOException
+ {
+ return provider.openServerSocketChannel();
+ }
+
+ public SocketChannel openSocketChannel()
+ throws IOException
+ {
+ return provider.openSocketChannel();
+ }
+
+ public synchronized Channel inheritedChannel() throws IOException {
+ System.out.println("RMIDSelectorProvider.inheritedChannel");
+ if (channel == null) {
+ // Create and bind a new server socket channel
+ channel = ServerSocketChannel.open();
+
+ // Enable SO_REUSEADDR before binding
+ channel.setOption(SO_REUSEADDR, true);
+
+ // Enable SO_REUSEPORT, if supported, before binding
+ if (channel.supportedOptions().contains(SO_REUSEPORT)) {
+ channel.setOption(SO_REUSEPORT, true);
+ }
+
+ channel.bind(new InetSocketAddress(0));
+
+ System.out.println(RMID.EPHEMERAL_MSG + channel.socket().getLocalPort());
+ }
+ return channel;
+ }
+}
--- a/jdk/test/java/rmi/testlibrary/TestParams.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/rmi/testlibrary/TestParams.java Thu Oct 27 21:22:57 2016 +0000
@@ -34,6 +34,7 @@
/** variables that hold value property values */
public static final String testSrc;
public static final String testClasses;
+ public static final String testClassPath;
/** name of default security policy for test JVM */
public static final String defaultPolicy;
@@ -57,6 +58,7 @@
static {
testSrc = TestLibrary.getProperty("test.src", ".");
testClasses = TestLibrary.getProperty("test.classes", ".");
+ testClassPath = TestLibrary.getProperty("test.class.path", ".");
String dp = TestLibrary.getProperty("java.security.policy", null);
if (dp == null) {
--- a/jdk/test/java/util/Arrays/ParallelPrefix.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/util/Arrays/ParallelPrefix.java Thu Oct 27 21:22:57 2016 +0000
@@ -26,7 +26,6 @@
* @summary unit test for Arrays.ParallelPrefix().
* @author Tristan Yan
* @run testng ParallelPrefix
- * @key intermittent
*/
import java.util.Arrays;
--- a/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -89,7 +89,7 @@
String[] jresResult = new String[4];
if (jreSupportsLocale) {
for (int i = 0; i < 4; i++) {
- jresResult[i] = "sun.util.locale.provider."+classNames[i];
+ jresResult[i] = "sun.text." + classNames[i];
}
}
--- a/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.sh Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.sh Thu Oct 27 21:22:57 2016 +0000
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,6 @@
#
#
# @test
-# @bug 4052440 8062588
+# @bug 4052440 8062588 8165804
# @summary BreakIteratorProvider tests
# @run shell ExecTest.sh foo BreakIteratorProviderTest
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/ImageCompressionTypesTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @bug 6294607
+ * @summary Test verifies whether ImageWriteParam.getCompressionTypes()
+ * returns any duplicate compression type for ImageIO plugins.
+ * @run main ImageCompressionTypesTest
+ */
+
+import java.util.Iterator;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
+
+public class ImageCompressionTypesTest {
+
+ static ImageWriter writer = null;
+
+ public ImageCompressionTypesTest(String format) {
+ Iterator it = ImageIO.getImageWritersByFormatName(format);
+ while (it.hasNext()) {
+ writer = (ImageWriter) it.next();
+ break;
+ }
+ ImageWriteParam param = writer.getDefaultWriteParam();
+
+ param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+ System.out.println("Checking compression types for : " + format);
+ String compTypes[] = param.getCompressionTypes();
+ if (compTypes.length > 1) {
+ for (int i = 0; i < compTypes.length; i++) {
+ for (int j = i + 1; j < compTypes.length; j++) {
+ if (compTypes[i].equalsIgnoreCase(compTypes[j])) {
+ throw new RuntimeException("Duplicate compression"
+ + " type exists for image format " + format);
+ }
+ }
+ }
+ }
+ }
+
+ public static void main(String args[]) {
+ final String[] formats = {"bmp", "png", "gif", "jpg", "tiff"};
+ for (String format : formats) {
+ new ImageCompressionTypesTest(format);
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/metadata/GetElementsByTagNameTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8167281
+ * @summary Test verifies that Element.getElementsByTagName("*") is not empty
+ * for valid image.
+ * @run main GetElementsByTagNameTest
+ */
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataFormatImpl;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.MemoryCacheImageInputStream;
+import org.w3c.dom.Element;
+
+public class GetElementsByTagNameTest {
+
+ public static void main(String[] args) throws IOException {
+ // Generate some trivial image and save it to a temporary array
+ ByteArrayOutputStream tmp = new ByteArrayOutputStream();
+ ImageIO.write(new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB),
+ "gif", tmp);
+
+ // Read the stream
+ ImageInputStream in = new MemoryCacheImageInputStream(
+ new ByteArrayInputStream(tmp.toByteArray()));
+ ImageReader reader = ImageIO.getImageReaders(in).next();
+ reader.setInput(in);
+
+ // Retrieve standard image metadata tree
+ IIOMetadata meta = reader.getImageMetadata(0);
+ if (meta == null || !meta.isStandardMetadataFormatSupported()) {
+ throw new Error("Test failure: Missing metadata");
+ }
+ Element root = (Element) meta.
+ getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
+
+ // Test getElementsByTagName("*")
+ if (root.getElementsByTagName("*").getLength() == 0) {
+ throw new RuntimeException("getElementsByTagName(\"*\") returns"
+ + " nothing");
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/metadata/NthItemNodeListTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8167281
+ * @summary Test verifies that accessing nth item in NodeList doesn't throw
+ * IndexOutOfBoundsException.
+ * @run main NthItemNodeListTest
+ */
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataFormatImpl;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.MemoryCacheImageInputStream;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class NthItemNodeListTest {
+
+ public static void main(String[] args) throws IOException {
+ // Generate some trivial image and save it to a temporary array
+ ByteArrayOutputStream tmp = new ByteArrayOutputStream();
+ ImageIO.write(new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB),
+ "gif", tmp);
+
+ // Read it back in
+ ImageInputStream in = new MemoryCacheImageInputStream(
+ new ByteArrayInputStream(tmp.toByteArray()));
+ ImageReader reader = ImageIO.getImageReaders(in).next();
+ reader.setInput(in);
+
+ // Retrieve standard image metadata tree
+ IIOMetadata meta = reader.getImageMetadata(0);
+ if (meta == null || !meta.isStandardMetadataFormatSupported()) {
+ throw new Error("Test failure: Missing metadata");
+ }
+ Element root = (Element) meta.
+ getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
+
+ NodeList nodeList = root.
+ getElementsByTagName(root.getFirstChild().getNodeName());
+ /*
+ * Accessing the nth node should return null and not throw
+ * IndexOutOfBoundsException.
+ */
+ Node n = (nodeList.item(nodeList.getLength()));
+ }
+}
+
--- a/jdk/test/javax/print/attribute/Services_getDocFl.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/javax/print/attribute/Services_getDocFl.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
/*
* @test
- * @bug 4901243 8040139
+ * @bug 4901243 8040139 8167291
* @summary JPG, GIF, and PNG DocFlavors (URL) should be supported if Postscript is supported.
* @run main Services_getDocFl
*/
@@ -58,6 +58,7 @@
pngImagesSupported = false;
gifImagesSupported = false;
jpgImagesSupported = false;
+ psSupported = false;
for (int j=0; j<flavors.length; j++) {
System.out.println(flavors[j]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Clip/OpenNonIntegralNumberOfSampleframes.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.LineUnavailableException;
+
+/**
+ * @test
+ * @bug 8167435
+ */
+public final class OpenNonIntegralNumberOfSampleframes {
+
+ /**
+ * We will try to use all formats, in this case all our providers will be
+ * covered by supported/unsupported formats.
+ */
+ private static final List<AudioFormat> formats = new ArrayList<>(2900);
+
+ private static final Encoding[] encodings = {
+ Encoding.ALAW, Encoding.ULAW, Encoding.PCM_SIGNED,
+ Encoding.PCM_UNSIGNED, Encoding.PCM_FLOAT
+ };
+
+ private static final int[] sampleRates = {
+ 8000, 11025, 16000, 32000, 44100
+ };
+
+ private static final int[] sampleBits = {
+ 4, 8, 11, 16, 20, 24, 32, 48, 64, 128
+ };
+
+ private static final int[] channels = {
+ 1, 2, 3, 4, 5, 6
+ };
+
+ static {
+ for (final Boolean end : new boolean[]{false, true}) {
+ for (final int sampleSize : sampleBits) {
+ for (final int sampleRate : sampleRates) {
+ for (final int channel : channels) {
+ final int frameSize = ((sampleSize + 7) / 8) * channel;
+ if (frameSize == 1) {
+ // frameSize=1 is ok for any buffers, skip it
+ continue;
+ }
+ for (final Encoding enc : encodings) {
+ formats.add(
+ new AudioFormat(enc, sampleRate, sampleSize,
+ channel, frameSize,
+ sampleRate, end));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public static void main(final String[] args) {
+ for (final AudioFormat af : formats) {
+ try (Clip clip = AudioSystem.getClip()) {
+ final int bufferSize = af.getFrameSize() + 1;
+ try {
+ clip.open(af, new byte[100], 0, bufferSize);
+ } catch (final IllegalArgumentException ignored) {
+ // expected exception
+ continue;
+ } catch (final LineUnavailableException e) {
+ // should not occur, we passed incorrect bufferSize
+ e.printStackTrace();
+ }
+ System.err.println("af = " + af);
+ System.err.println("bufferSize = " + bufferSize);
+ throw new RuntimeException("Expected exception is not thrown");
+ } catch (final LineUnavailableException ignored) {
+ // the test is not applicable
+ }
+ }
+ }
+}
--- a/jdk/test/javax/swing/JMenuItem/8139169/ScreenMenuBarInputTwice.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/javax/swing/JMenuItem/8139169/ScreenMenuBarInputTwice.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* 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 @@
*/
/* @test
- * @bug 8139169
+ * @bug 8139169 8158390
* @summary verifies if TextArea gets input twice due to Apple's Screen Menubar
* @requires (os.family=="mac")
* @library ../../regtesthelpers
@@ -65,15 +65,13 @@
public static void main(String[] args) throws Exception {
robot = new Robot();
+ robot.setAutoDelay(200);
+ robot.setAutoWaitForIdle(true);
createUIWithSeperateMenuBar();
- robot.delay(2000);
shortcutTestCase();
- robot.delay(2000);
cleanUp();
createUIWithIntegratedMenuBar();
- robot.delay(2000);
menuTestCase();
- robot.delay(2000);
cleanUp();
}
@@ -188,7 +186,6 @@
robot.keyRelease(VK_COMMA);
robot.keyRelease(VK_SHIFT);
robot.keyRelease(VK_META);
- robot.delay(2000);
checkText(textArea.getText());
}
@@ -198,13 +195,10 @@
robot.mouseMove(mousePoint.x, mousePoint.y);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
- robot.delay(2000);
mousePoint = Util.getCenterPoint(menuItem);
robot.mouseMove(mousePoint.x, mousePoint.y);
- robot.delay(2000);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
- robot.delay(2000);
checkText(textArea.getText());
}
--- a/jdk/test/javax/swing/JTextArea/ScrollbarFlicker/ScrollFlickerTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/javax/swing/JTextArea/ScrollbarFlicker/ScrollFlickerTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -29,8 +29,6 @@
import javax.swing.*;
import java.awt.*;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
public class ScrollFlickerTest {
@@ -56,18 +54,19 @@
robot.delay(200);
SwingUtilities.invokeAndWait(() -> {
- scroll.getViewport().addChangeListener((e) -> cnt++);
Insets insets = scroll.getInsets();
scroll.setSize(insets.left + insets.right +
scroll.getVerticalScrollBar().getPreferredSize().width, 50);
scroll.revalidate();
});
-
+ robot.delay(200);
+ SwingUtilities.invokeAndWait(() ->
+ scroll.getViewport().addChangeListener((e) -> cnt++));
robot.delay(1000);
SwingUtilities.invokeLater(frame::dispose);
- if (cnt > 2) {
+ if (cnt > 0) {
throw new RuntimeException("Scroll bar flickers");
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.Color;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+
+/*
+ * @test
+ * @bug 8166591
+ * @key headful
+ * @summary [macos 10.12] Trackpad scrolling of text on OS X 10.12 Sierra
+ * is very fast (Trackpad, Retina only)
+ * @run main/manual/othervm TooMuchWheelRotationEventsTest
+ */
+public class TooMuchWheelRotationEventsTest {
+
+ private static volatile boolean testResult = false;
+ private static volatile CountDownLatch countDownLatch;
+ private static final String INSTRUCTIONS = "INSTRUCTIONS:\n"
+ + "Try to check the issue on Mac OS X 10.12 Sierra with trackpad"
+ + " on Retina display.\n"
+ + "\n"
+ + "If the trackpad is not supported, press PASS\n"
+ + "\n"
+ + "Use the trackpad to slightly scroll the JTextArea horizontally and vertically.\n"
+ + "If the text area is scrolled too fast press FAIL, else press PASS.";
+
+ public static void main(String args[]) throws Exception {
+ countDownLatch = new CountDownLatch(1);
+
+ SwingUtilities.invokeLater(TooMuchWheelRotationEventsTest::createUI);
+ countDownLatch.await(15, TimeUnit.MINUTES);
+
+ if (!testResult) {
+ throw new RuntimeException("Test fails!");
+ }
+ }
+
+ private static void createUI() {
+
+ final JFrame mainFrame = new JFrame("Trackpad scrolling test");
+ GridBagLayout layout = new GridBagLayout();
+ JPanel mainControlPanel = new JPanel(layout);
+ JPanel resultButtonPanel = new JPanel(layout);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ JPanel testPanel = createTestPanel();
+
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ mainControlPanel.add(testPanel, gbc);
+
+ JTextArea instructionTextArea = new JTextArea();
+ instructionTextArea.setText(INSTRUCTIONS);
+ instructionTextArea.setEditable(false);
+ instructionTextArea.setBackground(Color.white);
+
+ gbc.gridx = 0;
+ gbc.gridy = 1;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ mainControlPanel.add(instructionTextArea, gbc);
+
+ JButton passButton = new JButton("Pass");
+ passButton.setActionCommand("Pass");
+ passButton.addActionListener((ActionEvent e) -> {
+ testResult = true;
+ mainFrame.dispose();
+ countDownLatch.countDown();
+
+ });
+
+ JButton failButton = new JButton("Fail");
+ failButton.setActionCommand("Fail");
+ failButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ mainFrame.dispose();
+ countDownLatch.countDown();
+ }
+ });
+
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ resultButtonPanel.add(passButton, gbc);
+
+ gbc.gridx = 1;
+ gbc.gridy = 0;
+ resultButtonPanel.add(failButton, gbc);
+
+ gbc.gridx = 0;
+ gbc.gridy = 2;
+ mainControlPanel.add(resultButtonPanel, gbc);
+
+ mainFrame.add(mainControlPanel);
+ mainFrame.pack();
+
+ mainFrame.addWindowListener(new WindowAdapter() {
+
+ @Override
+ public void windowClosing(WindowEvent e) {
+ mainFrame.dispose();
+ countDownLatch.countDown();
+ }
+ });
+ mainFrame.setVisible(true);
+ }
+
+ private static JPanel createTestPanel() {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ JTextArea textArea = new JTextArea(20, 20);
+ textArea.setText(getLongString());
+ JScrollPane scrollPane = new JScrollPane(textArea);
+ panel.add(scrollPane);
+ return panel;
+ }
+
+ private static String getLongString() {
+
+ String lowCaseString = getLongString('a', 'z');
+ String upperCaseString = getLongString('A', 'Z');
+ String digitsString = getLongString('0', '9');
+
+ int repeat = 30;
+ StringBuilder lowCaseBuilder = new StringBuilder();
+ StringBuilder upperCaseBuilder = new StringBuilder();
+ StringBuilder digitsBuilder = new StringBuilder();
+
+ for (int i = 0; i < repeat; i++) {
+ lowCaseBuilder.append(lowCaseString).append(' ');
+ upperCaseBuilder.append(upperCaseString).append(' ');
+ digitsBuilder.append(digitsString).append(' ');
+ }
+
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < 200; i++) {
+ builder.append(upperCaseBuilder).append('\n')
+ .append(lowCaseBuilder).append('\n')
+ .append(digitsBuilder).append("\n\n\n");
+ }
+
+ return builder.toString();
+ }
+
+ private static String getLongString(char c1, char c2) {
+
+ char[] chars = new char[c2 - c1 + 1];
+ for (char i = c1; i <= c2; i++) {
+ chars[i - c1] = i;
+ }
+ return new String(chars);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/motif/8165485/MotifHiDPIIconsTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.Color;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.ScrollPaneConstants;
+import javax.swing.SwingUtilities;
+
+/*
+ * @test
+ * @bug 8165485
+ * @summary Bad rendering of Swing UI controls with Motif L&F on HiDPI display
+ * @run main/manual/othervm -Dsun.java2d.uiScale=2
+ * -Dswing.defaultlaf=com.sun.java.swing.plaf.motif.MotifLookAndFeel MotifHiDPIIconsTest
+ */
+public class MotifHiDPIIconsTest {
+
+ private static volatile boolean testResult = false;
+ private static volatile CountDownLatch countDownLatch;
+ private static final String INSTRUCTIONS = "INSTRUCTIONS:\n"
+ + "Check that the icons are painted smoothly on Swing UI controls:\n"
+ + " - JRadioButton\n"
+ + " - JCheckBox\n"
+ + " - JComboBox\n"
+ + " - JScrollPane (vertical and horizontal scroll bars)\n"
+ + "\n"
+ + "If so, press PASS, else press FAIL.\n";
+
+ public static void main(String args[]) throws Exception {
+ countDownLatch = new CountDownLatch(1);
+
+ SwingUtilities.invokeLater(MotifHiDPIIconsTest::createUI);
+ countDownLatch.await(15, TimeUnit.MINUTES);
+
+ if (!testResult) {
+ throw new RuntimeException("Test fails!");
+ }
+ }
+
+ private static void createUI() {
+
+ final JFrame mainFrame = new JFrame("Motif L&F icons test");
+ GridBagLayout layout = new GridBagLayout();
+ JPanel mainControlPanel = new JPanel(layout);
+ JPanel resultButtonPanel = new JPanel(layout);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+
+
+ JPanel testPanel = createJPanel();
+
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ mainControlPanel.add(testPanel, gbc);
+
+ JTextArea instructionTextArea = new JTextArea();
+ instructionTextArea.setText(INSTRUCTIONS);
+ instructionTextArea.setEditable(false);
+ instructionTextArea.setBackground(Color.white);
+
+ gbc.gridx = 0;
+ gbc.gridy = 1;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ mainControlPanel.add(instructionTextArea, gbc);
+
+ JButton passButton = new JButton("Pass");
+ passButton.setActionCommand("Pass");
+ passButton.addActionListener((ActionEvent e) -> {
+ testResult = true;
+ mainFrame.dispose();
+ countDownLatch.countDown();
+
+ });
+
+ JButton failButton = new JButton("Fail");
+ failButton.setActionCommand("Fail");
+ failButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ mainFrame.dispose();
+ countDownLatch.countDown();
+ }
+ });
+
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ resultButtonPanel.add(passButton, gbc);
+
+ gbc.gridx = 1;
+ gbc.gridy = 0;
+ resultButtonPanel.add(failButton, gbc);
+
+ gbc.gridx = 0;
+ gbc.gridy = 2;
+ mainControlPanel.add(resultButtonPanel, gbc);
+
+ mainFrame.add(mainControlPanel);
+ mainFrame.pack();
+
+ mainFrame.addWindowListener(new WindowAdapter() {
+
+ @Override
+ public void windowClosing(WindowEvent e) {
+ mainFrame.dispose();
+ countDownLatch.countDown();
+ }
+ });
+ mainFrame.setVisible(true);
+ }
+
+ private static JPanel createJPanel() {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+
+ JPanel iconPanel = new JPanel(new FlowLayout());
+ JRadioButton radioButton = new JRadioButton();
+ radioButton.setSelected(false);
+ iconPanel.add(radioButton);
+ radioButton = new JRadioButton();
+ radioButton.setSelected(true);
+ iconPanel.add(radioButton);
+ panel.add(iconPanel);
+
+ iconPanel = new JPanel(new FlowLayout());
+ JCheckBox checkBox = new JCheckBox();
+ checkBox.setSelected(false);
+ iconPanel.add(checkBox);
+ checkBox = new JCheckBox();
+ checkBox.setSelected(true);
+ iconPanel.add(checkBox);
+ panel.add(iconPanel);
+
+ iconPanel = new JPanel(new FlowLayout());
+ JComboBox<String> comboBox = new JComboBox(new String[]{"111", "222"});
+ iconPanel.add(comboBox);
+ panel.add(iconPanel);
+
+ iconPanel = new JPanel(new FlowLayout());
+ JTextArea textArea = new JTextArea(3, 7);
+ textArea.setText("AAA");
+ JScrollPane scrollPane = new JScrollPane(textArea);
+ scrollPane.setHorizontalScrollBarPolicy(
+ ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
+ scrollPane.setVerticalScrollBarPolicy(
+ ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
+ iconPanel.add(scrollPane);
+ panel.add(iconPanel);
+
+ return panel;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/Caret/8163124/CaretFloatingPointAPITest.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.geom.Line2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeListener;
+import javax.swing.plaf.TextUI;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Caret;
+import javax.swing.text.DefaultHighlighter;
+import javax.swing.text.Document;
+import javax.swing.text.Highlighter;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.Position;
+
+/*
+ * @test
+ * @bug 8163175
+ * @summary PlainView.modelToView() method should return Rectangle2D
+ * @run main/manual CaretFloatingPointAPITest
+ */
+public class CaretFloatingPointAPITest {
+
+ private static volatile boolean testResult = false;
+ private static volatile CountDownLatch countDownLatch;
+ private static final String INSTRUCTIONS = "INSTRUCTIONS:\n\n"
+ + "Verify that cursor position is not rounded on HiDPI display.\n\n"
+ + "If the display does not support HiDPI mode press PASS.\n\n"
+ + "1. Press the Right-Arrow key several times to move the red caret"
+ + " in the text field.\n"
+ + "2. Check that the caret has the same position between chars"
+ + " in diffrent locations.\n\n"
+ + "If so, press PASS, else press FAIL.\n";
+
+ public static void main(String args[]) throws Exception {
+ countDownLatch = new CountDownLatch(1);
+
+ SwingUtilities.invokeLater(CaretFloatingPointAPITest::createUI);
+ countDownLatch.await(15, TimeUnit.MINUTES);
+
+ if (!testResult) {
+ throw new RuntimeException("Test fails!");
+ }
+ }
+
+ private static void createUI() {
+
+ final JFrame mainFrame = new JFrame("Metal L&F icons test");
+ GridBagLayout layout = new GridBagLayout();
+ JPanel mainControlPanel = new JPanel(layout);
+ JPanel resultButtonPanel = new JPanel(layout);
+
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ JTextField textField = new JTextField("aaaaaaaaaaaaaaaaaaaaaaa");
+ Dimension size = new Dimension(400, 100);
+ textField.setPreferredSize(size);
+ textField.setFont(textField.getFont().deriveFont(28.0f));
+ textField.setCaretColor(Color.RED);
+ textField.setCaret(new CustomCaret());
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.insets = new Insets(5, 15, 5, 15);
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ mainControlPanel.add(textField, gbc);
+
+ JTextArea instructionTextArea = new JTextArea();
+ instructionTextArea.setText(INSTRUCTIONS);
+ instructionTextArea.setEditable(false);
+ instructionTextArea.setBackground(Color.white);
+
+ gbc.gridx = 0;
+ gbc.gridy = 1;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ mainControlPanel.add(instructionTextArea, gbc);
+
+ JButton passButton = new JButton("Pass");
+ passButton.setActionCommand("Pass");
+ passButton.addActionListener((ActionEvent e) -> {
+ testResult = true;
+ mainFrame.dispose();
+ countDownLatch.countDown();
+
+ });
+
+ JButton failButton = new JButton("Fail");
+ failButton.setActionCommand("Fail");
+ failButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ mainFrame.dispose();
+ countDownLatch.countDown();
+ }
+ });
+
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+
+ resultButtonPanel.add(passButton, gbc);
+
+ gbc.gridx = 1;
+ gbc.gridy = 0;
+ resultButtonPanel.add(failButton, gbc);
+
+ gbc.gridx = 0;
+ gbc.gridy = 2;
+ mainControlPanel.add(resultButtonPanel, gbc);
+
+ mainFrame.add(mainControlPanel);
+ mainFrame.pack();
+
+ mainFrame.addWindowListener(new WindowAdapter() {
+
+ @Override
+ public void windowClosing(WindowEvent e) {
+ mainFrame.dispose();
+ countDownLatch.countDown();
+ }
+ });
+ mainFrame.setVisible(true);
+ }
+
+ static class CustomCaret implements Caret {
+
+ private JTextComponent component;
+ private boolean visible;
+ private boolean selectionVisible = true;
+ int blinkRate;
+ int dot;
+ int mark;
+ Position.Bias dotBias;
+ Position.Bias markBias;
+ Object selectionTag;
+ Point2D magicCaretPosition;
+
+ private MouseListener mouseListener = new CaretMouseListener();
+
+ @Override
+ public void install(JTextComponent c) {
+ this.component = c;
+ c.addMouseListener(mouseListener);
+ }
+
+ @Override
+ public void deinstall(JTextComponent c) {
+ c.removeMouseListener(mouseListener);
+ this.component = null;
+ }
+
+ @Override
+ public void paint(Graphics g) {
+
+ if (component == null) {
+ return;
+ }
+
+ int dot = getDot();
+ Rectangle2D r = null;
+ try {
+ r = component.modelToView2D(dot);
+ } catch (BadLocationException e) {
+ return;
+ }
+
+ if (r == null) {
+ return;
+ }
+
+ Rectangle2D cr = getCaretRectangle(r);
+ repaint(cr.getBounds());
+
+ g.setColor(component.getCaretColor());
+ float cx = (float) cr.getX();
+ float cy = (float) cr.getY();
+ float cw = (float) cr.getWidth();
+ float ch = (float) cr.getHeight();
+ float c = cx + cw / 2;
+
+ Graphics2D g2d = (Graphics2D) g;
+ g2d.draw(new Line2D.Float(c, cy, c, cy + ch));
+ g2d.draw(new Line2D.Float(cx, cy, cx + cw, cy));
+ g2d.draw(new Line2D.Float(cx, cy + ch, cx + cw, cy + ch));
+ }
+
+ void repaint(Rectangle r) {
+ component.repaint(r);
+ }
+
+ Rectangle2D getCaretRectangle(Rectangle2D r) {
+ int d = 3;
+ double cx = r.getX() - d;
+ double cy = r.getY();
+ double cw = 2 * d;
+ double ch = r.getHeight();
+ return new Rectangle2D.Double(cx, cy, cw, ch);
+ }
+
+ @Override
+ public void addChangeListener(ChangeListener l) {
+ }
+
+ @Override
+ public void removeChangeListener(ChangeListener l) {
+ }
+
+ @Override
+ public boolean isVisible() {
+ return visible;
+ }
+
+ @Override
+ public void setVisible(boolean v) {
+ this.visible = true;
+ }
+
+ @Override
+ public boolean isSelectionVisible() {
+ return selectionVisible;
+ }
+
+ @Override
+ public void setSelectionVisible(boolean v) {
+ this.selectionVisible = v;
+ updateSelection();
+ }
+
+ @Override
+ public void setMagicCaretPosition(Point p) {
+ magicCaretPosition = p;
+ }
+
+ @Override
+ public Point getMagicCaretPosition() {
+ if (magicCaretPosition != null) {
+ return new Point((int) magicCaretPosition.getX(),
+ (int) magicCaretPosition.getY());
+ }
+ return null;
+ }
+
+ @Override
+ public void setBlinkRate(int rate) {
+ this.blinkRate = rate;
+ }
+
+ @Override
+ public int getBlinkRate() {
+ return blinkRate;
+ }
+
+ @Override
+ public int getDot() {
+ return dot;
+ }
+
+ @Override
+ public int getMark() {
+ return mark;
+ }
+
+ @Override
+ public void setDot(int dot) {
+ setDot(dot, Position.Bias.Forward);
+ }
+
+ private void setDot(int dot, Position.Bias bias) {
+ handleSetDot(dot, bias);
+ updateSelection();
+ }
+
+ @Override
+ public void moveDot(int dot) {
+ moveDot(dot, Position.Bias.Forward);
+ }
+
+ private void moveDot(int dot, Position.Bias bias) {
+ changeCaretPosition(dot, bias);
+ updateSelection();
+ }
+
+ void handleSetDot(int dot, Position.Bias dotBias) {
+
+ if (component == null) {
+ return;
+ }
+
+ Document doc = component.getDocument();
+ if (doc != null) {
+ dot = Math.min(dot, doc.getLength());
+ }
+
+ dot = Math.max(dot, 0);
+
+ if (dot == 0) {
+ dotBias = Position.Bias.Forward;
+ }
+
+ mark = dot;
+
+ if (this.dot != dot || this.dotBias != dotBias) {
+ changeCaretPosition(dot, dotBias);
+ updateSelection();
+ }
+
+ this.markBias = this.dotBias;
+ }
+
+ void changeCaretPosition(int dot, Position.Bias dotBias) {
+ this.dot = dot;
+ this.dotBias = dotBias;
+ setMagicCaretPosition(null);
+ SwingUtilities.invokeLater(this::repaintNewCaret);
+ }
+
+ private void updateSelection() {
+ Highlighter h = component.getHighlighter();
+ if (h != null) {
+ int p0 = Math.min(dot, mark);
+ int p1 = Math.max(dot, mark);
+
+ if (p0 == p1 || !selectionVisible) {
+ if (selectionTag != null) {
+ h.removeHighlight(selectionTag);
+ selectionTag = null;
+ }
+ } else {
+ try {
+ if (selectionTag != null) {
+ h.changeHighlight(selectionTag, p0, p1);
+ } else {
+ Highlighter.HighlightPainter p = getSelectionPainter();
+ selectionTag = h.addHighlight(p0, p1, p);
+ }
+ } catch (BadLocationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+
+ void repaintNewCaret() {
+ if (component != null) {
+ TextUI mapper = component.getUI();
+ Document doc = component.getDocument();
+ if ((mapper != null) && (doc != null)) {
+ Rectangle2D newLoc;
+ try {
+ newLoc = mapper.modelToView2D(component, this.dot, this.dotBias);
+ } catch (BadLocationException e) {
+ newLoc = null;
+ }
+ if (newLoc != null) {
+ adjustVisibility(newLoc.getBounds());
+ if (getMagicCaretPosition() == null) {
+ setMagicCaretPosition(new Point((int) newLoc.getX(),
+ (int) newLoc.getY()));
+ }
+ }
+ damage(newLoc.getBounds());
+ }
+ }
+ }
+
+ protected Highlighter.HighlightPainter getSelectionPainter() {
+ return DefaultHighlighter.DefaultPainter;
+ }
+
+ protected void adjustVisibility(Rectangle nloc) {
+ if (component == null) {
+ return;
+ }
+ if (SwingUtilities.isEventDispatchThread()) {
+ component.scrollRectToVisible(nloc);
+ } else {
+ SwingUtilities.invokeLater(() -> {
+ component.scrollRectToVisible(nloc);
+ });
+ }
+ }
+
+ protected synchronized void damage(Rectangle r) {
+ if (r != null && component != null) {
+ component.repaint(r);
+ }
+ }
+
+ private class CaretMouseListener extends MouseAdapter {
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ Point pt = new Point(e.getX(), e.getY());
+ Position.Bias[] biasRet = new Position.Bias[1];
+ int pos = component.getUI().viewToModel(component, pt, biasRet);
+ if (biasRet[0] == null) {
+ biasRet[0] = Position.Bias.Forward;
+ }
+ if (pos >= 0) {
+ setDot(pos);
+ }
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/JTextComponent/8156217/TextSelectionTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.text.JTextComponent;
+
+/**
+ * @test
+ * @bug 8156217
+ * @summary Selected text is shifted on HiDPI display
+ * @run main/manual/othervm -Dsun.java2d.uiScale=2 TextSelectionTest
+ */
+public class TextSelectionTest {
+
+ private static final String INSTRUCTIONS = "This is a manual test.\n"
+ + "\n"
+ + "Select the current text from the end to the beginning.\n"
+ + "\n"
+ + "If the text is slightly shiftted from one side to another\n"
+ + "and back during selection press Fail.\n"
+ + "Otherwise, press Pass.";
+
+ private static final CountDownLatch latch = new CountDownLatch(1);
+ private static volatile boolean passed = false;
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(TextSelectionTest::createAndShowGUI);
+ latch.await(3, TimeUnit.MINUTES);
+ System.out.println("passed: " + passed);
+ if (!passed) {
+ throw new RuntimeException("Test fails!");
+ }
+ }
+
+ private static void createAndShowGUI() {
+
+ JFrame frame = new JFrame("Follow the instructions below:");
+ frame.setSize(700, 500);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ JPanel panel = new JPanel(new BorderLayout());
+ JTextComponent textComponent = new JTextArea(INSTRUCTIONS);
+ textComponent.setEditable(false);
+ Font font = textComponent.getFont();
+ font = font.deriveFont(24.0f);
+ textComponent.setFont(font);
+ panel.add(textComponent, BorderLayout.CENTER);
+
+ JPanel buttonsPanel = new JPanel(new FlowLayout());
+ JButton passButton = new JButton("Pass");
+ passButton.addActionListener((e) -> {
+ passed = true;
+ latch.countDown();
+ frame.dispose();
+ });
+ JButton failsButton = new JButton("Fail");
+ failsButton.addActionListener((e) -> {
+ passed = false;
+ latch.countDown();
+ frame.dispose();
+ });
+
+ buttonsPanel.add(passButton);
+ buttonsPanel.add(failsButton);
+ panel.add(buttonsPanel, BorderLayout.SOUTH);
+
+ frame.getContentPane().add(panel);
+
+ frame.addWindowListener(new WindowAdapter() {
+
+ @Override
+ public void windowClosing(WindowEvent e) {
+ latch.countDown();
+ }
+ });
+ frame.setVisible(true);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/View/8156217/FPMethodCalledTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Robot;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.plaf.metal.MetalLookAndFeel;
+import javax.swing.plaf.metal.MetalTextFieldUI;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Element;
+import javax.swing.text.PasswordView;
+import javax.swing.text.PlainView;
+import javax.swing.text.View;
+import javax.swing.text.WrappedPlainView;
+
+/**
+ * @test
+ * @bug 8156217
+ * @key headful
+ * @summary Selected text is shifted on HiDPI display
+ * @run main FPMethodCalledTest
+ */
+public class FPMethodCalledTest {
+
+ private static JFrame frame;
+ private static JTextField textField;
+
+ public static void main(String[] args) throws Exception {
+
+ for (Test test : TESTS) {
+ test(test);
+ }
+ }
+
+ static void test(final Test test) throws Exception {
+ try {
+ Robot robot = new Robot();
+ robot.setAutoDelay(50);
+ SwingUtilities.invokeAndWait(() -> {
+ createAndShowGUI(test);
+ });
+
+ robot.waitForIdle();
+
+ SwingUtilities.invokeAndWait(() -> {
+ textField.select(1, 3);
+ });
+
+ robot.waitForIdle();
+
+ SwingUtilities.invokeAndWait(() -> {
+ Resultable resultable = test.resultable;
+ if (!resultable.getResult()) {
+ throw new RuntimeException("Test fails for: " + resultable);
+ }
+ });
+ } finally {
+ SwingUtilities.invokeAndWait(() -> {
+ if (frame != null) {
+ frame.dispose();
+ }
+ });
+ }
+ }
+
+ static void createAndShowGUI(Test test) {
+
+ try {
+ UIManager.setLookAndFeel(new MetalLookAndFeel());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ frame = new JFrame();
+ frame.setSize(300, 300);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ JPanel panel = new JPanel(new FlowLayout());
+
+ String text = "AAAAAAA";
+ textField = test.isPasswordField()
+ ? new JPasswordField(text)
+ : new JTextField(text);
+
+ textField.setUI(new MetalTextFieldUI() {
+
+ @Override
+ public View create(Element elem) {
+ return test.createView(elem);
+ }
+ });
+
+ panel.add(textField);
+ frame.getContentPane().add(panel);
+ frame.setVisible(true);
+ }
+
+ private static final Test[] TESTS = {
+ new Test() {
+ @Override
+ View createView(Element elem) {
+ PlainViewINTAPI view = new PlainViewINTAPI(elem);
+ resultable = view;
+ return view;
+ }
+ },
+ new Test() {
+ @Override
+ View createView(Element elem) {
+ PlainViewFPAPI view = new PlainViewFPAPI(elem);
+ resultable = view;
+ return view;
+ }
+ },
+ new Test() {
+ @Override
+ View createView(Element elem) {
+ PlainViewMixedAPI view = new PlainViewMixedAPI(elem);
+ resultable = view;
+ return view;
+ }
+ },
+ new Test() {
+ @Override
+ View createView(Element elem) {
+ WrappedPlainViewINTAPI view = new WrappedPlainViewINTAPI(elem);
+ resultable = view;
+ return view;
+ }
+ },
+ new Test() {
+ @Override
+ View createView(Element elem) {
+ WrappedPlainViewFPAPI view = new WrappedPlainViewFPAPI(elem);
+ resultable = view;
+ return view;
+ }
+ },
+ new Test() {
+ @Override
+ View createView(Element elem) {
+ WrappedPlainViewMixedAPI view = new WrappedPlainViewMixedAPI(elem);
+ resultable = view;
+ return view;
+ }
+ },
+ new Test(true) {
+
+ @Override
+ View createView(Element elem) {
+ PasswordViewINTAPI view = new PasswordViewINTAPI(elem);
+ resultable = view;
+ return view;
+ }
+ },
+ new Test(true) {
+
+ @Override
+ View createView(Element elem) {
+ PasswordViewFPAPI view = new PasswordViewFPAPI(elem);
+ resultable = view;
+ return view;
+ }
+ },
+ new Test(true) {
+
+ @Override
+ View createView(Element elem) {
+ PasswordViewMixedAPI view = new PasswordViewMixedAPI(elem);
+ resultable = view;
+ return view;
+ }
+ }
+ };
+
+ static interface Resultable {
+
+ boolean getResult();
+ }
+
+ static abstract class Test {
+
+ Resultable resultable;
+ final boolean isPasswordField;
+
+ public Test() {
+ this(false);
+ }
+
+ public Test(boolean isPasswordField) {
+ this.isPasswordField = isPasswordField;
+ }
+
+ boolean isPasswordField() {
+ return isPasswordField;
+ }
+
+ abstract View createView(Element elem);
+ }
+
+ static class PlainViewINTAPI extends PlainView implements Resultable {
+
+ boolean drawLine = false;
+ boolean drawSelected = false;
+ boolean drawUnselected = false;
+
+ public PlainViewINTAPI(Element elem) {
+ super(elem);
+ }
+
+ @Override
+ protected void drawLine(int lineIndex, Graphics g, int x, int y) {
+ drawLine = true;
+ super.drawLine(lineIndex, g, x, y);
+ }
+
+ @Override
+ protected int drawSelectedText(Graphics g, int x, int y,
+ int p0, int p1) throws BadLocationException {
+ drawSelected = true;
+ return super.drawSelectedText(g, x, y, p0, p1);
+ }
+
+ @Override
+ protected int drawUnselectedText(Graphics g, int x, int y,
+ int p0, int p1) throws BadLocationException {
+ drawUnselected = true;
+ return super.drawUnselectedText(g, x, y, p0, p1);
+ }
+
+ @Override
+ public boolean getResult() {
+ return drawLine && drawSelected && drawUnselected;
+ }
+ }
+
+ static class PlainViewFPAPI extends PlainView implements Resultable {
+
+ boolean drawLine = false;
+ boolean drawSelected = false;
+ boolean drawUnselected = false;
+
+ public PlainViewFPAPI(Element elem) {
+ super(elem);
+ }
+
+ @Override
+ protected void drawLine(int lineIndex, Graphics2D g, float x, float y) {
+ drawLine = true;
+ super.drawLine(lineIndex, g, x, y);
+ }
+
+ @Override
+ protected float drawSelectedText(Graphics2D g, float x, float y,
+ int p0, int p1) throws BadLocationException {
+ drawSelected = true;
+ return super.drawSelectedText(g, x, y, p0, p1);
+ }
+
+ @Override
+ protected float drawUnselectedText(Graphics2D g, float x, float y,
+ int p0, int p1) throws BadLocationException {
+ drawUnselected = true;
+ return super.drawUnselectedText(g, x, y, p0, p1);
+ }
+
+ @Override
+ public boolean getResult() {
+ return drawSelected;
+ }
+ }
+
+ static class PlainViewMixedAPI extends PlainView implements Resultable {
+
+ boolean isIntMethodCalled = false;
+ boolean isFPMethodCalled = false;
+
+ public PlainViewMixedAPI(Element elem) {
+ super(elem);
+ }
+
+ @Override
+ protected int drawSelectedText(Graphics g, int x, int y,
+ int p0, int p1) throws BadLocationException {
+ isIntMethodCalled = true;
+ return super.drawSelectedText(g, x, y, p0, p1);
+ }
+
+ @Override
+ protected float drawSelectedText(Graphics2D g, float x, float y,
+ int p0, int p1) throws BadLocationException {
+ isFPMethodCalled = true;
+ return super.drawSelectedText(g, x, y, p0, p1);
+ }
+
+ @Override
+ public boolean getResult() {
+ return !isIntMethodCalled && isFPMethodCalled;
+ }
+ }
+
+ static class WrappedPlainViewINTAPI extends WrappedPlainView implements Resultable {
+
+ boolean drawLine = false;
+ boolean drawSelected = false;
+ boolean drawUnselected = false;
+
+ public WrappedPlainViewINTAPI(Element elem) {
+ super(elem);
+ }
+
+ @Override
+ protected void drawLine(int p0, int p1, Graphics g, int x, int y) {
+ drawLine = true;
+ super.drawLine(p0, p1, g, x, y);
+ }
+
+ @Override
+ protected int drawSelectedText(Graphics g, int x, int y,
+ int p0, int p1) throws BadLocationException {
+ drawSelected = true;
+ return super.drawSelectedText(g, x, y, p0, p1);
+ }
+
+ @Override
+ protected int drawUnselectedText(Graphics g, int x, int y,
+ int p0, int p1) throws BadLocationException {
+ drawUnselected = true;
+ return super.drawUnselectedText(g, x, y, p0, p1);
+ }
+
+ @Override
+ public boolean getResult() {
+ return drawLine && drawSelected && drawUnselected;
+ }
+ }
+
+ static class WrappedPlainViewFPAPI extends WrappedPlainView implements Resultable {
+
+ boolean drawLine = false;
+ boolean drawSelected = false;
+ boolean drawUnselected = false;
+
+ public WrappedPlainViewFPAPI(Element elem) {
+ super(elem);
+ }
+
+ @Override
+ protected void drawLine(int p0, int p1, Graphics2D g, float x, float y) {
+ drawLine = true;
+ super.drawLine(p0, p1, g, x, y);
+ }
+
+ @Override
+ protected float drawSelectedText(Graphics2D g, float x, float y,
+ int p0, int p1) throws BadLocationException {
+ drawSelected = true;
+ return super.drawSelectedText(g, x, y, p0, p1);
+ }
+
+ @Override
+ protected float drawUnselectedText(Graphics2D g, float x, float y,
+ int p0, int p1) throws BadLocationException {
+ drawUnselected = true;
+ return super.drawUnselectedText(g, x, y, p0, p1);
+ }
+
+ @Override
+ public boolean getResult() {
+ return drawLine && drawSelected && drawUnselected;
+ }
+ }
+
+ static class WrappedPlainViewMixedAPI extends WrappedPlainView implements Resultable {
+
+ boolean isIntMethodCalled = false;
+ boolean isFPMethodCalled = false;
+
+ public WrappedPlainViewMixedAPI(Element elem) {
+ super(elem);
+ }
+
+ @Override
+ protected int drawUnselectedText(Graphics g, int x, int y,
+ int p0, int p1) throws BadLocationException {
+ isIntMethodCalled = true;
+ return super.drawUnselectedText(g, x, y, p0, p1);
+ }
+
+ @Override
+ protected float drawUnselectedText(Graphics2D g, float x, float y,
+ int p0, int p1) throws BadLocationException {
+ isFPMethodCalled = true;
+ return super.drawUnselectedText(g, x, y, p0, p1);
+ }
+
+ @Override
+ public boolean getResult() {
+ return !isIntMethodCalled && isFPMethodCalled;
+ }
+ }
+
+ static class PasswordViewINTAPI extends PasswordView implements Resultable {
+
+ boolean isIntMethodCalled = false;
+
+ public PasswordViewINTAPI(Element elem) {
+ super(elem);
+
+ }
+
+ @Override
+ protected int drawEchoCharacter(Graphics g, int x, int y, char c) {
+ isIntMethodCalled = true;
+ return super.drawEchoCharacter(g, x, y, c);
+ }
+
+ @Override
+ public boolean getResult() {
+ return isIntMethodCalled;
+ }
+ }
+
+ static class PasswordViewFPAPI extends PasswordView implements Resultable {
+
+ boolean isFPMethodCalled = false;
+
+ public PasswordViewFPAPI(Element elem) {
+ super(elem);
+
+ }
+
+ @Override
+ protected float drawEchoCharacter(Graphics2D g, float x, float y, char c) {
+ isFPMethodCalled = true;
+ return super.drawEchoCharacter(g, x, y, c);
+ }
+
+ @Override
+ public boolean getResult() {
+ return isFPMethodCalled;
+ }
+ }
+
+ static class PasswordViewMixedAPI extends PasswordView implements Resultable {
+
+ boolean isIntMethodCalled = false;
+ boolean isFPMethodCalled = false;
+
+ public PasswordViewMixedAPI(Element elem) {
+ super(elem);
+
+ }
+
+ @Override
+ protected int drawEchoCharacter(Graphics g, int x, int y, char c) {
+ isIntMethodCalled = true;
+ return super.drawEchoCharacter(g, x, y, c);
+ }
+
+ @Override
+ protected float drawEchoCharacter(Graphics2D g, float x, float y, char c) {
+ isFPMethodCalled = true;
+ return super.drawEchoCharacter(g, x, y, c);
+ }
+
+ @Override
+ public boolean getResult() {
+ return !isIntMethodCalled && isFPMethodCalled;
+ }
+ }
+}
--- a/jdk/test/sun/security/smartcardio/TestChannel.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/sun/security/smartcardio/TestChannel.java Thu Oct 27 21:22:57 2016 +0000
@@ -23,11 +23,12 @@
/*
* @test
- * @bug 6239117
+ * @bug 6239117 8168851
* @summary test logical channels work
* @author Andreas Sterbenz
* @modules java.smartcardio/javax.smartcardio
* @run main/manual TestChannel
+ * @run main/othervm/manual/java.security.policy==test.policy TestChannel
*/
// This test requires special hardware.
--- a/jdk/test/sun/security/smartcardio/TestControl.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/sun/security/smartcardio/TestControl.java Thu Oct 27 21:22:57 2016 +0000
@@ -23,11 +23,12 @@
/*
* @test
- * @bug 6239117 6470320
+ * @bug 6239117 6470320 8168851
* @summary test if transmitControlCommand() works
* @author Andreas Sterbenz
* @modules java.smartcardio/javax.smartcardio
* @run main/manual TestControl
+ * @run main/othervm/manual/java.security.policy==test.policy TestControl
*/
// This test requires special hardware.
--- a/jdk/test/sun/security/smartcardio/TestDefault.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/sun/security/smartcardio/TestDefault.java Thu Oct 27 21:22:57 2016 +0000
@@ -23,11 +23,12 @@
/*
* @test
- * @bug 6327047
+ * @bug 6327047 8168851
* @summary verify that TerminalFactory.getDefault() works
* @author Andreas Sterbenz
* @modules java.smartcardio/javax.smartcardio
* @run main/manual TestDefault
+ * @run main/othervm/manual/java.security.policy==test.policy TestDefault
*/
// This test requires special hardware.
--- a/jdk/test/sun/security/smartcardio/TestDirect.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/sun/security/smartcardio/TestDirect.java Thu Oct 27 21:22:57 2016 +0000
@@ -23,10 +23,11 @@
/*
* @test
- * @bug 8046343
+ * @bug 8046343 8168851
* @summary Make sure that direct protocol is available
* @modules java.smartcardio/javax.smartcardio
* @run main/manual TestDirect
+ * @run main/othervm/manual/java.security.policy==test.policy TestDirect
*/
// This test requires special hardware.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/smartcardio/test.policy Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,3 @@
+grant codebase "file:${test.classes}/*" {
+ permission javax.smartcardio.CardPermission "*", "connect,getBasicChannel,reset,transmitControl";
+};
--- a/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* 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,31 +29,22 @@
/*
* @test
* @bug 4392475
+ * @library /javax/net/ssl/templates
* @summary Calling setWantClientAuth(true) disables anonymous suites
* @run main/othervm/timeout=180 AnonCipherWithWantClientAuth
*/
-import java.io.*;
-import java.net.*;
-import javax.net.ssl.*;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.security.Security;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+
public class AnonCipherWithWantClientAuth {
/*
- * =============================================================
- * Set the various variables needed for the tests, then
- * specify what tests to run on each side.
- */
-
- /*
- * Should we run the client or server in a separate thread?
- * Both sides can throw exceptions, but do you have a preference
- * as to which side should be the main thread.
- */
- static boolean separateServerThread = false;
-
- /*
* Where do we find the keystores?
*/
static String pathToStores = "../../../../javax/net/ssl/etc";
@@ -61,106 +52,7 @@
static String trustStoreFile = "truststore";
static String passwd = "passphrase";
- /*
- * Is the server ready to serve?
- */
- volatile static boolean serverReady = false;
-
- /*
- * Turn on SSL debugging?
- */
- static boolean debug = false;
-
- /*
- * If the client or server is doing some kind of object creation
- * that the other side depends on, and that thread prematurely
- * exits, you may experience a hang. The test harness will
- * terminate all hung threads after its timeout has expired,
- * currently 3 minutes by default, but you might try to be
- * smart about it....
- */
-
- /*
- * Define the server side of the test.
- *
- * If the server prematurely exits, serverReady will be set to true
- * to avoid infinite hangs.
- */
- void doServerSide() throws Exception {
- SSLServerSocketFactory sslssf =
- (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
- SSLServerSocket sslServerSocket =
- (SSLServerSocket) sslssf.createServerSocket(serverPort);
- serverPort = sslServerSocket.getLocalPort();
- String ciphers[]={"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
- "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
- "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"};
- sslServerSocket.setEnabledCipherSuites(ciphers);
- sslServerSocket.setWantClientAuth(true);
- /*
- * Signal Client, we're ready for his connect.
- */
- serverReady = true;
-
- SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
- InputStream sslIS = sslSocket.getInputStream();
- OutputStream sslOS = sslSocket.getOutputStream();
-
- sslIS.read();
- sslOS.write(85);
- sslOS.flush();
-
- sslSocket.close();
- }
-
- /*
- * Define the client side of the test.
- *
- * If the server prematurely exits, serverReady will be set to true
- * to avoid infinite hangs.
- */
- void doClientSide() throws Exception {
-
- /*
- * Wait for server to get started.
- */
- while (!serverReady) {
- Thread.sleep(50);
- }
-
- SSLSocketFactory sslsf =
- (SSLSocketFactory) SSLSocketFactory.getDefault();
- SSLSocket sslSocket = (SSLSocket)
- sslsf.createSocket("localhost", serverPort);
- String ciphers[] = {"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
- "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"};
- sslSocket.setEnabledCipherSuites(ciphers);
- sslSocket.setUseClientMode(true);
-
- InputStream sslIS = sslSocket.getInputStream();
- OutputStream sslOS = sslSocket.getOutputStream();
-
- sslOS.write(280);
- sslOS.flush();
- sslIS.read();
-
- sslSocket.close();
- }
-
- /*
- * =============================================================
- * The remainder is just support stuff
- */
-
- // use any free port by default
- volatile int serverPort = 0;
-
- volatile Exception serverException = null;
- volatile Exception clientException = null;
-
public static void main(String[] args) throws Exception {
- // reset security properties to make sure that the algorithms
- // and keys used in this test are not disabled.
Security.setProperty("jdk.tls.disabledAlgorithms", "");
Security.setProperty("jdk.certpath.disabledAlgorithms", "");
@@ -170,100 +62,84 @@
String trustFilename =
System.getProperty("test.src", "./") + "/" + pathToStores +
"/" + trustStoreFile;
-
- System.setProperty("javax.net.ssl.keyStore", keyFilename);
- System.setProperty("javax.net.ssl.keyStorePassword", passwd);
- System.setProperty("javax.net.ssl.trustStore", trustFilename);
- System.setProperty("javax.net.ssl.trustStorePassword", passwd);
-
- if (debug)
- System.setProperty("javax.net.debug", "all");
+ SSLTest.setup(keyFilename, trustFilename, passwd);
- /*
- * Start the tests.
- */
- new AnonCipherWithWantClientAuth();
- }
-
- Thread clientThread = null;
- Thread serverThread = null;
+ new SSLTest()
+ .setServerPeer(test -> {
+ SSLServerSocketFactory sslssf =
+ (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+ SSLServerSocket sslServerSocket =
+ (SSLServerSocket) sslssf.createServerSocket(SSLTest.FREE_PORT);
+ test.setServerPort(sslServerSocket.getLocalPort());
+ SSLTest.print("Server is listening on port "
+ + test.getServerPort());
- /*
- * Primary constructor, used to drive remainder of the test.
- *
- * Fork off the other side, then do your work.
- */
- AnonCipherWithWantClientAuth () throws Exception {
- if (separateServerThread) {
- startServer(true);
- startClient(false);
- } else {
- startClient(true);
- startServer(false);
- }
+ String ciphers[] = {
+ "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
+ "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
+ "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" };
+ sslServerSocket.setEnabledCipherSuites(ciphers);
+ sslServerSocket.setWantClientAuth(true);
+
+ // Signal the client, the server is ready to accept connection.
+ test.signalServerReady();
- /*
- * Wait for other side to close down.
- */
- if (separateServerThread) {
- serverThread.join();
- } else {
- clientThread.join();
- }
+ // Try to accept a connection in 30 seconds.
+ SSLSocket sslSocket = SSLTest.accept(sslServerSocket);
+ if (sslSocket == null) {
+ // Ignore the test case if no connection within 30 seconds.
+ SSLTest.print("No incoming client connection in 30 seconds."
+ + " Ignore in server side.");
+ return;
+ }
+ SSLTest.print("Server accepted connection");
- /*
- * When we get here, the test is pretty much over.
- *
- * If the main thread excepted, that propagates back
- * immediately. If the other thread threw an exception, we
- * should report back.
- */
- if (serverException != null)
- throw serverException;
- if (clientException != null)
- throw clientException;
- }
+ // handle the connection
+ try {
+ // Is it the expected client connection?
+ //
+ // Naughty test cases or third party routines may try to
+ // connection to this server port unintentionally. In
+ // order to mitigate the impact of unexpected client
+ // connections and avoid intermittent failure, it should
+ // be checked that the accepted connection is really linked
+ // to the expected client.
+ boolean clientIsReady = test.waitForClientSignal();
- void startServer(boolean newThread) throws Exception {
- if (newThread) {
- serverThread = new Thread() {
- public void run() {
- try {
- doServerSide();
- } catch (Exception e) {
- /*
- * Our server thread just died.
- */
- System.err.println("Server died...");
- serverReady = true;
- serverException = e;
+ if (clientIsReady) {
+ // Run the application in server side.
+ SSLTest.print("Run server application");
+
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslIS.read();
+ sslOS.write(85);
+ sslOS.flush();
+ } else {
+ System.out.println(
+ "The client is not the expected one or timeout. "
+ + "Ignore in server side.");
}
+ } finally {
+ sslSocket.close();
+ sslServerSocket.close();
}
- };
- serverThread.start();
- } else {
- doServerSide();
- }
- }
+ })
+ .setClientApplication((socket, test) -> {
+ String ciphers[] = {
+ "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
+ "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5" };
+ socket.setEnabledCipherSuites(ciphers);
+ socket.setUseClientMode(true);
- void startClient(boolean newThread) throws Exception {
- if (newThread) {
- clientThread = new Thread() {
- public void run() {
- try {
- doClientSide();
- } catch (Exception e) {
- /*
- * Our client thread just died.
- */
- System.err.println("Client died...");
- clientException = e;
- }
- }
- };
- clientThread.start();
- } else {
- doClientSide();
- }
+ InputStream sslIS = socket.getInputStream();
+ OutputStream sslOS = socket.getOutputStream();
+
+ sslOS.write(280);
+ sslOS.flush();
+ sslIS.read();
+ })
+ .runTest();
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/ConcealedPackage.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8146486
+ * @summary Fail to create a MR modular JAR with a versioned entry in
+ * base-versioned empty package
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.FileUtils
+ * @run testng ConcealedPackage
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.spi.ToolProvider;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import jdk.testlibrary.FileUtils;
+
+public class ConcealedPackage {
+ private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
+ .orElseThrow(() -> new RuntimeException("jar tool not found"));
+ private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac")
+ .orElseThrow(() -> new RuntimeException("javac tool not found"));
+ private final String linesep = System.lineSeparator();
+ private final Path userdir;
+ private final ByteArrayOutputStream outbytes = new ByteArrayOutputStream();
+ private final PrintStream out = new PrintStream(outbytes, true);
+ private final ByteArrayOutputStream errbytes = new ByteArrayOutputStream();
+ private final PrintStream err = new PrintStream(errbytes, true);
+
+ public ConcealedPackage() throws IOException {
+ Path testsrc = Paths.get(System.getProperty("test.src"));
+ userdir = Paths.get(System.getProperty("user.dir", "."));
+
+ // compile the classes directory
+ Path source = testsrc.resolve("src").resolve("classes");
+ Path destination = Paths.get("classes");
+ javac(source, destination);
+
+ // compile the mr9 directory including module-info.java
+ source = testsrc.resolve("src").resolve("mr9");
+ destination = Paths.get("mr9");
+ javac(source, destination);
+
+ // move module-info.class for later use
+ Files.move(destination.resolve("module-info.class"),
+ Paths.get("module-info.class"));
+ }
+
+ private void javac(Path source, Path destination) throws IOException {
+ String[] args = Stream.concat(
+ Stream.of("-d", destination.toString()),
+ Files.walk(source)
+ .map(Path::toString)
+ .filter(s -> s.endsWith(".java"))
+ ).toArray(String[]::new);
+ JAVAC_TOOL.run(System.out, System.err, args);
+ }
+
+ private int jar(String cmd) {
+ outbytes.reset();
+ errbytes.reset();
+ return JAR_TOOL.run(out, err, cmd.split(" +"));
+ }
+
+ @AfterClass
+ public void cleanup() throws IOException {
+ Files.walk(userdir, 1)
+ .filter(p -> !p.equals(userdir))
+ .forEach(p -> {
+ try {
+ if (Files.isDirectory(p)) {
+ FileUtils.deleteFileTreeWithRetry(p);
+ } else {
+ FileUtils.deleteFileIfExistsWithRetry(p);
+ }
+ } catch (IOException x) {
+ throw new UncheckedIOException(x);
+ }
+ });
+ }
+
+ // updates a valid multi-release jar with a new public class in
+ // versioned section and fails
+ @Test
+ public void test1() {
+ // successful build of multi-release jar
+ int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
+ Assert.assertEquals(rc, 0);
+
+ jar("-tf mmr.jar");
+
+ String s = new String(outbytes.toByteArray());
+ Set<String> actual = Arrays.stream(s.split(linesep)).collect(Collectors.toSet());
+ Set<String> expected = Set.of(
+ "META-INF/",
+ "META-INF/MANIFEST.MF",
+ "p/",
+ "p/Hi.class",
+ "META-INF/versions/9/p/Hi.class"
+ );
+ Assert.assertEquals(actual, expected);
+
+ // failed build because of new public class
+ rc = jar("-uf mmr.jar --release 9 -C mr9 p/internal/Bar.class");
+ Assert.assertEquals(rc, 1);
+
+ s = new String(errbytes.toByteArray());
+ Assert.assertTrue(s.contains("p/internal/Bar.class, contains a new public "
+ + "class not found in base entries")
+ );
+ }
+
+ // updates a valid multi-release jar with a module-info class and new
+ // concealed public class in versioned section and succeeds
+ @Test
+ public void test2() {
+ // successful build of multi-release jar
+ int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
+ Assert.assertEquals(rc, 0);
+
+ // successful build because of module-info and new public class
+ rc = jar("-uf mmr.jar module-info.class --release 9 -C mr9 p/internal/Bar.class");
+ Assert.assertEquals(rc, 0);
+
+ String s = new String(errbytes.toByteArray());
+ Assert.assertTrue(s.contains("p/internal/Bar.class is a public class in a "
+ + "concealed package, \nplacing this jar on the class path "
+ + "will result in incompatible public interfaces")
+ );
+
+ jar("-tf mmr.jar");
+
+ s = new String(outbytes.toByteArray());
+ Set<String> actual = Arrays.stream(s.split(linesep)).collect(Collectors.toSet());
+ Set<String> expected = Set.of(
+ "META-INF/",
+ "META-INF/MANIFEST.MF",
+ "p/",
+ "p/Hi.class",
+ "META-INF/versions/9/p/Hi.class",
+ "META-INF/versions/9/p/internal/Bar.class",
+ "module-info.class"
+ );
+ Assert.assertEquals(actual, expected);
+ }
+
+ // jar tool fails building mmr.jar because of new public class
+ @Test
+ public void test3() {
+ int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 .");
+ Assert.assertEquals(rc, 1);
+
+ String s = new String(errbytes.toByteArray());
+ Assert.assertTrue(s.contains("p/internal/Bar.class, contains a new public "
+ + "class not found in base entries")
+ );
+ }
+
+ // jar tool succeeds building mmr.jar because of concealed package
+ @Test
+ public void test4() {
+ int rc = jar("-cf mmr.jar module-info.class -C classes . " +
+ "--release 9 module-info.class -C mr9 .");
+ Assert.assertEquals(rc, 0);
+
+ String s = new String(errbytes.toByteArray());
+ Assert.assertTrue(s.contains("p/internal/Bar.class is a public class in a "
+ + "concealed package, \nplacing this jar on the class path "
+ + "will result in incompatible public interfaces")
+ );
+
+ jar("-tf mmr.jar");
+
+ s = new String(outbytes.toByteArray());
+ Set<String> actual = Arrays.stream(s.split(linesep)).collect(Collectors.toSet());
+ Set<String> expected = Set.of(
+ "META-INF/",
+ "META-INF/MANIFEST.MF",
+ "module-info.class",
+ "META-INF/versions/9/module-info.class",
+ "p/",
+ "p/Hi.class",
+ "META-INF/versions/9/p/",
+ "META-INF/versions/9/p/Hi.class",
+ "META-INF/versions/9/p/internal/",
+ "META-INF/versions/9/p/internal/Bar.class"
+ );
+ Assert.assertEquals(actual, expected);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/src/classes/p/Hi.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p;
+
+public class Hi {
+ public void sayHi() {
+ System.out.println("Hi");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/src/mr9/module-info.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m1 {
+ exports p;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/src/mr9/p/Hi.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p;
+
+public class Hi {
+ public void sayHi() {
+ System.out.println("Hello");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/src/mr9/p/internal/Bar.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p.internal;
+
+public class Bar {
+ @Override
+ public String toString() {
+ return "p.internal.Bar";
+ }
+}
--- a/jdk/test/tools/jlink/JLinkTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/tools/jlink/JLinkTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -109,19 +109,16 @@
.modulePath(helper.defaultModulePath())
.output(helper.createNewImageDir(moduleName))
.addMods("leaf1")
- .option("")
.call().assertSuccess();
JImageGenerator.getJLinkTask()
.modulePath(helper.defaultModulePath())
.addMods("leaf1")
.option("--output")
- .option("")
.call().assertFailure("Error: no value given for --output");
JImageGenerator.getJLinkTask()
.modulePath("")
.output(helper.createNewImageDir(moduleName))
.addMods("leaf1")
- .option("")
.call().assertFailure("Error: no value given for --module-path");
}
@@ -132,7 +129,6 @@
.modulePath(helper.defaultModulePath())
.output(helper.createNewImageDir(moduleName))
.addMods("m")
- .option("")
.call().assertSuccess();
moduleName = "mod";
jmod = helper.generateDefaultJModule(moduleName).assertSuccess();
@@ -140,7 +136,6 @@
.modulePath(helper.defaultModulePath())
.output(helper.createNewImageDir(moduleName))
.addMods("m")
- .option("")
.call().assertSuccess();
}
@@ -282,18 +277,21 @@
helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: Invalid compression level invalid");
}
- // @file
+ // orphan argument - JDK-8166810
{
- Path path = Paths.get("embedded.properties");
- Files.write(path, Collections.singletonList("--strip-debug --add-modules " +
- "toto.unknown --compress UNKNOWN\n"));
- String[] userOptions = {"@", path.toAbsolutePath().toString()};
- String moduleName = "configembeddednocompresscomposite2";
+ String[] userOptions = {"--compress", "2", "foo" };
+ String moduleName = "orphanarg1";
helper.generateDefaultJModule(moduleName, "composite2");
- Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
- helper.checkImage(imageDir, moduleName, null, null);
+ helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: orphan argument: foo");
}
+ // orphan argument - JDK-8166810
+ {
+ String[] userOptions = {"--output", "foo", "bar" };
+ String moduleName = "orphanarg2";
+ helper.generateDefaultJModule(moduleName, "composite2");
+ helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: orphan argument: bar");
+ }
}
private static void testCompress(Helper helper, String moduleName, String... userOptions) throws IOException {
--- a/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -40,7 +40,7 @@
/*
* @test
- * @bug 8152143 8152704 8155649
+ * @bug 8152143 8152704 8155649 8165804
* @summary IncludeLocalesPlugin tests
* @author Naoto Sato
* @library ../../lib
@@ -236,6 +236,7 @@
"/jdk.localedata/sun/text/resources/ext/thai_dict",
"/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th",
"/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class",
+ "/jdk.localedata/sun/text/resources/ext/BreakIteratorResources_th.class",
"/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
"/jdk.localedata/sun/text/resources/ext/FormatData_ja.class",
"/jdk.localedata/sun/text/resources/ext/FormatData_th.class",
@@ -261,6 +262,7 @@
"/jdk.localedata/sun/text/resources/ext/thai_dict",
"/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th",
"/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class",
+ "/jdk.localedata/sun/text/resources/ext/BreakIteratorResources_th.class",
"/jdk.localedata/sun/text/resources/ext/FormatData_th.class"),
List.of(
"/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
@@ -431,13 +433,23 @@
for (Object[] data : testData) {
// create image for each test data
- System.out.println("Invoking jlink with \"" + data[INCLUDE_LOCALES_OPTION] + "\"");
- Result result = JImageGenerator.getJLinkTask()
+ Result result;
+ if (data[INCLUDE_LOCALES_OPTION].toString().isEmpty()) {
+ System.out.println("Invoking jlink with no --include-locales option");
+ result = JImageGenerator.getJLinkTask()
+ .modulePath(helper.defaultModulePath())
+ .output(helper.createNewImageDir(moduleName))
+ .addMods((String) data[ADDMODS_OPTION])
+ .call();
+ } else {
+ System.out.println("Invoking jlink with \"" + data[INCLUDE_LOCALES_OPTION] + "\"");
+ result = JImageGenerator.getJLinkTask()
.modulePath(helper.defaultModulePath())
.output(helper.createNewImageDir(moduleName))
.addMods((String) data[ADDMODS_OPTION])
.option((String) data[INCLUDE_LOCALES_OPTION])
.call();
+ }
String errorMsg = (String) data[ERROR_MESSAGE];
if (errorMsg.isEmpty()) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/classpath/JavaClassPathTest.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import jdk.testlibrary.OutputAnalyzer;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+import static jdk.testlibrary.ProcessTools.*;
+
+/**
+ * @test
+ * @bug 8168205
+ * @summary Test the default class path if -Djava.class.path is set
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build CompilerUtils jdk.testlibrary.*
+ * @run testng JavaClassPathTest
+ */
+
+public class JavaClassPathTest {
+ private static final Path SRC_DIR = Paths.get(System.getProperty("test.src"),
+ "src");
+ private static final Path MODS_DIR = Paths.get("mods");
+ private static final String TEST_MODULE = "m";
+ private static final String TEST_MAIN = "jdk.test.Main";
+
+ @BeforeTest
+ public void setup() throws Exception {
+ boolean compiled = CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE),
+ MODS_DIR.resolve(TEST_MODULE));
+ assertTrue(compiled, "module " + TEST_MODULE + " did not compile");
+
+ // add the class and a resource to the current working directory
+ Path file = Paths.get("jdk/test/Main.class");
+ Files.createDirectories(file.getParent());
+ Files.copy(MODS_DIR.resolve(TEST_MODULE).resolve(file), file);
+
+ Path res = Paths.get("jdk/test/res.properties");
+ Files.createFile(res);
+ }
+
+ @DataProvider(name = "classpath")
+ public Object[][] classpath() {
+ return new Object[][]{
+ // true indicates that class path default to current working directory
+ { "", true },
+ { "-Djava.class.path", true },
+ { "-Djava.class.path=", true },
+ { "-Djava.class.path=.", true },
+ };
+ }
+
+ @Test(dataProvider = "classpath")
+ public void testUnnamedModule(String option, boolean expected) throws Throwable {
+ List<String> args = new ArrayList<>();
+ if (!option.isEmpty()) {
+ args.add(option);
+ }
+ args.add(TEST_MAIN);
+ args.add(Boolean.toString(expected));
+
+ assertTrue(execute(args).getExitValue() == 0);
+ }
+
+ @DataProvider(name = "moduleAndClassPath")
+ public Object[][] moduleAndClassPath() {
+ return new Object[][]{
+ // true indicates that class path default to current working directory
+ { "", false },
+ { "-Djava.class.path", false },
+ { "-Djava.class.path=", false },
+ { "-Djava.class.path=.", true },
+ };
+ }
+
+ @Test(dataProvider = "moduleAndClassPath")
+ public void testNamedModule(String option, boolean expected) throws Throwable {
+ List<String> args = new ArrayList<>();
+ if (!option.isEmpty()) {
+ args.add(option);
+ }
+ args.add("--module-path");
+ args.add(MODS_DIR.toString());
+ args.add("-m");
+ args.add(TEST_MODULE + "/" + TEST_MAIN);
+ args.add(Boolean.toString(expected));
+
+ assertTrue(execute(args).getExitValue() == 0);
+ }
+
+ private OutputAnalyzer execute(List<String> options) throws Throwable {
+ ProcessBuilder pb =
+ createJavaProcessBuilder(options.toArray(new String[0]));
+ Map<String,String> env = pb.environment();
+ // remove CLASSPATH environment variable
+ String value = env.remove("CLASSPATH");
+ return executeCommand(pb)
+ .outputTo(System.out)
+ .errorTo(System.out);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/classpath/src/m/jdk/test/Main.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test;
+
+import java.net.URL;
+
+public class Main {
+ static final String JAVA_CLASS_PATH = "java.class.path";
+
+ public static void main(String[] args) throws Exception {
+ String value = System.getProperty(JAVA_CLASS_PATH);
+ if (value == null) {
+ throw new RuntimeException(JAVA_CLASS_PATH + " is expected non-null" +
+ " for compatibility");
+ }
+
+ boolean expected = args[0].equals("true");
+ ClassLoader loader = ClassLoader.getSystemClassLoader();
+ URL url = loader.getResource("jdk/test/res.properties");
+ if ((expected && url == null) || (!expected && url != null)) {
+ throw new RuntimeException("URL: " + url + " expected non-null: " + expected);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/classpath/src/m/module-info.java Thu Oct 27 21:22:57 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m {
+}
+
--- a/jdk/test/tools/pack200/MultiRelease.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/tools/pack200/MultiRelease.java Thu Oct 27 21:22:57 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -60,6 +60,7 @@
} else {
System.out.println("All tests(" + pass + ") passes");
}
+ Utils.cleanup();
}
/*
--- a/jdk/test/tools/pack200/Utils.java Thu Oct 27 16:29:00 2016 +0000
+++ b/jdk/test/tools/pack200/Utils.java Thu Oct 27 21:22:57 2016 +0000
@@ -94,7 +94,7 @@
}
File srcDir = new File(getVerifierDir(), "src");
List<File> javaFileList = findFiles(srcDir, createFilter(JAVA_FILE_EXT));
- File tmpFile = File.createTempFile("javac", ".tmp");
+ File tmpFile = File.createTempFile("javac", ".tmp", new File("."));
XCLASSES.mkdirs();
FileOutputStream fos = null;
PrintStream ps = null;
@@ -208,6 +208,10 @@
Utils.createFilter(".idx")));
toDelete.addAll(Utils.findFiles(new File("."),
Utils.createFilter(".gidx")));
+ toDelete.addAll(Utils.findFiles(new File("."),
+ Utils.createFilter(".tmp")));
+ toDelete.addAll(Utils.findFiles(new File("."),
+ Utils.createFilter(".class")));
for (File f : toDelete) {
f.delete();
}