This one is only used by DOMAdapter.getExpandedTypeID(int), which
* is mostly called from the compiled translets.
*/
- public final int getExpandedTypeID2(int nodeHandle)
- {
+ public final int getExpandedTypeID2(int nodeHandle) {
int nodeID = makeNodeIdentity(nodeHandle);
- //return (nodeID != NULL) ? _exptype2(nodeID) : NULL;
-
if (nodeID != NULL) {
if (nodeID < m_blocksize)
return m_exptype_map0[nodeID];
@@ -2026,12 +1965,10 @@ public class SAX2DTM2 extends SAX2DTM
* END of DTM base accessor interfaces
*************************************************************************/
-
/**
* Return the node type from the expanded type
*/
- public final int _exptype2Type(int exptype)
- {
+ public final int _exptype2Type(int exptype) {
if (NULL != exptype)
return m_extendedTypes[exptype].getNodeType();
else
@@ -2046,16 +1983,14 @@ public class SAX2DTM2 extends SAX2DTM
*
* @return The prefix if there is one, or null.
*/
- public int getIdForNamespace(String uri)
- {
+ public int getIdForNamespace(String uri) {
int index = m_values.indexOf(uri);
- if (index < 0)
- {
- m_values.addElement(uri);
+ if (index < 0) {
+ m_values.add(uri);
return m_valueIndex++;
- }
- else
+ } else {
return index;
+ }
}
/**
@@ -2079,15 +2014,25 @@ public class SAX2DTM2 extends SAX2DTM
* @param attributes The specified or defaulted attributes.
* @throws SAXException Any SAX exception, possibly
* wrapping another exception.
- * @see org.xml.sax.ContentHandler#startElement
+ * @see ContentHandler#startElement
*/
- public void startElement(String uri, String localName, String qName, Attributes attributes)
- throws SAXException
+ public void startElement(String uri, String localName, String qName,
+ Attributes attributes) throws SAXException
{
-
charactersFlush();
- int exName = m_expandedNameTable.getExpandedTypeID(uri, localName, DTM.ELEMENT_NODE);
+ // in case URI and localName are empty, the input is not using the
+ // namespaces feature. Then we should take the part after the last
+ // colon of qName as localName (strip all namespace prefixes)
+ if ((uri == null || uri.isEmpty()) &&
+ (localName == null || localName.isEmpty()))
+ {
+ final int colon = qName.lastIndexOf(':');
+ localName = (colon > -1) ? qName.substring(colon + 1) : qName;
+ }
+
+ int exName = m_expandedNameTable.getExpandedTypeID(uri, localName,
+ DTM.ELEMENT_NODE);
int prefixIndex = (qName.length() != localName.length())
? m_valuesOrPrefixes.stringToIndex(qName) : 0;
@@ -2095,7 +2040,7 @@ public class SAX2DTM2 extends SAX2DTM
int elemNode = addNode(DTM.ELEMENT_NODE, exName,
m_parents.peek(), m_previous, prefixIndex, true);
- if(m_indexing)
+ if (m_indexing)
indexNode(exName, elemNode);
m_parents.push(elemNode);
@@ -2104,31 +2049,31 @@ public class SAX2DTM2 extends SAX2DTM
int nDecls = m_prefixMappings.size();
String prefix;
- if(!m_pastFirstElement)
- {
+ if (!m_pastFirstElement) {
// SPECIAL CASE: Implied declaration at root element
- prefix="xml";
+ prefix = "xml";
String declURL = "http://www.w3.org/XML/1998/namespace";
- exName = m_expandedNameTable.getExpandedTypeID(null, prefix, DTM.NAMESPACE_NODE);
- m_values.addElement(declURL);
+ exName = m_expandedNameTable.getExpandedTypeID(null, prefix,
+ DTM.NAMESPACE_NODE);
+ m_values.add(declURL);
int val = m_valueIndex++;
addNode(DTM.NAMESPACE_NODE, exName, elemNode,
DTM.NULL, val, false);
m_pastFirstElement=true;
}
- for (int i = startDecls; i < nDecls; i += 2)
- {
- prefix = (String) m_prefixMappings.elementAt(i);
+ for (int i = startDecls; i < nDecls; i += 2) {
+ prefix = m_prefixMappings.elementAt(i);
if (prefix == null)
continue;
- String declURL = (String) m_prefixMappings.elementAt(i + 1);
+ String declURL = m_prefixMappings.elementAt(i + 1);
- exName = m_expandedNameTable.getExpandedTypeID(null, prefix, DTM.NAMESPACE_NODE);
+ exName = m_expandedNameTable.getExpandedTypeID(null, prefix,
+ DTM.NAMESPACE_NODE);
- m_values.addElement(declURL);
+ m_values.add(declURL);
int val = m_valueIndex++;
addNode(DTM.NAMESPACE_NODE, exName, elemNode, DTM.NULL, val, false);
@@ -2136,28 +2081,37 @@ public class SAX2DTM2 extends SAX2DTM
int n = attributes.getLength();
- for (int i = 0; i < n; i++)
- {
+ for (int i = 0; i < n; i++) {
String attrUri = attributes.getURI(i);
+ String attrLocalName = attributes.getLocalName(i);
String attrQName = attributes.getQName(i);
String valString = attributes.getValue(i);
+ // in case URI and localName are empty, the input is not using the
+ // namespaces feature. Then we should take the part after the last
+ // colon of qName as localName (strip all namespace prefixes)
+ // When the URI is empty but localName has colons then we can also
+ // assume non namespace aware and prefixes can be stripped
+ if (attrUri == null || attrUri.isEmpty()) {
+ if (attrLocalName == null || attrLocalName.isEmpty()) {
+ final int colon = attrQName.lastIndexOf(':');
+ attrLocalName = (colon > -1) ? attrQName.substring(colon + 1) : attrQName;
+ } else {
+ final int colon = attrLocalName.lastIndexOf(':');
+ attrLocalName = (colon > -1) ? attrLocalName.substring(colon + 1) : attrLocalName;
+ }
+ }
+
int nodeType;
-
- String attrLocalName = attributes.getLocalName(i);
-
- if ((null != attrQName)
- && (attrQName.equals("xmlns")
- || attrQName.startsWith("xmlns:")))
+ if ((null != attrQName) &&
+ (attrQName.equals("xmlns") || attrQName.startsWith("xmlns:")))
{
prefix = getPrefix(attrQName, attrUri);
if (declAlreadyDeclared(prefix))
continue; // go to the next attribute.
nodeType = DTM.NAMESPACE_NODE;
- }
- else
- {
+ } else {
nodeType = DTM.ATTRIBUTE_NODE;
if (m_buildIdIndex && attributes.getType(i).equalsIgnoreCase("ID"))
@@ -2166,36 +2120,31 @@ public class SAX2DTM2 extends SAX2DTM
// Bit of a hack... if somehow valString is null, stringToIndex will
// return -1, which will make things very unhappy.
- if(null == valString)
+ if (null == valString)
valString = "";
- m_values.addElement(valString);
+ m_values.add(valString);
int val = m_valueIndex++;
- if (attrLocalName.length() != attrQName.length())
- {
-
+ if (attrLocalName.length() != attrQName.length()) {
prefixIndex = m_valuesOrPrefixes.stringToIndex(attrQName);
-
int dataIndex = m_data.size();
-
m_data.addElement(prefixIndex);
m_data.addElement(val);
-
val = -dataIndex;
}
- exName = m_expandedNameTable.getExpandedTypeID(attrUri, attrLocalName, nodeType);
- addNode(nodeType, exName, elemNode, DTM.NULL, val,
- false);
+ exName = m_expandedNameTable.getExpandedTypeID(attrUri, attrLocalName,
+ nodeType);
+ addNode(nodeType, exName, elemNode, DTM.NULL, val, false);
}
- if (null != m_wsfilter)
- {
- short wsv = m_wsfilter.getShouldStripSpace(makeNodeHandle(elemNode), this);
- boolean shouldStrip = (DTMWSFilter.INHERIT == wsv)
- ? getShouldStripWhitespace()
- : (DTMWSFilter.STRIP == wsv);
+ if (null != m_wsfilter) {
+ short wsv = m_wsfilter.getShouldStripSpace(makeNodeHandle(elemNode),
+ this);
+ boolean shouldStrip = (DTMWSFilter.INHERIT == wsv) ?
+ getShouldStripWhitespace() :
+ (DTMWSFilter.STRIP == wsv);
pushShouldStripWhitespace(shouldStrip);
}
@@ -2223,7 +2172,7 @@ public class SAX2DTM2 extends SAX2DTM
* empty string if qualified names are not available.
* @throws SAXException Any SAX exception, possibly
* wrapping another exception.
- * @see org.xml.sax.ContentHandler#endElement
+ * @see ContentHandler#endElement
*/
public void endElement(String uri, String localName, String qName)
throws SAXException
@@ -2257,9 +2206,7 @@ public class SAX2DTM2 extends SAX2DTM
* @param length The number of characters to use from the array.
* @throws SAXException The application may raise an exception.
*/
- public void comment(char ch[], int start, int length) throws SAXException
- {
-
+ public void comment(char ch[], int start, int length) throws SAXException {
if (m_insideDTD) // ignore comments if we're inside the DTD
return;
@@ -2267,7 +2214,7 @@ public class SAX2DTM2 extends SAX2DTM
// %OPT% Saving the comment string in a Vector has a lower cost than
// saving it in DTMStringPool.
- m_values.addElement(new String(ch, start, length));
+ m_values.add(new String(ch, start, length));
int dataIndex = m_valueIndex++;
m_previous = addNode(DTM.COMMENT_NODE, DTM.COMMENT_NODE,
@@ -2279,13 +2226,10 @@ public class SAX2DTM2 extends SAX2DTM
*
* @throws SAXException Any SAX exception, possibly
* wrapping another exception.
- * @see org.xml.sax.ContentHandler#startDocument
+ * @see ContentHandler#startDocument
*/
- public void startDocument() throws SAXException
- {
-
- int doc = addNode(DTM.DOCUMENT_NODE,
- DTM.DOCUMENT_NODE,
+ public void startDocument() throws SAXException {
+ int doc = addNode(DTM.DOCUMENT_NODE, DTM.DOCUMENT_NODE,
DTM.NULL, DTM.NULL, 0, true);
m_parents.push(doc);
@@ -2299,10 +2243,9 @@ public class SAX2DTM2 extends SAX2DTM
*
* @throws SAXException Any SAX exception, possibly
* wrapping another exception.
- * @see org.xml.sax.ContentHandler#endDocument
+ * @see ContentHandler#endDocument
*/
- public void endDocument() throws SAXException
- {
+ public void endDocument() throws SAXException {
super.endDocument();
// Add a NULL entry to the end of the node arrays as
@@ -2334,16 +2277,15 @@ public class SAX2DTM2 extends SAX2DTM
* @return The index identity of the node that was added.
*/
protected final int addNode(int type, int expandedTypeID,
- int parentIndex, int previousSibling,
- int dataOrPrefix, boolean canHaveFirstChild)
+ int parentIndex, int previousSibling,
+ int dataOrPrefix, boolean canHaveFirstChild)
{
// Common to all nodes:
int nodeIndex = m_size++;
// Have we overflowed a DTM Identity's addressing range?
//if(m_dtmIdent.size() == (nodeIndex>>>DTMManager.IDENT_DTM_NODE_BITS))
- if (nodeIndex == m_maxNodeIndex)
- {
+ if (nodeIndex == m_maxNodeIndex) {
addNewDTMID(nodeIndex);
m_maxNodeIndex += (1 << DTMManager.IDENT_DTM_NODE_BITS);
}
@@ -2366,8 +2308,7 @@ public class SAX2DTM2 extends SAX2DTM
// is called, to handle successive characters() events.
// Special handling by type: Declare namespaces, attach first child
- switch(type)
- {
+ switch(type) {
case DTM.NAMESPACE_NODE:
declareNamespaceInContext(parentIndex,nodeIndex);
break;
@@ -2376,8 +2317,7 @@ public class SAX2DTM2 extends SAX2DTM
default:
if (DTM.NULL != previousSibling) {
m_nextsib.setElementAt(nodeIndex,previousSibling);
- }
- else if (DTM.NULL != parentIndex) {
+ } else if (DTM.NULL != parentIndex) {
m_firstch.setElementAt(nodeIndex,parentIndex);
}
break;
@@ -2390,16 +2330,12 @@ public class SAX2DTM2 extends SAX2DTM
* Check whether accumulated text should be stripped; if not,
* append the appropriate flavor of text/cdata node.
*/
- protected final void charactersFlush()
- {
-
- if (m_textPendingStart >= 0) // -1 indicates no-text-in-progress
- {
+ protected final void charactersFlush() {
+ if (m_textPendingStart >= 0) { // -1 indicates no-text-in-progress
int length = m_chars.size() - m_textPendingStart;
boolean doStrip = false;
- if (getShouldStripWhitespace())
- {
+ if (getShouldStripWhitespace()) {
doStrip = m_chars.isWhitespace(m_textPendingStart, length);
}
@@ -2412,19 +2348,19 @@ public class SAX2DTM2 extends SAX2DTM
// If the offset and length do not exceed the given limits
// (offset < 2^21 and length < 2^10), then save both the offset
// and length in a bitwise encoded value.
- if (length <= TEXT_LENGTH_MAX
- && m_textPendingStart <= TEXT_OFFSET_MAX) {
+ if (length <= TEXT_LENGTH_MAX &&
+ m_textPendingStart <= TEXT_OFFSET_MAX) {
m_previous = addNode(m_coalescedTextType, DTM.TEXT_NODE,
- m_parents.peek(), m_previous,
- length + (m_textPendingStart << TEXT_LENGTH_BITS),
- false);
+ m_parents.peek(), m_previous,
+ length + (m_textPendingStart << TEXT_LENGTH_BITS),
+ false);
} else {
// Store offset and length in the m_data array if one exceeds
// the given limits. Use a negative dataIndex as an indication.
int dataIndex = m_data.size();
m_previous = addNode(m_coalescedTextType, DTM.TEXT_NODE,
- m_parents.peek(), m_previous, -dataIndex, false);
+ m_parents.peek(), m_previous, -dataIndex, false);
m_data.addElement(m_textPendingStart);
m_data.addElement(length);
@@ -2452,7 +2388,7 @@ public class SAX2DTM2 extends SAX2DTM
* none is supplied.
* @throws SAXException Any SAX exception, possibly
* wrapping another exception.
- * @see org.xml.sax.ContentHandler#processingInstruction
+ * @see ContentHandler#processingInstruction
*/
public void processingInstruction(String target, String data)
throws SAXException
@@ -2467,7 +2403,7 @@ public class SAX2DTM2 extends SAX2DTM
-dataIndex, false);
m_data.addElement(m_valuesOrPrefixes.stringToIndex(target));
- m_values.addElement(data);
+ m_values.add(data);
m_data.addElement(m_valueIndex++);
}
@@ -2865,9 +2801,9 @@ public class SAX2DTM2 extends SAX2DTM
}
if (m_xstrf != null)
- return m_xstrf.newstr((String)m_values.elementAt(dataIndex));
+ return m_xstrf.newstr(m_values.get(dataIndex));
else
- return new XMLStringDefault((String)m_values.elementAt(dataIndex));
+ return new XMLStringDefault(m_values.get(dataIndex));
}
}
@@ -2966,7 +2902,7 @@ public class SAX2DTM2 extends SAX2DTM
dataIndex = m_data.elementAt(dataIndex + 1);
}
- return (String)m_values.elementAt(dataIndex);
+ return m_values.get(dataIndex);
}
}
@@ -3106,7 +3042,7 @@ public class SAX2DTM2 extends SAX2DTM
dataIndex = m_data.elementAt(dataIndex + 1);
}
- String str = (String)m_values.elementAt(dataIndex);
+ String str = m_values.get(dataIndex);
if(normalize)
FastStringBuffer.sendNormalizedSAXcharacters(str.toCharArray(),
@@ -3160,7 +3096,7 @@ public class SAX2DTM2 extends SAX2DTM
dataIndex = m_data.elementAt(dataIndex + 1);
}
- return (String)m_values.elementAt(dataIndex);
+ return m_values.get(dataIndex);
}
}
@@ -3202,8 +3138,7 @@ public class SAX2DTM2 extends SAX2DTM
if (uri.length() == 0) {
handler.startElement(name);
return name;
- }
- else {
+ } else {
int qnameIndex = m_dataOrQName.elementAt(nodeID);
if (qnameIndex == 0) {
@@ -3223,14 +3158,12 @@ public class SAX2DTM2 extends SAX2DTM
String prefix;
if (prefixIndex > 0) {
prefix = qName.substring(0, prefixIndex);
- }
- else {
+ } else {
prefix = null;
}
handler.namespaceAfterStartElement(prefix, uri);
return qName;
}
-
}
/**
@@ -3285,7 +3218,7 @@ public class SAX2DTM2 extends SAX2DTM
dataIndex = m_data.elementAt(dataIndex + 1);
}
- String nodeValue = (String)m_values.elementAt(dataIndex);
+ String nodeValue = m_values.get(dataIndex);
handler.namespaceAfterStartElement(nodeName, nodeValue);
@@ -3335,7 +3268,6 @@ public class SAX2DTM2 extends SAX2DTM
}
-
/**
* Copy an Attribute node to a SerializationHandler
*
@@ -3347,14 +3279,6 @@ public class SAX2DTM2 extends SAX2DTM
SerializationHandler handler)
throws SAXException
{
- /*
- final String uri = getNamespaceName(node);
- if (uri.length() != 0) {
- final String prefix = getPrefix(node);
- handler.namespaceAfterStartElement(prefix, uri);
- }
- handler.addAttribute(getNodeName(node), getNodeValue(node));
- */
final ExtendedType extType = m_extendedTypes[exptype];
final String uri = extType.getNamespace();
final String localName = extType.getLocalName();
@@ -3377,7 +3301,7 @@ public class SAX2DTM2 extends SAX2DTM
}
String nodeName = (prefix != null) ? qname : localName;
- String nodeValue = (String)m_values.elementAt(valueIndex);
+ String nodeValue = m_values.get(valueIndex);
handler.addAttribute(uri, localName, nodeName, "CDATA", nodeValue);
}
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/AltCatalog.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/AltCatalog.java
index 3bb99efec67..07e9ee1fd77 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/AltCatalog.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/AltCatalog.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -58,7 +58,7 @@ class AltCatalog extends BaseEntry {
}
/**
- * Returns the catalog attribute as an URI String.
+ * Returns the catalog attribute as a URI String.
* @return The value of the catalog attribute
*/
String getCatalogId() {
@@ -66,7 +66,7 @@ class AltCatalog extends BaseEntry {
}
/**
- * Returns the catalog attribute as an URI.
+ * Returns the catalog attribute as a URI.
* @return The value of the catalog attribute
*/
URI getCatalogURI() {
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/BaseEntry.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/BaseEntry.java
index 943b9f23264..3d5718d661d 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/BaseEntry.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/BaseEntry.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@ package javax.xml.catalog;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Objects;
+import static javax.xml.catalog.CatalogMessages.ERR_INVALID_ARGUMENT;
/**
* Represents a general Catalog entry.
@@ -210,13 +211,12 @@ abstract class BaseEntry {
* @param arg The name of the argument
* @param uri The URI to be verified
* @return The URI created from the specified uri
- * @throws IllegalArgumentException if the specified uri is null,
- * or an URL can not be created based on the specified base and uri
+ * @throws NullPointerException if the specified uri is null
+ * @throws IllegalArgumentException if a URL can not be created based on
+ * the specified base and uri
*/
URL verifyURI(String arg, URL base, String uri) {
- if (uri == null) {
- CatalogMessages.reportIAE(new Object[]{uri, arg}, null);
- }
+ CatalogMessages.reportNPEOnNull(arg, uri);
URL url = null;
uri = Normalizer.normalizeURI(uri);
@@ -228,32 +228,9 @@ abstract class BaseEntry {
url = new URL(uri);
}
} catch (MalformedURLException e) {
- CatalogMessages.reportIAE(new Object[]{uri, arg}, e);
+ CatalogMessages.reportIAE(ERR_INVALID_ARGUMENT,
+ new Object[]{uri, arg}, e);
}
return url;
}
-
- /**
- * Construct an absolute URI from a relative one, using the current base
- * URI.
- *
- * @param sysid The (possibly relative) system identifier
- * @return The system identifier made absolute with respect to the current
- * {@link #base}.
- */
- protected String makeAbsolute(String sysid) {
- URL local = null;
-
- sysid = Util.fixSlashes(sysid);
- /**
- * try { local = new URL(base, sysid); } catch (MalformedURLException e)
- * { catalogManager.debug.message(1, "Malformed URL on system
- * identifier", sysid); }
- */
- if (local != null) {
- return local.toString();
- } else {
- return sysid;
- }
- }
}
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/Catalog.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Catalog.java
index 16f70ad7581..fcefd012666 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/Catalog.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Catalog.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@ import java.util.stream.Stream;
*
@@ -84,7 +84,7 @@ public interface Catalog {
*
* @param systemId the system identifier of the entity to be matched
*
- * @return an URI string if a mapping is found, or null otherwise
+ * @return a URI string if a mapping is found, or null otherwise
*/
public String matchSystem(String systemId);
@@ -108,7 +108,7 @@ public interface Catalog {
*
* @param publicId the public identifier of the entity to be matched
* @see CatalogFeatures.Feature
- * @return an URI string if a mapping is found, or null otherwise
+ * @return a URI string if a mapping is found, or null otherwise
*/
public String matchPublic(String publicId);
@@ -134,7 +134,7 @@ public interface Catalog {
*
* @param uri the URI reference of the entity to be matched
*
- * @return an URI string if a mapping is found, or null otherwise
+ * @return a URI string if a mapping is found, or null otherwise
*/
public String matchURI(String uri);
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java
index e448e47ae5c..01d0b533055 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -56,14 +56,14 @@ import jdk.xml.internal.SecuritySupport;
*
*
* | FILES |
- * A semicolon-delimited list of catalog files. Relative file paths are
- * considered relative to ${user.dir}.
+ * | A semicolon-delimited list of URIs to locate the catalog files.
+ * The URIs must be absolute and have a URL protocol handler for the URI scheme.
* |
* javax.xml.catalog.files |
* javax.xml.catalog.files |
* javax.xml.catalog.files |
* String |
- * File paths |
+ * URIs |
*
* Reads the first catalog as the current catalog; Loads others if no match
* is found in the current catalog including delegate catalogs if any.
@@ -170,7 +170,7 @@ import jdk.xml.internal.SecuritySupport;
* Properties set through the Catalog API override those that may have been set
* by system properties and/or in {@code jaxp.properties}. In case of multiple
* interfaces, the latest in a procedure shall take preference. For
- * {@link Feature#FILES}, this means that the path(s) specified through the methods
+ * {@link Feature#FILES}, this means that the URI(s) specified through the methods
* of the {@link CatalogManager} will override any that may have been entered
* through the {@link Builder}.
*
@@ -188,7 +188,7 @@ import jdk.xml.internal.SecuritySupport;
* in the following sample code:
* {@code
CatalogFeatures f = CatalogFeatures.builder()
- .with(Feature.FILES, "catalog.xml")
+ .with(Feature.FILES, "file:///etc/xml/catalog")
.with(Feature.PREFER, "public")
.with(Feature.DEFER, "true")
.with(Feature.RESOLVE, "ignore")
@@ -202,14 +202,14 @@ import jdk.xml.internal.SecuritySupport;
* Schema Validation ({@link javax.xml.validation}), and XML Transformation
* ({@link javax.xml.transform}). The features described above can be set through JAXP
* factories or processors that define a setProperty or setAttribute interface.
- * For example, the following code snippet sets a path to a catalog file on a SAX
+ * For example, the following code snippet sets a URI to a catalog file on a SAX
* parser through the {@code javax.xml.catalog.files} property:
*
* {@code
* SAXParserFactory spf = SAXParserFactory.newInstance();
* spf.setFeature(XMLConstants.USE_CATALOG, true); [1]
* SAXParser parser = spf.newSAXParser();
- * parser.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), "catalog.xml");
+ * parser.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), "file:///etc/xml/catalog");
* }
*
* [1] Note that this statement is not required since the default value of
@@ -275,7 +275,7 @@ import jdk.xml.internal.SecuritySupport;
The following XInclude element:
- can be resolved using an uri entry:
+ can be resolved using a URI entry:
or
@@ -291,7 +291,7 @@ import jdk.xml.internal.SecuritySupport;
- can be resolved using an uri entry:
+ can be resolved using a URI entry:
or
@@ -308,7 +308,7 @@ import jdk.xml.internal.SecuritySupport;
The following include element:
- can be resolved using an uri entry:
+ can be resolved using a URI entry:
or
@@ -323,7 +323,7 @@ import jdk.xml.internal.SecuritySupport;
The following include element:
- can be resolved using an uri entry:
+ can be resolved using a URI entry:
or
@@ -338,7 +338,7 @@ import jdk.xml.internal.SecuritySupport;
The document in the following element:
- can be resolved using an uri entry:
+ can be resolved using a URI entry:
or
@@ -559,7 +559,7 @@ public class CatalogFeatures {
values = new String[Feature.values().length];
states = new State[Feature.values().length];
for (Feature cf : Feature.values()) {
- setProperty(cf.ordinal(), State.DEFAULT, cf.defaultValue());
+ setProperty(cf, State.DEFAULT, cf.defaultValue());
}
//read system properties or jaxp.properties
readSystemProperties();
@@ -571,52 +571,27 @@ public class CatalogFeatures {
*/
private void setProperties(Builder builder) {
builder.values.entrySet().stream().forEach((entry) -> {
- setProperty(entry.getKey().ordinal(), State.APIPROPERTY, entry.getValue());
+ setProperty(entry.getKey(), State.APIPROPERTY, entry.getValue());
});
}
/**
- * Sets the value of a property by its index, updates only if it shall override.
+ * Sets the value of a property, updates only if it shall override.
*
* @param index the index of the property
* @param state the state of the property
* @param value the value of the property
* @throws IllegalArgumentException if the value is invalid
*/
- private void setProperty(int index, State state, String value) {
+ private void setProperty(Feature feature, State state, String value) {
+ int index = feature.ordinal();
if (value != null && value.length() != 0) {
- if (index == Feature.PREFER.ordinal()) {
- if (!value.equals(PREFER_SYSTEM) && !value.equals(PREFER_PUBLIC)) {
- CatalogMessages.reportIAE(new Object[]{value, Feature.PREFER.name()}, null);
- }
- } else if (index == Feature.DEFER.ordinal()) {
- if (!value.equals(DEFER_TRUE) && !value.equals(DEFER_FALSE)) {
- CatalogMessages.reportIAE(new Object[]{value, Feature.DEFER.name()}, null);
- }
- } else if (index == Feature.RESOLVE.ordinal()) {
- if (!value.equals(RESOLVE_STRICT) && !value.equals(RESOLVE_CONTINUE)
- && !value.equals(RESOLVE_IGNORE)) {
- CatalogMessages.reportIAE(new Object[]{value, Feature.RESOLVE.name()}, null);
- }
- } else if (index == Feature.FILES.ordinal()) {
- try {
- String[] catalogFile = value.split(";[ ]*");
- for (String temp : catalogFile) {
- if (Util.verifyAndGetURI(temp, null) == null) {
- CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, null);
- }
- }
- }catch (MalformedURLException | URISyntaxException | IllegalArgumentException ex) {
- CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, ex);
- }
+ if (state != State.APIPROPERTY) {
+ Util.validateFeatureInput(feature, value);
}
if (states[index] == null || state.compareTo(states[index]) >= 0) {
values[index] = value;
states[index] = state;
}
- } else {
- if (state == State.SYSTEMPROPERTY || state == State.JAXPDOTPROPERTIES) {
- CatalogMessages.reportIAE(new Object[]{value, Feature.values()[index].name()}, null);
- }
}
}
@@ -639,13 +614,13 @@ public class CatalogFeatures {
if (cf.hasSystemProperty()) {
String value = SecuritySupport.getSystemProperty(sysPropertyName);
if (value != null && !value.equals("")) {
- setProperty(cf.ordinal(), State.SYSTEMPROPERTY, value);
+ setProperty(cf, State.SYSTEMPROPERTY, value);
return true;
}
value = SecuritySupport.readJAXPProperty(sysPropertyName);
if (value != null && !value.equals("")) {
- setProperty(cf.ordinal(), State.JAXPDOTPROPERTIES, value);
+ setProperty(cf, State.JAXPDOTPROPERTIES, value);
return true;
}
}
@@ -685,9 +660,7 @@ public class CatalogFeatures {
* property
*/
public Builder with(Feature feature, String value) {
- if (value == null || value.length() == 0) {
- CatalogMessages.reportIAE(new Object[]{value, feature.name()}, null);
- }
+ Util.validateFeatureInput(feature, value);
values.put(feature, value);
return this;
}
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java
index 6630424c15a..cbf77e5c9c0 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,7 @@ class CatalogImpl extends GroupEntry implements Catalog {
/*
A list of catalog entry files from the input, excluding the current catalog.
- Paths in the List are normalized.
+ URIs in the List are verified during input validation or property retrieval.
*/
List inputFiles;
@@ -86,43 +86,44 @@ class CatalogImpl extends GroupEntry implements Catalog {
SAXParser parser;
/**
- * Construct a Catalog with specified path.
+ * Construct a Catalog with specified URI.
*
- * @param file The path to a catalog file.
+ * @param uris the uri(s) to one or more catalogs
* @throws CatalogException If an error happens while parsing the specified
* catalog file.
*/
- public CatalogImpl(CatalogFeatures f, String... file) throws CatalogException {
- this(null, f, file);
+ public CatalogImpl(CatalogFeatures f, URI... uris) throws CatalogException {
+ this(null, f, uris);
}
/**
- * Construct a Catalog with specified path.
+ * Construct a Catalog with specified URI.
*
* @param parent The parent catalog
- * @param file The path to a catalog file.
+ * @param uris the uri(s) to one or more catalogs
* @throws CatalogException If an error happens while parsing the specified
* catalog file.
*/
- public CatalogImpl(CatalogImpl parent, CatalogFeatures f, String... file) throws CatalogException {
+ public CatalogImpl(CatalogImpl parent, CatalogFeatures f, URI... uris) throws CatalogException {
super(CatalogEntryType.CATALOG, parent);
if (f == null) {
throw new NullPointerException(
formatMessage(CatalogMessages.ERR_NULL_ARGUMENT, new Object[]{"CatalogFeatures"}));
}
- if (file.length > 0) {
- CatalogMessages.reportNPEOnNull("The path to the catalog file", file[0]);
- }
-
init(f);
//Path of catalog files
- String[] catalogFile = file;
- if (level == 0 && file.length == 0) {
+ String[] catalogFile = null;
+ if (level == 0 && uris.length == 0) {
String files = features.get(Feature.FILES);
if (files != null) {
- catalogFile = files.split(";[ ]*");
+ catalogFile = files.split(";");
+ }
+ } else {
+ catalogFile = new String[uris.length];
+ for (int i=0; i {
- getCatalog(getSystemId(file));
+ inputFiles.stream().forEach((uri) -> {
+ getCatalog(URI.create(uri));
});
}
}
@@ -454,12 +432,11 @@ class CatalogImpl extends GroupEntry implements Catalog {
}
CatalogImpl c = null;
- String path = uri.toASCIIString();
if (verifyCatalogFile(uri)) {
- c = getLoadedCatalog(path);
+ c = getLoadedCatalog(uri.toASCIIString());
if (c == null) {
- c = new CatalogImpl(this, features, path);
+ c = new CatalogImpl(this, features, uri);
c.load();
}
}
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogManager.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogManager.java
index 7dd1e9cf873..f8ce697b266 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogManager.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
*/
package javax.xml.catalog;
+import java.net.URI;
/**
* The Catalog Manager manages the creation of XML Catalogs and Catalog Resolvers.
@@ -39,30 +40,36 @@ public final class CatalogManager {
/**
* Creates a {@code Catalog} object using the specified feature settings and
- * path to one or more catalog files.
+ * uri(s) to one or more catalog files.
*
- * If {@code paths} is empty, system property {@code javax.xml.catalog.files}
- * will be read to locate the initial list of catalog files.
+ * If {@code uris} is empty, system property {@code javax.xml.catalog.files},
+ * as defined in {@link CatalogFeatures}, will be read to locate the initial
+ * list of catalog files.
*
- * If more than one catalog files are specified through the paths argument or
+ * If multiple catalog files are specified through the {@code uris} argument or
* {@code javax.xml.catalog.files} property, the first entry is considered
* the main catalog, while others are treated as alternative catalogs after
* those referenced by the {@code nextCatalog} elements in the main catalog.
*
* As specified in
*
- * XML Catalogs, OASIS Standard V1.1, invalid path entries will be ignored.
- * No error will be reported. In case all entries are invalid, the resolver
- * will return as no mapping is found.
+ * XML Catalogs, OASIS Standard V1.1, if a catalog entry is invalid, it
+ * is ignored. In case all entries are invalid, the resulting Catalog object
+ * will contain no Catalog elements. Any matching operation using the Catalog
+ * will return null.
*
* @param features the catalog features
- * @param paths path(s) to one or more catalogs.
+ * @param uris uri(s) to one or more catalogs.
*
* @return an instance of a {@code Catalog}
+ * @throws IllegalArgumentException if either the URIs are not absolute
+ * or do not have a URL protocol handler for the URI scheme
* @throws CatalogException If an error occurs while parsing the catalog
+ * @throws SecurityException if access to the resource is denied by the security manager
*/
- public static Catalog catalog(CatalogFeatures features, String... paths) {
- CatalogImpl catalog = new CatalogImpl(features, paths);
+ public static Catalog catalog(CatalogFeatures features, URI... uris) {
+ Util.validateUrisSyntax(uris);
+ CatalogImpl catalog = new CatalogImpl(features, uris);
catalog.load();
return catalog;
}
@@ -80,30 +87,36 @@ public final class CatalogManager {
/**
* Creates an instance of a {@code CatalogResolver} using the specified feature
- * settings and path to one or more catalog files.
+ * settings and uri(s) to one or more catalog files.
*
- * If {@code paths} is empty, system property {@code javax.xml.catalog.files}
- * will be read to locate the initial list of catalog files.
+ * If {@code uris} is empty, system property {@code javax.xml.catalog.files},
+ * as defined in {@link CatalogFeatures}, will be read to locate the initial
+ * list of catalog files.
*
- * If more than one catalog files are specified through the paths argument or
+ * If multiple catalog files are specified through the {@code uris} argument or
* {@code javax.xml.catalog.files} property, the first entry is considered
* the main catalog, while others are treated as alternative catalogs after
* those referenced by the {@code nextCatalog} elements in the main catalog.
*
* As specified in
*
- * XML Catalogs, OASIS Standard V1.1, invalid path entries will be ignored.
- * No error will be reported. In case all entries are invalid, the resolver
- * will return as no mapping is found.
+ * XML Catalogs, OASIS Standard V1.1, if a catalog entry is invalid, it
+ * is ignored. In case all entries are invalid, the resulting CatalogResolver
+ * object will contain no valid catalog. Any resolution operation using the
+ * resolver therefore will return as no mapping is found. See {@link CatalogResolver}
+ * for the behavior when no mapping is found.
*
* @param features the catalog features
- * @param paths the path(s) to one or more catalogs
+ * @param uris the uri(s) to one or more catalogs
*
* @return an instance of a {@code CatalogResolver}
+ * @throws IllegalArgumentException if either the URIs are not absolute
+ * or do not have a URL protocol handler for the URI scheme
* @throws CatalogException If an error occurs while parsing the catalog
+ * @throws SecurityException if access to the resource is denied by the security manager
*/
- public static CatalogResolver catalogResolver(CatalogFeatures features, String... paths) {
- Catalog catalog = catalog(features, paths);
+ public static CatalogResolver catalogResolver(CatalogFeatures features, URI... uris) {
+ Catalog catalog = catalog(features, uris);
return new CatalogResolverImpl(catalog);
}
}
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.java
index 97a0cd57cc7..6a6996fa686 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* 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,10 +24,11 @@
*/
package javax.xml.catalog;
-import jdk.xml.internal.SecuritySupport;
+import java.net.URI;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
+import jdk.xml.internal.SecuritySupport;
/**
* Catalog Error messages
@@ -38,6 +39,8 @@ final class CatalogMessages {
public static final String ERR_INVALID_CATALOG = "InvalidCatalog";
public static final String ERR_INVALID_ENTRY_TYPE = "InvalidEntryType";
+ public static final String ERR_URI_NOTABSOLUTE = "UriNotAbsolute";
+ public static final String ERR_URI_NOTVALIDURL = "UriNotValidUrl";
public static final String ERR_INVALID_ARGUMENT = "InvalidArgument";
public static final String ERR_NULL_ARGUMENT = "NullArgument";
public static final String ERR_CIRCULAR_REFERENCE = "CircularReference";
@@ -120,7 +123,7 @@ final class CatalogMessages {
* @param name the name of the argument
* @param value the value of the argument
*/
- static void reportNPEOnNull(String name, String value) {
+ static void reportNPEOnNull(String name, Object value) {
if (value == null) {
throw new NullPointerException(
formatMessage(ERR_NULL_ARGUMENT, new Object[]{name}));
@@ -132,9 +135,9 @@ final class CatalogMessages {
* @param arguments the arguments for formating the error message
* @param cause the cause if any
*/
- static void reportIAE(Object[] arguments, Throwable cause) {
+ static void reportIAE(String key, Object[] arguments, Throwable cause) {
throw new IllegalArgumentException(
- formatMessage(ERR_INVALID_ARGUMENT, arguments), cause);
+ formatMessage(key, arguments), cause);
}
/**
@@ -174,7 +177,7 @@ final class CatalogMessages {
/**
* Returns sanitized URI.
- * @param uri an URI to be sanitized
+ * @param uri a URI to be sanitized
*/
static String sanitize(String uri) {
if (uri == null) {
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.properties b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.properties
index 69341fdbd84..a1133ca9da5 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.properties
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.properties
@@ -31,6 +31,8 @@ InvalidEntryType = The entry type ''{0}'' is not valid.
CircularReference = Circular reference is not allowed: ''{0}''.
#errors
+UriNotAbsolute = The specified URI ''{0}'' is not absolute.
+UriNotValidUrl = The specified URI ''{0}'' is not a valid URL.
InvalidArgument = The specified argument ''{0}'' (case sensitive) for ''{1}'' is not valid.
NullArgument = The argument ''{0}'' can not be null.
InvalidPath = The path ''{0}'' is invalid.
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java
index 5f08c54cc12..64b2ea85071 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,6 @@
package javax.xml.catalog;
import java.io.StringReader;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
import javax.xml.catalog.BaseEntry.CatalogEntryType;
import javax.xml.parsers.SAXParser;
import javax.xml.transform.Source;
@@ -94,25 +90,6 @@ class CatalogReader extends DefaultHandler implements EntityResolver, URIResolve
this.parser = parser;
}
- /**
- * Returns when the specified path is valid.
- * @param path a path
- * @return true if the path is valid, false otherwise
- */
- boolean isValidPath(String path) {
- boolean valid = true;
- try {
- Path p = Paths.get(new URI(path));
- if (!p.toFile().exists()) {
- valid = false;
- }
- } catch (URISyntaxException ex) {
- valid = false;
- }
-
- return valid;
- }
-
@Override
public void startElement(String namespaceURI,
String localName,
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolver.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolver.java
index ecf506f5cab..fe1b6f2177d 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolver.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,7 @@ import org.xml.sax.InputSource;
* {@link javax.xml.stream.XMLResolver} and {@link org.w3c.dom.ls.LSResourceResolver}
* however, make no such distinction.
* In consistent with the existing Java API, this CatalogResolver recognizes a
- * system identifier as an URI and will search both {@code system} and {@code uri}
+ * system identifier as a URI and will search both {@code system} and {@code uri}
* entries in a catalog in order to find a matching entry.
*
* The search is started in the current catalog. If a match is found,
@@ -137,9 +137,9 @@ public interface CatalogResolver extends EntityResolver, XMLResolver,
* with the specified {@code href} attribute. The {@code href} attribute will
* be used literally, with no attempt to be made absolute to the {@code base}.
*
- * If the value is an URN, the {@code href} attribute is recognized as a
+ * If the value is a URN, the {@code href} attribute is recognized as a
* {@code publicId}, and used to search {@code public} entries.
- * If the value is an URI, it is taken as a {@code systemId}, and used to
+ * If the value is a URI, it is taken as a {@code systemId}, and used to
* search both {@code system} and {@code uri} entries.
*
*
@@ -219,7 +219,7 @@ public interface CatalogResolver extends EntityResolver, XMLResolver,
* @param publicId the public identifier of the external entity being
* referenced, or {@code null} if no public identifier was
* supplied or if the resource is not an entity.
- * @param systemId the system identifier, an URI reference of the
+ * @param systemId the system identifier, a URI reference of the
* external resource being referenced
* @param baseUri the absolute base URI, not used by the CatalogResolver
*
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolverImpl.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolverImpl.java
index fe6223d9324..0977479ca9d 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolverImpl.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolverImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -73,7 +73,7 @@ final class CatalogResolverImpl implements CatalogResolver {
systemId = Normalizer.normalizeURI(Util.getNotNullOrEmpty(systemId));
publicId = Normalizer.normalizePublicId(Normalizer.decodeURN(Util.getNotNullOrEmpty(publicId)));
- //check whether systemId is an urn
+ //check whether systemId is a urn
if (systemId != null && systemId.startsWith(Util.URN)) {
systemId = Normalizer.decodeURN(systemId);
if (publicId != null && !publicId.equals(systemId)) {
@@ -123,7 +123,7 @@ final class CatalogResolverImpl implements CatalogResolver {
return null;
}
- //check whether uri is an urn
+ //check whether uri is a urn
if (uri != null && uri.startsWith(Util.URN)) {
String publicId = Normalizer.decodeURN(uri);
if (publicId != null) {
@@ -131,7 +131,7 @@ final class CatalogResolverImpl implements CatalogResolver {
}
}
- //if no match with a public id, continue search for an URI
+ //if no match with a public id, continue search for a URI
if (result == null) {
//remove fragment if any.
int hashPos = uri.indexOf("#");
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java
index e04f8cdb363..b0dd80c733f 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,6 @@
package javax.xml.catalog;
import java.net.URI;
-import java.nio.file.Files;
-import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -217,7 +215,7 @@ class GroupEntry extends BaseEntry {
* @param systemId The system identifier of the external entity being
* referenced.
*
- * @return An URI string if a mapping is found, or null otherwise.
+ * @return a URI string if a mapping is found, or null otherwise.
*/
public String matchSystem(String systemId) {
systemEntrySearched = true;
@@ -285,7 +283,7 @@ class GroupEntry extends BaseEntry {
* @param publicId The public identifier of the external entity being
* referenced.
*
- * @return An URI string if a mapping is found, or null otherwise.
+ * @return a URI string if a mapping is found, or null otherwise.
*/
public String matchPublic(String publicId) {
/*
@@ -329,7 +327,7 @@ class GroupEntry extends BaseEntry {
*
* @param uri The URI reference of a resource.
*
- * @return An URI string if a mapping is found, or null otherwise.
+ * @return a URI string if a mapping is found, or null otherwise.
*/
public String matchURI(String uri) {
String match = null;
@@ -455,7 +453,7 @@ class GroupEntry extends BaseEntry {
delegateCatalog = getLoadedCatalog(catalogId);
if (delegateCatalog == null) {
if (verifyCatalogFile(catalogURI)) {
- delegateCatalog = new CatalogImpl(catalog, features, catalogId);
+ delegateCatalog = new CatalogImpl(catalog, features, catalogURI);
delegateCatalog.load();
delegateCatalogs.put(catalogId, delegateCatalog);
}
@@ -504,7 +502,8 @@ class GroupEntry extends BaseEntry {
}
//Ignore it if it doesn't exist
- if (!Files.exists(Paths.get(catalogURI))) {
+ if (Util.isFileUri(catalogURI) &&
+ !Util.isFileUriExist(catalogURI, false)) {
return false;
}
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/UriEntry.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/UriEntry.java
index 0c1aa295c9c..9f5b4987008 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/UriEntry.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/UriEntry.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@ package javax.xml.catalog;
import java.net.URL;
/**
- * Represents an uriEntry entry.
+ * Represents a uri entry.
*
* @since 9
*/
@@ -36,7 +36,7 @@ final class UriEntry extends BaseEntry {
URL uri;
/**
- * Construct a group entry.
+ * Construct a uri entry.
* @param name The name attribute.
* @param uri The uri attribute.
*/
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java
index f2b00a21ee6..bec119f1143 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,13 +25,20 @@
package javax.xml.catalog;
import java.io.File;
+import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.Iterator;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import static javax.xml.catalog.CatalogFeatures.DEFER_FALSE;
+import static javax.xml.catalog.CatalogFeatures.DEFER_TRUE;
+import javax.xml.catalog.CatalogFeatures.Feature;
+import static javax.xml.catalog.CatalogFeatures.PREFER_PUBLIC;
+import static javax.xml.catalog.CatalogFeatures.PREFER_SYSTEM;
+import static javax.xml.catalog.CatalogFeatures.RESOLVE_CONTINUE;
+import static javax.xml.catalog.CatalogFeatures.RESOLVE_IGNORE;
+import static javax.xml.catalog.CatalogFeatures.RESOLVE_STRICT;
import jdk.xml.internal.SecuritySupport;
/**
@@ -39,22 +46,25 @@ import jdk.xml.internal.SecuritySupport;
* @since 9
*/
class Util {
+
final static String URN = "urn:publicid:";
final static String PUBLICID_PREFIX = "-//";
final static String PUBLICID_PREFIX_ALT = "+//";
+ final static String SCHEME_FILE = "file";
+ final static String SCHEME_JAR = "jar";
+ final static String SCHEME_JARFILE = "jar:file:";
/**
* Finds an entry in the catalog that matches with the publicId or systemId.
*
- * The resolution follows the following rules determined by the prefer setting:
+ * The resolution follows the following rules determined by the prefer
+ * setting:
*
- * prefer "system": attempts to resolve with a system entry;
- * attempts to resolve with a public entry when only
- * publicId is specified.
+ * prefer "system": attempts to resolve with a system entry; attempts to
+ * resolve with a public entry when only publicId is specified.
*
- * prefer "public": attempts to resolve with a system entry;
- * attempts to resolve with a public entry if no matching
- * system entry is found.
+ * prefer "public": attempts to resolve with a system entry; attempts to
+ * resolve with a public entry if no matching system entry is found.
*
* If no match is found, continue searching uri entries
*
@@ -70,9 +80,9 @@ class Util {
catalog.reset();
if (systemId != null) {
/*
- If a system identifier is specified, it is used no matter how
- prefer is set.
- */
+ If a system identifier is specified, it is used no matter how
+ prefer is set.
+ */
resolvedSystemId = catalog.matchSystem(systemId);
}
@@ -91,7 +101,7 @@ class Util {
if (resolvedSystemId == null) {
Iterator iter = catalog.catalogs().iterator();
while (iter.hasNext()) {
- resolvedSystemId = resolve((CatalogImpl)iter.next(), publicId, systemId);
+ resolvedSystemId = resolve((CatalogImpl) iter.next(), publicId, systemId);
if (resolvedSystemId != null) {
break;
}
@@ -102,73 +112,112 @@ class Util {
return resolvedSystemId;
}
- /**
- * Resolves the specified file path to an absolute systemId. If it is
- * relative, it shall be resolved using the base or user.dir property if
- * base is not specified.
- *
- * @param file The specified file path
- * @param baseURI the base URI
- * @return The URI
- * @throws CatalogException if the specified file path can not be converted
- * to a system id
- */
- static URI verifyAndGetURI(String file, URL baseURI)
- throws MalformedURLException, URISyntaxException, IllegalArgumentException {
- URL filepath;
- URI temp;
- if (file != null && file.length() > 0) {
- File f = new File(file);
-
- if (baseURI != null && !f.isAbsolute()) {
- filepath = new URL(baseURI, fixSlashes(file));
- temp = filepath.toURI();
- } else {
- temp = resolveURI(file);
- }
- //Paths.get may throw IllegalArgumentException
- Path path = Paths.get(temp);
- if (path.toFile().isFile()) {
- return temp;
- }
+ static void validateUrisSyntax(URI... uris) {
+ for (URI uri : uris) {
+ validateUriSyntax(uri);
+ }
+ }
+
+ static void validateUrisSyntax(String... uris) {
+ for (String uri : uris) {
+ validateUriSyntax(URI.create(uri));
}
- return null;
}
/**
- * Resolves the specified uri. If the uri is relative, makes it absolute by
- * the user.dir directory.
+ * Validate that the URI must be absolute and a valid URL.
*
- * @param uri The specified URI.
- * @return The resolved URI
+ * Note that this method does not verify the existence of the resource. The
+ * Catalog standard requires that such resources be ignored.
+ *
+ * @param uri
+ * @throws IllegalArgumentException if the uri is not absolute and a valid
+ * URL
*/
- static URI resolveURI(String uri) throws MalformedURLException {
- if (uri == null) {
- uri = "";
+ static void validateUriSyntax(URI uri) {
+ CatalogMessages.reportNPEOnNull("URI input", uri);
+
+ if (!uri.isAbsolute()) {
+ CatalogMessages.reportIAE(CatalogMessages.ERR_URI_NOTABSOLUTE,
+ new Object[]{uri}, null);
}
- URI temp = null;
try {
- URL url = new URL(uri);
- temp = url.toURI();
- } catch (MalformedURLException | URISyntaxException mue) {
- File file = new File(uri);
- temp = file.toURI();
+ // check if the scheme was valid
+ uri.toURL();
+ } catch (MalformedURLException ex) {
+ CatalogMessages.reportIAE(CatalogMessages.ERR_URI_NOTVALIDURL,
+ new Object[]{uri}, null);
}
- return temp;
+ // verify the resource exists where possible
+ if (isFileUri(uri)) {
+ if (!isFileUriExist(uri, false)) {
+ CatalogMessages.reportIAE(CatalogMessages.ERR_URI_NOTVALIDURL,
+ new Object[]{uri}, null);
+ }
+ }
}
/**
- * Replace backslashes with forward slashes. (URLs always use forward
- * slashes.)
+ * Checks whether the URI is a file URI, including JAR file.
*
- * @param sysid The input system identifier.
- * @return The same system identifier with backslashes turned into forward
- * slashes.
+ * @param uri the specified URI.
+ * @return true if it is a file or JAR file URI, false otherwise
*/
- static String fixSlashes(String sysid) {
- return sysid.replace('\\', '/');
+ static boolean isFileUri(URI uri) {
+ if (SCHEME_FILE.equals(uri.getScheme())
+ || SCHEME_JAR.equals(uri.getScheme())) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Verifies whether the file resource exists.
+ *
+ * @param uri the URI to locate the resource
+ * @param openJarFile a flag to indicate whether a JAR file should be
+ * opened. This operation may be expensive.
+ * @return true if the resource exists, false otherwise.
+ */
+ static boolean isFileUriExist(URI uri, boolean openJarFile) {
+ if (uri != null && uri.isAbsolute()) {
+ if (null != uri.getScheme()) {
+ switch (uri.getScheme()) {
+ case SCHEME_FILE:
+ String path = uri.getPath();
+ File f1 = new File(path);
+ if (f1.isFile()) {
+ return true;
+ }
+ break;
+ case SCHEME_JAR:
+ String tempUri = uri.toString();
+ int pos = tempUri.indexOf("!");
+ if (pos < 0) {
+ return false;
+ }
+ if (openJarFile) {
+ String jarFile = tempUri.substring(SCHEME_JARFILE.length(), pos);
+ String entryName = tempUri.substring(pos + 2);
+ try {
+ JarFile jf = new JarFile(jarFile);
+ JarEntry je = jf.getJarEntry(entryName);
+ if (je != null) {
+ return true;
+ }
+ } catch (IOException ex) {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ break;
+ }
+ }
+ }
+ return false;
}
/**
@@ -187,11 +236,12 @@ class Util {
}
/**
- * Checks whether the specified string is null or empty, returns the original
- * string with leading and trailing spaces removed if not.
+ * Checks whether the specified string is null or empty, returns the
+ * original string with leading and trailing spaces removed if not.
+ *
* @param test the string to be tested
- * @return the original string with leading and trailing spaces removed,
- * or null if it is null or empty
+ * @return the original string with leading and trailing spaces removed, or
+ * null if it is null or empty
*
*/
static String getNotNullOrEmpty(String test) {
@@ -206,4 +256,39 @@ class Util {
}
}
}
+
+ /**
+ * Validates the input for features.
+ *
+ * @param f the feature
+ * @param value the value
+ * @throws IllegalArgumentException if the value is invalid for the feature
+ */
+ static void validateFeatureInput(Feature f, String value) {
+ CatalogMessages.reportNPEOnNull(f.name(), value);
+ if (value.length() == 0) {
+ CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
+ new Object[]{value, f.name()}, null);
+ }
+
+ if (f == Feature.PREFER) {
+ if (!value.equals(PREFER_SYSTEM) && !value.equals(PREFER_PUBLIC)) {
+ CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
+ new Object[]{value, Feature.PREFER.name()}, null);
+ }
+ } else if (f == Feature.DEFER) {
+ if (!value.equals(DEFER_TRUE) && !value.equals(DEFER_FALSE)) {
+ CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
+ new Object[]{value, Feature.DEFER.name()}, null);
+ }
+ } else if (f == Feature.RESOLVE) {
+ if (!value.equals(RESOLVE_STRICT) && !value.equals(RESOLVE_CONTINUE)
+ && !value.equals(RESOLVE_IGNORE)) {
+ CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
+ new Object[]{value, Feature.RESOLVE.name()}, null);
+ }
+ } else if (f == Feature.FILES) {
+ Util.validateUrisSyntax(value.split(";"));
+ }
+ }
}
diff --git a/jaxp/test/javax/xml/jaxp/functional/catalog/SpecifyCatalogTest.java b/jaxp/test/javax/xml/jaxp/functional/catalog/SpecifyCatalogTest.java
index 47506989742..e81a84b020b 100644
--- a/jaxp/test/javax/xml/jaxp/functional/catalog/SpecifyCatalogTest.java
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/SpecifyCatalogTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -81,7 +81,7 @@ public class SpecifyCatalogTest {
@Test
public void specifyCatalogViaSysProps() {
setSystemProperty(FEATURE_FILES,
- getCatalogPath("specifyCatalog-sysProps.xml"));
+ getCatalogPath("specifyCatalog-sysProps.xml").toASCIIString());
checkResolutionOnEntityResolver(catalogResolver((String[]) null),
"http://local/base/dtd/docSysPropsSys.dtd");
@@ -107,6 +107,6 @@ public class SpecifyCatalogTest {
}
private static CatalogFeatures createFeature(String catalogName) {
- return builder().with(FILES, getCatalogPath(catalogName)).build();
+ return builder().with(FILES, getCatalogPath(catalogName).toASCIIString()).build();
}
}
diff --git a/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/dummy.xml b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/dummy.xml
new file mode 100644
index 00000000000..f6fed01ba5a
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/dummy.xml
@@ -0,0 +1 @@
+
diff --git a/jaxp/test/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java b/jaxp/test/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java
index 01d45ff591b..36f4e239fa8 100644
--- a/jaxp/test/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java
+++ b/jaxp/test/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* 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,17 +25,16 @@ package catalog;
import java.io.File;
import java.io.IOException;
+import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-
import javax.xml.catalog.CatalogFeatures;
import javax.xml.catalog.CatalogManager;
import javax.xml.catalog.CatalogResolver;
-
import jaxp.library.JAXPTestUtilities;
/*
@@ -115,20 +114,20 @@ final class CatalogTestUtils {
}
// Gets the paths of the specified catalogs.
- private static String[] getCatalogPaths(String... catalogNames) {
+ private static URI[] getCatalogPaths(String... catalogNames) {
return catalogNames == null
? null
: Stream.of(catalogNames).map(
catalogName -> getCatalogPath(catalogName)).collect(
- Collectors.toList()).toArray(new String[0]);
+ Collectors.toList()).toArray(new URI[0]);
}
// Gets the paths of the specified catalogs.
- static String getCatalogPath(String catalogName) {
+ static URI getCatalogPath(String catalogName) {
return catalogName == null
? null
- : JAXPTestUtilities.getPathByClassName(CatalogTestUtils.class, "catalogFiles")
- + catalogName;
+ : Paths.get(JAXPTestUtilities.getPathByClassName(CatalogTestUtils.class, "catalogFiles")
+ + catalogName).toUri();
}
/* ********** jaxp.properties ********** */
diff --git a/jaxp/test/javax/xml/jaxp/libs/jaxp/library/JarUtils.java b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/JarUtils.java
new file mode 100644
index 00000000000..bc579a352fe
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/JarUtils.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 jaxp.library;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * This class consists exclusively of static utility methods that are useful
+ * for creating and manipulating JAR files.
+ */
+
+public final class JarUtils {
+ private JarUtils() { }
+
+ /**
+ * Creates a JAR file.
+ *
+ * Equivalent to {@code jar cfm -C file...}
+ *
+ * The input files are resolved against the given directory. Any input
+ * files that are directories are processed recursively.
+ */
+ public static void createJarFile(Path jarfile, Manifest man, Path dir, Path... file)
+ throws IOException
+ {
+ // create the target directory
+ Path parent = jarfile.getParent();
+ if (parent != null)
+ Files.createDirectories(parent);
+
+ List entries = new ArrayList<>();
+ for (Path entry : file) {
+ Files.find(dir.resolve(entry), Integer.MAX_VALUE,
+ (p, attrs) -> attrs.isRegularFile())
+ .map(e -> dir.relativize(e))
+ .forEach(entries::add);
+ }
+
+ try (OutputStream out = Files.newOutputStream(jarfile);
+ JarOutputStream jos = new JarOutputStream(out))
+ {
+ if (man != null) {
+ JarEntry je = new JarEntry(JarFile.MANIFEST_NAME);
+ jos.putNextEntry(je);
+ man.write(jos);
+ jos.closeEntry();
+ }
+
+ for (Path entry : entries) {
+ String name = toJarEntryName(entry);
+ jos.putNextEntry(new JarEntry(name));
+ Files.copy(dir.resolve(entry), jos);
+ jos.closeEntry();
+ }
+ }
+ }
+
+ /**
+ * Creates a JAR file.
+ *
+ * Equivalent to {@code jar cf -C file...}
+ *
+ * The input files are resolved against the given directory. Any input
+ * files that are directories are processed recursively.
+ */
+ public static void createJarFile(Path jarfile, Path dir, Path... file)
+ throws IOException
+ {
+ createJarFile(jarfile, null, dir, file);
+ }
+
+ /**
+ * Creates a JAR file.
+ *
+ * Equivalent to {@code jar cf -C file...}
+ *
+ * The input files are resolved against the given directory. Any input
+ * files that are directories are processed recursively.
+ */
+ public static void createJarFile(Path jarfile, Path dir, String... input)
+ throws IOException
+ {
+ Path[] paths = Stream.of(input).map(Paths::get).toArray(Path[]::new);
+ createJarFile(jarfile, dir, paths);
+ }
+
+ /**
+ * Creates a JAR file from the contents of a directory.
+ *
+ * Equivalent to {@code jar cf -C .}
+ */
+ public static void createJarFile(Path jarfile, Path dir) throws IOException {
+ createJarFile(jarfile, dir, Paths.get("."));
+ }
+
+ /**
+ * Map a file path to the equivalent name in a JAR file
+ */
+ private static String toJarEntryName(Path file) {
+ Path normalized = file.normalize();
+ return normalized.subpath(0, normalized.getNameCount()) // drop root
+ .toString()
+ .replace(File.separatorChar, '/');
+ }
+}
diff --git a/jaxp/test/javax/xml/jaxp/libs/jaxp/library/SimpleHttpServer.java b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/SimpleHttpServer.java
new file mode 100644
index 00000000000..290697d81c9
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/SimpleHttpServer.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 jaxp.library;
+
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpContext;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * A simple HTTP Server
+ */
+public class SimpleHttpServer {
+ HttpServer _httpserver;
+ ExecutorService _executor;
+
+ String _address;
+
+ String _context, _docroot;
+ int _port;
+
+ public SimpleHttpServer(String context, String docroot) {
+ //let the system pick up an ephemeral port in a bind operation
+ this(0, context, docroot);
+ }
+
+ public SimpleHttpServer(int port, String context, String docroot) {
+ _port = port;
+ _context = context;
+ _docroot = docroot;
+ }
+
+ public void start() {
+ MyHttpHandler handler = new MyHttpHandler(_docroot);
+ InetSocketAddress addr = new InetSocketAddress(_port);
+ try {
+ _httpserver = HttpServer.create(addr, 0);
+ } catch (IOException ex) {
+ throw new RuntimeException("cannot create httpserver", ex);
+ }
+
+ //TestHandler is mapped to /test
+ HttpContext ctx = _httpserver.createContext(_context, handler);
+
+ _executor = Executors.newCachedThreadPool();
+ _httpserver.setExecutor(_executor);
+ _httpserver.start();
+
+ _address = "http://localhost:" + _httpserver.getAddress().getPort();
+ }
+
+ public void stop() {
+ _httpserver.stop(2);
+ _executor.shutdown();
+ }
+
+ public String getAddress() {
+ return _address;
+ }
+
+ static class MyHttpHandler implements HttpHandler {
+
+ String _docroot;
+
+ public MyHttpHandler(String docroot) {
+ _docroot = docroot;
+ }
+
+ public void handle(HttpExchange t)
+ throws IOException {
+ InputStream is = t.getRequestBody();
+ Headers map = t.getRequestHeaders();
+ Headers rmap = t.getResponseHeaders();
+ OutputStream os = t.getResponseBody();
+ URI uri = t.getRequestURI();
+ String path = uri.getPath();
+
+
+ while (is.read() != -1) ;
+ is.close();
+
+ File f = new File(_docroot, path);
+ if (!f.exists()) {
+ notfound(t, path);
+ return;
+ }
+
+ String method = t.getRequestMethod();
+ if (method.equals("HEAD")) {
+ rmap.set("Content-Length", Long.toString(f.length()));
+ t.sendResponseHeaders(200, -1);
+ t.close();
+ } else if (!method.equals("GET")) {
+ t.sendResponseHeaders(405, -1);
+ t.close();
+ return;
+ }
+
+ if (path.endsWith(".html") || path.endsWith(".htm")) {
+ rmap.set("Content-Type", "text/html");
+ } else {
+ rmap.set("Content-Type", "text/plain");
+ }
+
+ t.sendResponseHeaders (200, f.length());
+
+ FileInputStream fis = new FileInputStream(f);
+ int count = 0;
+ try {
+ byte[] buf = new byte[16 * 1024];
+ int len;
+ while ((len = fis.read(buf)) != -1) {
+ os.write(buf, 0, len);
+ count += len;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ fis.close();
+ os.close();
+ }
+
+ void moved(HttpExchange t) throws IOException {
+ Headers req = t.getRequestHeaders();
+ Headers map = t.getResponseHeaders();
+ URI uri = t.getRequestURI();
+ String host = req.getFirst("Host");
+ String location = "http://" + host + uri.getPath() + "/";
+ map.set("Content-Type", "text/html");
+ map.set("Location", location);
+ t.sendResponseHeaders(301, -1);
+ t.close();
+ }
+
+ void notfound(HttpExchange t, String p) throws IOException {
+ t.getResponseHeaders().set("Content-Type", "text/html");
+ t.sendResponseHeaders(404, 0);
+ OutputStream os = t.getResponseBody();
+ String s = "File not found";
+ s = s + p + "";
+ os.write(s.getBytes());
+ os.close();
+ t.close();
+ }
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogAccessTest.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogAccessTest.java
new file mode 100644
index 00000000000..d2e7edee6f0
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogAccessTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 catalog;
+
+import java.net.URI;
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.catalog.CatalogManager;
+import javax.xml.catalog.CatalogResolver;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+import org.xml.sax.InputSource;
+import static jaxp.library.JAXPTestUtilities.tryRunWithAllPerm;
+
+/*
+ * @test
+ * @bug 8171243
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @run testng/othervm -DrunSecMngr=true catalog.CatalogAccessTest
+ * @summary the Catalog API grants no privilege to external resources. This test
+ * verifies that SecurityException will be thrown if access to resources is denied
+ * by the security manager.
+ */
+@Listeners({jaxp.library.BasePolicy.class})
+public class CatalogAccessTest {
+ static final CatalogFeatures FEATURES = CatalogFeatures.builder().
+ with(CatalogFeatures.Feature.PREFER, "system").build();
+
+ /*
+ * Verifies that the SecurityException is thrown if access to the resource is
+ * denied by the security manager.
+ */
+ @Test(dataProvider = "accessTest", expectedExceptions = SecurityException.class)
+ public void testSecurity(String cfile, String sysId, String pubId) throws Exception {
+ CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, URI.create(cfile));
+ InputSource is = cr.resolveEntity(pubId, sysId);
+ Assert.fail("Failed to throw SecurityException");
+ }
+
+ /*
+ DataProvider: used for SecurityException testing
+ Data columns:
+ catalog uri, systemId, publicId
+ */
+ @DataProvider(name = "accessTest")
+ Object[][] getDataForAccessTest() throws Exception {
+ String systemId = "http://www.sys00test.com/rewrite.dtd";
+ String publicId = "PUB-404";
+ String urlFile = tryRunWithAllPerm(() ->
+ getClass().getResource("rewriteSystem_id.xml").toExternalForm());
+ return new Object[][]{
+ {urlFile, systemId, publicId}
+ };
+ }
+}
diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java
new file mode 100644
index 00000000000..44d52295bd7
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 catalog;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import static java.nio.file.StandardOpenOption.APPEND;
+import static java.nio.file.StandardOpenOption.CREATE;
+import javax.xml.catalog.Catalog;
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.catalog.CatalogManager;
+import javax.xml.catalog.CatalogResolver;
+import static jaxp.library.JAXPTestUtilities.getSystemProperty;
+import jaxp.library.JarUtils;
+import jaxp.library.SimpleHttpServer;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+import org.xml.sax.InputSource;
+
+/*
+ * @test
+ * @bug 8151154 8171243
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @run testng/othervm catalog.CatalogFileInputTest
+ * @summary Verifies that the Catalog API accepts valid URIs only;
+ Verifies that the CatalogFeatures' builder throws
+ * IllegalArgumentException on invalid file inputs.
+ * This test was splitted from CatalogTest.java due to
+ * JDK-8168968, it has to only run without SecurityManager
+ * because an ACE will be thrown for invalid path.
+ */
+@Listeners({jaxp.library.FilePolicy.class, jaxp.library.NetAccessPolicy.class})
+public class CatalogFileInputTest extends CatalogSupportBase {
+
+ static final CatalogFeatures FEATURES = CatalogFeatures.builder().
+ with(CatalogFeatures.Feature.PREFER, "system").build();
+ static String USER_DIR = getSystemProperty("user.dir");
+ static String CLS_DIR = getSystemProperty("test.classes");
+ static String SRC_DIR = System.getProperty("test.src");
+ static String JAR_CONTENT = "META-INF";
+ final static String SCHEME_JARFILE = "jar:";
+ static final String REMOTE_FILE_LOCATION = "/jar/META-INF";
+ static final String DOCROOT = SRC_DIR;
+ static final String TESTCONTEXT = REMOTE_FILE_LOCATION; //mapped to local file path
+ SimpleHttpServer _httpserver;
+ String _remoteFilePath;
+
+ /*
+ * Initializing fields
+ */
+ @BeforeClass
+ public void setUpClass() throws Exception {
+ super.setUp();
+
+ // set up HttpServer
+ _httpserver = new SimpleHttpServer(TESTCONTEXT, DOCROOT);
+ _httpserver.start();
+ _remoteFilePath = _httpserver.getAddress() + REMOTE_FILE_LOCATION;
+
+ }
+
+ @AfterClass
+ protected void tearDown() throws Exception {
+ if (_httpserver != null) {
+ _httpserver.stop();
+ }
+ }
+
+ /*
+ * Verifies that the Catalog can be created with file system paths including JAR
+ * and http URL, and used to resolve a systemId as expected.
+ */
+ @Test(dataProvider = "acceptedURI")
+ public void testMatch(String uri, String sysId, String pubId,
+ String expectedId, String msg) throws Exception {
+ CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, URI.create(uri));
+ InputSource is = cr.resolveEntity(pubId, sysId);
+ Assert.assertNotNull(is, msg);
+ Assert.assertEquals(expectedId, is.getSystemId(), msg);
+ }
+
+ @Test(dataProvider = "invalidCatalog")
+ public void testEmptyCatalog(String uri, String publicId, String msg) {
+ Catalog c = CatalogManager.catalog(FEATURES, uri != null? URI.create(uri) : null);
+ Assert.assertNull(c.matchSystem(publicId), msg);
+ }
+
+ @Test(dataProvider = "invalidCatalog", expectedExceptions = CatalogException.class)
+ public void testCatalogResolverWEmptyCatalog(String uri, String publicId, String msg) {
+ CatalogResolver cr = CatalogManager.catalogResolver(
+ CatalogFeatures.builder().with(CatalogFeatures.Feature.RESOLVE, "strict").build(),
+ uri != null? URI.create(uri) : null);
+ InputSource is = cr.resolveEntity(publicId, "");
+ }
+
+ @Test(dataProvider = "invalidCatalog")
+ public void testCatalogResolverWEmptyCatalog1(String uri, String publicId, String msg) {
+ CatalogResolver cr = CatalogManager.catalogResolver(
+ CatalogFeatures.builder().with(CatalogFeatures.Feature.RESOLVE, "continue").build(),
+ uri != null? URI.create(uri) : null);
+ Assert.assertNull(cr.resolveEntity(publicId, ""), msg);
+ }
+
+ @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
+ public void testFileInput(String file) {
+ CatalogFeatures features = CatalogFeatures.builder()
+ .with(CatalogFeatures.Feature.FILES, file)
+ .build();
+ }
+
+ @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
+ public void testInvalidUri(String file) {
+ CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, file != null? URI.create(file) : null);
+ }
+
+ @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
+ public void testInvalidUri1(String file) {
+ Catalog c = CatalogManager.catalog(FEATURES, file != null? URI.create(file) : null);
+ System.err.println("Catalog =" + c);
+ }
+
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testNullFileInput() {
+ CatalogFeatures features = CatalogFeatures.builder()
+ .with(CatalogFeatures.Feature.FILES, null)
+ .build();
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testNullUri() {
+ URI uri = null;
+ CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, uri);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testNullUri1() {
+ URI uri = null;
+ Catalog c = CatalogManager.catalog(FEATURES, uri);
+ }
+
+ String systemId = "http://www.sys00test.com/rewrite.dtd";
+ String publicId = "PUB-404";
+ String expected = "http://www.groupxmlbase.com/dtds/rewrite.dtd";
+ String errMsg = "Relative rewriteSystem with xml:base at group level failed";
+
+ /*
+ DataProvider: used to verify CatalogResolver's resolveEntity function.
+ Data columns:
+ catalog, systemId, publicId, expectedUri, msg
+ */
+ @DataProvider(name = "acceptedURI")
+ Object[][] getData() throws Exception {
+ String filename = "rewriteSystem_id.xml";
+ String urlFile = getClass().getResource(filename).toExternalForm();
+ String urlHttp = _remoteFilePath + "/jax-ws-catalog.xml";
+ String remoteXSD = _remoteFilePath + "/catalog/ws-addr.xsd";
+ File file = new File(CLS_DIR + "/JDK8171243.jar!/META-INF/jax-ws-catalog.xml");
+ String jarPath = SCHEME_JARFILE + file.toURI().toString();
+ String xsd = jarPath.substring(0, jarPath.lastIndexOf("/")) + "/catalog/ws-addr.xsd";
+
+ // create JAR file
+ try {
+ JarUtils.createJarFile(Paths.get(CLS_DIR + "/JDK8171243.jar"),
+ Paths.get(SRC_DIR + "/jar"), JAR_CONTENT);
+ } catch (IOException ex) {
+ Assert.fail("Failed to create JAR: " + ex.getMessage());
+ }
+
+ return new Object[][]{
+ // URL
+ {urlFile, systemId, publicId, expected, errMsg},
+ {urlHttp, "http://www.w3.org/2006/03/addressing/ws-addr.xsd", "", remoteXSD, "http test failed."},
+ // JAR file
+ {jarPath, "http://www.w3.org/2006/03/addressing/ws-addr.xsd", "", xsd, "jar file test failed."},
+ };
+ }
+
+ /*
+ * DataProvider: invalid catalog result in empty catalog
+ * Note: the difference from invalidInput is that invalidInput is syntactically
+ * rejected with an IAE.
+ */
+ @DataProvider(name = "invalidCatalog")
+ public Object[][] getInvalidCatalog() throws Exception {
+ String catalogUri = getClass().getResource("catalog_invalid.xml").toExternalForm();
+ return new Object[][]{
+ {catalogUri, "-//W3C//DTD XHTML 1.0 Strict//EN",
+ "The catalog is invalid, attempting to match the public entry shall return null."}
+ };
+ }
+
+ /*
+ * DataProvider: a list of invalid inputs, expects IAE
+ * Note: exclude null since NPE would have been expected
+ */
+ @DataProvider(name = "invalidInput")
+ public Object[][] getFiles() throws Exception {
+ String filename = "rewriteSystem_id.xml";
+ copyFile(Paths.get(SRC_DIR + "/" + filename), Paths.get(filename));
+ String absolutePath = getClass().getResource(filename).getFile();
+
+ return new Object[][]{
+ {""},
+ {"file:a/b\\c"},
+ {"file:/../../.."},
+ {"c:/te:t"},
+ {"c:/te?t"},
+ {"c/te*t"},
+ {"in|valid.txt"},
+ {"shema:invalid.txt"},
+ // relative file path
+ {filename},
+ // absolute file path
+ {absolutePath}
+ };
+ }
+
+ /*
+ DataProvider: a list of invalid inputs
+ */
+ @DataProvider(name = "nullTest")
+ public Object[][] getNull() throws Exception {
+
+ return new Object[][]{
+ {null},
+ };
+ }
+
+ void copyFile(Path src, Path target) throws Exception {
+
+ try (InputStream in = Files.newInputStream(src);
+ BufferedReader reader
+ = new BufferedReader(new InputStreamReader(in));
+ OutputStream out = new BufferedOutputStream(
+ Files.newOutputStream(target, CREATE, APPEND));
+ BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out))) {
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+ bw.write(line);
+ }
+ } catch (IOException x) {
+ throw new Exception(x.getMessage());
+ }
+ }
+}
diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogInvalidPathTest.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogInvalidPathTest.java
deleted file mode 100644
index e8da1d0c3f4..00000000000
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogInvalidPathTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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 catalog;
-
-import javax.xml.catalog.CatalogFeatures;
-
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-/*
- * @test
- * @bug 8151154
- * @run testng/othervm catalog.CatalogInvalidPathTest
- * @summary Verifies that the CatalogFeatures' builder throws
- * IllegalArgumentException on invalid file inputs.
- * This test was splitted from CatalogTest.java due to
- * JDK-8168968, it has to only run without SecurityManager
- * because an ACE will be thrown for invalid path.
- */
-public class CatalogInvalidPathTest {
- /*
- DataProvider: for testing the verification of file paths by
- the CatalogFeatures builder
- */
- @DataProvider(name = "invalidPaths")
- public Object[][] getFiles() {
- return new Object[][]{
- {null},
- {""},
- {"file:a/b\\c"},
- {"file:/../../.."},
- {"c:/te:t"},
- {"c:/te?t"},
- {"c/te*t"},
- {"in|valid.txt"},
- {"shema:invalid.txt"},
- };
- }
-
- @Test(dataProvider = "invalidPaths", expectedExceptions = IllegalArgumentException.class)
- public void testFileInput(String file) {
- CatalogFeatures features = CatalogFeatures.builder()
- .with(CatalogFeatures.Feature.FILES, file)
- .build();
- }
-}
diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java
index 236e5cda0dc..0f603014c88 100644
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,13 @@ import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
+import java.nio.file.Paths;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
import javax.xml.XMLConstants;
import javax.xml.catalog.CatalogFeatures;
import javax.xml.catalog.CatalogResolver;
@@ -133,8 +140,8 @@ public class CatalogSupportBase {
dtd_system = filepath + "system.dtd";
dtd_systemResolved = "";
- xml_catalog = filepath + "CatalogSupport.xml";
- xml_bogus_catalog = filepath + "CatalogSupport_bogus.xml";
+ xml_catalog = Paths.get(filepath + "CatalogSupport.xml").toUri().toASCIIString();
+ xml_bogus_catalog = Paths.get(filepath + "CatalogSupport_bogus.xml").toUri().toASCIIString();
xml_xInclude = "\n" +
" 0) {
result = c.matchPublic(publicId);
@@ -430,8 +434,9 @@ public class CatalogTest extends CatalogSupportBase {
* system entry is found.
*/
@Test(dataProvider = "resolveWithPrefer")
- public void resolveWithPrefer(String prefer, String cfile, String publicId, String systemId, String expected) {
- String catalogFile = getClass().getResource(cfile).getFile();
+ public void resolveWithPrefer(String prefer, String cfile, String publicId,
+ String systemId, String expected) throws Exception {
+ URI catalogFile = getClass().getResource(cfile).toURI();
CatalogFeatures f = CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, prefer).with(CatalogFeatures.Feature.RESOLVE, "ignore").build();
CatalogResolver catalogResolver = CatalogManager.catalogResolver(f, catalogFile);
String result = catalogResolver.resolveEntity(publicId, systemId).getSystemId();
@@ -445,8 +450,8 @@ public class CatalogTest extends CatalogSupportBase {
* be loaded is determined by the defer attribute.
*/
@Test(dataProvider = "invalidAltCatalogs", expectedExceptions = CatalogException.class)
- public void testDeferAltCatalogs(String file) {
- String catalogFile = getClass().getResource(file).getFile();
+ public void testDeferAltCatalogs(String file) throws Exception {
+ URI catalogFile = getClass().getResource(file).toURI();
CatalogFeatures features = CatalogFeatures.builder().with(CatalogFeatures.Feature.DEFER, "true").build();
/*
Since the defer attribute is set to false in the specified catalog file,
@@ -462,8 +467,8 @@ public class CatalogTest extends CatalogSupportBase {
* PREFER from Features API taking precedence over catalog file
*/
@Test
- public void testJDK8146237() {
- String catalogFile = getClass().getResource("JDK8146237_catalog.xml").getFile();
+ public void testJDK8146237() throws Exception {
+ URI catalogFile = getClass().getResource("JDK8146237_catalog.xml").toURI();
try {
CatalogFeatures features = CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, "system").build();
@@ -482,8 +487,8 @@ public class CatalogTest extends CatalogSupportBase {
Verifies that the resulting systemId does not contain duplicate slashes
*/
@Test
- public void testRewriteSystem() {
- String catalog = getClass().getResource("rewriteCatalog.xml").getFile();
+ public void testRewriteSystem() throws Exception {
+ URI catalog = getClass().getResource("rewriteCatalog.xml").toURI();
try {
CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog);
@@ -500,8 +505,8 @@ public class CatalogTest extends CatalogSupportBase {
Verifies that the resulting systemId does not contain duplicate slashes
*/
@Test
- public void testRewriteUri() {
- String catalog = getClass().getResource("rewriteCatalog.xml").getFile();
+ public void testRewriteUri() throws Exception {
+ URI catalog = getClass().getResource("rewriteCatalog.xml").toURI();
try {
@@ -519,18 +524,18 @@ public class CatalogTest extends CatalogSupportBase {
*/
@Test(expectedExceptions = NullPointerException.class)
public void testFeatureNull() {
- CatalogResolver resolver = CatalogManager.catalogResolver(null, "");
+ CatalogResolver resolver = CatalogManager.catalogResolver(null, null);
}
/*
@bug 8144966
- Verifies that passing null as the path will result in a NPE.
+ Verifies that passing null as the URI will result in a NPE.
*/
@Test(expectedExceptions = NullPointerException.class)
public void testPathNull() {
- String path = null;
- CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), path);
+ URI uri = null;
+ CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), uri);
}
/*
@@ -540,10 +545,11 @@ public class CatalogTest extends CatalogSupportBase {
that matches the expected value.
*/
@Test(dataProvider = "catalog")
- public void testCatalogResolver(String test, String expected, String catalogFile, String xml, SAXParser saxParser) {
- String catalog = null;
+ public void testCatalogResolver(String test, String expected, String catalogFile,
+ String xml, SAXParser saxParser) throws Exception {
+ URI catalog = null;
if (catalogFile != null) {
- catalog = getClass().getResource(catalogFile).getFile();
+ catalog = getClass().getResource(catalogFile).toURI();
}
String url = getClass().getResource(xml).getFile();
try {
@@ -565,8 +571,8 @@ public class CatalogTest extends CatalogSupportBase {
catalog is provided, the resolver will throw an exception by default.
*/
@Test
- public void testInvalidCatalog() {
- String catalog = getClass().getResource("catalog_invalid.xml").getFile();
+ public void testInvalidCatalog() throws Exception {
+ URI catalog = getClass().getResource("catalog_invalid.xml").toURI();
String test = "testInvalidCatalog";
try {
@@ -590,7 +596,7 @@ public class CatalogTest extends CatalogSupportBase {
*/
@Test
public void testIgnoreInvalidCatalog() {
- String catalog = getClass().getResource("catalog_invalid.xml").getFile();
+ String catalog = getClass().getResource("catalog_invalid.xml").toExternalForm();
CatalogFeatures f = CatalogFeatures.builder()
.with(Feature.FILES, catalog)
.with(Feature.PREFER, "public")
@@ -600,7 +606,7 @@ public class CatalogTest extends CatalogSupportBase {
String test = "testInvalidCatalog";
try {
- CatalogResolver resolver = CatalogManager.catalogResolver(f, "");
+ CatalogResolver resolver = CatalogManager.catalogResolver(f);
String actualSystemId = resolver.resolveEntity(null, "http://remote/xml/dtd/sys/alice/docAlice.dtd").getSystemId();
System.out.println("testIgnoreInvalidCatalog: expected [null]");
System.out.println("testIgnoreInvalidCatalog: expected [null]");
diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/MANIFEST.MF b/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..81f87a7e492
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Created-By: 9-ea (Oracle Corporation)
+
diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/catalog/ws-addr.xsd b/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/catalog/ws-addr.xsd
new file mode 100644
index 00000000000..47362edbe22
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/catalog/ws-addr.xsd
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/jax-ws-catalog.xml b/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/jax-ws-catalog.xml
new file mode 100644
index 00000000000..9de01d468e8
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/jax-ws-catalog.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java b/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java
index 1ae853d81e0..7b67f09760c 100644
--- a/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java
+++ b/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java
@@ -37,6 +37,7 @@ import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
@@ -74,11 +75,30 @@ import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
* @run testng/othervm -DrunSecMngr=true transform.TransformerTest
* @run testng/othervm transform.TransformerTest
* @summary Transformer Tests
- * @bug 6272879 6305029 6505031 8150704 8162598 8169112 8169772
+ * @bug 6272879 6305029 6505031 8150704 8162598 8169112 8169631 8169772
*/
@Listeners({jaxp.library.FilePolicy.class})
public class TransformerTest {
+ // some global constants
+ private static final String LINE_SEPARATOR =
+ getSystemProperty("line.separator");
+
+ private static final String NAMESPACES =
+ "http://xml.org/sax/features/namespaces";
+
+ private static final String NAMESPACE_PREFIXES =
+ "http://xml.org/sax/features/namespace-prefixes";
+
+ private static abstract class TestTemplate {
+ protected void printSnippet(String title, String snippet) {
+ StringBuilder div = new StringBuilder();
+ for (int i = 0; i < title.length(); i++)
+ div.append("=");
+ System.out.println(title + "\n" + div + "\n" + snippet + "\n");
+ }
+ }
+
/**
* Reads the contents of the given file into a string.
* WARNING: this method adds a final line feed even if the last line of the file doesn't contain one.
@@ -101,44 +121,7 @@ public class TransformerTest {
}
}
- /**
- * Utility method for testBug8162598().
- * Provides a convenient way to check/assert the expected namespaces
- * of a Node and its siblings.
- *
- * @param test
- * The node to check
- * @param nstest
- * Expected namespace of the node
- * @param nsb
- * Expected namespace of the first sibling
- * @param nsc
- * Expected namespace of the first sibling of the first sibling
- */
- private void checkNodeNS8162598(Node test, String nstest, String nsb, String nsc) {
- String testNodeName = test.getNodeName();
- if (nstest == null) {
- Assert.assertNull(test.getNamespaceURI(), "unexpected namespace for " + testNodeName);
- } else {
- Assert.assertEquals(test.getNamespaceURI(), nstest, "unexpected namespace for " + testNodeName);
- }
- Node b = test.getChildNodes().item(0);
- if (nsb == null) {
- Assert.assertNull(b.getNamespaceURI(), "unexpected namespace for " + testNodeName + "->b");
- } else {
- Assert.assertEquals(b.getNamespaceURI(), nsb, "unexpected namespace for " + testNodeName + "->b");
- }
- Node c = b.getChildNodes().item(0);
- if (nsc == null) {
- Assert.assertNull(c.getNamespaceURI(), "unexpected namespace for " + testNodeName + "->b->c");
- } else {
- Assert.assertEquals(c.getNamespaceURI(), nsc, "unexpected namespace for " + testNodeName + "->b->c");
- }
- }
-
private class XMLReaderFor6305029 implements XMLReader {
- private static final String NAMESPACES = "http://xml.org/sax/features/namespaces";
- private static final String NAMESPACE_PREFIXES = "http://xml.org/sax/features/namespace-prefixes";
private boolean namespaces = true;
private boolean namespacePrefixes = false;
private EntityResolver resolver;
@@ -235,8 +218,6 @@ public class TransformerTest {
*/
@Test
public final void testBug6272879() throws IOException, TransformerException {
- final String LINE_SEPARATOR = getSystemProperty("line.separator");
-
final String xsl =
"" + LINE_SEPARATOR +
"" + LINE_SEPARATOR +
@@ -349,9 +330,125 @@ public class TransformerTest {
Assert.assertTrue(s.contains("map1key1value") && s.contains("map2key1value"));
}
+ private static class Test8169631 extends TestTemplate {
+ private final static String xsl =
+ "" + LINE_SEPARATOR +
+ "" + LINE_SEPARATOR +
+ " " + LINE_SEPARATOR +
+ " " + LINE_SEPARATOR +
+ " " + LINE_SEPARATOR +
+ " " + LINE_SEPARATOR +
+ " " + LINE_SEPARATOR +
+ " " + LINE_SEPARATOR +
+ "" + LINE_SEPARATOR;
+
+ private final static String sourceXml =
+ "" + LINE_SEPARATOR +
+ "" + LINE_SEPARATOR +
+ " 1" + LINE_SEPARATOR +
+ " 2 " + LINE_SEPARATOR +
+ " 3 " + LINE_SEPARATOR +
+ "" + LINE_SEPARATOR;
+
+ /**
+ * Utility method to print out transformation result and check values.
+ *
+ * @param type
+ * Text describing type of transformation
+ * @param result
+ * Resulting output of transformation
+ * @param elementCount
+ * Counter of elements to check
+ * @param attribCount
+ * Counter of attributes to check
+ */
+ private void verifyResult(String type, String result, int elementCount,
+ int attribCount)
+ {
+ printSnippet("Result of transformation from " + type + ":",
+ result);
+ Assert.assertEquals(
+ result.contains("" + elementCount + ""),
+ true, "Result of transformation from " + type +
+ " should have count of " + elementCount + " elements.");
+ Assert.assertEquals(
+ result.contains("" + attribCount +
+ ""), true, "Result of transformation from " +
+ type + " should have count of "+ attribCount + " attributes.");
+ }
+
+ public void run() throws IOException, TransformerException,
+ SAXException, ParserConfigurationException
+ {
+ printSnippet("Source:", sourceXml);
+
+ printSnippet("Stylesheet:", xsl);
+
+ // create default transformer (namespace aware)
+ TransformerFactory tf1 = TransformerFactory.newInstance();
+ ByteArrayInputStream bais = new ByteArrayInputStream(xsl.getBytes());
+ Transformer t1 = tf1.newTransformer(new StreamSource(bais));
+
+ // test transformation from stream source with namespace support
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ bais = new ByteArrayInputStream(sourceXml.getBytes());
+ t1.transform(new StreamSource(bais), new StreamResult(baos));
+ verifyResult("StreamSource with namespace support", baos.toString(), 0, 1);
+
+ // test transformation from DOM source with namespace support
+ bais.reset();
+ baos.reset();
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ Document doc = dbf.newDocumentBuilder().parse(new InputSource(bais));
+ t1.transform(new DOMSource(doc), new StreamResult(baos));
+ verifyResult("DOMSource with namespace support", baos.toString(), 0, 1);
+
+ // test transformation from DOM source without namespace support
+ bais.reset();
+ baos.reset();
+ dbf.setNamespaceAware(false);
+ doc = dbf.newDocumentBuilder().parse(new InputSource(bais));
+ t1.transform(new DOMSource(doc), new StreamResult(baos));
+ verifyResult("DOMSource without namespace support", baos.toString(), 3, 3);
+
+ // test transformation from SAX source with namespace support
+ bais.reset();
+ baos.reset();
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+ spf.setNamespaceAware(true);
+ XMLReader xmlr = spf.newSAXParser().getXMLReader();
+ SAXSource saxS = new SAXSource(xmlr, new InputSource(bais));
+ t1.transform(saxS, new StreamResult(baos));
+ verifyResult("SAXSource with namespace support", baos.toString(), 0, 1);
+
+ // test transformation from SAX source without namespace support
+ bais.reset();
+ baos.reset();
+ spf.setNamespaceAware(false);
+ xmlr = spf.newSAXParser().getXMLReader();
+ saxS = new SAXSource(xmlr, new InputSource(bais));
+ t1.transform(saxS, new StreamResult(baos));
+ verifyResult("SAXSource without namespace support", baos.toString(), 3, 3);
+ }
+ }
+
+ /*
+ * @bug 8169631
+ * @summary Test combinations of namespace awareness settings on
+ * XSL transformations
+ */
+ @Test
+ public final void testBug8169631() throws IOException, SAXException,
+ TransformerException, ParserConfigurationException
+ {
+ new Test8169631().run();
+ }
+
/*
* @bug 8150704
- * @summary Test that XSL transformation with lots of temporary result trees will not run out of DTM IDs.
+ * @summary Test that XSL transformation with lots of temporary result
+ * trees will not run out of DTM IDs.
*/
@Test
public final void testBug8150704() throws TransformerException, IOException {
@@ -375,16 +472,8 @@ public class TransformerTest {
System.out.println("Passed.");
}
- /*
- * @bug 8162598
- * @summary Test XSLTC handling of namespaces, especially empty namespace definitions to reset the
- * default namespace
- */
- @Test
- public final void testBug8162598() throws IOException, TransformerException {
- final String LINE_SEPARATOR = getSystemProperty("line.separator");
-
- final String xsl =
+ private static class Test8162598 extends TestTemplate {
+ private static final String xsl =
"" + LINE_SEPARATOR +
"" + LINE_SEPARATOR +
" " + LINE_SEPARATOR +
@@ -402,39 +491,85 @@ public class TransformerTest {
" " + LINE_SEPARATOR +
"";
+ private static final String sourceXml =
+ "" + LINE_SEPARATOR;
+ /**
+ * Utility method for testBug8162598().
+ * Provides a convenient way to check/assert the expected namespaces
+ * of a Node and its siblings.
+ *
+ * @param test
+ * The node to check
+ * @param nstest
+ * Expected namespace of the node
+ * @param nsb
+ * Expected namespace of the first sibling
+ * @param nsc
+ * Expected namespace of the first sibling of the first sibling
+ */
- final String sourceXml =
- "" + LINE_SEPARATOR;
+ private void checkNodeNS(Node test, String nstest, String nsb, String nsc) {
+ String testNodeName = test.getNodeName();
+ if (nstest == null) {
+ Assert.assertNull(test.getNamespaceURI(), "unexpected namespace for " + testNodeName);
+ } else {
+ Assert.assertEquals(test.getNamespaceURI(), nstest, "unexpected namespace for " + testNodeName);
+ }
+ Node b = test.getChildNodes().item(0);
+ if (nsb == null) {
+ Assert.assertNull(b.getNamespaceURI(), "unexpected namespace for " + testNodeName + "->b");
+ } else {
+ Assert.assertEquals(b.getNamespaceURI(), nsb, "unexpected namespace for " + testNodeName + "->b");
+ }
+ Node c = b.getChildNodes().item(0);
+ if (nsc == null) {
+ Assert.assertNull(c.getNamespaceURI(), "unexpected namespace for " + testNodeName + "->b->c");
+ } else {
+ Assert.assertEquals(c.getNamespaceURI(), nsc, "unexpected namespace for " + testNodeName + "->b->c");
+ }
+ }
- System.out.println("Stylesheet:");
- System.out.println("=============================");
- System.out.println(xsl);
- System.out.println();
+ public void run() throws IOException, TransformerException {
+ printSnippet("Source:", sourceXml);
- System.out.println("Source before transformation:");
- System.out.println("=============================");
- System.out.println(sourceXml);
- System.out.println();
+ printSnippet("Stylesheet:", xsl);
- // transform to DOM result
- TransformerFactory tf = TransformerFactory.newInstance();
- Transformer t = tf.newTransformer(new StreamSource(new ByteArrayInputStream(xsl.getBytes())));
- DOMResult result = new DOMResult();
- t.transform(new StreamSource(new ByteArrayInputStream(sourceXml.getBytes())), result);
- Document document = (Document)result.getNode();
+ // transform to DOM result
+ TransformerFactory tf = TransformerFactory.newInstance();
+ ByteArrayInputStream bais = new ByteArrayInputStream(xsl.getBytes());
+ Transformer t = tf.newTransformer(new StreamSource(bais));
+ DOMResult result = new DOMResult();
+ bais = new ByteArrayInputStream(sourceXml.getBytes());
+ t.transform(new StreamSource(bais), result);
+ Document document = (Document)result.getNode();
- System.out.println("Result after transformation:");
- System.out.println("============================");
- OutputFormat format = new OutputFormat();
- format.setIndenting(true);
- new XMLSerializer(System.out, format).serialize(document);
- System.out.println();
- checkNodeNS8162598(document.getElementsByTagName("test1").item(0), "ns2", "ns2", null);
- checkNodeNS8162598(document.getElementsByTagName("test2").item(0), "ns1", "ns2", null);
- checkNodeNS8162598(document.getElementsByTagName("test3").item(0), null, null, null);
- checkNodeNS8162598(document.getElementsByTagName("test4").item(0), null, null, null);
- checkNodeNS8162598(document.getElementsByTagName("test5").item(0), "ns1", "ns1", null);
- Assert.assertNull(document.getElementsByTagName("test6").item(0).getNamespaceURI(), "unexpected namespace for test6");
+ System.out.println("Result after transformation:");
+ System.out.println("============================");
+ OutputFormat format = new OutputFormat();
+ format.setIndenting(true);
+ new XMLSerializer(System.out, format).serialize(document);
+ System.out.println();
+
+ checkNodeNS(document.getElementsByTagName("test1").item(0), "ns2", "ns2", null);
+ checkNodeNS(document.getElementsByTagName("test2").item(0), "ns1", "ns2", null);
+ checkNodeNS(document.getElementsByTagName("test3").item(0), null, null, null);
+ checkNodeNS(document.getElementsByTagName("test4").item(0), null, null, null);
+ checkNodeNS(document.getElementsByTagName("test5").item(0), "ns1", "ns1", null);
+ Assert.assertNull(document.getElementsByTagName("test6").item(0).getNamespaceURI(),
+ "unexpected namespace for test6");
+ }
+ }
+
+ /*
+ * @bug 8162598
+ * @summary Test XSLTC handling of namespaces, especially empty namespace
+ * definitions to reset the default namespace
+ */
+ @Test
+ public final void testBug8162598() throws IOException,
+ TransformerException
+ {
+ new Test8162598().run();
}
/**
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index 26ce3b439e7..2b9c99ea42a 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -397,3 +397,5 @@ c8c9c334743caf8155c9809b6b4ac315d3a66476 jdk-9+148
72554d319b474b3636c7d02fe3c110254d111b1a jdk-9+149
77e4e30d9d111272cd4a45a2203e8f570d40b12e jdk-9+150
c48b4d4768b1c2b8fe5d1a844ca13732e5dfbe2a jdk-9+151
+6f8fb1cf7e5f61c40dcc3654f9a623c505f6de1f jdk-9+152
+7a532a9a227137155b905341d4b99939db51220e jdk-9+153
diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/DetailImpl.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/DetailImpl.java
index 047d3be90b3..36291b975b5 100644
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/DetailImpl.java
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/DetailImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* 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,13 +47,13 @@ public abstract class DetailImpl extends FaultElementImpl implements Detail {
public DetailEntry addDetailEntry(Name name) throws SOAPException {
DetailEntry entry = createDetailEntry(name);
addNode(entry);
- return (DetailEntry) circumventBug5034339(entry);
+ return entry;
}
public DetailEntry addDetailEntry(QName qname) throws SOAPException {
DetailEntry entry = createDetailEntry(qname);
addNode(entry);
- return (DetailEntry) circumventBug5034339(entry);
+ return entry;
}
protected SOAPElement addElement(Name name) throws SOAPException {
@@ -119,28 +119,4 @@ public abstract class DetailImpl extends FaultElementImpl implements Detail {
return true;
}
- //overriding this method since the only two uses of this method
- // are in ElementImpl and DetailImpl
- //whereas the original base impl does the correct job for calls to it inside ElementImpl
- // But it would not work for DetailImpl.
- protected SOAPElement circumventBug5034339(SOAPElement element) {
-
- Name elementName = element.getElementName();
- if (!isNamespaceQualified(elementName)) {
- String prefix = elementName.getPrefix();
- String defaultNamespace = getNamespaceURI(prefix);
- if (defaultNamespace != null) {
- Name newElementName =
- NameImpl.create(
- elementName.getLocalName(),
- elementName.getPrefix(),
- defaultNamespace);
- SOAPElement newElement = createDetailEntry(newElementName);
- replaceChild(newElement, element);
- return newElement;
- }
- }
- return element;
- }
-
}
diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/ElementImpl.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/ElementImpl.java
index 5189dd802bd..10070cc7aa6 100644
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/ElementImpl.java
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/ElementImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -127,8 +127,11 @@ public class ElementImpl
}
public SOAPElement addChildElement(String localName) throws SOAPException {
- return (SOAPElement) addChildElement(
- NameImpl.createFromUnqualifiedName(localName));
+ String nsUri = getNamespaceURI("");
+ Name name = (nsUri == null || nsUri.isEmpty())
+ ? NameImpl.createFromUnqualifiedName(localName)
+ : NameImpl.createFromQualifiedName(localName, nsUri);
+ return addChildElement(name);
}
public SOAPElement addChildElement(String localName, String prefix)
@@ -372,13 +375,13 @@ public class ElementImpl
protected SOAPElement addElement(Name name) throws SOAPException {
SOAPElement newElement = createElement(name);
addNode(newElement);
- return circumventBug5034339(newElement);
+ return newElement;
}
protected SOAPElement addElement(QName name) throws SOAPException {
SOAPElement newElement = createElement(name);
addNode(newElement);
- return circumventBug5034339(newElement);
+ return newElement;
}
protected SOAPElement createElement(Name name) {
@@ -1226,26 +1229,6 @@ public class ElementImpl
return !"".equals(name.getNamespaceURI());
}
- protected SOAPElement circumventBug5034339(SOAPElement element) {
-
- Name elementName = element.getElementName();
- if (!isNamespaceQualified(elementName)) {
- String prefix = elementName.getPrefix();
- String defaultNamespace = getNamespaceURI(prefix);
- if (defaultNamespace != null) {
- Name newElementName =
- NameImpl.create(
- elementName.getLocalName(),
- elementName.getPrefix(),
- defaultNamespace);
- SOAPElement newElement = createElement(newElementName);
- replaceChild(newElement, element);
- return newElement;
- }
- }
- return element;
- }
-
//TODO: This is a temporary SAAJ workaround for optimizing XWS
// should be removed once the corresponding JAXP bug is fixed
// It appears the bug will be fixed in JAXP 1.4 (not by Appserver 9 timeframe)
diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxWriter.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxWriter.java
index 7166afd1e1c..a53cb79a7a1 100644
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxWriter.java
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,10 @@
package com.sun.xml.internal.messaging.saaj.util.stax;
-import java.util.Arrays;
import java.util.Iterator;
+import java.util.Arrays;
+import java.util.List;
+import java.util.LinkedList;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
@@ -42,6 +44,17 @@ import org.w3c.dom.Node;
/**
* SaajStaxWriter builds a SAAJ SOAPMessage by using XMLStreamWriter interface.
*
+ *
+ * Defers creation of SOAPElement until all the aspects of the name of the element are known.
+ * In some cases, the namespace uri is indicated only by the {@link #writeNamespace(String, String)} call.
+ * After opening an element ({@code writeStartElement}, {@code writeEmptyElement} methods), all attributes
+ * and namespace assignments are retained within {@link DeferredElement} object ({@code deferredElement} field).
+ * As soon as any other method than {@code writeAttribute}, {@code writeNamespace}, {@code writeDefaultNamespace}
+ * or {@code setNamespace} is called, the contents of {@code deferredElement} is transformed into new SOAPElement
+ * (which is appropriately inserted into the SOAPMessage under construction).
+ * This mechanism is necessary to fix JDK-8159058 issue.
+ *
+ *
* @author shih-chang.chen@oracle.com
*/
public class SaajStaxWriter implements XMLStreamWriter {
@@ -49,6 +62,7 @@ public class SaajStaxWriter implements XMLStreamWriter {
protected SOAPMessage soap;
protected String envURI;
protected SOAPElement currentElement;
+ protected DeferredElement deferredElement;
static final protected String Envelope = "Envelope";
static final protected String Header = "Header";
@@ -58,6 +72,7 @@ public class SaajStaxWriter implements XMLStreamWriter {
public SaajStaxWriter(final SOAPMessage msg, String uri) throws SOAPException {
soap = msg;
this.envURI = uri;
+ this.deferredElement = new DeferredElement();
}
public SOAPMessage getSOAPMessage() {
@@ -70,11 +85,8 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeStartElement(final String localName) throws XMLStreamException {
- try {
- currentElement = currentElement.addChildElement(localName);
- } catch (SOAPException e) {
- throw new XMLStreamException(e);
- }
+ currentElement = deferredElement.flushTo(currentElement);
+ deferredElement.setLocalName(localName);
}
@Override
@@ -84,8 +96,10 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeStartElement(final String prefix, final String ln, final String ns) throws XMLStreamException {
- try {
- if (envURI.equals(ns)) {
+ currentElement = deferredElement.flushTo(currentElement);
+
+ if (envURI.equals(ns)) {
+ try {
if (Envelope.equals(ln)) {
currentElement = getEnvelope();
fixPrefix(prefix);
@@ -99,13 +113,16 @@ public class SaajStaxWriter implements XMLStreamWriter {
fixPrefix(prefix);
return;
}
+ } catch (SOAPException e) {
+ throw new XMLStreamException(e);
}
- currentElement = (prefix == null) ?
- currentElement.addChildElement(new QName(ns, ln)) :
- currentElement.addChildElement(ln, prefix, ns);
- } catch (SOAPException e) {
- throw new XMLStreamException(e);
+
}
+
+ deferredElement.setLocalName(ln);
+ deferredElement.setNamespaceUri(ns);
+ deferredElement.setPrefix(prefix);
+
}
private void fixPrefix(final String prfx) throws XMLStreamException {
@@ -136,11 +153,13 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeEndElement() throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
if (currentElement != null) currentElement = currentElement.getParentElement();
}
@Override
public void writeEndDocument() throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
}
@Override
@@ -158,19 +177,14 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeAttribute(final String prefix, final String ns, final String ln, final String value) throws XMLStreamException {
- try {
- if (ns == null) {
- if (prefix == null && xmlns.equals(ln)) {
- currentElement.addNamespaceDeclaration("", value);
- } else {
- currentElement.setAttributeNS("", ln, value);
- }
+ if (ns == null && prefix == null && xmlns.equals(ln)) {
+ writeNamespace("", value);
+ } else {
+ if (deferredElement.isInitialized()) {
+ deferredElement.addAttribute(prefix, ns, ln, value);
} else {
- QName name = (prefix == null) ? new QName(ns, ln) : new QName(ns, ln, prefix);
- currentElement.addAttribute(name, value);
+ addAttibuteToElement(currentElement, prefix, ns, ln, value);
}
- } catch (SOAPException e) {
- throw new XMLStreamException(e);
}
}
@@ -181,16 +195,16 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeNamespace(String prefix, final String uri) throws XMLStreamException {
-
// make prefix default if null or "xmlns" (according to javadoc)
- if (prefix == null || "xmlns".equals(prefix)) {
- prefix = "";
- }
-
- try {
- currentElement.addNamespaceDeclaration(prefix, uri);
- } catch (SOAPException e) {
- throw new XMLStreamException(e);
+ String thePrefix = prefix == null || "xmlns".equals(prefix) ? "" : prefix;
+ if (deferredElement.isInitialized()) {
+ deferredElement.addNamespaceDeclaration(thePrefix, uri);
+ } else {
+ try {
+ currentElement.addNamespaceDeclaration(thePrefix, uri);
+ } catch (SOAPException e) {
+ throw new XMLStreamException(e);
+ }
}
}
@@ -201,35 +215,40 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeComment(final String data) throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
Comment c = soap.getSOAPPart().createComment(data);
currentElement.appendChild(c);
}
@Override
public void writeProcessingInstruction(final String target) throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
Node n = soap.getSOAPPart().createProcessingInstruction(target, "");
currentElement.appendChild(n);
}
@Override
public void writeProcessingInstruction(final String target, final String data) throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
Node n = soap.getSOAPPart().createProcessingInstruction(target, data);
currentElement.appendChild(n);
}
@Override
public void writeCData(final String data) throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
Node n = soap.getSOAPPart().createCDATASection(data);
currentElement.appendChild(n);
}
@Override
public void writeDTD(final String dtd) throws XMLStreamException {
- //TODO ... Don't do anything here
+ currentElement = deferredElement.flushTo(currentElement);
}
@Override
public void writeEntityRef(final String name) throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
Node n = soap.getSOAPPart().createEntityReference(name);
currentElement.appendChild(n);
}
@@ -257,6 +276,7 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeCharacters(final String text) throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
try {
currentElement.addTextNode(text);
} catch (SOAPException e) {
@@ -266,6 +286,7 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
char[] chr = (start == 0 && len == text.length) ? text : Arrays.copyOfRange(text, start, start + len);
try {
currentElement.addTextNode(new String(chr));
@@ -281,10 +302,16 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void setPrefix(final String prefix, final String uri) throws XMLStreamException {
- try {
- this.currentElement.addNamespaceDeclaration(prefix, uri);
- } catch (SOAPException e) {
- throw new XMLStreamException(e);
+ // TODO: this in fact is not what would be expected from XMLStreamWriter
+ // (e.g. XMLStreamWriter for writing to output stream does not write anything as result of
+ // this method, it just rememebers that given prefix is associated with the given uri
+ // for the scope; to actually declare the prefix assignment in the resulting XML, one
+ // needs to call writeNamespace(...) method
+ // Kept for backwards compatibility reasons - this might be worth of further investigation.
+ if (deferredElement.isInitialized()) {
+ deferredElement.addNamespaceDeclaration(prefix, uri);
+ } else {
+ throw new XMLStreamException("Namespace not associated with any element");
}
}
@@ -331,4 +358,209 @@ public class SaajStaxWriter implements XMLStreamWriter {
}
};
}
+
+ static void addAttibuteToElement(SOAPElement element, String prefix, String ns, String ln, String value)
+ throws XMLStreamException {
+ try {
+ if (ns == null) {
+ element.setAttributeNS("", ln, value);
+ } else {
+ QName name = prefix == null ? new QName(ns, ln) : new QName(ns, ln, prefix);
+ element.addAttribute(name, value);
+ }
+ } catch (SOAPException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ /**
+ * Holds details of element that needs to be deferred in order to manage namespace assignments correctly.
+ *
+ *
+ * An instance of can be set with all the aspects of the element name (local name, prefix, namespace uri).
+ * Attributes and namespace declarations (special case of attribute) can be added.
+ * Namespace declarations are handled so that the element namespace is updated if it is implied by the namespace
+ * declaration and the namespace was not set to non-{@code null} value previously.
+ *
+ *
+ *
+ * The state of this object can be {@link #flushTo(SOAPElement) flushed} to SOAPElement - new SOAPElement will
+ * be added a child element; the new element will have exactly the shape as represented by the state of this
+ * object. Note that the {@link #flushTo(SOAPElement)} method does nothing
+ * (and returns the argument immediately) if the state of this object is not initialized
+ * (i.e. local name is null).
+ *
+ *
+ * @author ondrej.cerny@oracle.com
+ */
+ static class DeferredElement {
+ private String prefix;
+ private String localName;
+ private String namespaceUri;
+ private final List namespaceDeclarations;
+ private final List attributeDeclarations;
+
+ DeferredElement() {
+ this.namespaceDeclarations = new LinkedList();
+ this.attributeDeclarations = new LinkedList();
+ reset();
+ }
+
+
+ /**
+ * Set prefix of the element.
+ * @param prefix namespace prefix
+ */
+ public void setPrefix(final String prefix) {
+ this.prefix = prefix;
+ }
+
+ /**
+ * Set local name of the element.
+ *
+ *
+ * This method initializes the element.
+ *
+ *
+ * @param localName local name {@code not null}
+ */
+ public void setLocalName(final String localName) {
+ if (localName == null) {
+ throw new IllegalArgumentException("localName can not be null");
+ }
+ this.localName = localName;
+ }
+
+ /**
+ * Set namespace uri.
+ *
+ * @param namespaceUri namespace uri
+ */
+ public void setNamespaceUri(final String namespaceUri) {
+ this.namespaceUri = namespaceUri;
+ }
+
+ /**
+ * Adds namespace prefix assignment to the element.
+ *
+ * @param prefix prefix (not {@code null})
+ * @param namespaceUri namespace uri
+ */
+ public void addNamespaceDeclaration(final String prefix, final String namespaceUri) {
+ if (null == this.namespaceUri && null != namespaceUri && prefix.equals(emptyIfNull(this.prefix))) {
+ this.namespaceUri = namespaceUri;
+ }
+ this.namespaceDeclarations.add(new NamespaceDeclaration(prefix, namespaceUri));
+ }
+
+ /**
+ * Adds attribute to the element.
+ * @param prefix prefix
+ * @param ns namespace
+ * @param ln local name
+ * @param value value
+ */
+ public void addAttribute(final String prefix, final String ns, final String ln, final String value) {
+ if (ns == null && prefix == null && xmlns.equals(ln)) {
+ this.addNamespaceDeclaration(prefix, value);
+ } else {
+ this.attributeDeclarations.add(new AttributeDeclaration(prefix, ns, ln, value));
+ }
+ }
+
+ /**
+ * Flushes state of this element to the {@code target} element.
+ *
+ *
+ * If this element is initialized then it is added with all the namespace declarations and attributes
+ * to the {@code target} element as a child. The state of this element is reset to uninitialized.
+ * The newly added element object is returned.
+ *
+ *
+ * If this element is not initialized then the {@code target} is returned immediately, nothing else is done.
+ *
+ *
+ * @param target target element
+ * @return {@code target} or new element
+ * @throws XMLStreamException on error
+ */
+ public SOAPElement flushTo(final SOAPElement target) throws XMLStreamException {
+ try {
+ if (this.localName != null) {
+ // add the element appropriately (based on namespace declaration)
+ final SOAPElement newElement;
+ if (this.namespaceUri == null) {
+ // add element with inherited scope
+ newElement = target.addChildElement(this.localName);
+ } else if (prefix == null) {
+ newElement = target.addChildElement(new QName(this.namespaceUri, this.localName));
+ } else {
+ newElement = target.addChildElement(this.localName, this.prefix, this.namespaceUri);
+ }
+ // add namespace declarations
+ for (NamespaceDeclaration namespace : this.namespaceDeclarations) {
+ target.addNamespaceDeclaration(namespace.prefix, namespace.namespaceUri);
+ }
+ // add attribute declarations
+ for (AttributeDeclaration attribute : this.attributeDeclarations) {
+ addAttibuteToElement(newElement,
+ attribute.prefix, attribute.namespaceUri, attribute.localName, attribute.value);
+ }
+ // reset state
+ this.reset();
+
+ return newElement;
+ } else {
+ return target;
+ }
+ // else after reset state -> not initialized
+ } catch (SOAPException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ /**
+ * Is the element initialized?
+ * @return boolean indicating whether it was initialized after last flush
+ */
+ public boolean isInitialized() {
+ return this.localName != null;
+ }
+
+ private void reset() {
+ this.localName = null;
+ this.prefix = null;
+ this.namespaceUri = null;
+ this.namespaceDeclarations.clear();
+ this.attributeDeclarations.clear();
+ }
+
+ private static String emptyIfNull(String s) {
+ return s == null ? "" : s;
+ }
+ }
+
+ static class NamespaceDeclaration {
+ final String prefix;
+ final String namespaceUri;
+
+ NamespaceDeclaration(String prefix, String namespaceUri) {
+ this.prefix = prefix;
+ this.namespaceUri = namespaceUri;
+ }
+ }
+
+ static class AttributeDeclaration {
+ final String prefix;
+ final String namespaceUri;
+ final String localName;
+ final String value;
+
+ AttributeDeclaration(String prefix, String namespaceUri, String localName, String value) {
+ this.prefix = prefix;
+ this.namespaceUri = namespaceUri;
+ this.localName = localName;
+ this.value = value;
+ }
+ }
}
diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java
index 9b743e20c59..37a42e75c53 100644
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,10 @@
package com.sun.xml.internal.ws.api.message.saaj;
-import java.util.Arrays;
import java.util.Iterator;
+import java.util.Arrays;
+import java.util.List;
+import java.util.LinkedList;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
@@ -42,6 +44,17 @@ import org.w3c.dom.Node;
/**
* SaajStaxWriter builds a SAAJ SOAPMessage by using XMLStreamWriter interface.
*
+ *
+ * Defers creation of SOAPElement until all the aspects of the name of the element are known.
+ * In some cases, the namespace uri is indicated only by the {@link #writeNamespace(String, String)} call.
+ * After opening an element ({@code writeStartElement}, {@code writeEmptyElement} methods), all attributes
+ * and namespace assignments are retained within {@link DeferredElement} object ({@code deferredElement} field).
+ * As soon as any other method than {@code writeAttribute}, {@code writeNamespace}, {@code writeDefaultNamespace}
+ * or {@code setNamespace} is called, the contents of {@code deferredElement} is transformed into new SOAPElement
+ * (which is appropriately inserted into the SOAPMessage under construction).
+ * This mechanism is necessary to fix JDK-8159058 issue.
+ *
+ *
* @author shih-chang.chen@oracle.com
*/
public class SaajStaxWriter implements XMLStreamWriter {
@@ -49,6 +62,7 @@ public class SaajStaxWriter implements XMLStreamWriter {
protected SOAPMessage soap;
protected String envURI;
protected SOAPElement currentElement;
+ protected DeferredElement deferredElement;
static final protected String Envelope = "Envelope";
static final protected String Header = "Header";
@@ -58,6 +72,7 @@ public class SaajStaxWriter implements XMLStreamWriter {
public SaajStaxWriter(final SOAPMessage msg, String uri) throws SOAPException {
soap = msg;
this.envURI = uri;
+ this.deferredElement = new DeferredElement();
}
public SOAPMessage getSOAPMessage() {
@@ -70,11 +85,8 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeStartElement(final String localName) throws XMLStreamException {
- try {
- currentElement = currentElement.addChildElement(localName);
- } catch (SOAPException e) {
- throw new XMLStreamException(e);
- }
+ currentElement = deferredElement.flushTo(currentElement);
+ deferredElement.setLocalName(localName);
}
@Override
@@ -84,8 +96,10 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeStartElement(final String prefix, final String ln, final String ns) throws XMLStreamException {
- try {
- if (envURI.equals(ns)) {
+ currentElement = deferredElement.flushTo(currentElement);
+
+ if (envURI.equals(ns)) {
+ try {
if (Envelope.equals(ln)) {
currentElement = getEnvelope();
fixPrefix(prefix);
@@ -99,13 +113,16 @@ public class SaajStaxWriter implements XMLStreamWriter {
fixPrefix(prefix);
return;
}
+ } catch (SOAPException e) {
+ throw new XMLStreamException(e);
}
- currentElement = (prefix == null) ?
- currentElement.addChildElement(new QName(ns, ln)) :
- currentElement.addChildElement(ln, prefix, ns);
- } catch (SOAPException e) {
- throw new XMLStreamException(e);
+
}
+
+ deferredElement.setLocalName(ln);
+ deferredElement.setNamespaceUri(ns);
+ deferredElement.setPrefix(prefix);
+
}
private void fixPrefix(final String prfx) throws XMLStreamException {
@@ -136,11 +153,13 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeEndElement() throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
if (currentElement != null) currentElement = currentElement.getParentElement();
}
@Override
public void writeEndDocument() throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
}
@Override
@@ -158,19 +177,14 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeAttribute(final String prefix, final String ns, final String ln, final String value) throws XMLStreamException {
- try {
- if (ns == null) {
- if (prefix == null && xmlns.equals(ln)) {
- currentElement.addNamespaceDeclaration("", value);
- } else {
- currentElement.setAttributeNS("", ln, value);
- }
+ if (ns == null && prefix == null && xmlns.equals(ln)) {
+ writeNamespace("", value);
+ } else {
+ if (deferredElement.isInitialized()) {
+ deferredElement.addAttribute(prefix, ns, ln, value);
} else {
- QName name = (prefix == null) ? new QName(ns, ln) : new QName(ns, ln, prefix);
- currentElement.addAttribute(name, value);
+ addAttibuteToElement(currentElement, prefix, ns, ln, value);
}
- } catch (SOAPException e) {
- throw new XMLStreamException(e);
}
}
@@ -181,16 +195,16 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeNamespace(String prefix, final String uri) throws XMLStreamException {
-
// make prefix default if null or "xmlns" (according to javadoc)
- if (prefix == null || "xmlns".equals(prefix)) {
- prefix = "";
- }
-
- try {
- currentElement.addNamespaceDeclaration(prefix, uri);
- } catch (SOAPException e) {
- throw new XMLStreamException(e);
+ String thePrefix = prefix == null || "xmlns".equals(prefix) ? "" : prefix;
+ if (deferredElement.isInitialized()) {
+ deferredElement.addNamespaceDeclaration(thePrefix, uri);
+ } else {
+ try {
+ currentElement.addNamespaceDeclaration(thePrefix, uri);
+ } catch (SOAPException e) {
+ throw new XMLStreamException(e);
+ }
}
}
@@ -201,35 +215,40 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeComment(final String data) throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
Comment c = soap.getSOAPPart().createComment(data);
currentElement.appendChild(c);
}
@Override
public void writeProcessingInstruction(final String target) throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
Node n = soap.getSOAPPart().createProcessingInstruction(target, "");
currentElement.appendChild(n);
}
@Override
public void writeProcessingInstruction(final String target, final String data) throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
Node n = soap.getSOAPPart().createProcessingInstruction(target, data);
currentElement.appendChild(n);
}
@Override
public void writeCData(final String data) throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
Node n = soap.getSOAPPart().createCDATASection(data);
currentElement.appendChild(n);
}
@Override
public void writeDTD(final String dtd) throws XMLStreamException {
- //TODO ... Don't do anything here
+ currentElement = deferredElement.flushTo(currentElement);
}
@Override
public void writeEntityRef(final String name) throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
Node n = soap.getSOAPPart().createEntityReference(name);
currentElement.appendChild(n);
}
@@ -257,6 +276,7 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeCharacters(final String text) throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
try {
currentElement.addTextNode(text);
} catch (SOAPException e) {
@@ -266,6 +286,7 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException {
+ currentElement = deferredElement.flushTo(currentElement);
char[] chr = (start == 0 && len == text.length) ? text : Arrays.copyOfRange(text, start, start + len);
try {
currentElement.addTextNode(new String(chr));
@@ -281,10 +302,16 @@ public class SaajStaxWriter implements XMLStreamWriter {
@Override
public void setPrefix(final String prefix, final String uri) throws XMLStreamException {
- try {
- this.currentElement.addNamespaceDeclaration(prefix, uri);
- } catch (SOAPException e) {
- throw new XMLStreamException(e);
+ // TODO: this in fact is not what would be expected from XMLStreamWriter
+ // (e.g. XMLStreamWriter for writing to output stream does not write anything as result of
+ // this method, it just rememebers that given prefix is associated with the given uri
+ // for the scope; to actually declare the prefix assignment in the resulting XML, one
+ // needs to call writeNamespace(...) method
+ // Kept for backwards compatibility reasons - this might be worth of further investigation.
+ if (deferredElement.isInitialized()) {
+ deferredElement.addNamespaceDeclaration(prefix, uri);
+ } else {
+ throw new XMLStreamException("Namespace not associated with any element");
}
}
@@ -315,12 +342,12 @@ public class SaajStaxWriter implements XMLStreamWriter {
return currentElement.lookupPrefix(namespaceURI);
}
public Iterator getPrefixes(final String namespaceURI) {
- return new Iterator() {
+ return new Iterator() {
String prefix = getPrefix(namespaceURI);
public boolean hasNext() {
return (prefix != null);
}
- public Object next() {
+ public String next() {
if (!hasNext()) throw new java.util.NoSuchElementException();
String next = prefix;
prefix = null;
@@ -331,4 +358,209 @@ public class SaajStaxWriter implements XMLStreamWriter {
}
};
}
+
+ static void addAttibuteToElement(SOAPElement element, String prefix, String ns, String ln, String value)
+ throws XMLStreamException {
+ try {
+ if (ns == null) {
+ element.setAttributeNS("", ln, value);
+ } else {
+ QName name = prefix == null ? new QName(ns, ln) : new QName(ns, ln, prefix);
+ element.addAttribute(name, value);
+ }
+ } catch (SOAPException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ /**
+ * Holds details of element that needs to be deferred in order to manage namespace assignments correctly.
+ *
+ *
+ * An instance of can be set with all the aspects of the element name (local name, prefix, namespace uri).
+ * Attributes and namespace declarations (special case of attribute) can be added.
+ * Namespace declarations are handled so that the element namespace is updated if it is implied by the namespace
+ * declaration and the namespace was not set to non-{@code null} value previously.
+ *
+ *
+ *
+ * The state of this object can be {@link #flushTo(SOAPElement) flushed} to SOAPElement - new SOAPElement will
+ * be added a child element; the new element will have exactly the shape as represented by the state of this
+ * object. Note that the {@link #flushTo(SOAPElement)} method does nothing
+ * (and returns the argument immediately) if the state of this object is not initialized
+ * (i.e. local name is null).
+ *
+ *
+ * @author ondrej.cerny@oracle.com
+ */
+ static class DeferredElement {
+ private String prefix;
+ private String localName;
+ private String namespaceUri;
+ private final List namespaceDeclarations;
+ private final List attributeDeclarations;
+
+ DeferredElement() {
+ this.namespaceDeclarations = new LinkedList();
+ this.attributeDeclarations = new LinkedList();
+ reset();
+ }
+
+
+ /**
+ * Set prefix of the element.
+ * @param prefix namespace prefix
+ */
+ public void setPrefix(final String prefix) {
+ this.prefix = prefix;
+ }
+
+ /**
+ * Set local name of the element.
+ *
+ *
+ * This method initializes the element.
+ *
+ *
+ * @param localName local name {@code not null}
+ */
+ public void setLocalName(final String localName) {
+ if (localName == null) {
+ throw new IllegalArgumentException("localName can not be null");
+ }
+ this.localName = localName;
+ }
+
+ /**
+ * Set namespace uri.
+ *
+ * @param namespaceUri namespace uri
+ */
+ public void setNamespaceUri(final String namespaceUri) {
+ this.namespaceUri = namespaceUri;
+ }
+
+ /**
+ * Adds namespace prefix assignment to the element.
+ *
+ * @param prefix prefix (not {@code null})
+ * @param namespaceUri namespace uri
+ */
+ public void addNamespaceDeclaration(final String prefix, final String namespaceUri) {
+ if (null == this.namespaceUri && null != namespaceUri && prefix.equals(emptyIfNull(this.prefix))) {
+ this.namespaceUri = namespaceUri;
+ }
+ this.namespaceDeclarations.add(new NamespaceDeclaration(prefix, namespaceUri));
+ }
+
+ /**
+ * Adds attribute to the element.
+ * @param prefix prefix
+ * @param ns namespace
+ * @param ln local name
+ * @param value value
+ */
+ public void addAttribute(final String prefix, final String ns, final String ln, final String value) {
+ if (ns == null && prefix == null && xmlns.equals(ln)) {
+ this.addNamespaceDeclaration(prefix, value);
+ } else {
+ this.attributeDeclarations.add(new AttributeDeclaration(prefix, ns, ln, value));
+ }
+ }
+
+ /**
+ * Flushes state of this element to the {@code target} element.
+ *
+ *
+ * If this element is initialized then it is added with all the namespace declarations and attributes
+ * to the {@code target} element as a child. The state of this element is reset to uninitialized.
+ * The newly added element object is returned.
+ *
+ *
+ * If this element is not initialized then the {@code target} is returned immediately, nothing else is done.
+ *
+ *
+ * @param target target element
+ * @return {@code target} or new element
+ * @throws XMLStreamException on error
+ */
+ public SOAPElement flushTo(final SOAPElement target) throws XMLStreamException {
+ try {
+ if (this.localName != null) {
+ // add the element appropriately (based on namespace declaration)
+ final SOAPElement newElement;
+ if (this.namespaceUri == null) {
+ // add element with inherited scope
+ newElement = target.addChildElement(this.localName);
+ } else if (prefix == null) {
+ newElement = target.addChildElement(new QName(this.namespaceUri, this.localName));
+ } else {
+ newElement = target.addChildElement(this.localName, this.prefix, this.namespaceUri);
+ }
+ // add namespace declarations
+ for (NamespaceDeclaration namespace : this.namespaceDeclarations) {
+ target.addNamespaceDeclaration(namespace.prefix, namespace.namespaceUri);
+ }
+ // add attribute declarations
+ for (AttributeDeclaration attribute : this.attributeDeclarations) {
+ addAttibuteToElement(newElement,
+ attribute.prefix, attribute.namespaceUri, attribute.localName, attribute.value);
+ }
+ // reset state
+ this.reset();
+
+ return newElement;
+ } else {
+ return target;
+ }
+ // else after reset state -> not initialized
+ } catch (SOAPException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ /**
+ * Is the element initialized?
+ * @return boolean indicating whether it was initialized after last flush
+ */
+ public boolean isInitialized() {
+ return this.localName != null;
+ }
+
+ private void reset() {
+ this.localName = null;
+ this.prefix = null;
+ this.namespaceUri = null;
+ this.namespaceDeclarations.clear();
+ this.attributeDeclarations.clear();
+ }
+
+ private static String emptyIfNull(String s) {
+ return s == null ? "" : s;
+ }
+ }
+
+ static class NamespaceDeclaration {
+ final String prefix;
+ final String namespaceUri;
+
+ NamespaceDeclaration(String prefix, String namespaceUri) {
+ this.prefix = prefix;
+ this.namespaceUri = namespaceUri;
+ }
+ }
+
+ static class AttributeDeclaration {
+ final String prefix;
+ final String namespaceUri;
+ final String localName;
+ final String value;
+
+ AttributeDeclaration(String prefix, String namespaceUri, String localName, String value) {
+ this.prefix = prefix;
+ this.namespaceUri = namespaceUri;
+ this.localName = localName;
+ this.value = value;
+ }
+ }
}
diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java
index 09eaa938b46..d84fa5e7d11 100644
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@ import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.reflect.Method;
+import java.net.URI;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -332,13 +333,13 @@ public class XmlUtil {
* (com.sun.org.apache.xml.internal) for modular runtime.
*/
private static EntityResolver createCatalogResolver(ArrayList urls) throws Exception {
- // Prepare array of catalog paths
- String[] paths = urls.stream()
- .map(u -> u.toExternalForm())
- .toArray(c -> new String[c]);
+ // Prepare array of catalog URIs
+ URI[] uris = urls.stream()
+ .map(u -> URI.create(u.toExternalForm()))
+ .toArray(URI[]::new);
//Create CatalogResolver with new JDK9+ API
- return (EntityResolver) CatalogManager.catalogResolver(catalogFeatures, paths);
+ return (EntityResolver) CatalogManager.catalogResolver(catalogFeatures, uris);
}
// Cache CatalogFeatures instance for future usages.
diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/Options.java b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/Options.java
index bce8f27cbc2..10c1bda5157 100644
--- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/Options.java
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/Options.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -777,13 +777,13 @@ public class Options
* Adds a new catalog file.
*/
public void addCatalog(File catalogFile) throws IOException {
- String newUrl = catalogFile.getPath();
+ URI newUrl = catalogFile.toURI();
if (!catalogUrls.contains(newUrl)) {
catalogUrls.add(newUrl);
}
try {
entityResolver = CatalogManager.catalogResolver(catalogFeatures,
- catalogUrls.toArray(new String[0]));
+ catalogUrls.stream().toArray(URI[]::new));
} catch (Exception ex) {
entityResolver = null;
}
@@ -791,7 +791,7 @@ public class Options
// Since javax.xml.catalog is unmodifiable we need to track catalog
// URLs added and create new catalog each time addCatalog is called
- private final ArrayList catalogUrls = new ArrayList();
+ private final ArrayList catalogUrls = new ArrayList<>();
// Cache CatalogFeatures instance for future usages.
// Resolve feature is set to "continue" value for backward compatibility.
diff --git a/jdk/.hgtags b/jdk/.hgtags
index 0b80fe4f688..a73fb2ebf2a 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -394,3 +394,5 @@ c41140100bf1e5c10c7b8f3bde91c16eff7485f5 jdk-9+147
5a846396a24c7aff01d6a8feaa7afc0a6369f04d jdk-9+149
71e198ef3839045e829a879af1d709be16ab0f88 jdk-9+150
d27bab22ff62823902d93d1d35ca397cfd50d059 jdk-9+151
+a20f2cf90762673e1bc4980fd6597e70a2578045 jdk-9+152
+1c4411322327aea3f91011ec3977a12a05b09629 jdk-9+153
diff --git a/jdk/make/CompileModuleTools.gmk b/jdk/make/CompileModuleTools.gmk
index b366182e507..2bfe520b233 100644
--- a/jdk/make/CompileModuleTools.gmk
+++ b/jdk/make/CompileModuleTools.gmk
@@ -37,6 +37,5 @@ $(eval $(call SetupJavaCompilation,BUILD_JIGSAW_TOOLS, \
build/tools/jigsaw, \
BIN := $(TOOLS_CLASSES_DIR), \
ADD_JAVAC_FLAGS := \
- --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED \
--add-exports java.base/jdk.internal.module=ALL-UNNAMED \
))
diff --git a/jdk/make/ModuleTools.gmk b/jdk/make/ModuleTools.gmk
index 30cf959e174..71ca1cf8eaa 100644
--- a/jdk/make/ModuleTools.gmk
+++ b/jdk/make/ModuleTools.gmk
@@ -39,7 +39,6 @@ TOOL_GENGRAPHS := $(BUILD_JAVA) -esa -ea -cp $(TOOLS_CLASSES_DIR) \
build.tools.jigsaw.GenGraphs
TOOL_MODULESUMMARY := $(BUILD_JAVA) -esa -ea -cp $(TOOLS_CLASSES_DIR) \
- --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED \
build.tools.jigsaw.ModuleSummary
TOOL_ADD_PACKAGES_ATTRIBUTE := $(BUILD_JAVA) $(JAVA_FLAGS_SMALL) \
diff --git a/jdk/make/data/fontconfig/solaris.fontconfig.properties b/jdk/make/data/fontconfig/solaris.fontconfig.properties
index bbd68b5024d..03f61e7709d 100644
--- a/jdk/make/data/fontconfig/solaris.fontconfig.properties
+++ b/jdk/make/data/fontconfig/solaris.fontconfig.properties
@@ -436,15 +436,15 @@ sequence.fallback=latin-1,latin-2,latin-7,cyrillic-iso8859-5,greek,latin-5,latin
filename.-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arial.ttf
filename.-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/ariali.ttf
-filename.-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialb.ttf
+filename.-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialbd.ttf
filename.-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialbi.ttf
filename.-monotype-courier_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cour.ttf
filename.-monotype-courier_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/couri.ttf
-filename.-monotype-courier_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courb.ttf
+filename.-monotype-courier_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courbd.ttf
filename.-monotype-courier_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courbi.ttf
filename.-monotype-times_new_roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/times.ttf
filename.-monotype-times_new_roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesi.ttf
-filename.-monotype-times_new_roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesb.ttf
+filename.-monotype-times_new_roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesbd.ttf
filename.-monotype-times_new_roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesbi.ttf
filename.-monotype-angsana_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsa.ttf
diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk
index 72943c0afdd..743422b0afe 100644
--- a/jdk/make/lib/Awt2dLibraries.gmk
+++ b/jdk/make/lib/Awt2dLibraries.gmk
@@ -222,6 +222,8 @@ endif
# applies to debug builds.
ifeq ($(TOOLCHAIN_TYPE), gcc)
BUILD_LIBAWT_debug_mem.c_CFLAGS := -w
+ # This option improves performance of MaskFill in Java2D by 20% for some gcc
+ LIBAWT_CFLAGS += -fgcse-after-reload
endif
$(eval $(call SetupNativeCompilation,BUILD_LIBAWT, \
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java
index d376fc395fe..895b17ac578 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java
@@ -69,6 +69,10 @@ class HttpsURLConnection extends HttpURLConnection
/**
* Returns the server's X.509 certificate chain, or null if
* the server did not authenticate.
+ *
+ * Note: The returned value may not be a valid certificate chain
+ * and should not be relied on for trust decisions.
+ *
* @return the server certificate chain
*/
public abstract Certificate[] getServerCertificates()
diff --git a/jdk/src/java.base/share/classes/java/io/File.java b/jdk/src/java.base/share/classes/java/io/File.java
index 1598694ef2f..0bbaf4d5d0b 100644
--- a/jdk/src/java.base/share/classes/java/io/File.java
+++ b/jdk/src/java.base/share/classes/java/io/File.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1962,6 +1962,9 @@ public class File
name = sb.toString();
}
+ // Normalize the path component
+ name = fs.normalize(name);
+
File f = new File(dir, name);
if (!name.equals(f.getName()) || f.isInvalid()) {
if (System.getSecurityManager() != null)
diff --git a/jdk/src/java.base/share/classes/java/lang/Class.java b/jdk/src/java.base/share/classes/java/lang/Class.java
index 589ba51089c..b0e3d3af0cd 100644
--- a/jdk/src/java.base/share/classes/java/lang/Class.java
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java
@@ -508,8 +508,9 @@ public final class Class implements java.io.Serializable,
public T newInstance()
throws InstantiationException, IllegalAccessException
{
- if (System.getSecurityManager() != null) {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), false);
}
// NOTE: the following code may not be strictly correct under
@@ -1223,38 +1224,27 @@ public final class Class implements java.io.Serializable,
// Perform access check
final Class> enclosingCandidate = enclosingInfo.getEnclosingClass();
- enclosingCandidate.checkMemberAccess(Member.DECLARED,
- Reflection.getCallerClass(), true);
- // Client is ok to access declared methods but j.l.Class might not be.
- Method[] candidates = AccessController.doPrivileged(
- new PrivilegedAction<>() {
- @Override
- public Method[] run() {
- return enclosingCandidate.getDeclaredMethods();
- }
- });
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ enclosingCandidate.checkMemberAccess(sm, Member.DECLARED,
+ Reflection.getCallerClass(), true);
+ }
+ Method[] candidates = enclosingCandidate.privateGetDeclaredMethods(false);
+
/*
* Loop over all declared methods; match method name,
* number of and type of parameters, *and* return
* type. Matching return type is also necessary
* because of covariant returns, etc.
*/
- for(Method m: candidates) {
- if (m.getName().equals(enclosingInfo.getName()) ) {
- Class>[] candidateParamClasses = m.getParameterTypes();
- if (candidateParamClasses.length == parameterClasses.length) {
- boolean matches = true;
- for(int i = 0; i < candidateParamClasses.length; i++) {
- if (!candidateParamClasses[i].equals(parameterClasses[i])) {
- matches = false;
- break;
- }
- }
-
- if (matches) { // finally, check return type
- if (m.getReturnType().equals(returnType) )
- return m;
- }
+ ReflectionFactory fact = getReflectionFactory();
+ for (Method m : candidates) {
+ if (m.getName().equals(enclosingInfo.getName()) &&
+ arrayContentsEq(parameterClasses,
+ fact.getExecutableSharedParameterTypes(m))) {
+ // finally, check return type
+ if (m.getReturnType().equals(returnType)) {
+ return fact.copyMethod(m);
}
}
}
@@ -1390,33 +1380,23 @@ public final class Class implements java.io.Serializable,
// Perform access check
final Class> enclosingCandidate = enclosingInfo.getEnclosingClass();
- enclosingCandidate.checkMemberAccess(Member.DECLARED,
- Reflection.getCallerClass(), true);
- // Client is ok to access declared methods but j.l.Class might not be.
- Constructor>[] candidates = AccessController.doPrivileged(
- new PrivilegedAction<>() {
- @Override
- public Constructor>[] run() {
- return enclosingCandidate.getDeclaredConstructors();
- }
- });
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ enclosingCandidate.checkMemberAccess(sm, Member.DECLARED,
+ Reflection.getCallerClass(), true);
+ }
+
+ Constructor>[] candidates = enclosingCandidate
+ .privateGetDeclaredConstructors(false);
/*
* Loop over all declared constructors; match number
* of and type of parameters.
*/
- for(Constructor> c: candidates) {
- Class>[] candidateParamClasses = c.getParameterTypes();
- if (candidateParamClasses.length == parameterClasses.length) {
- boolean matches = true;
- for(int i = 0; i < candidateParamClasses.length; i++) {
- if (!candidateParamClasses[i].equals(parameterClasses[i])) {
- matches = false;
- break;
- }
- }
-
- if (matches)
- return c;
+ ReflectionFactory fact = getReflectionFactory();
+ for (Constructor> c : candidates) {
+ if (arrayContentsEq(parameterClasses,
+ fact.getExecutableSharedParameterTypes(c))) {
+ return fact.copyConstructor(c);
}
}
@@ -1446,9 +1426,13 @@ public final class Class implements java.io.Serializable,
public Class> getDeclaringClass() throws SecurityException {
final Class> candidate = getDeclaringClass0();
- if (candidate != null)
- candidate.checkPackageAccess(
+ if (candidate != null) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ candidate.checkPackageAccess(sm,
ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
+ }
+ }
return candidate;
}
@@ -1496,9 +1480,13 @@ public final class Class implements java.io.Serializable,
enclosingCandidate = enclosingClass;
}
- if (enclosingCandidate != null)
- enclosingCandidate.checkPackageAccess(
+ if (enclosingCandidate != null) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ enclosingCandidate.checkPackageAccess(sm,
ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
+ }
+ }
return enclosingCandidate;
}
@@ -1688,7 +1676,10 @@ public final class Class implements java.io.Serializable,
*/
@CallerSensitive
public Class>[] getClasses() {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), false);
+ }
// Privileged so this implementation can look at DECLARED classes,
// something the caller might not have privilege to do. The code here
@@ -1754,7 +1745,10 @@ public final class Class implements java.io.Serializable,
*/
@CallerSensitive
public Field[] getFields() throws SecurityException {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
return copyFields(privateGetPublicFields(null));
}
@@ -1841,7 +1835,10 @@ public final class Class implements java.io.Serializable,
*/
@CallerSensitive
public Method[] getMethods() throws SecurityException {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
return copyMethods(privateGetPublicMethods());
}
@@ -1877,7 +1874,10 @@ public final class Class implements java.io.Serializable,
*/
@CallerSensitive
public Constructor>[] getConstructors() throws SecurityException {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
return copyConstructors(privateGetDeclaredConstructors(true));
}
@@ -1928,7 +1928,10 @@ public final class Class implements java.io.Serializable,
public Field getField(String name)
throws NoSuchFieldException, SecurityException {
Objects.requireNonNull(name);
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
Field field = getField0(name);
if (field == null) {
throw new NoSuchFieldException(name);
@@ -2034,10 +2037,13 @@ public final class Class implements java.io.Serializable,
public Method getMethod(String name, Class>... parameterTypes)
throws NoSuchMethodException, SecurityException {
Objects.requireNonNull(name);
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
Method method = getMethod0(name, parameterTypes);
if (method == null) {
- throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
+ throw new NoSuchMethodException(methodToString(name, parameterTypes));
}
return getReflectionFactory().copyMethod(method);
}
@@ -2092,8 +2098,12 @@ public final class Class implements java.io.Serializable,
*/
@CallerSensitive
public Constructor getConstructor(Class>... parameterTypes)
- throws NoSuchMethodException, SecurityException {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ throws NoSuchMethodException, SecurityException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
return getReflectionFactory().copyConstructor(
getConstructor0(parameterTypes, Member.PUBLIC));
}
@@ -2136,7 +2146,10 @@ public final class Class implements java.io.Serializable,
*/
@CallerSensitive
public Class>[] getDeclaredClasses() throws SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), false);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), false);
+ }
return getDeclaredClasses0();
}
@@ -2185,7 +2198,10 @@ public final class Class implements java.io.Serializable,
*/
@CallerSensitive
public Field[] getDeclaredFields() throws SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
return copyFields(privateGetDeclaredFields(false));
}
@@ -2244,7 +2260,10 @@ public final class Class implements java.io.Serializable,
*/
@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
return copyMethods(privateGetDeclaredMethods(false));
}
@@ -2289,7 +2308,10 @@ public final class Class implements java.io.Serializable,
*/
@CallerSensitive
public Constructor>[] getDeclaredConstructors() throws SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
return copyConstructors(privateGetDeclaredConstructors(false));
}
@@ -2338,7 +2360,10 @@ public final class Class implements java.io.Serializable,
public Field getDeclaredField(String name)
throws NoSuchFieldException, SecurityException {
Objects.requireNonNull(name);
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
Field field = searchFields(privateGetDeclaredFields(false), name);
if (field == null) {
throw new NoSuchFieldException(name);
@@ -2399,10 +2424,13 @@ public final class Class implements java.io.Serializable,
public Method getDeclaredMethod(String name, Class>... parameterTypes)
throws NoSuchMethodException, SecurityException {
Objects.requireNonNull(name);
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) {
- throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
+ throw new NoSuchMethodException(methodToString(name, parameterTypes));
}
return getReflectionFactory().copyMethod(method);
}
@@ -2448,8 +2476,13 @@ public final class Class implements java.io.Serializable,
*/
@CallerSensitive
public Constructor getDeclaredConstructor(Class>... parameterTypes)
- throws NoSuchMethodException, SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ throws NoSuchMethodException, SecurityException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
+
return getReflectionFactory().copyConstructor(
getConstructor0(parameterTypes, Member.DECLARED));
}
@@ -2697,51 +2730,49 @@ public final class Class implements java.io.Serializable,
*
* Default policy: allow all clients access with normal Java access
* control.
+ *
+ * NOTE: should only be called if a SecurityManager is installed
*/
- private void checkMemberAccess(int which, Class> caller, boolean checkProxyInterfaces) {
- final SecurityManager s = System.getSecurityManager();
- if (s != null) {
- /* Default policy allows access to all {@link Member#PUBLIC} members,
- * as well as access to classes that have the same class loader as the caller.
- * In all other cases, it requires RuntimePermission("accessDeclaredMembers")
- * permission.
- */
- final ClassLoader ccl = ClassLoader.getClassLoader(caller);
+ private void checkMemberAccess(SecurityManager sm, int which,
+ Class> caller, boolean checkProxyInterfaces) {
+ /* Default policy allows access to all {@link Member#PUBLIC} members,
+ * as well as access to classes that have the same class loader as the caller.
+ * In all other cases, it requires RuntimePermission("accessDeclaredMembers")
+ * permission.
+ */
+ final ClassLoader ccl = caller.getClassLoader0();
+ if (which != Member.PUBLIC) {
final ClassLoader cl = getClassLoader0();
- if (which != Member.PUBLIC) {
- if (ccl != cl) {
- s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
- }
+ if (ccl != cl) {
+ sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
}
- this.checkPackageAccess(ccl, checkProxyInterfaces);
}
+ this.checkPackageAccess(sm, ccl, checkProxyInterfaces);
}
/*
* Checks if a client loaded in ClassLoader ccl is allowed to access this
* class under the current package access policy. If access is denied,
* throw a SecurityException.
+ *
+ * NOTE: this method should only be called if a SecurityManager is active
*/
- private void checkPackageAccess(final ClassLoader ccl, boolean checkProxyInterfaces) {
- final SecurityManager s = System.getSecurityManager();
- if (s != null) {
- final ClassLoader cl = getClassLoader0();
+ private void checkPackageAccess(SecurityManager sm, final ClassLoader ccl,
+ boolean checkProxyInterfaces) {
+ final ClassLoader cl = getClassLoader0();
- if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
- String name = this.getName();
- int i = name.lastIndexOf('.');
- if (i != -1) {
- // skip the package access check on a proxy class in default proxy package
- String pkg = name.substring(0, i);
- if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) {
- s.checkPackageAccess(pkg);
- }
+ if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
+ String pkg = this.getPackageName();
+ if (pkg != null && !pkg.isEmpty()) {
+ // skip the package access check on a proxy class in default proxy package
+ if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) {
+ sm.checkPackageAccess(pkg);
}
}
- // check package access on the proxy interfaces
- if (checkProxyInterfaces && Proxy.isProxyClass(this)) {
- ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces());
- }
+ }
+ // check package access on the proxy interfaces
+ if (checkProxyInterfaces && Proxy.isProxyClass(this)) {
+ ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces());
}
}
@@ -2755,11 +2786,9 @@ public final class Class implements java.io.Serializable,
while (c.isArray()) {
c = c.getComponentType();
}
- String baseName = c.getName();
- int index = baseName.lastIndexOf('.');
- if (index != -1) {
- name = baseName.substring(0, index).replace('.', '/')
- +"/"+name;
+ String baseName = c.getPackageName();
+ if (baseName != null && !baseName.isEmpty()) {
+ name = baseName.replace('.', '/') + "/" + name;
}
} else {
name = name.substring(1);
@@ -3233,7 +3262,7 @@ public final class Class implements java.io.Serializable,
return constructor;
}
}
- throw new NoSuchMethodException(getName() + "." + argumentTypesToString(parameterTypes));
+ throw new NoSuchMethodException(methodToString("", parameterTypes));
}
//
@@ -3294,8 +3323,11 @@ public final class Class implements java.io.Serializable,
private native Constructor[] getDeclaredConstructors0(boolean publicOnly);
private native Class>[] getDeclaredClasses0();
- private static String argumentTypesToString(Class>[] argTypes) {
- StringJoiner sj = new StringJoiner(", ", "(", ")");
+ /**
+ * Helper method to get the method name from arguments.
+ */
+ private String methodToString(String name, Class>[] argTypes) {
+ StringJoiner sj = new StringJoiner(", ", getName() + "." + name + "(", ")");
if (argTypes != null) {
for (int i = 0; i < argTypes.length; i++) {
Class> c = argTypes[i];
diff --git a/jdk/src/java.base/share/classes/java/lang/SecurityManager.java b/jdk/src/java.base/share/classes/java/lang/SecurityManager.java
index f004feea821..8a819ee6db7 100644
--- a/jdk/src/java.base/share/classes/java/lang/SecurityManager.java
+++ b/jdk/src/java.base/share/classes/java/lang/SecurityManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,18 +25,30 @@
package java.lang;
-import java.security.*;
+import java.lang.RuntimePermission;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Member;
+import java.lang.reflect.Module;
import java.io.FileDescriptor;
import java.io.File;
import java.io.FilePermission;
-import java.util.PropertyPermission;
-import java.lang.RuntimePermission;
-import java.net.SocketPermission;
-import java.net.NetPermission;
-import java.util.Hashtable;
import java.net.InetAddress;
-import java.lang.reflect.*;
-import java.net.URL;
+import java.net.SocketPermission;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PrivilegedAction;
+import java.security.Security;
+import java.security.SecurityPermission;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.PropertyPermission;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import jdk.internal.reflect.CallerSensitive;
import sun.security.util.SecurityConstants;
@@ -1415,46 +1427,108 @@ class SecurityManager {
}
}
- if (packages == null)
+ if (packages == null) {
packages = new String[0];
+ }
return packages;
}
+ // The non-exported packages of the modules in the boot layer that are
+ // loaded by the platform class loader or its ancestors. A non-exported
+ // package is a package that either is not exported at all by its containing
+ // module or is exported in a qualified fashion by its containing module.
+ private static final Set nonExportedPkgs;
+
+ static {
+ // Get the modules in the boot layer
+ Stream bootLayerModules = Layer.boot().modules().stream();
+
+ // Filter out the modules loaded by the boot or platform loader
+ PrivilegedAction> pa = () ->
+ bootLayerModules.filter(SecurityManager::isBootOrPlatformModule)
+ .collect(Collectors.toSet());
+ Set modules = AccessController.doPrivileged(pa);
+
+ // Filter out the non-exported packages
+ nonExportedPkgs = modules.stream()
+ .map(Module::getDescriptor)
+ .map(SecurityManager::nonExportedPkgs)
+ .flatMap(Set::stream)
+ .collect(Collectors.toSet());
+ }
+
/**
- * Throws a SecurityException if the
- * calling thread is not allowed to access the package specified by
- * the argument.
+ * Returns true if the module's loader is the boot or platform loader.
+ */
+ private static boolean isBootOrPlatformModule(Module m) {
+ return m.getClassLoader() == null ||
+ m.getClassLoader() == ClassLoader.getPlatformClassLoader();
+ }
+
+ /**
+ * Returns the non-exported packages of the specified module.
+ */
+ private static Set nonExportedPkgs(ModuleDescriptor md) {
+ // start with all packages in the module
+ Set pkgs = new HashSet<>(md.packages());
+
+ // remove the non-qualified exported packages
+ md.exports().stream()
+ .filter(p -> !p.isQualified())
+ .map(Exports::source)
+ .forEach(pkgs::remove);
+
+ // remove the non-qualified open packages
+ md.opens().stream()
+ .filter(p -> !p.isQualified())
+ .map(Opens::source)
+ .forEach(pkgs::remove);
+
+ return pkgs;
+ }
+
+ /**
+ * Throws a {@code SecurityException} if the calling thread is not allowed
+ * to access the specified package.
*
- * This method is used by the loadClass method of class
- * loaders.
+ * This method is called by the {@code loadClass} method of class loaders.
*
- * This method first gets a list of
- * restricted packages by obtaining a comma-separated list from
- * a call to
- * java.security.Security.getProperty("package.access"),
- * and checks to see if pkg starts with or equals
- * any of the restricted packages. If it does, then
- * checkPermission gets called with the
- * RuntimePermission("accessClassInPackage."+pkg)
- * permission.
+ * This method checks if the specified package starts with or equals
+ * any of the packages in the {@code package.access} Security Property.
+ * An implementation may also check the package against an additional
+ * list of restricted packages as noted below. If the package is restricted,
+ * {@link #checkPermission(Permission)} is called with a
+ * {@code RuntimePermission("accessClassInPackage."+pkg)} permission.
*
- * If this method is overridden, then
- * super.checkPackageAccess should be called
- * as the first line in the overridden method.
+ * If this method is overridden, then {@code super.checkPackageAccess}
+ * should be called as the first line in the overridden method.
+ *
+ * @implNote
+ * This implementation also restricts all non-exported packages of modules
+ * loaded by {@linkplain ClassLoader#getPlatformClassLoader
+ * the platform class loader} or its ancestors. A "non-exported package"
+ * refers to a package that is not exported to all modules. Specifically,
+ * it refers to a package that either is not exported at all by its
+ * containing module or is exported in a qualified fashion by its
+ * containing module.
*
* @param pkg the package name.
- * @exception SecurityException if the calling thread does not have
+ * @throws SecurityException if the calling thread does not have
* permission to access the specified package.
- * @exception NullPointerException if the package name argument is
- * null.
- * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
- * loadClass
+ * @throws NullPointerException if the package name argument is
+ * {@code null}.
+ * @see java.lang.ClassLoader#loadClass(String, boolean) loadClass
* @see java.security.Security#getProperty getProperty
- * @see #checkPermission(java.security.Permission) checkPermission
+ * @see #checkPermission(Permission) checkPermission
*/
public void checkPackageAccess(String pkg) {
- if (pkg == null) {
- throw new NullPointerException("package name can't be null");
+ Objects.requireNonNull(pkg, "package name can't be null");
+
+ // check if pkg is not exported to all modules
+ if (nonExportedPkgs.contains(pkg)) {
+ checkPermission(
+ new RuntimePermission("accessClassInPackage." + pkg));
+ return;
}
String[] restrictedPkgs;
@@ -1512,36 +1586,48 @@ class SecurityManager {
}
/**
- * Throws a SecurityException if the
- * calling thread is not allowed to define classes in the package
- * specified by the argument.
+ * Throws a {@code SecurityException} if the calling thread is not
+ * allowed to define classes in the specified package.
*
- * This method is used by the loadClass method of some
+ * This method is called by the {@code loadClass} method of some
* class loaders.
*
- * This method first gets a list of restricted packages by
- * obtaining a comma-separated list from a call to
- * java.security.Security.getProperty("package.definition"),
- * and checks to see if pkg starts with or equals
- * any of the restricted packages. If it does, then
- * checkPermission gets called with the
- * RuntimePermission("defineClassInPackage."+pkg)
- * permission.
+ * This method checks if the specified package starts with or equals
+ * any of the packages in the {@code package.definition} Security
+ * Property. An implementation may also check the package against an
+ * additional list of restricted packages as noted below. If the package
+ * is restricted, {@link #checkPermission(Permission)} is called with a
+ * {@code RuntimePermission("defineClassInPackage."+pkg)} permission.
*
- * If this method is overridden, then
- * super.checkPackageDefinition should be called
- * as the first line in the overridden method.
+ * If this method is overridden, then {@code super.checkPackageDefinition}
+ * should be called as the first line in the overridden method.
+ *
+ * @implNote
+ * This implementation also restricts all non-exported packages of modules
+ * loaded by {@linkplain ClassLoader#getPlatformClassLoader
+ * the platform class loader} or its ancestors. A "non-exported package"
+ * refers to a package that is not exported to all modules. Specifically,
+ * it refers to a package that either is not exported at all by its
+ * containing module or is exported in a qualified fashion by its
+ * containing module.
*
* @param pkg the package name.
- * @exception SecurityException if the calling thread does not have
+ * @throws SecurityException if the calling thread does not have
* permission to define classes in the specified package.
- * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
+ * @throws NullPointerException if the package name argument is
+ * {@code null}.
+ * @see java.lang.ClassLoader#loadClass(String, boolean)
* @see java.security.Security#getProperty getProperty
- * @see #checkPermission(java.security.Permission) checkPermission
+ * @see #checkPermission(Permission) checkPermission
*/
public void checkPackageDefinition(String pkg) {
- if (pkg == null) {
- throw new NullPointerException("package name can't be null");
+ Objects.requireNonNull(pkg, "package name can't be null");
+
+ // check if pkg is not exported to all modules
+ if (nonExportedPkgs.contains(pkg)) {
+ checkPermission(
+ new RuntimePermission("defineClassInPackage." + pkg));
+ return;
}
String[] pkgs;
diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java
index 18620771d20..1577e215e35 100644
--- a/jdk/src/java.base/share/classes/java/lang/System.java
+++ b/jdk/src/java.base/share/classes/java/lang/System.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -310,12 +310,13 @@ public final class System {
* @see SecurityManager#checkPermission
* @see java.lang.RuntimePermission
*/
- public static
- void setSecurityManager(final SecurityManager s) {
- try {
- s.checkPackageAccess("java.lang");
- } catch (Exception e) {
- // no-op
+ public static void setSecurityManager(final SecurityManager s) {
+ if (s != null) {
+ try {
+ s.checkPackageAccess("java.lang");
+ } catch (Exception e) {
+ // no-op
+ }
}
setSecurityManager0(s);
}
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java b/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java
index c24f94951f0..53899611f59 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java
@@ -28,6 +28,8 @@ package java.lang.invoke;
import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+import jdk.internal.vm.annotation.Stable;
+
/**
* A {@code CallSite} is a holder for a variable {@link MethodHandle},
* which is called its {@code target}.
@@ -215,19 +217,36 @@ public class CallSite {
public abstract MethodHandle dynamicInvoker();
/*non-public*/ MethodHandle makeDynamicInvoker() {
- MethodHandle getTarget = GET_TARGET.bindArgumentL(0, this);
+ MethodHandle getTarget = getTargetHandle().bindArgumentL(0, this);
MethodHandle invoker = MethodHandles.exactInvoker(this.type());
return MethodHandles.foldArguments(invoker, getTarget);
}
- private static final MethodHandle GET_TARGET;
- private static final MethodHandle THROW_UCS;
- static {
+ private static @Stable MethodHandle GET_TARGET;
+ private static MethodHandle getTargetHandle() {
+ MethodHandle handle = GET_TARGET;
+ if (handle != null) {
+ return handle;
+ }
try {
- GET_TARGET = IMPL_LOOKUP.
- findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
- THROW_UCS = IMPL_LOOKUP.
- findStatic(CallSite.class, "uninitializedCallSite", MethodType.methodType(Object.class, Object[].class));
+ return GET_TARGET = IMPL_LOOKUP.
+ findVirtual(CallSite.class, "getTarget",
+ MethodType.methodType(MethodHandle.class));
+ } catch (ReflectiveOperationException e) {
+ throw newInternalError(e);
+ }
+ }
+
+ private static @Stable MethodHandle THROW_UCS;
+ private static MethodHandle uninitializedCallSiteHandle() {
+ MethodHandle handle = THROW_UCS;
+ if (handle != null) {
+ return handle;
+ }
+ try {
+ return THROW_UCS = IMPL_LOOKUP.
+ findStatic(CallSite.class, "uninitializedCallSite",
+ MethodType.methodType(Object.class, Object[].class));
} catch (ReflectiveOperationException e) {
throw newInternalError(e);
}
@@ -242,7 +261,7 @@ public class CallSite {
MethodType basicType = targetType.basicType();
MethodHandle invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_UNINIT_CS);
if (invoker == null) {
- invoker = THROW_UCS.asType(basicType);
+ invoker = uninitializedCallSiteHandle().asType(basicType);
invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_UNINIT_CS, invoker);
}
// unchecked view is OK since no values will be received or returned
@@ -250,12 +269,16 @@ public class CallSite {
}
// unsafe stuff:
- private static final long TARGET_OFFSET;
- private static final long CONTEXT_OFFSET;
- static {
+ private static @Stable long TARGET_OFFSET;
+ private static long getTargetOffset() {
+ long offset = TARGET_OFFSET;
+ if (offset > 0) {
+ return offset;
+ }
try {
- TARGET_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("target"));
- CONTEXT_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("context"));
+ offset = TARGET_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("target"));
+ assert(offset > 0);
+ return offset;
} catch (Exception ex) { throw newInternalError(ex); }
}
@@ -265,7 +288,7 @@ public class CallSite {
}
/*package-private*/
MethodHandle getTargetVolatile() {
- return (MethodHandle) UNSAFE.getObjectVolatile(this, TARGET_OFFSET);
+ return (MethodHandle) UNSAFE.getObjectVolatile(this, getTargetOffset());
}
/*package-private*/
void setTargetVolatile(MethodHandle newTarget) {
@@ -324,7 +347,7 @@ public class CallSite {
final int NON_SPREAD_ARG_COUNT = 3; // (caller, name, type)
if (NON_SPREAD_ARG_COUNT + argv.length > MethodType.MAX_MH_ARITY)
throw new BootstrapMethodError("too many bootstrap method arguments");
- MethodType bsmType = bootstrapMethod.type();
+
MethodType invocationType = MethodType.genericMethodType(NON_SPREAD_ARG_COUNT + argv.length);
MethodHandle typedBSM = bootstrapMethod.asType(invocationType);
MethodHandle spreader = invocationType.invokers().spreadInvoker(NON_SPREAD_ARG_COUNT);
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index d195d3d3db8..16a9e8a941d 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -846,8 +846,11 @@ public class MethodHandles {
// that does not bluntly restrict classes under packages within
// java.base from looking up MethodHandles or VarHandles.
if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) {
- if ((name.startsWith("java.") && !name.startsWith("java.util.concurrent.")) ||
- (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) {
+ if ((name.startsWith("java.") &&
+ !name.equals("java.lang.Thread") &&
+ !name.startsWith("java.util.concurrent.")) ||
+ (name.startsWith("sun.") &&
+ !name.startsWith("sun.invoke."))) {
throw newIllegalArgumentException("illegal lookupClass: " + lookupClass);
}
}
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java
index ffb8a6a7859..53e88de34f2 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java
@@ -1128,7 +1128,7 @@ class MethodType implements java.io.Serializable {
public String toMethodDescriptorString() {
String desc = methodDescriptor;
if (desc == null) {
- desc = BytecodeDescriptor.unparse(this);
+ desc = BytecodeDescriptor.unparseMethod(this.rtype, this.ptypes);
methodDescriptor = desc;
}
return desc;
@@ -1256,7 +1256,7 @@ s.writeObject(this.parameterArray());
private final ReferenceQueue stale;
public ConcurrentWeakInternSet() {
- this.map = new ConcurrentHashMap<>();
+ this.map = new ConcurrentHashMap<>(512);
this.stale = new ReferenceQueue<>();
}
diff --git a/jdk/src/java.base/share/classes/java/net/SocketInputStream.java b/jdk/src/java.base/share/classes/java/net/SocketInputStream.java
index 2fb035ef7d8..2f54d344659 100644
--- a/jdk/src/java.base/share/classes/java/net/SocketInputStream.java
+++ b/jdk/src/java.base/share/classes/java/net/SocketInputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -155,11 +155,12 @@ class SocketInputStream extends FileInputStream
}
// bounds check
- if (length <= 0 || off < 0 || off + length > b.length) {
+ if (length <= 0 || off < 0 || length > b.length - off) {
if (length == 0) {
return 0;
}
- throw new ArrayIndexOutOfBoundsException();
+ throw new ArrayIndexOutOfBoundsException("length == " + length
+ + " off == " + off + " buffer length == " + b.length);
}
boolean gotReset = false;
diff --git a/jdk/src/java.base/share/classes/java/net/SocketOutputStream.java b/jdk/src/java.base/share/classes/java/net/SocketOutputStream.java
index 4aa1e53761b..9cbe056066f 100644
--- a/jdk/src/java.base/share/classes/java/net/SocketOutputStream.java
+++ b/jdk/src/java.base/share/classes/java/net/SocketOutputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -97,11 +97,13 @@ class SocketOutputStream extends FileOutputStream
*/
private void socketWrite(byte b[], int off, int len) throws IOException {
- if (len <= 0 || off < 0 || off + len > b.length) {
+
+ if (len <= 0 || off < 0 || len > b.length - off) {
if (len == 0) {
return;
}
- throw new ArrayIndexOutOfBoundsException();
+ throw new ArrayIndexOutOfBoundsException("len == " + len
+ + " off == " + off + " buffer length == " + b.length);
}
FileDescriptor fd = impl.acquireFD();
diff --git a/jdk/src/java.base/share/classes/java/net/URL.java b/jdk/src/java.base/share/classes/java/net/URL.java
index 145cf29d001..b029b83d7ca 100644
--- a/jdk/src/java.base/share/classes/java/net/URL.java
+++ b/jdk/src/java.base/share/classes/java/net/URL.java
@@ -1556,9 +1556,6 @@ public final class URL implements java.io.Serializable {
path = file;
}
- if (port == -1) {
- port = 0;
- }
// Set the object fields.
this.protocol = protocol;
this.host = host;
diff --git a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java
index 57f45027ea2..11077b4032a 100644
--- a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java
+++ b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java
@@ -115,8 +115,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
if (security != null) {
security.checkCreateClassLoader();
}
- this.ucp = new URLClassPath(urls);
this.acc = AccessController.getContext();
+ this.ucp = new URLClassPath(urls, acc);
}
URLClassLoader(String name, URL[] urls, ClassLoader parent,
@@ -127,8 +127,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
if (security != null) {
security.checkCreateClassLoader();
}
- this.ucp = new URLClassPath(urls);
this.acc = acc;
+ this.ucp = new URLClassPath(urls, acc);
}
/**
@@ -159,8 +159,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
if (security != null) {
security.checkCreateClassLoader();
}
- this.ucp = new URLClassPath(urls);
this.acc = AccessController.getContext();
+ this.ucp = new URLClassPath(urls, acc);
}
URLClassLoader(URL[] urls, AccessControlContext acc) {
@@ -170,8 +170,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
if (security != null) {
security.checkCreateClassLoader();
}
- this.ucp = new URLClassPath(urls);
this.acc = acc;
+ this.ucp = new URLClassPath(urls, acc);
}
/**
@@ -203,8 +203,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
if (security != null) {
security.checkCreateClassLoader();
}
- this.ucp = new URLClassPath(urls, factory);
this.acc = AccessController.getContext();
+ this.ucp = new URLClassPath(urls, factory, acc);
}
@@ -238,8 +238,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
if (security != null) {
security.checkCreateClassLoader();
}
- this.ucp = new URLClassPath(urls);
this.acc = AccessController.getContext();
+ this.ucp = new URLClassPath(urls, acc);
}
/**
@@ -271,8 +271,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
if (security != null) {
security.checkCreateClassLoader();
}
- this.ucp = new URLClassPath(urls, factory);
this.acc = AccessController.getContext();
+ this.ucp = new URLClassPath(urls, factory, acc);
}
/* A map (used as a set) to keep track of closeable local resources
diff --git a/jdk/src/java.base/share/classes/java/net/URLConnection.java b/jdk/src/java.base/share/classes/java/net/URLConnection.java
index 7a125faf145..e2ed0cfcbdd 100644
--- a/jdk/src/java.base/share/classes/java/net/URLConnection.java
+++ b/jdk/src/java.base/share/classes/java/net/URLConnection.java
@@ -30,8 +30,10 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.security.PrivilegedAction;
import java.util.Hashtable;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.Date;
import java.util.Iterator;
+import java.util.Locale;
import java.util.Objects;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
@@ -231,7 +233,7 @@ public abstract class URLConnection {
*/
protected boolean allowUserInteraction = defaultAllowUserInteraction;
- private static boolean defaultUseCaches = true;
+ private static volatile boolean defaultUseCaches = true;
/**
* If {@code true}, the protocol is allowed to use caching
@@ -243,12 +245,18 @@ public abstract class URLConnection {
*
* Its default value is the value given in the last invocation of the
* {@code setDefaultUseCaches} method.
+ *
+ * The default setting may be overridden per protocol with
+ * {@link #setDefaultUseCaches(String,boolean)}.
*
* @see java.net.URLConnection#setUseCaches(boolean)
* @see java.net.URLConnection#getUseCaches()
* @see java.net.URLConnection#setDefaultUseCaches(boolean)
*/
- protected boolean useCaches = defaultUseCaches;
+ protected boolean useCaches;
+
+ private static final ConcurrentHashMap defaultCaching =
+ new ConcurrentHashMap<>();
/**
* Some protocols support skipping the fetching of the object unless
@@ -460,6 +468,11 @@ public abstract class URLConnection {
*/
protected URLConnection(URL url) {
this.url = url;
+ if (url == null) {
+ this.useCaches = defaultUseCaches;
+ } else {
+ this.useCaches = getDefaultUseCaches(url.getProtocol());
+ }
}
/**
@@ -981,7 +994,8 @@ public abstract class URLConnection {
* is true, the connection is allowed to use whatever caches it can.
* If false, caches are to be ignored.
* The default value comes from DefaultUseCaches, which defaults to
- * true.
+ * true. A default value can also be set per-protocol using
+ * {@link #setDefaultUseCaches(String,boolean)}.
*
* @param usecaches a {@code boolean} indicating whether
* or not to allow caching
@@ -1032,9 +1046,10 @@ public abstract class URLConnection {
* Returns the default value of a {@code URLConnection}'s
* {@code useCaches} flag.
*
- * Ths default is "sticky", being a part of the static state of all
+ * This default is "sticky", being a part of the static state of all
* URLConnections. This flag applies to the next, and all following
- * URLConnections that are created.
+ * URLConnections that are created. This default value can be over-ridden
+ * per protocol using {@link #setDefaultUseCaches(String,boolean)}
*
* @return the default value of a {@code URLConnection}'s
* {@code useCaches} flag.
@@ -1046,7 +1061,8 @@ public abstract class URLConnection {
/**
* Sets the default value of the {@code useCaches} field to the
- * specified value.
+ * specified value. This default value can be over-ridden
+ * per protocol using {@link #setDefaultUseCaches(String,boolean)}
*
* @param defaultusecaches the new value.
* @see #getDefaultUseCaches()
@@ -1055,6 +1071,43 @@ public abstract class URLConnection {
defaultUseCaches = defaultusecaches;
}
+ /**
+ * Sets the default value of the {@code useCaches} field for the named
+ * protocol to the given value. This value overrides any default setting
+ * set by {@link #setDefaultUseCaches(boolean)} for the given protocol.
+ * Successive calls to this method change the setting and affect the
+ * default value for all future connections of that protocol. The protocol
+ * name is case insensitive.
+ *
+ * @param protocol the protocol to set the default for
+ * @param defaultVal whether caching is enabled by default for the given protocol
+ * @since 9
+ */
+ public static void setDefaultUseCaches(String protocol, boolean defaultVal) {
+ protocol = protocol.toLowerCase(Locale.US);
+ defaultCaching.put(protocol, defaultVal);
+ }
+
+ /**
+ * Returns the default value of the {@code useCaches} flag for the given protocol. If
+ * {@link #setDefaultUseCaches(String,boolean)} was called for the given protocol,
+ * then that value is returned. Otherwise, if {@link #setDefaultUseCaches(boolean)}
+ * was called, then that value is returned. If neither method was called,
+ * the return value is {@code true}. The protocol name is case insensitive.
+ *
+ * @param protocol the protocol whose defaultUseCaches setting is required
+ * @return the default value of the {@code useCaches} flag for the given protocol.
+ * @since 9
+ */
+ public static boolean getDefaultUseCaches(String protocol) {
+ Boolean protoDefault = defaultCaching.get(protocol.toLowerCase(Locale.US));
+ if (protoDefault != null) {
+ return protoDefault.booleanValue();
+ } else {
+ return defaultUseCaches;
+ }
+ }
+
/**
* Sets the general request property. If a property with the key already
* exists, overwrite its value with the new value.
diff --git a/jdk/src/java.base/share/classes/java/net/URLStreamHandler.java b/jdk/src/java.base/share/classes/java/net/URLStreamHandler.java
index 30c9791cd95..8ce586bdcaa 100644
--- a/jdk/src/java.base/share/classes/java/net/URLStreamHandler.java
+++ b/jdk/src/java.base/share/classes/java/net/URLStreamHandler.java
@@ -161,9 +161,9 @@ public abstract class URLStreamHandler {
(spec.charAt(start + 1) == '/')) {
start += 2;
i = spec.indexOf('/', start);
- if (i < 0) {
+ if (i < 0 || i > limit) {
i = spec.indexOf('?', start);
- if (i < 0)
+ if (i < 0 || i > limit)
i = limit;
}
@@ -171,8 +171,14 @@ public abstract class URLStreamHandler {
int ind = authority.indexOf('@');
if (ind != -1) {
- userInfo = authority.substring(0, ind);
- host = authority.substring(ind+1);
+ if (ind != authority.lastIndexOf('@')) {
+ // more than one '@' in authority. This is not server based
+ userInfo = null;
+ host = null;
+ } else {
+ userInfo = authority.substring(0, ind);
+ host = authority.substring(ind+1);
+ }
} else {
userInfo = null;
}
diff --git a/jdk/src/java.base/share/classes/java/util/Collections.java b/jdk/src/java.base/share/classes/java/util/Collections.java
index 7119fff3e89..22b4557ae2f 100644
--- a/jdk/src/java.base/share/classes/java/util/Collections.java
+++ b/jdk/src/java.base/share/classes/java/util/Collections.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -4354,6 +4354,11 @@ public class Collections {
private Object readResolve() {
return EMPTY_SET;
}
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
}
/**
@@ -4786,6 +4791,10 @@ public class Collections {
public boolean removeIf(Predicate super E> filter) {
throw new UnsupportedOperationException();
}
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(element);
+ }
}
/**
@@ -4848,6 +4857,10 @@ public class Collections {
public Spliterator spliterator() {
return singletonSpliterator(element);
}
+ @Override
+ public int hashCode() {
+ return 31 + Objects.hashCode(element);
+ }
}
/**
@@ -4970,6 +4983,11 @@ public class Collections {
BiFunction super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(k) ^ Objects.hashCode(v);
+ }
}
// Miscellaneous
diff --git a/jdk/src/java.base/share/classes/java/util/Date.java b/jdk/src/java.base/share/classes/java/util/Date.java
index bb9494766bd..312a74b6033 100644
--- a/jdk/src/java.base/share/classes/java/util/Date.java
+++ b/jdk/src/java.base/share/classes/java/util/Date.java
@@ -82,17 +82,19 @@ import sun.util.calendar.ZoneInfo;
* well; for example, the time scale used by the satellite-based
* global positioning system (GPS) is synchronized to UTC but is
* not adjusted for leap seconds. An interesting source of
- * further information is the U.S. Naval Observatory, particularly
- * the Directorate of Time at:
+ * further information is the United States Naval Observatory (USNO):
*
- * http://www.usno.navy.mil
+ * http://www.usno.navy.mil/USNO
*
*
- * and their definitions of "Systems of Time" at:
+ * and the material regarding "Systems of Time" at:
*
* http://www.usno.navy.mil/USNO/time/master-clock/systems-of-time
*
*
+ * which has descriptions of various different time systems including
+ * UT, UT1, and UTC.
+ *
* In all methods of class {@code Date} that accept or return
* year, month, date, hours, minutes, and seconds values, the
* following representations are used:
diff --git a/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java b/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java
index 26a03e0dae6..2bc0cc1b5d9 100644
--- a/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java
+++ b/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@ import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
+import jdk.internal.vm.annotation.Stable;
/**
* Container class for immutable collections. Not part of the public API.
@@ -105,6 +106,11 @@ class ImmutableCollections {
return null; // but the compiler doesn't know this
}
+ @Override
+ public Iterator iterator() {
+ return Collections.emptyIterator();
+ }
+
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
@@ -112,9 +118,26 @@ class ImmutableCollections {
private Object writeReplace() {
return new CollSer(CollSer.IMM_LIST);
}
+
+ @Override
+ public boolean contains(Object o) {
+ Objects.requireNonNull(o);
+ return false;
+ }
+
+ @Override
+ public boolean containsAll(Collection> o) {
+ return o.isEmpty(); // implicit nullcheck of o
+ }
+
+ @Override
+ public int hashCode() {
+ return 1;
+ }
}
static final class List1 extends AbstractImmutableList {
+ @Stable
private final E e0;
List1(E e0) {
@@ -129,7 +152,6 @@ class ImmutableCollections {
@Override
public E get(int index) {
Objects.checkIndex(index, 1);
- // assert index == 0
return e0;
}
@@ -140,10 +162,22 @@ class ImmutableCollections {
private Object writeReplace() {
return new CollSer(CollSer.IMM_LIST, e0);
}
+
+ @Override
+ public boolean contains(Object o) {
+ return o.equals(e0); // implicit nullcheck of o
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 + e0.hashCode();
+ }
}
static final class List2 extends AbstractImmutableList {
+ @Stable
private final E e0;
+ @Stable
private final E e1;
List2(E e0, E e1) {
@@ -166,6 +200,17 @@ class ImmutableCollections {
}
}
+ @Override
+ public boolean contains(Object o) {
+ return o.equals(e0) || o.equals(e1); // implicit nullcheck of o
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 31 + e0.hashCode();
+ return 31 * hash + e1.hashCode();
+ }
+
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
@@ -176,6 +221,7 @@ class ImmutableCollections {
}
static final class ListN extends AbstractImmutableList {
+ @Stable
private final E[] elements;
@SafeVarargs
@@ -200,6 +246,25 @@ class ImmutableCollections {
return elements[index];
}
+ @Override
+ public boolean contains(Object o) {
+ for (E e : elements) {
+ if (o.equals(e)) { // implicit nullcheck of o
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 1;
+ for (E e : elements) {
+ hash = 31 * hash + e.hashCode();
+ }
+ return hash;
+ }
+
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
@@ -238,7 +303,13 @@ class ImmutableCollections {
@Override
public boolean contains(Object o) {
- return super.contains(Objects.requireNonNull(o));
+ Objects.requireNonNull(o);
+ return false;
+ }
+
+ @Override
+ public boolean containsAll(Collection> o) {
+ return o.isEmpty(); // implicit nullcheck of o
}
@Override
@@ -253,9 +324,15 @@ class ImmutableCollections {
private Object writeReplace() {
return new CollSer(CollSer.IMM_SET);
}
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
}
static final class Set1 extends AbstractImmutableSet {
+ @Stable
private final E e0;
Set1(E e0) {
@@ -269,7 +346,7 @@ class ImmutableCollections {
@Override
public boolean contains(Object o) {
- return super.contains(Objects.requireNonNull(o));
+ return o.equals(e0); // implicit nullcheck of o
}
@Override
@@ -284,17 +361,21 @@ class ImmutableCollections {
private Object writeReplace() {
return new CollSer(CollSer.IMM_SET, e0);
}
+
+ @Override
+ public int hashCode() {
+ return e0.hashCode();
+ }
}
static final class Set2 extends AbstractImmutableSet {
- private final E e0;
- private final E e1;
+ @Stable
+ final E e0;
+ @Stable
+ final E e1;
Set2(E e0, E e1) {
- Objects.requireNonNull(e0);
- Objects.requireNonNull(e1);
-
- if (e0.equals(e1)) {
+ if (e0.equals(Objects.requireNonNull(e1))) { // implicit nullcheck of e0
throw new IllegalArgumentException("duplicate element: " + e0);
}
@@ -314,7 +395,12 @@ class ImmutableCollections {
@Override
public boolean contains(Object o) {
- return super.contains(Objects.requireNonNull(o));
+ return o.equals(e0) || o.equals(e1); // implicit nullcheck of o
+ }
+
+ @Override
+ public int hashCode() {
+ return e0.hashCode() + e1.hashCode();
}
@Override
@@ -358,8 +444,10 @@ class ImmutableCollections {
* @param the element type
*/
static final class SetN extends AbstractImmutableSet {
- private final E[] elements;
- private final int size;
+ @Stable
+ final E[] elements;
+ @Stable
+ final int size;
@SafeVarargs
@SuppressWarnings("unchecked")
@@ -368,8 +456,8 @@ class ImmutableCollections {
elements = (E[])new Object[EXPAND_FACTOR * input.length];
for (int i = 0; i < input.length; i++) {
- E e = Objects.requireNonNull(input[i]);
- int idx = probe(e);
+ E e = input[i];
+ int idx = probe(e); // implicit nullcheck of e
if (idx >= 0) {
throw new IllegalArgumentException("duplicate element: " + e);
} else {
@@ -385,8 +473,7 @@ class ImmutableCollections {
@Override
public boolean contains(Object o) {
- Objects.requireNonNull(o);
- return probe(o) >= 0;
+ return probe(o) >= 0; // implicit nullcheck of o
}
@Override
@@ -414,8 +501,21 @@ class ImmutableCollections {
};
}
+ @Override
+ public int hashCode() {
+ int h = 0;
+ for (E e : elements) {
+ if (e != null) {
+ h += e.hashCode();
+ }
+ }
+ return h;
+ }
+
// returns index at which element is present; or if absent,
- // (-i - 1) where i is location where element should be inserted
+ // (-i - 1) where i is location where element should be inserted.
+ // Callers are relying on this method to perform an implicit nullcheck
+ // of pe
private int probe(Object pe) {
int idx = Math.floorMod(pe.hashCode() ^ SALT, elements.length);
while (true) {
@@ -481,12 +581,14 @@ class ImmutableCollections {
@Override
public boolean containsKey(Object o) {
- return super.containsKey(Objects.requireNonNull(o));
+ Objects.requireNonNull(o);
+ return false;
}
@Override
public boolean containsValue(Object o) {
- return super.containsValue(Objects.requireNonNull(o));
+ Objects.requireNonNull(o);
+ return false;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
@@ -496,10 +598,17 @@ class ImmutableCollections {
private Object writeReplace() {
return new CollSer(CollSer.IMM_MAP);
}
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
}
static final class Map1 extends AbstractImmutableMap {
+ @Stable
private final K k0;
+ @Stable
private final V v0;
Map1(K k0, V v0) {
@@ -514,12 +623,12 @@ class ImmutableCollections {
@Override
public boolean containsKey(Object o) {
- return super.containsKey(Objects.requireNonNull(o));
+ return o.equals(k0); // implicit nullcheck of o
}
@Override
public boolean containsValue(Object o) {
- return super.containsValue(Objects.requireNonNull(o));
+ return o.equals(v0); // implicit nullcheck of o
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
@@ -529,6 +638,11 @@ class ImmutableCollections {
private Object writeReplace() {
return new CollSer(CollSer.IMM_MAP, k0, v0);
}
+
+ @Override
+ public int hashCode() {
+ return k0.hashCode() ^ v0.hashCode();
+ }
}
/**
@@ -541,12 +655,13 @@ class ImmutableCollections {
* @param the value type
*/
static final class MapN extends AbstractImmutableMap {
- private final Object[] table; // pairs of key, value
- private final int size; // number of pairs
+ @Stable
+ final Object[] table; // pairs of key, value
+ @Stable
+ final int size; // number of pairs
MapN(Object... input) {
- Objects.requireNonNull(input);
- if ((input.length & 1) != 0) {
+ if ((input.length & 1) != 0) { // implicit nullcheck of input
throw new InternalError("length is odd");
}
size = input.length >> 1;
@@ -573,12 +688,30 @@ class ImmutableCollections {
@Override
public boolean containsKey(Object o) {
- return probe(Objects.requireNonNull(o)) >= 0;
+ return probe(o) >= 0; // implicit nullcheck of o
}
@Override
public boolean containsValue(Object o) {
- return super.containsValue(Objects.requireNonNull(o));
+ for (int i = 1; i < table.length; i += 2) {
+ Object v = table[i];
+ if (v != null && o.equals(v)) { // implicit nullcheck of o
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 0;
+ for (int i = 0; i < table.length; i += 2) {
+ Object k = table[i];
+ if (k != null) {
+ hash += k.hashCode() ^ table[i + 1].hashCode();
+ }
+ }
+ return hash;
}
@Override
@@ -638,7 +771,9 @@ class ImmutableCollections {
}
// returns index at which the probe key is present; or if absent,
- // (-i - 1) where i is location where element should be inserted
+ // (-i - 1) where i is location where element should be inserted.
+ // Callers are relying on this method to perform an implicit nullcheck
+ // of pk.
private int probe(Object pk) {
int idx = Math.floorMod(pk.hashCode() ^ SALT, table.length >> 1) << 1;
while (true) {
diff --git a/jdk/src/java.base/share/classes/java/util/KeyValueHolder.java b/jdk/src/java.base/share/classes/java/util/KeyValueHolder.java
index 96ca0753ac6..3b7250ee6aa 100644
--- a/jdk/src/java.base/share/classes/java/util/KeyValueHolder.java
+++ b/jdk/src/java.base/share/classes/java/util/KeyValueHolder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
package java.util;
+import jdk.internal.vm.annotation.Stable;
+
/**
* An immutable container for a key and a value, suitable for use
* in creating and populating {@code Map} instances.
@@ -48,7 +50,9 @@ package java.util;
* @since 9
*/
final class KeyValueHolder implements Map.Entry {
+ @Stable
final K key;
+ @Stable
final V value;
KeyValueHolder(K k, V v) {
diff --git a/jdk/src/java.base/share/classes/java/util/List.java b/jdk/src/java.base/share/classes/java/util/List.java
index 0f14c298805..dda514b313f 100644
--- a/jdk/src/java.base/share/classes/java/util/List.java
+++ b/jdk/src/java.base/share/classes/java/util/List.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1027,8 +1027,7 @@ public interface List extends Collection {
@SafeVarargs
@SuppressWarnings("varargs")
static List of(E... elements) {
- Objects.requireNonNull(elements);
- switch (elements.length) {
+ switch (elements.length) { // implicit null check of elements
case 0:
return ImmutableCollections.List0.instance();
case 1:
diff --git a/jdk/src/java.base/share/classes/java/util/Map.java b/jdk/src/java.base/share/classes/java/util/Map.java
index b41e90dc866..153b86b8084 100644
--- a/jdk/src/java.base/share/classes/java/util/Map.java
+++ b/jdk/src/java.base/share/classes/java/util/Map.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1602,8 +1602,7 @@ public interface Map {
@SafeVarargs
@SuppressWarnings("varargs")
static Map ofEntries(Entry extends K, ? extends V>... entries) {
- Objects.requireNonNull(entries);
- if (entries.length == 0) {
+ if (entries.length == 0) { // implicit null check of entries
return ImmutableCollections.Map0.instance();
} else if (entries.length == 1) {
return new ImmutableCollections.Map1<>(entries[0].getKey(),
diff --git a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java b/jdk/src/java.base/share/classes/java/util/ResourceBundle.java
index 109ca64a42e..d49ae25ee01 100644
--- a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java
+++ b/jdk/src/java.base/share/classes/java/util/ResourceBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,6 +43,7 @@ package java.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
+import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
@@ -365,7 +366,7 @@ public abstract class ResourceBundle {
@Override
public ResourceBundle getBundle(String baseName, Locale locale, Module module) {
// use the given module as the caller to bypass the access check
- return getBundleImpl(module, module, getLoader(module),
+ return getBundleImpl(module, module,
baseName, locale, Control.INSTANCE);
}
@@ -537,63 +538,19 @@ public abstract class ResourceBundle {
return locale;
}
- /*
- * Automatic determination of the ClassLoader to be used to load
- * resources on behalf of the client.
- */
- private static ClassLoader getLoader(Class> caller) {
- ClassLoader cl = caller == null ? null : caller.getClassLoader();
- if (cl == null) {
- // When the caller's loader is the boot class loader, cl is null
- // here. In that case, ClassLoader.getSystemClassLoader() may
- // return the same class loader that the application is
- // using. We therefore use a wrapper ClassLoader to create a
- // separate scope for bundles loaded on behalf of the Java
- // runtime so that these bundles cannot be returned from the
- // cache to the application (5048280).
- cl = RBClassLoader.INSTANCE;
- }
- return cl;
- }
-
private static ClassLoader getLoader(Module module) {
PrivilegedAction pa = module::getClassLoader;
return AccessController.doPrivileged(pa);
}
/**
- * A wrapper of ClassLoader.getSystemClassLoader().
+ * @param module a non-null-screened module form the {@link CacheKey#getModule()}.
+ * @return the ClassLoader to use in {@link Control#needsReload}
+ * and {@link Control#newBundle}
*/
- private static class RBClassLoader extends ClassLoader {
- private static final RBClassLoader INSTANCE = AccessController.doPrivileged(
- new PrivilegedAction() {
- public RBClassLoader run() {
- return new RBClassLoader();
- }
- });
- private RBClassLoader() {
- }
- public Class> loadClass(String name) throws ClassNotFoundException {
- ClassLoader loader = ClassLoader.getSystemClassLoader();
- if (loader != null) {
- return loader.loadClass(name);
- }
- return Class.forName(name);
- }
- public URL getResource(String name) {
- ClassLoader loader = ClassLoader.getSystemClassLoader();
- if (loader != null) {
- return loader.getResource(name);
- }
- return ClassLoader.getSystemResource(name);
- }
- public InputStream getResourceAsStream(String name) {
- ClassLoader loader = ClassLoader.getSystemClassLoader();
- if (loader != null) {
- return loader.getResourceAsStream(name);
- }
- return ClassLoader.getSystemResourceAsStream(name);
- }
+ private static ClassLoader getLoaderForControl(Module module) {
+ ClassLoader loader = getLoader(module);
+ return loader == null ? ClassLoader.getSystemClassLoader() : loader;
}
/**
@@ -610,23 +567,23 @@ public abstract class ResourceBundle {
/**
* Key used for cached resource bundles. The key checks the base
- * name, the locale, the class loader, and the caller module
+ * name, the locale, the bundle module, and the caller module
* to determine if the resource is a match to the requested one.
- * The loader may be null, but the base name, the locale and
- * module must have a non-null value.
+ * The base name, the locale and both modules must have a non-null value.
*/
- private static class CacheKey implements Cloneable {
+ private static final class CacheKey {
// These four are the actual keys for lookup in Map.
- private String name;
- private Locale locale;
- private KeyElementReference loaderRef;
- private KeyElementReference moduleRef;
- private KeyElementReference callerRef;
-
+ private final String name;
+ private volatile Locale locale;
+ private final KeyElementReference moduleRef;
+ private final KeyElementReference callerRef;
+ // this is the part of hashCode that pertains to module and callerModule
+ // which can be GCed..
+ private final int modulesHash;
// bundle format which is necessary for calling
// Control.needsReload().
- private String format;
+ private volatile String format;
// These time values are in CacheKey so that NONEXISTENT_BUNDLE
// doesn't need to be cloned for caching.
@@ -639,63 +596,55 @@ public abstract class ResourceBundle {
private volatile long expirationTime;
// Placeholder for an error report by a Throwable
- private Throwable cause;
-
- // Hash code value cache to avoid recalculating the hash code
- // of this instance.
- private int hashCodeCache;
+ private volatile Throwable cause;
// ResourceBundleProviders for loading ResourceBundles
- private ServiceLoader providers;
- private boolean providersChecked;
+ private volatile ServiceLoader providers;
+ private volatile boolean providersChecked;
// Boolean.TRUE if the factory method caller provides a ResourceBundleProvier.
- private Boolean callerHasProvider;
+ private volatile Boolean callerHasProvider;
- CacheKey(String baseName, Locale locale, ClassLoader loader, Module module, Module caller) {
+ CacheKey(String baseName, Locale locale, Module module, Module caller) {
Objects.requireNonNull(module);
+ Objects.requireNonNull(caller);
this.name = baseName;
this.locale = locale;
- if (loader == null) {
- this.loaderRef = null;
- } else {
- this.loaderRef = new KeyElementReference<>(loader, referenceQueue, this);
- }
this.moduleRef = new KeyElementReference<>(module, referenceQueue, this);
this.callerRef = new KeyElementReference<>(caller, referenceQueue, this);
+ this.modulesHash = module.hashCode() ^ caller.hashCode();
+ }
- calculateHashCode();
+ CacheKey(CacheKey src) {
+ // Create References to src's modules
+ this.moduleRef = new KeyElementReference<>(
+ Objects.requireNonNull(src.getModule()), referenceQueue, this);
+ this.callerRef = new KeyElementReference<>(
+ Objects.requireNonNull(src.getCallerModule()), referenceQueue, this);
+ // Copy fields from src. ResourceBundleProviders related fields
+ // and "cause" should not be copied.
+ this.name = src.name;
+ this.locale = src.locale;
+ this.modulesHash = src.modulesHash;
+ this.format = src.format;
+ this.loadTime = src.loadTime;
+ this.expirationTime = src.expirationTime;
}
String getName() {
return name;
}
- CacheKey setName(String baseName) {
- if (!this.name.equals(baseName)) {
- this.name = baseName;
- calculateHashCode();
- }
- return this;
- }
-
Locale getLocale() {
return locale;
}
CacheKey setLocale(Locale locale) {
- if (!this.locale.equals(locale)) {
- this.locale = locale;
- calculateHashCode();
- }
+ this.locale = locale;
return this;
}
- ClassLoader getLoader() {
- return (loaderRef != null) ? loaderRef.get() : null;
- }
-
Module getModule() {
return moduleRef.get();
}
@@ -728,7 +677,7 @@ public abstract class ResourceBundle {
try {
final CacheKey otherEntry = (CacheKey)other;
//quick check to see if they are not equal
- if (hashCodeCache != otherEntry.hashCodeCache) {
+ if (modulesHash != otherEntry.modulesHash) {
return false;
}
//are the names the same?
@@ -739,24 +688,11 @@ public abstract class ResourceBundle {
if (!locale.equals(otherEntry.locale)) {
return false;
}
- //are refs (both non-null) or (both null)?
- if (loaderRef == null) {
- return otherEntry.loaderRef == null;
- }
- ClassLoader loader = getLoader();
+ // are modules and callerModules the same and non-null?
Module module = getModule();
Module caller = getCallerModule();
-
- return (otherEntry.loaderRef != null)
- // with a null reference we can no longer find
- // out which class loader or module was referenced; so
- // treat it as unequal
- && (loader != null)
- && (loader == otherEntry.getLoader())
- && (module != null)
- && (module.equals(otherEntry.getModule()))
- && (caller != null)
- && (caller.equals(otherEntry.getCallerModule()));
+ return ((module != null) && (module.equals(otherEntry.getModule())) &&
+ (caller != null) && (caller.equals(otherEntry.getCallerModule())));
} catch (NullPointerException | ClassCastException e) {
}
return false;
@@ -764,51 +700,7 @@ public abstract class ResourceBundle {
@Override
public int hashCode() {
- return hashCodeCache;
- }
-
- private void calculateHashCode() {
- hashCodeCache = name.hashCode() << 3;
- hashCodeCache ^= locale.hashCode();
- ClassLoader loader = getLoader();
- if (loader != null) {
- hashCodeCache ^= loader.hashCode();
- }
- Module module = getModule();
- if (module != null) {
- hashCodeCache ^= module.hashCode();
- }
- Module caller = getCallerModule();
- if (caller != null) {
- hashCodeCache ^= caller.hashCode();
- }
- }
-
- @Override
- public Object clone() {
- try {
- CacheKey clone = (CacheKey) super.clone();
- if (loaderRef != null) {
- clone.loaderRef = new KeyElementReference<>(getLoader(),
- referenceQueue, clone);
- }
- clone.moduleRef = new KeyElementReference<>(getModule(),
- referenceQueue, clone);
- clone.callerRef = new KeyElementReference<>(getCallerModule(),
- referenceQueue, clone);
-
- // Clear the reference to ResourceBundleProviders and the flag
- clone.providers = null;
- clone.providersChecked = false;
- // Clear the reference to a Throwable
- clone.cause = null;
- // Clear callerHasProvider
- clone.callerHasProvider = null;
- return clone;
- } catch (CloneNotSupportedException e) {
- //this should never happen
- throw new InternalError(e);
- }
+ return (name.hashCode() << 3) ^ locale.hashCode() ^ modulesHash;
}
String getFormat() {
@@ -845,8 +737,12 @@ public abstract class ResourceBundle {
l = "\"\"";
}
}
- return "CacheKey[" + name + ", lc=" + l + ", ldr=" + getLoader()
- + "(format=" + format + ")]";
+ return "CacheKey[" + name +
+ ", locale=" + l +
+ ", module=" + getModule() +
+ ", callerModule=" + getCallerModule() +
+ ", format=" + format +
+ "]";
}
}
@@ -1568,7 +1464,7 @@ public abstract class ResourceBundle {
Locale locale,
Class> caller,
Control control) {
- return getBundleImpl(baseName, locale, caller, getLoader(caller), control);
+ return getBundleImpl(baseName, locale, caller, caller.getClassLoader(), control);
}
/**
@@ -1587,26 +1483,25 @@ public abstract class ResourceBundle {
Class> caller,
ClassLoader loader,
Control control) {
- if (caller != null && caller.getModule().isNamed()) {
- Module module = caller.getModule();
- ClassLoader ml = getLoader(module);
- // get resource bundles for a named module only
- // if loader is the module's class loader
- if (loader == ml || (ml == null && loader == RBClassLoader.INSTANCE)) {
- return getBundleImpl(module, module, loader, baseName, locale, control);
- }
- }
- // find resource bundles from unnamed module
- Module unnamedModule = loader != null
- ? loader.getUnnamedModule()
- : ClassLoader.getSystemClassLoader().getUnnamedModule();
-
if (caller == null) {
throw new InternalError("null caller");
}
-
Module callerModule = caller.getModule();
- return getBundleImpl(callerModule, unnamedModule, loader, baseName, locale, control);
+
+ // get resource bundles for a named module only if loader is the module's class loader
+ if (callerModule.isNamed() && loader == getLoader(callerModule)) {
+ return getBundleImpl(callerModule, callerModule, baseName, locale, control);
+ }
+
+ // find resource bundles from unnamed module of given class loader
+ // Java agent can add to the bootclasspath e.g. via
+ // java.lang.instrument.Instrumentation and load classes in unnamed module.
+ // It may call RB::getBundle that will end up here with loader == null.
+ Module unnamedModule = loader != null
+ ? loader.getUnnamedModule()
+ : BootLoader.getUnnamedModule();
+
+ return getBundleImpl(callerModule, unnamedModule, baseName, locale, control);
}
private static ResourceBundle getBundleFromModule(Class> caller,
@@ -1622,12 +1517,11 @@ public abstract class ResourceBundle {
sm.checkPermission(GET_CLASSLOADER_PERMISSION);
}
}
- return getBundleImpl(callerModule, module, getLoader(module), baseName, locale, control);
+ return getBundleImpl(callerModule, module, baseName, locale, control);
}
private static ResourceBundle getBundleImpl(Module callerModule,
Module module,
- ClassLoader loader,
String baseName,
Locale locale,
Control control) {
@@ -1636,10 +1530,10 @@ public abstract class ResourceBundle {
}
// We create a CacheKey here for use by this call. The base name
- // loader, and module will never change during the bundle loading
+ // and modules will never change during the bundle loading
// process. We have to make sure that the locale is set before
// using it as a cache key.
- CacheKey cacheKey = new CacheKey(baseName, locale, loader, module, callerModule);
+ CacheKey cacheKey = new CacheKey(baseName, locale, module, callerModule);
ResourceBundle bundle = null;
// Quick lookup of the cache.
@@ -1708,6 +1602,11 @@ public abstract class ResourceBundle {
bundle = baseBundle;
}
+ // keep callerModule and module reachable for as long as we are operating
+ // with WeakReference(s) to them (in CacheKey)...
+ Reference.reachabilityFence(callerModule);
+ Reference.reachabilityFence(module);
+
return bundle;
}
@@ -1745,7 +1644,7 @@ public abstract class ResourceBundle {
}
// Before we do the real loading work, see whether we need to
- // do some housekeeping: If references to class loaders or
+ // do some housekeeping: If references to modules or
// resource bundles have been nulled out, remove all related
// information from the cache.
Object ref;
@@ -1781,31 +1680,24 @@ public abstract class ResourceBundle {
}
if (bundle != NONEXISTENT_BUNDLE) {
- CacheKey constKey = (CacheKey) cacheKey.clone();
trace("findBundle: %d %s %s formats: %s%n", index, candidateLocales, cacheKey, formats);
- try {
- if (module.isNamed()) {
- bundle = loadBundle(cacheKey, formats, control, module, callerModule);
- } else {
- bundle = loadBundle(cacheKey, formats, control, expiredBundle);
- }
- if (bundle != null) {
- if (bundle.parent == null) {
- bundle.setParent(parent);
- }
- bundle.locale = targetLocale;
- bundle = putBundleInCache(cacheKey, bundle, control);
- return bundle;
- }
-
- // Put NONEXISTENT_BUNDLE in the cache as a mark that there's no bundle
- // instance for the locale.
- putBundleInCache(cacheKey, NONEXISTENT_BUNDLE, control);
- } finally {
- if (constKey.getCause() instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- }
+ if (module.isNamed()) {
+ bundle = loadBundle(cacheKey, formats, control, module, callerModule);
+ } else {
+ bundle = loadBundle(cacheKey, formats, control, expiredBundle);
}
+ if (bundle != null) {
+ if (bundle.parent == null) {
+ bundle.setParent(parent);
+ }
+ bundle.locale = targetLocale;
+ bundle = putBundleInCache(cacheKey, bundle, control);
+ return bundle;
+ }
+
+ // Put NONEXISTENT_BUNDLE in the cache as a mark that there's no bundle
+ // instance for the locale.
+ putBundleInCache(cacheKey, NONEXISTENT_BUNDLE, control);
}
return parent;
}
@@ -1991,12 +1883,20 @@ public abstract class ResourceBundle {
// specified by the getFormats() value.
Locale targetLocale = cacheKey.getLocale();
+ Module module = cacheKey.getModule();
+ if (module == null) {
+ // should not happen
+ throw new InternalError(
+ "Module for cache key: " + cacheKey + " has been GCed.");
+ }
+ ClassLoader loader = getLoaderForControl(module);
+
ResourceBundle bundle = null;
for (String format : formats) {
try {
// ResourceBundle.Control.newBundle may be overridden
bundle = control.newBundle(cacheKey.getName(), targetLocale, format,
- cacheKey.getLoader(), reload);
+ loader, reload);
} catch (LinkageError | Exception error) {
// We need to handle the LinkageError case due to
// inconsistent case-sensitivity in ClassLoader.
@@ -2138,12 +2038,15 @@ public abstract class ResourceBundle {
if (!bundle.expired && expirationTime >= 0 &&
expirationTime <= System.currentTimeMillis()) {
try {
- bundle.expired = control.needsReload(key.getName(),
- key.getLocale(),
- key.getFormat(),
- key.getLoader(),
- bundle,
- key.loadTime);
+ Module module = cacheKey.getModule();
+ bundle.expired =
+ module == null || // already GCed
+ control.needsReload(key.getName(),
+ key.getLocale(),
+ key.getFormat(),
+ getLoaderForControl(module),
+ bundle,
+ key.loadTime);
} catch (Exception e) {
cacheKey.setCause(e);
}
@@ -2185,7 +2088,7 @@ public abstract class ResourceBundle {
Control control) {
setExpirationTime(cacheKey, control);
if (cacheKey.expirationTime != Control.TTL_DONT_CACHE) {
- CacheKey key = (CacheKey) cacheKey.clone();
+ CacheKey key = new CacheKey(cacheKey);
BundleReference bundleRef = new BundleReference(bundle, referenceQueue, key);
bundle.cacheKey = key;
@@ -2231,7 +2134,7 @@ public abstract class ResourceBundle {
/**
* Removes all resource bundles from the cache that have been loaded
- * by the caller's module using the caller's class loader.
+ * by the caller's module.
*
* @since 1.6
* @see ResourceBundle.Control#getTimeToLive(String,Locale)
@@ -2239,47 +2142,29 @@ public abstract class ResourceBundle {
@CallerSensitive
public static final void clearCache() {
Class> caller = Reflection.getCallerClass();
- clearCache(getLoader(caller), caller.getModule());
+ cacheList.keySet().removeIf(
+ key -> key.getCallerModule() == caller.getModule()
+ );
}
/**
* Removes all resource bundles from the cache that have been loaded
- * by the caller's module using the given class loader.
+ * by the given class loader.
*
* @param loader the class loader
* @exception NullPointerException if loader is null
* @since 1.6
* @see ResourceBundle.Control#getTimeToLive(String,Locale)
*/
- @CallerSensitive
public static final void clearCache(ClassLoader loader) {
Objects.requireNonNull(loader);
- clearCache(loader, Reflection.getCallerClass().getModule());
- }
-
- /**
- * Removes all resource bundles from the cache that have been loaded by the
- * given {@code module}.
- *
- * @param module the module
- * @throws NullPointerException
- * if {@code module} is {@code null}
- * @throws SecurityException
- * if the caller doesn't have the permission to
- * {@linkplain Module#getClassLoader() get the class loader}
- * of the given {@code module}
- * @since 9
- * @see ResourceBundle.Control#getTimeToLive(String,Locale)
- */
- public static final void clearCache(Module module) {
- clearCache(module.getClassLoader(), module);
- }
-
- private static void clearCache(ClassLoader loader, Module module) {
- Set set = cacheList.keySet();
- set.stream()
- .filter((key) -> (key.getLoader() == loader && key.getModule() == module))
- .forEach(set::remove);
+ cacheList.keySet().removeIf(
+ key -> {
+ Module m;
+ return (m = key.getModule()) != null &&
+ getLoader(m) == loader;
+ }
+ );
}
/**
diff --git a/jdk/src/java.base/share/classes/java/util/Set.java b/jdk/src/java.base/share/classes/java/util/Set.java
index 08ef3297161..2dd9060f7df 100644
--- a/jdk/src/java.base/share/classes/java/util/Set.java
+++ b/jdk/src/java.base/share/classes/java/util/Set.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -689,8 +689,7 @@ public interface Set extends Collection {
@SafeVarargs
@SuppressWarnings("varargs")
static Set of(E... elements) {
- Objects.requireNonNull(elements);
- switch (elements.length) {
+ switch (elements.length) { // implicit null check of elements
case 0:
return ImmutableCollections.Set0.instance();
case 1:
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
index 5e56fe1b05e..93bb08dd48f 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
@@ -185,7 +185,14 @@ public class ForkJoinWorkerThread extends Thread {
static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
/** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
private static final ThreadGroup innocuousThreadGroup =
- ThreadLocalRandom.createThreadGroup("InnocuousForkJoinWorkerThreadGroup");
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<>() {
+ public ThreadGroup run() {
+ ThreadGroup group = Thread.currentThread().getThreadGroup();
+ for (ThreadGroup p; (p = group.getParent()) != null; )
+ group = p;
+ return new ThreadGroup(group, "InnocuousForkJoinWorkerThreadGroup");
+ }});
/** An AccessControlContext supporting no privileges */
private static final AccessControlContext INNOCUOUS_ACC =
@@ -215,6 +222,5 @@ public class ForkJoinWorkerThread extends Thread {
public void setContextClassLoader(ClassLoader cl) {
throw new SecurityException("setContextClassLoader");
}
-
}
}
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java
index cb1b4f260f5..e76f2d10597 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java
@@ -985,34 +985,6 @@ public class ThreadLocalRandom extends Random {
U.putObjectRelease(thread, INHERITEDACCESSCONTROLCONTEXT, acc);
}
- /**
- * Returns a new group with the system ThreadGroup (the
- * topmost, parent-less group) as parent. Uses Unsafe to
- * traverse Thread.group and ThreadGroup.parent fields.
- */
- static final ThreadGroup createThreadGroup(String name) {
- if (name == null)
- throw new NullPointerException();
- try {
- long tg = U.objectFieldOffset
- (Thread.class.getDeclaredField("group"));
- long gp = U.objectFieldOffset
- (ThreadGroup.class.getDeclaredField("parent"));
- ThreadGroup group = (ThreadGroup)
- U.getObject(Thread.currentThread(), tg);
- while (group != null) {
- ThreadGroup parent = (ThreadGroup)U.getObject(group, gp);
- if (parent == null)
- return new ThreadGroup(group, name);
- group = parent;
- }
- } catch (ReflectiveOperationException e) {
- throw new Error(e);
- }
- // fall through if null as cannot-happen safeguard
- throw new Error("Cannot create ThreadGroup");
- }
-
// Serialization support
private static final long serialVersionUID = -5851777807851030925L;
@@ -1087,17 +1059,17 @@ public class ThreadLocalRandom extends Random {
static {
try {
SEED = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocalRandomSeed"));
+ (Thread.class.getDeclaredField("threadLocalRandomSeed"));
PROBE = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocalRandomProbe"));
+ (Thread.class.getDeclaredField("threadLocalRandomProbe"));
SECONDARY = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+ (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
THREADLOCALS = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocals"));
+ (Thread.class.getDeclaredField("threadLocals"));
INHERITABLETHREADLOCALS = U.objectFieldOffset
- (Thread.class.getDeclaredField("inheritableThreadLocals"));
+ (Thread.class.getDeclaredField("inheritableThreadLocals"));
INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
- (Thread.class.getDeclaredField("inheritedAccessControlContext"));
+ (Thread.class.getDeclaredField("inheritedAccessControlContext"));
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
@@ -1123,7 +1095,7 @@ public class ThreadLocalRandom extends Random {
// at end of to survive static initialization circularity
static {
if (java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction() {
+ new java.security.PrivilegedAction<>() {
public Boolean run() {
return Boolean.getBoolean("java.util.secureRandomSeed");
}})) {
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
index 55af35b0139..1de994f06ec 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -40,6 +40,7 @@ import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
import java.util.function.IntBinaryOperator;
import java.util.function.IntUnaryOperator;
import jdk.internal.misc.Unsafe;
@@ -411,7 +412,17 @@ public abstract class AtomicIntegerFieldUpdater {
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.offset = U.objectFieldOffset(field);
}
@@ -432,6 +443,15 @@ public abstract class AtomicIntegerFieldUpdater {
return false;
}
+ /**
+ * Returns true if the two classes have the same class loader and
+ * package qualifier
+ */
+ private static boolean isSamePackage(Class> class1, Class> class2) {
+ return class1.getClassLoader() == class2.getClassLoader()
+ && Objects.equals(class1.getPackageName(), class2.getPackageName());
+ }
+
/**
* Checks that target argument is instance of cclass. On
* failure, throws cause.
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
index ff444676685..bd60f0bdcbb 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -40,6 +40,7 @@ import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
import java.util.function.LongBinaryOperator;
import java.util.function.LongUnaryOperator;
import jdk.internal.misc.Unsafe;
@@ -409,7 +410,17 @@ public abstract class AtomicLongFieldUpdater {
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.offset = U.objectFieldOffset(field);
}
@@ -540,7 +551,17 @@ public abstract class AtomicLongFieldUpdater {
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.offset = U.objectFieldOffset(field);
}
@@ -621,4 +642,13 @@ public abstract class AtomicLongFieldUpdater {
} while (acl != null);
return false;
}
+
+ /**
+ * Returns true if the two classes have the same class loader and
+ * package qualifier
+ */
+ static boolean isSamePackage(Class> class1, Class> class2) {
+ return class1.getClassLoader() == class2.getClassLoader()
+ && Objects.equals(class1.getPackageName(), class2.getPackageName());
+ }
}
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
index 2b75d5654ae..56f6751b9f0 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -40,6 +40,7 @@ import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
import java.util.function.BinaryOperator;
import java.util.function.UnaryOperator;
import jdk.internal.misc.Unsafe;
@@ -351,7 +352,17 @@ public abstract class AtomicReferenceFieldUpdater {
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.vclass = vclass;
this.offset = U.objectFieldOffset(field);
@@ -373,6 +384,15 @@ public abstract class AtomicReferenceFieldUpdater {
return false;
}
+ /**
+ * Returns true if the two classes have the same class loader and
+ * package qualifier
+ */
+ private static boolean isSamePackage(Class> class1, Class> class2) {
+ return class1.getClassLoader() == class2.getClassLoader()
+ && Objects.equals(class1.getPackageName(), class2.getPackageName());
+ }
+
/**
* Checks that target argument is instance of cclass. On
* failure, throws cause.
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java
index a70094e3623..95030782a71 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java
@@ -41,7 +41,6 @@ import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.DoubleBinaryOperator;
import java.util.function.LongBinaryOperator;
-import jdk.internal.misc.Unsafe;
/**
* A package-local class holding common representation and mechanics
@@ -191,7 +190,7 @@ abstract class Striped64 extends Number {
* Duplicated from ThreadLocalRandom because of packaging restrictions.
*/
static final int getProbe() {
- return U.getInt(Thread.currentThread(), PROBE);
+ return (int) THREAD_PROBE.get(Thread.currentThread());
}
/**
@@ -203,7 +202,7 @@ abstract class Striped64 extends Number {
probe ^= probe << 13; // xorshift
probe ^= probe >>> 17;
probe ^= probe << 5;
- U.putInt(Thread.currentThread(), PROBE, probe);
+ THREAD_PROBE.set(Thread.currentThread(), probe);
return probe;
}
@@ -373,18 +372,28 @@ abstract class Striped64 extends Number {
}
}
- // Unsafe and VarHandle mechanics
- private static final Unsafe U = Unsafe.getUnsafe();
+ // VarHandle mechanics
private static final VarHandle BASE;
private static final VarHandle CELLSBUSY;
- private static final long PROBE;
+ private static final VarHandle THREAD_PROBE;
static {
try {
MethodHandles.Lookup l = MethodHandles.lookup();
- BASE = l.findVarHandle(Striped64.class, "base", long.class);
- CELLSBUSY = l.findVarHandle(Striped64.class, "cellsBusy", int.class);
- PROBE = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocalRandomProbe"));
+ BASE = l.findVarHandle(Striped64.class,
+ "base", long.class);
+ CELLSBUSY = l.findVarHandle(Striped64.class,
+ "cellsBusy", int.class);
+ l = java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<>() {
+ public MethodHandles.Lookup run() {
+ try {
+ return MethodHandles.privateLookupIn(Thread.class, MethodHandles.lookup());
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
+ }});
+ THREAD_PROBE = l.findVarHandle(Thread.class,
+ "threadLocalRandomProbe", int.class);
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java b/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java
index 7bf6e8a54cd..b1e40a338b9 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java
@@ -425,11 +425,11 @@ public class LockSupport {
static {
try {
PARKBLOCKER = U.objectFieldOffset
- (Thread.class.getDeclaredField("parkBlocker"));
+ (Thread.class.getDeclaredField("parkBlocker"));
SECONDARY = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+ (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
TID = U.objectFieldOffset
- (Thread.class.getDeclaredField("tid"));
+ (Thread.class.getDeclaredField("tid"));
} catch (ReflectiveOperationException e) {
throw new Error(e);
diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/HandshakeCompletedEvent.java b/jdk/src/java.base/share/classes/javax/net/ssl/HandshakeCompletedEvent.java
index 1317f0021f4..67e8d7548a7 100644
--- a/jdk/src/java.base/share/classes/javax/net/ssl/HandshakeCompletedEvent.java
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/HandshakeCompletedEvent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, 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
@@ -120,6 +120,9 @@ public class HandshakeCompletedEvent extends EventObject
* Note: This method can be used only when using certificate-based
* cipher suites; using it with non-certificate-based cipher suites,
* such as Kerberos, will throw an SSLPeerUnverifiedException.
+ *
+ * Note: The returned value may not be a valid certificate chain
+ * and should not be relied on for trust decisions.
*
* @return an ordered array of the peer certificates,
* with the peer's own certificate first followed by
@@ -140,6 +143,9 @@ public class HandshakeCompletedEvent extends EventObject
* Note: This method can be used only when using certificate-based
* cipher suites; using it with non-certificate-based cipher suites,
* such as Kerberos, will throw an SSLPeerUnverifiedException.
+ *
+ * Note: The returned value may not be a valid certificate chain
+ * and should not be relied on for trust decisions.
*
* Note: this method exists for compatibility with previous
* releases. New applications should use
diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/HttpsURLConnection.java b/jdk/src/java.base/share/classes/javax/net/ssl/HttpsURLConnection.java
index 7c775321640..7d93ef274c6 100644
--- a/jdk/src/java.base/share/classes/javax/net/ssl/HttpsURLConnection.java
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/HttpsURLConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, 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
@@ -104,6 +104,9 @@ class HttpsURLConnection extends HttpURLConnection
* Note: This method can be used only when using certificate-based
* cipher suites; using it with non-certificate-based cipher suites,
* such as Kerberos, will throw an SSLPeerUnverifiedException.
+ *
+ * Note: The returned value may not be a valid certificate chain
+ * and should not be relied on for trust decisions.
*
* @return an ordered array of server certificates,
* with the peer's own certificate first followed by
diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSession.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSession.java
index 2a04e159728..a355d187889 100644
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSession.java
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSession.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, 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
@@ -219,6 +219,9 @@ public interface SSLSession {
* Note: This method can be used only when using certificate-based
* cipher suites; using it with non-certificate-based cipher suites,
* such as Kerberos, will throw an SSLPeerUnverifiedException.
+ *
+ * Note: The returned value may not be a valid certificate chain
+ * and should not be relied on for trust decisions.
*
* @return an ordered array of peer certificates,
* with the peer's own certificate first followed by any
@@ -259,6 +262,9 @@ public interface SSLSession {
* Note: This method can be used only when using certificate-based
* cipher suites; using it with non-certificate-based cipher suites,
* such as Kerberos, will throw an SSLPeerUnverifiedException.
+ *
+ * Note: The returned value may not be a valid certificate chain
+ * and should not be relied on for trust decisions.
*
* Note: this method exists for compatibility with previous
* releases. New applications should use
diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java b/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java
index 695d8028068..d67c342fb0a 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java
@@ -38,6 +38,7 @@ import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
+import java.security.AccessControlContext;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.CodeSigner;
@@ -83,6 +84,7 @@ public class URLClassPath {
private static final String JAVA_VERSION;
private static final boolean DEBUG;
private static final boolean DISABLE_JAR_CHECKING;
+ private static final boolean DISABLE_ACC_CHECKING;
static {
Properties props = GetPropertyAction.privilegedGetProperties();
@@ -90,6 +92,9 @@ public class URLClassPath {
DEBUG = (props.getProperty("sun.misc.URLClassPath.debug") != null);
String p = props.getProperty("sun.misc.URLClassPath.disableJarChecking");
DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
+
+ p = props.getProperty("jdk.net.URLClassPath.disableRestrictedPermissions");
+ DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
}
/* The original search path of URLs. */
@@ -110,6 +115,11 @@ public class URLClassPath {
/* Whether this URLClassLoader has been closed yet */
private boolean closed = false;
+ /* The context to be used when loading classes and resources. If non-null
+ * this is the context that was captured during the creation of the
+ * URLClassLoader. null implies no additional security restrictions. */
+ private final AccessControlContext acc;
+
/**
* Creates a new URLClassPath for the given URLs. The URLs will be
* searched in the order specified for classes and resources. A URL
@@ -119,8 +129,12 @@ public class URLClassPath {
* @param urls the directory and JAR file URLs to search for classes
* and resources
* @param factory the URLStreamHandlerFactory to use when creating new URLs
+ * @param acc the context to be used when loading classes and resources, may
+ * be null
*/
- public URLClassPath(URL[] urls, URLStreamHandlerFactory factory) {
+ public URLClassPath(URL[] urls,
+ URLStreamHandlerFactory factory,
+ AccessControlContext acc) {
for (int i = 0; i < urls.length; i++) {
path.add(urls[i]);
}
@@ -128,10 +142,22 @@ public class URLClassPath {
if (factory != null) {
jarHandler = factory.createURLStreamHandler("jar");
}
+ if (DISABLE_ACC_CHECKING)
+ this.acc = null;
+ else
+ this.acc = acc;
}
+ /**
+ * Constructs a URLClassPath with no additional security restrictions.
+ * Used by code that implements the class path.
+ */
public URLClassPath(URL[] urls) {
- this(urls, null);
+ this(urls, null, null);
+ }
+
+ public URLClassPath(URL[] urls, AccessControlContext acc) {
+ this(urls, null, acc);
}
public synchronized List closeLoaders() {
@@ -356,6 +382,14 @@ public class URLClassPath {
} catch (IOException e) {
// Silently ignore for now...
continue;
+ } catch (SecurityException se) {
+ // Always silently ignore. The context, if there is one, that
+ // this URLClassPath was given during construction will never
+ // have permission to access the URL.
+ if (DEBUG) {
+ System.err.println("Failed to access " + url + ", " + se );
+ }
+ continue;
}
// Finally, add the Loader to the search path.
loaders.add(loader);
@@ -378,7 +412,7 @@ public class URLClassPath {
&& file != null && (file.indexOf("!/") == file.length() - 2)) {
// extract the nested URL
URL nestedUrl = new URL(file.substring(0, file.length() - 2));
- return new JarLoader(nestedUrl, jarHandler, lmap);
+ return new JarLoader(nestedUrl, jarHandler, lmap, acc);
} else if (file != null && file.endsWith("/")) {
if ("file".equals(protocol)) {
return new FileLoader(url);
@@ -386,10 +420,10 @@ public class URLClassPath {
return new Loader(url);
}
} else {
- return new JarLoader(url, jarHandler, lmap);
+ return new JarLoader(url, jarHandler, lmap, acc);
}
}
- });
+ }, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (IOException)pae.getException();
}
@@ -585,10 +619,11 @@ public class URLClassPath {
*/
static class JarLoader extends Loader {
private JarFile jar;
- private URL csu;
+ private final URL csu;
private JarIndex index;
private URLStreamHandler handler;
- private HashMap lmap;
+ private final HashMap lmap;
+ private final AccessControlContext acc;
private boolean closed = false;
private static final JavaUtilZipFileAccess zipAccess =
SharedSecrets.getJavaUtilZipFileAccess();
@@ -598,13 +633,15 @@ public class URLClassPath {
* a JAR file.
*/
JarLoader(URL url, URLStreamHandler jarHandler,
- HashMap loaderMap)
+ HashMap loaderMap,
+ AccessControlContext acc)
throws IOException
{
super(new URL("jar", "", -1, url + "!/", jarHandler));
csu = url;
handler = jarHandler;
lmap = loaderMap;
+ this.acc = acc;
ensureOpen();
}
@@ -663,8 +700,7 @@ public class URLClassPath {
}
return null;
}
- }
- );
+ }, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (IOException)pae.getException();
}
@@ -859,9 +895,9 @@ public class URLClassPath {
new PrivilegedExceptionAction<>() {
public JarLoader run() throws IOException {
return new JarLoader(url, handler,
- lmap);
+ lmap, acc);
}
- });
+ }, acc);
/* this newly opened jar file has its own index,
* merge it into the parent's index, taking into
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java
new file mode 100644
index 00000000000..d808fe1db48
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.internal.module;
+
+import java.io.PrintStream;
+import java.lang.module.Configuration;
+import java.lang.module.ResolvedModule;
+import java.net.URI;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayDeque;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import static java.util.stream.Collectors.*;
+
+/**
+ * A Builder to compute ModuleHashes from a given configuration
+ */
+public class ModuleHashesBuilder {
+ private final Configuration configuration;
+ private final Set hashModuleCandidates;
+
+ /**
+ * Constructs a ModuleHashesBuilder that finds the packaged modules
+ * from the location of ModuleReference found from the given Configuration.
+ *
+ * @param config Configuration for building module hashes
+ * @param modules the candidate modules to be hashed
+ */
+ public ModuleHashesBuilder(Configuration config, Set modules) {
+ this.configuration = config;
+ this.hashModuleCandidates = modules;
+ }
+
+ /**
+ * Returns a map of a module M to ModuleHashes for the modules
+ * that depend upon M directly or indirectly.
+ *
+ * The key for each entry in the returned map is a module M that has
+ * no outgoing edges to any of the candidate modules to be hashed
+ * i.e. M is a leaf node in a connected subgraph containing M and
+ * other candidate modules from the module graph filtering
+ * the outgoing edges from M to non-candidate modules.
+ */
+ public Map computeHashes(Set roots) {
+ // build a graph containing the the packaged modules and
+ // its transitive dependences matching --hash-modules
+ Graph.Builder builder = new Graph.Builder<>();
+ Deque deque = new ArrayDeque<>(configuration.modules());
+ Set visited = new HashSet<>();
+ while (!deque.isEmpty()) {
+ ResolvedModule rm = deque.pop();
+ if (!visited.contains(rm)) {
+ visited.add(rm);
+ builder.addNode(rm.name());
+ for (ResolvedModule dm : rm.reads()) {
+ if (!visited.contains(dm)) {
+ deque.push(dm);
+ }
+ builder.addEdge(rm.name(), dm.name());
+ }
+ }
+ }
+
+ // each node in a transposed graph is a matching packaged module
+ // in which the hash of the modules that depend upon it is recorded
+ Graph transposedGraph = builder.build().transpose();
+
+ // traverse the modules in topological order that will identify
+ // the modules to record the hashes - it is the first matching
+ // module and has not been hashed during the traversal.
+ Set mods = new HashSet<>();
+ Map hashes = new HashMap<>();
+ builder.build()
+ .orderedNodes()
+ .filter(mn -> roots.contains(mn) && !mods.contains(mn))
+ .forEach(mn -> {
+ // Compute hashes of the modules that depend on mn directly and
+ // indirectly excluding itself.
+ Set ns = transposedGraph.dfs(mn)
+ .stream()
+ .filter(n -> !n.equals(mn) && hashModuleCandidates.contains(n))
+ .collect(toSet());
+ mods.add(mn);
+ mods.addAll(ns);
+
+ if (!ns.isEmpty()) {
+ Map moduleToPath = ns.stream()
+ .collect(toMap(Function.identity(), this::moduleToPath));
+ hashes.put(mn, ModuleHashes.generate(moduleToPath, "SHA-256"));
+ }
+ });
+ return hashes;
+ }
+
+ private Path moduleToPath(String name) {
+ ResolvedModule rm = configuration.findModule(name).orElseThrow(
+ () -> new InternalError("Selected module " + name + " not on module path"));
+
+ URI uri = rm.reference().location().get();
+ Path path = Paths.get(uri);
+ String fn = path.getFileName().toString();
+ if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
+ throw new UnsupportedOperationException(path + " is not a modular JAR or jmod file");
+ }
+ return path;
+ }
+
+ /*
+ * Utilty class
+ */
+ static class Graph {
+ private final Set nodes;
+ private final Map> edges;
+
+ public Graph(Set nodes, Map> edges) {
+ this.nodes = Collections.unmodifiableSet(nodes);
+ this.edges = Collections.unmodifiableMap(edges);
+ }
+
+ public Set nodes() {
+ return nodes;
+ }
+
+ public Map> edges() {
+ return edges;
+ }
+
+ public Set adjacentNodes(T u) {
+ return edges.get(u);
+ }
+
+ public boolean contains(T u) {
+ return nodes.contains(u);
+ }
+
+ /**
+ * Returns nodes sorted in topological order.
+ */
+ public Stream orderedNodes() {
+ TopoSorter sorter = new TopoSorter<>(this);
+ return sorter.result.stream();
+ }
+
+ /**
+ * Traverse this graph and performs the given action in topological order
+ */
+ public void ordered(Consumer action) {
+ TopoSorter sorter = new TopoSorter<>(this);
+ sorter.ordered(action);
+ }
+
+ /**
+ * Traverses this graph and performs the given action in reverse topological order
+ */
+ public void reverse(Consumer action) {
+ TopoSorter sorter = new TopoSorter<>(this);
+ sorter.reverse(action);
+ }
+
+ /**
+ * Returns a transposed graph from this graph
+ */
+ public Graph transpose() {
+ Builder builder = new Builder<>();
+ nodes.stream().forEach(builder::addNode);
+ // reverse edges
+ edges.keySet().forEach(u -> {
+ edges.get(u).stream()
+ .forEach(v -> builder.addEdge(v, u));
+ });
+ return builder.build();
+ }
+
+ /**
+ * Returns all nodes reachable from the given root.
+ */
+ public Set dfs(T root) {
+ return dfs(Set.of(root));
+ }
+
+ /**
+ * Returns all nodes reachable from the given set of roots.
+ */
+ public Set dfs(Set roots) {
+ Deque deque = new LinkedList<>(roots);
+ Set visited = new HashSet<>();
+ while (!deque.isEmpty()) {
+ T u = deque.pop();
+ if (!visited.contains(u)) {
+ visited.add(u);
+ if (contains(u)) {
+ adjacentNodes(u).stream()
+ .filter(v -> !visited.contains(v))
+ .forEach(deque::push);
+ }
+ }
+ }
+ return visited;
+ }
+
+ public void printGraph(PrintStream out) {
+ out.println("graph for " + nodes);
+ nodes.stream()
+ .forEach(u -> adjacentNodes(u).stream()
+ .forEach(v -> out.format(" %s -> %s%n", u, v)));
+ }
+
+ static class Builder {
+ final Set nodes = new HashSet<>();
+ final Map> edges = new HashMap<>();
+
+ public void addNode(T node) {
+ if (nodes.contains(node)) {
+ return;
+ }
+ nodes.add(node);
+ edges.computeIfAbsent(node, _e -> new HashSet<>());
+ }
+
+ public void addEdge(T u, T v) {
+ addNode(u);
+ addNode(v);
+ edges.get(u).add(v);
+ }
+
+ public Graph build() {
+ return new Graph(nodes, edges);
+ }
+ }
+ }
+
+ /**
+ * Topological sort
+ */
+ private static class TopoSorter {
+ final Deque result = new LinkedList<>();
+ final Deque nodes;
+ final Graph graph;
+
+ TopoSorter(Graph graph) {
+ this.graph = graph;
+ this.nodes = new LinkedList<>(graph.nodes);
+ sort();
+ }
+
+ public void ordered(Consumer action) {
+ result.iterator().forEachRemaining(action);
+ }
+
+ public void reverse(Consumer action) {
+ result.descendingIterator().forEachRemaining(action);
+ }
+
+ private void sort() {
+ Deque visited = new LinkedList<>();
+ Deque done = new LinkedList<>();
+ T node;
+ while ((node = nodes.poll()) != null) {
+ if (!visited.contains(node)) {
+ visit(node, visited, done);
+ }
+ }
+ }
+
+ private void visit(T node, Deque visited, Deque done) {
+ if (visited.contains(node)) {
+ if (!done.contains(node)) {
+ throw new IllegalArgumentException("Cyclic detected: " +
+ node + " " + graph.edges().get(node));
+ }
+ return;
+ }
+ visited.add(node);
+ graph.edges().get(node).stream()
+ .forEach(x -> visit(x, visited, done));
+ done.add(node);
+ result.addLast(node);
+ }
+ }
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/util/jar/JarIndex.java b/jdk/src/java.base/share/classes/jdk/internal/util/jar/JarIndex.java
index 367ac31b07a..f0d14a886a5 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/util/jar/JarIndex.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/util/jar/JarIndex.java
@@ -29,6 +29,7 @@ import java.io.*;
import java.util.*;
import java.util.jar.*;
import java.util.zip.*;
+import static sun.security.action.GetPropertyAction.privilegedGetProperty;
/**
* This class is used to maintain mappings from packages, classes
@@ -72,7 +73,7 @@ public class JarIndex {
* be added to the index. Otherwise, just the directory names are added.
*/
private static final boolean metaInfFilenames =
- "true".equals(System.getProperty("sun.misc.JarIndex.metaInfFilenames"));
+ "true".equals(privilegedGetProperty("sun.misc.JarIndex.metaInfFilenames"));
/**
* Constructs a new, empty jar index.
diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java
index b0efb66a390..9d7ed9f2282 100644
--- a/jdk/src/java.base/share/classes/module-info.java
+++ b/jdk/src/java.base/share/classes/module-info.java
@@ -249,7 +249,6 @@ module java.base {
jdk.crypto.token;
exports sun.security.jca to
java.smartcardio,
- java.xml.crypto,
jdk.crypto.ec,
jdk.crypto.token,
jdk.naming.dns;
@@ -279,6 +278,7 @@ module java.base {
java.security.jgss,
java.security.sasl,
java.smartcardio,
+ java.xml.crypto,
jdk.crypto.ec,
jdk.crypto.token,
jdk.jartool,
@@ -290,6 +290,8 @@ module java.base {
jdk.crypto.token,
jdk.jartool,
jdk.security.auth;
+ exports sun.security.validator to
+ jdk.jartool;
exports sun.text.resources to
jdk.localedata;
exports sun.util.cldr to
@@ -308,7 +310,6 @@ module java.base {
// JDK-internal service types
uses jdk.internal.logger.DefaultLoggerFinder;
uses sun.security.ssl.ClientKeyExchangeService;
- uses sun.security.util.AuthResourcesProvider;
uses sun.text.spi.JavaTimeDateTimePatternProvider;
uses sun.util.spi.CalendarProvider;
uses sun.util.locale.provider.LocaleDataMetaInfo;
@@ -320,6 +321,4 @@ module java.base {
provides java.nio.file.spi.FileSystemProvider with
jdk.internal.jrtfs.JrtFileSystemProvider;
- provides sun.security.util.AuthResourcesProvider with
- sun.security.util.AuthResourcesProviderImpl;
}
diff --git a/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java b/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java
index c275b0b91a6..738abcb9426 100644
--- a/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java
+++ b/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java
@@ -96,7 +96,7 @@ public final class ReflectUtil {
final Class> declaringClass = m.getDeclaringClass();
- checkPackageAccess(declaringClass);
+ privateCheckPackageAccess(sm, declaringClass);
if (Modifier.isPublic(m.getModifiers()) &&
Modifier.isPublic(declaringClass.getModifiers()))
@@ -114,9 +114,27 @@ public final class ReflectUtil {
* also check the package access on the proxy interfaces.
*/
public static void checkPackageAccess(Class> clazz) {
- checkPackageAccess(clazz.getName());
+ SecurityManager s = System.getSecurityManager();
+ if (s != null) {
+ privateCheckPackageAccess(s, clazz);
+ }
+ }
+
+ /**
+ * NOTE: should only be called if a SecurityManager is installed
+ */
+ private static void privateCheckPackageAccess(SecurityManager s, Class> clazz) {
+ while (clazz.isArray()) {
+ clazz = clazz.getComponentType();
+ }
+
+ String pkg = clazz.getPackageName();
+ if (pkg != null && !pkg.isEmpty()) {
+ s.checkPackageAccess(pkg);
+ }
+
if (isNonPublicProxyClass(clazz)) {
- checkProxyPackageAccess(clazz);
+ privateCheckProxyPackageAccess(s, clazz);
}
}
@@ -195,15 +213,21 @@ public final class ReflectUtil {
public static void checkProxyPackageAccess(Class> clazz) {
SecurityManager s = System.getSecurityManager();
if (s != null) {
- // check proxy interfaces if the given class is a proxy class
- if (Proxy.isProxyClass(clazz)) {
- for (Class> intf : clazz.getInterfaces()) {
- checkPackageAccess(intf);
- }
- }
+ privateCheckProxyPackageAccess(s, clazz);
}
}
+ /**
+ * NOTE: should only be called if a SecurityManager is installed
+ */
+ private static void privateCheckProxyPackageAccess(SecurityManager s, Class> clazz) {
+ // check proxy interfaces if the given class is a proxy class
+ if (Proxy.isProxyClass(clazz)) {
+ for (Class> intf : clazz.getInterfaces()) {
+ privateCheckPackageAccess(s, intf);
+ }
+ }
+ }
/**
* Access check on the interfaces that a proxy class implements and throw
* {@code SecurityException} if it accesses a restricted package from
@@ -220,7 +244,7 @@ public final class ReflectUtil {
for (Class> intf : interfaces) {
ClassLoader cl = intf.getClassLoader();
if (needsPackageAccessCheck(ccl, cl)) {
- checkPackageAccess(intf);
+ privateCheckPackageAccess(sm, intf);
}
}
}
@@ -236,10 +260,11 @@ public final class ReflectUtil {
* package that bypasses checkPackageAccess.
*/
public static boolean isNonPublicProxyClass(Class> cls) {
- String name = cls.getName();
- int i = name.lastIndexOf('.');
- String pkg = (i != -1) ? name.substring(0, i) : "";
- return Proxy.isProxyClass(cls) && !pkg.startsWith(PROXY_PACKAGE);
+ if (!Proxy.isProxyClass(cls)) {
+ return false;
+ }
+ String pkg = cls.getPackageName();
+ return pkg == null || !pkg.startsWith(PROXY_PACKAGE);
}
/**
@@ -255,7 +280,7 @@ public final class ReflectUtil {
// check if it is a valid proxy instance
if (proxy == null || !Proxy.isProxyClass(proxy.getClass())) {
throw new IllegalArgumentException("Not a Proxy instance");
-}
+ }
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalArgumentException("Can't handle static method");
}
diff --git a/jdk/src/java.base/share/classes/sun/security/provider/ConfigFile.java b/jdk/src/java.base/share/classes/sun/security/provider/ConfigFile.java
index 25a975504d6..450a4292cff 100644
--- a/jdk/src/java.base/share/classes/sun/security/provider/ConfigFile.java
+++ b/jdk/src/java.base/share/classes/sun/security/provider/ConfigFile.java
@@ -331,9 +331,8 @@ public final class ConfigFile extends Configuration {
if (debugConfig != null) {
debugConfig.println(fnfe.toString());
}
- throw new IOException(ResourcesMgr.getString
- ("Configuration.Error.No.such.file.or.directory",
- "sun.security.util.AuthResources"));
+ throw new IOException(ResourcesMgr.getAuthResourceString
+ ("Configuration.Error.No.such.file.or.directory"));
}
}
@@ -661,8 +660,8 @@ public final class ConfigFile extends Configuration {
}
private IOException ioException(String resourceKey, Object... args) {
- MessageFormat form = new MessageFormat(ResourcesMgr.getString
- (resourceKey, "sun.security.util.AuthResources"));
+ MessageFormat form = new MessageFormat(
+ ResourcesMgr.getAuthResourceString(resourceKey));
return new IOException(form.format(args));
}
}
diff --git a/jdk/src/java.base/share/classes/sun/security/provider/DSA.java b/jdk/src/java.base/share/classes/sun/security/provider/DSA.java
index 554b0cc1cf7..5763e650284 100644
--- a/jdk/src/java.base/share/classes/sun/security/provider/DSA.java
+++ b/jdk/src/java.base/share/classes/sun/security/provider/DSA.java
@@ -322,19 +322,20 @@ abstract class DSA extends SignatureSpi {
} else {
// first decode the signature.
try {
- DerInputStream in = new DerInputStream(signature, offset,
- length);
+ // Enforce strict DER checking for signatures
+ DerInputStream in =
+ new DerInputStream(signature, offset, length, false);
DerValue[] values = in.getSequence(2);
+ // check number of components in the read sequence
+ // and trailing data
+ if ((values.length != 2) || (in.available() != 0)) {
+ throw new IOException("Invalid encoding for signature");
+ }
r = values[0].getBigInteger();
s = values[1].getBigInteger();
-
- // Check for trailing signature data
- if (in.available() != 0) {
- throw new IOException("Incorrect signature length");
- }
} catch (IOException e) {
- throw new SignatureException("invalid encoding for signature");
+ throw new SignatureException("Invalid encoding for signature", e);
}
}
@@ -427,13 +428,49 @@ abstract class DSA extends SignatureSpi {
return t5.mod(q);
}
- // NOTE: This following impl is defined in FIPS 186-4 AppendixB.2.1.
protected BigInteger generateK(BigInteger q) {
+ // Implementation defined in FIPS 186-4 AppendixB.2.1.
SecureRandom random = getSigningRandom();
byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8];
random.nextBytes(kValue);
- return new BigInteger(1, kValue).mod(q.subtract(BigInteger.ONE)).add(BigInteger.ONE);
+ BigInteger k = new BigInteger(1, kValue).mod(
+ q.subtract(BigInteger.ONE)).add(BigInteger.ONE);
+
+ // Using an equivalent exponent of fixed length (same as q or 1 bit
+ // less than q) to keep the kG timing relatively constant.
+ //
+ // Note that this is an extra step on top of the approach defined in
+ // FIPS 186-4 AppendixB.2.1 so as to make a fixed length K.
+ k = k.add(q).divide(BigInteger.TWO);
+
+ // An alternative implementation based on FIPS 186-4 AppendixB2.2
+ // with fixed-length K.
+ //
+ // Please keep it here as we may need to switch to it in the future.
+ //
+ // SecureRandom random = getSigningRandom();
+ // byte[] kValue = new byte[(q.bitLength() + 7)/8];
+ // BigInteger d = q.subtract(BigInteger.TWO);
+ // BigInteger k;
+ // do {
+ // random.nextBytes(kValue);
+ // BigInteger c = new BigInteger(1, kValue);
+ // if (c.compareTo(d) <= 0) {
+ // k = c.add(BigInteger.ONE);
+ // // Using an equivalent exponent of fixed length to keep
+ // // the g^k timing relatively constant.
+ // //
+ // // Note that this is an extra step on top of the approach
+ // // defined in FIPS 186-4 AppendixB.2.2 so as to make a
+ // // fixed length K.
+ // if (k.bitLength() >= q.bitLength()) {
+ // break;
+ // }
+ // }
+ // } while (true);
+
+ return k;
}
// Use the application-specified SecureRandom Object if provided.
diff --git a/jdk/src/java.base/share/classes/sun/security/provider/SubjectCodeSource.java b/jdk/src/java.base/share/classes/sun/security/provider/SubjectCodeSource.java
index a92ff27906a..26a3d4e3f89 100644
--- a/jdk/src/java.base/share/classes/sun/security/provider/SubjectCodeSource.java
+++ b/jdk/src/java.base/share/classes/sun/security/provider/SubjectCodeSource.java
@@ -34,6 +34,7 @@ import java.lang.reflect.Constructor;
import javax.security.auth.Subject;
import sun.security.provider.PolicyParser.PrincipalEntry;
+import sun.security.util.ResourcesMgr;
/**
* This SubjectCodeSource class contains
@@ -47,15 +48,6 @@ class SubjectCodeSource extends CodeSource implements java.io.Serializable {
private static final long serialVersionUID = 6039418085604715275L;
- private static final java.util.ResourceBundle rb =
- java.security.AccessController.doPrivileged
- (new java.security.PrivilegedAction() {
- public java.util.ResourceBundle run() {
- return (java.util.ResourceBundle.getBundle
- ("sun.security.util.AuthResources"));
- }
- });
-
private Subject subject;
private LinkedList principals;
private static final Class>[] PARAMS = { String.class };
@@ -391,7 +383,7 @@ class SubjectCodeSource extends CodeSource implements java.io.Serializable {
ListIterator li = principals.listIterator();
while (li.hasNext()) {
PrincipalEntry pppe = li.next();
- returnMe = returnMe + rb.getString("NEWLINE") +
+ returnMe = returnMe + ResourcesMgr.getAuthResourceString("NEWLINE") +
pppe.getPrincipalClass() + " " +
pppe.getPrincipalName();
}
diff --git a/jdk/src/java.base/share/classes/sun/security/rsa/RSASignature.java b/jdk/src/java.base/share/classes/sun/security/rsa/RSASignature.java
index 43e605a1457..a426f6cd374 100644
--- a/jdk/src/java.base/share/classes/sun/security/rsa/RSASignature.java
+++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSASignature.java
@@ -226,9 +226,10 @@ public abstract class RSASignature extends SignatureSpi {
* Decode the signature data. Verify that the object identifier matches
* and return the message digest.
*/
- public static byte[] decodeSignature(ObjectIdentifier oid, byte[] signature)
+ public static byte[] decodeSignature(ObjectIdentifier oid, byte[] sig)
throws IOException {
- DerInputStream in = new DerInputStream(signature);
+ // Enforce strict DER checking for signatures
+ DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
DerValue[] values = in.getSequence(2);
if ((values.length != 2) || (in.available() != 0)) {
throw new IOException("SEQUENCE length error");
diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java b/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java
index 1f155a6bf2a..b95de5ecde2 100644
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java
@@ -673,8 +673,11 @@ final class ClientHandshaker extends Handshaker {
} else {
// we wanted to resume, but the server refused
//
- // Invalidate the session in case of reusing next time.
- session.invalidate();
+ // Invalidate the session for initial handshake in case
+ // of reusing next time.
+ if (isInitialHandshake) {
+ session.invalidate();
+ }
session = null;
if (!enableNewSession) {
throw new SSLException("New session creation is disabled");
diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java b/jdk/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java
index 256720a7b93..b6ed37cc5a3 100644
--- a/jdk/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/X509KeyManagerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -818,6 +818,11 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
checker.init(false);
} catch (CertPathValidatorException cpve) {
// unlikely to happen
+ if (useDebug) {
+ debug.println(
+ "Cannot initialize algorithm constraints checker: " + cpve);
+ }
+
return false;
}
@@ -828,6 +833,11 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager
// We don't care about the unresolved critical extensions.
checker.check(cert, Collections.emptySet());
} catch (CertPathValidatorException cpve) {
+ if (useDebug) {
+ debug.println("Certificate (" + cert +
+ ") does not conform to algorithm constraints: " + cpve);
+ }
+
return false;
}
}
diff --git a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java
index 9730938c927..b73773f5711 100644
--- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java
+++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -3522,7 +3522,8 @@ public final class Main {
System.err.flush();
reply = (new BufferedReader(new InputStreamReader
(System.in))).readLine();
- if (collator.compare(reply, "") == 0 ||
+ if (reply == null ||
+ collator.compare(reply, "") == 0 ||
collator.compare(reply, rb.getString("n")) == 0 ||
collator.compare(reply, rb.getString("no")) == 0) {
reply = "NO";
diff --git a/jdk/src/java.base/share/classes/sun/security/util/AuthResourcesProvider.java b/jdk/src/java.base/share/classes/sun/security/util/AuthResourcesProvider.java
deleted file mode 100644
index 126286a6ff1..00000000000
--- a/jdk/src/java.base/share/classes/sun/security/util/AuthResourcesProvider.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.security.util;
-
-public interface AuthResourcesProvider extends java.util.spi.ResourceBundleProvider {
-}
diff --git a/jdk/src/java.base/share/classes/sun/security/util/AuthResourcesProviderImpl.java b/jdk/src/java.base/share/classes/sun/security/util/AuthResourcesProviderImpl.java
deleted file mode 100644
index 6572ad0113d..00000000000
--- a/jdk/src/java.base/share/classes/sun/security/util/AuthResourcesProviderImpl.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.security.util;
-
-import java.util.spi.AbstractResourceBundleProvider;
-
-public final class AuthResourcesProviderImpl extends AbstractResourceBundleProvider
- implements AuthResourcesProvider {
- public AuthResourcesProviderImpl() {
- super("java.class");
- }
-}
\ No newline at end of file
diff --git a/jdk/src/java.base/share/classes/sun/security/util/DerInputBuffer.java b/jdk/src/java.base/share/classes/sun/security/util/DerInputBuffer.java
index 26bd198741a..1e5600214bc 100644
--- a/jdk/src/java.base/share/classes/sun/security/util/DerInputBuffer.java
+++ b/jdk/src/java.base/share/classes/sun/security/util/DerInputBuffer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -147,6 +147,11 @@ class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
System.arraycopy(buf, pos, bytes, 0, len);
skip(len);
+ // check to make sure no extra leading 0s for DER
+ if (len >= 2 && (bytes[0] == 0) && (bytes[1] >= 0)) {
+ throw new IOException("Invalid encoding: redundant leading 0s");
+ }
+
if (makePositive) {
return new BigInteger(1, bytes);
} else {
diff --git a/jdk/src/java.base/share/classes/sun/security/util/DerInputStream.java b/jdk/src/java.base/share/classes/sun/security/util/DerInputStream.java
index 264bfd0e9c7..94c9085a7bc 100644
--- a/jdk/src/java.base/share/classes/sun/security/util/DerInputStream.java
+++ b/jdk/src/java.base/share/classes/sun/security/util/DerInputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -77,7 +77,7 @@ public class DerInputStream {
* @param data the buffer from which to create the string (CONSUMED)
*/
public DerInputStream(byte[] data) throws IOException {
- init(data, 0, data.length);
+ init(data, 0, data.length, true);
}
/**
@@ -92,23 +92,48 @@ public class DerInputStream {
* starting at "offset"
*/
public DerInputStream(byte[] data, int offset, int len) throws IOException {
- init(data, offset, len);
+ init(data, offset, len, true);
+ }
+
+ /**
+ * Create a DER input stream from part of a data buffer with
+ * additional arg to indicate whether to allow constructed
+ * indefinite-length encoding.
+ * The buffer is not copied, it is shared. Accordingly, the
+ * buffer should be treated as read-only.
+ *
+ * @param data the buffer from which to create the string (CONSUMED)
+ * @param offset the first index of data which will
+ * be read as DER input in the new stream
+ * @param len how long a chunk of the buffer to use,
+ * starting at "offset"
+ * @param allowIndefiniteLength whether to allow constructed
+ * indefinite-length encoding
+ */
+ public DerInputStream(byte[] data, int offset, int len,
+ boolean allowIndefiniteLength) throws IOException {
+ init(data, offset, len, allowIndefiniteLength);
}
/*
* private helper routine
*/
- private void init(byte[] data, int offset, int len) throws IOException {
+ private void init(byte[] data, int offset, int len,
+ boolean allowIndefiniteLength) throws IOException {
if ((offset+2 > data.length) || (offset+len > data.length)) {
throw new IOException("Encoding bytes too short");
}
// check for indefinite length encoding
if (DerIndefLenConverter.isIndefinite(data[offset+1])) {
- byte[] inData = new byte[len];
- System.arraycopy(data, offset, inData, 0, len);
+ if (!allowIndefiniteLength) {
+ throw new IOException("Indefinite length BER encoding found");
+ } else {
+ byte[] inData = new byte[len];
+ System.arraycopy(data, offset, inData, 0, len);
- DerIndefLenConverter derIn = new DerIndefLenConverter();
- buffer = new DerInputBuffer(derIn.convert(inData));
+ DerIndefLenConverter derIn = new DerIndefLenConverter();
+ buffer = new DerInputBuffer(derIn.convert(inData));
+ }
} else
buffer = new DerInputBuffer(data, offset, len);
buffer.mark(Integer.MAX_VALUE);
@@ -239,15 +264,19 @@ public class DerInputStream {
* representation.
*/
length--;
- int validBits = length*8 - buffer.read();
+ int excessBits = buffer.read();
+ if (excessBits < 0) {
+ throw new IOException("Unused bits of bit string invalid");
+ }
+ int validBits = length*8 - excessBits;
if (validBits < 0) {
- throw new IOException("valid bits of bit string invalid");
+ throw new IOException("Valid bits of bit string invalid");
}
byte[] repn = new byte[length];
if ((length != 0) && (buffer.read(repn) != length)) {
- throw new IOException("short read of DER bit string");
+ throw new IOException("Short read of DER bit string");
}
return new BitArray(validBits, repn);
@@ -263,7 +292,7 @@ public class DerInputStream {
int length = getDefiniteLength(buffer);
byte[] retval = new byte[length];
if ((length != 0) && (buffer.read(retval) != length))
- throw new IOException("short read of DER octet string");
+ throw new IOException("Short read of DER octet string");
return retval;
}
@@ -273,7 +302,7 @@ public class DerInputStream {
*/
public void getBytes(byte[] val) throws IOException {
if ((val.length != 0) && (buffer.read(val) != val.length)) {
- throw new IOException("short read of DER octet string");
+ throw new IOException("Short read of DER octet string");
}
}
@@ -357,7 +386,7 @@ public class DerInputStream {
DerInputStream newstr;
byte lenByte = (byte)buffer.read();
- int len = getLength((lenByte & 0xff), buffer);
+ int len = getLength(lenByte, buffer);
if (len == -1) {
// indefinite length encoding found
@@ -403,7 +432,7 @@ public class DerInputStream {
} while (newstr.available() > 0);
if (newstr.available() != 0)
- throw new IOException("extra data at end of vector");
+ throw new IOException("Extra data at end of vector");
/*
* Now stick them into the array we're returning.
@@ -494,7 +523,7 @@ public class DerInputStream {
int length = getDefiniteLength(buffer);
byte[] retval = new byte[length];
if ((length != 0) && (buffer.read(retval) != length))
- throw new IOException("short read of DER " +
+ throw new IOException("Short read of DER " +
stringName + " string");
return new String(retval, enc);
@@ -555,7 +584,11 @@ public class DerInputStream {
*/
static int getLength(int lenByte, InputStream in) throws IOException {
int value, tmp;
+ if (lenByte == -1) {
+ throw new IOException("Short read of DER length");
+ }
+ String mdName = "DerInputStream.getLength(): ";
tmp = lenByte;
if ((tmp & 0x080) == 0x00) { // short form, 1 byte datum
value = tmp;
@@ -569,17 +602,23 @@ public class DerInputStream {
if (tmp == 0)
return -1;
if (tmp < 0 || tmp > 4)
- throw new IOException("DerInputStream.getLength(): lengthTag="
- + tmp + ", "
+ throw new IOException(mdName + "lengthTag=" + tmp + ", "
+ ((tmp < 0) ? "incorrect DER encoding." : "too big."));
- for (value = 0; tmp > 0; tmp --) {
+ value = 0x0ff & in.read();
+ tmp--;
+ if (value == 0) {
+ // DER requires length value be encoded in minimum number of bytes
+ throw new IOException(mdName + "Redundant length bytes found");
+ }
+ while (tmp-- > 0) {
value <<= 8;
value += 0x0ff & in.read();
}
if (value < 0) {
- throw new IOException("DerInputStream.getLength(): "
- + "Invalid length bytes");
+ throw new IOException(mdName + "Invalid length bytes");
+ } else if (value <= 127) {
+ throw new IOException(mdName + "Should use short form for length");
}
}
return value;
diff --git a/jdk/src/java.base/share/classes/sun/security/util/DerValue.java b/jdk/src/java.base/share/classes/sun/security/util/DerValue.java
index 936e2ff70b7..b47064abce9 100644
--- a/jdk/src/java.base/share/classes/sun/security/util/DerValue.java
+++ b/jdk/src/java.base/share/classes/sun/security/util/DerValue.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -248,7 +248,7 @@ public class DerValue {
tag = (byte)in.read();
byte lenByte = (byte)in.read();
- length = DerInputStream.getLength((lenByte & 0xff), in);
+ length = DerInputStream.getLength(lenByte, in);
if (length == -1) { // indefinite length encoding found
DerInputBuffer inbuf = in.dup();
int readLen = inbuf.available();
@@ -361,7 +361,7 @@ public class DerValue {
tag = (byte)in.read();
byte lenByte = (byte)in.read();
- length = DerInputStream.getLength((lenByte & 0xff), in);
+ length = DerInputStream.getLength(lenByte, in);
if (length == -1) { // indefinite length encoding found
int readLen = in.available();
int offset = 2; // for tag and length bytes
diff --git a/jdk/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java b/jdk/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java
index 0e9bd41a71c..12aabe6f071 100644
--- a/jdk/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java
+++ b/jdk/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java
@@ -255,7 +255,13 @@ class ObjectIdentifier implements Serializable
+ " (tag = " + type_id + ")"
);
- encoding = new byte[in.getDefiniteLength()];
+ int len = in.getDefiniteLength();
+ if (len > in.available()) {
+ throw new IOException("ObjectIdentifier() -- length exceeds" +
+ "data available. Length: " + len + ", Available: " +
+ in.available());
+ }
+ encoding = new byte[len];
in.getBytes(encoding);
check(encoding);
}
diff --git a/jdk/src/java.base/share/classes/sun/security/util/ResourcesMgr.java b/jdk/src/java.base/share/classes/sun/security/util/ResourcesMgr.java
index 091f2ea8e13..725d21b6eb7 100644
--- a/jdk/src/java.base/share/classes/sun/security/util/ResourcesMgr.java
+++ b/jdk/src/java.base/share/classes/sun/security/util/ResourcesMgr.java
@@ -25,18 +25,22 @@
package sun.security.util;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.concurrent.ConcurrentHashMap;
+import jdk.internal.misc.VM;
+
/**
*/
public class ResourcesMgr {
-
// intended for java.security, javax.security and sun.security resources
- private static java.util.ResourceBundle bundle;
+ private final static String RESOURCES = "sun.security.util.Resources";
+ private final static String AUTH_RESOURCES = "sun.security.util.AuthResources";
- // intended for com.sun.security resources
- private static java.util.ResourceBundle altBundle;
+ private final static Map bundles = new ConcurrentHashMap<>();
public static String getString(String s) {
-
+ ResourceBundle bundle = bundles.get(RESOURCES);
if (bundle == null) {
// only load if/when needed
@@ -52,19 +56,15 @@ public class ResourcesMgr {
return bundle.getString(s);
}
- public static String getString(String s, final String altBundleName) {
-
- if (altBundle == null) {
-
- // only load if/when needed
- altBundle = java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction() {
- public java.util.ResourceBundle run() {
- return (java.util.ResourceBundle.getBundle(altBundleName));
- }
- });
+ public static String getAuthResourceString(String s) {
+ if (VM.initLevel() == 3) {
+ // cannot trigger loading of any resource bundle as
+ // it depends on the system class loader fully initialized.
+ throw new InternalError("system class loader is being initialized");
}
- return altBundle.getString(s);
+ return bundles.computeIfAbsent(AUTH_RESOURCES, ResourceBundle::getBundle)
+ .getString(s);
}
+
}
diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security
index fe45e0ba06c..5e778810bb7 100644
--- a/jdk/src/java.base/share/conf/security/java.security
+++ b/jdk/src/java.base/share/conf/security/java.security
@@ -298,111 +298,24 @@ keystore.type.compat=true
#
# List of comma-separated packages that start with or equal this string
-# will cause a security exception to be thrown when
-# passed to checkPackageAccess unless the
-# corresponding RuntimePermission ("accessClassInPackage."+package) has
-# been granted.
-package.access=sun.,\
- com.sun.xml.internal.,\
- com.sun.imageio.,\
- com.sun.istack.internal.,\
- com.sun.jmx.,\
- com.sun.media.sound.,\
- com.sun.naming.internal.,\
- com.sun.proxy.,\
- com.sun.corba.se.,\
- com.sun.org.apache.bcel.internal.,\
- com.sun.org.apache.regexp.internal.,\
- com.sun.org.apache.xerces.internal.,\
- com.sun.org.apache.xpath.internal.,\
- com.sun.org.apache.xalan.internal.extensions.,\
- com.sun.org.apache.xalan.internal.lib.,\
- com.sun.org.apache.xalan.internal.res.,\
- com.sun.org.apache.xalan.internal.templates.,\
- com.sun.org.apache.xalan.internal.utils.,\
- com.sun.org.apache.xalan.internal.xslt.,\
- com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
- com.sun.org.apache.xalan.internal.xsltc.compiler.,\
- com.sun.org.apache.xalan.internal.xsltc.trax.,\
- com.sun.org.apache.xalan.internal.xsltc.util.,\
- com.sun.org.apache.xml.internal.res.,\
- com.sun.org.apache.xml.internal.security.,\
- com.sun.org.apache.xml.internal.serializer.dom3.,\
- com.sun.org.apache.xml.internal.serializer.utils.,\
- com.sun.org.apache.xml.internal.utils.,\
- com.sun.org.glassfish.,\
- com.sun.tools.script.,\
- com.oracle.xmlns.internal.,\
- com.oracle.webservices.internal.,\
- org.jcp.xml.dsig.internal.,\
- jdk.internal.,\
- jdk.nashorn.internal.,\
- jdk.nashorn.tools.,\
- jdk.tools.jimage.,\
- com.sun.activation.registries.,\
- com.sun.java.accessibility.util.internal.,\
-#ifdef windows
- com.sun.java.accessibility.internal.,\
-#endif
-#ifdef macosx
- apple.,\
-#endif
+# will cause a security exception to be thrown when passed to the
+# SecurityManager::checkPackageAccess method unless the corresponding
+# RuntimePermission("accessClassInPackage."+package) has been granted.
+#
+package.access=sun.misc.,\
+ sun.reflect.,\
#
# List of comma-separated packages that start with or equal this string
-# will cause a security exception to be thrown when
-# passed to checkPackageDefinition unless the
-# corresponding RuntimePermission ("defineClassInPackage."+package) has
-# been granted.
+# will cause a security exception to be thrown when passed to the
+# SecurityManager::checkPackageDefinition method unless the corresponding
+# RuntimePermission("defineClassInPackage."+package) has been granted.
#
-# by default, none of the class loaders supplied with the JDK call
+# By default, none of the class loaders supplied with the JDK call
# checkPackageDefinition.
#
-package.definition=sun.,\
- com.sun.xml.internal.,\
- com.sun.imageio.,\
- com.sun.istack.internal.,\
- com.sun.jmx.,\
- com.sun.media.sound.,\
- com.sun.naming.internal.,\
- com.sun.proxy.,\
- com.sun.corba.se.,\
- com.sun.org.apache.bcel.internal.,\
- com.sun.org.apache.regexp.internal.,\
- com.sun.org.apache.xerces.internal.,\
- com.sun.org.apache.xpath.internal.,\
- com.sun.org.apache.xalan.internal.extensions.,\
- com.sun.org.apache.xalan.internal.lib.,\
- com.sun.org.apache.xalan.internal.res.,\
- com.sun.org.apache.xalan.internal.templates.,\
- com.sun.org.apache.xalan.internal.utils.,\
- com.sun.org.apache.xalan.internal.xslt.,\
- com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
- com.sun.org.apache.xalan.internal.xsltc.compiler.,\
- com.sun.org.apache.xalan.internal.xsltc.trax.,\
- com.sun.org.apache.xalan.internal.xsltc.util.,\
- com.sun.org.apache.xml.internal.res.,\
- com.sun.org.apache.xml.internal.security.,\
- com.sun.org.apache.xml.internal.serializer.dom3.,\
- com.sun.org.apache.xml.internal.serializer.utils.,\
- com.sun.org.apache.xml.internal.utils.,\
- com.sun.org.glassfish.,\
- com.sun.tools.script.,\
- com.oracle.xmlns.internal.,\
- com.oracle.webservices.internal.,\
- org.jcp.xml.dsig.internal.,\
- jdk.internal.,\
- jdk.nashorn.internal.,\
- jdk.nashorn.tools.,\
- jdk.tools.jimage.,\
- com.sun.activation.registries.,\
- com.sun.java.accessibility.util.internal.,\
-#ifdef windows
- com.sun.java.accessibility.internal.,\
-#endif
-#ifdef macosx
- apple.,\
-#endif
+package.definition=sun.misc.,\
+ sun.reflect.,\
#
# Determines whether this properties file can be appended to
@@ -658,6 +571,36 @@ krb5.kdc.bad.policy = tryLast
jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & denyAfter 2017-01-01, \
RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
+#
+# RMI Registry Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+#sun.rmi.registry.registryFilter=pattern;pattern
+#
+# RMI Distributed Garbage Collector (DGC) Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI DGC.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# The builtin DGC filter can approximately be represented as the filter pattern:
+#
+#sun.rmi.transport.dgcFilter=\
+# java.rmi.server.ObjID;\
+# java.rmi.server.UID;\
+# java.rmi.dgc.VMID;\
+# java.rmi.dgc.Lease;\
+# maxdepth=5;maxarray=10000
+
# Algorithm restrictions for signed JAR files
#
# In some environments, certain algorithms or key lengths may be undesirable
@@ -720,7 +663,7 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
# Note: The algorithm restrictions do not apply to trust anchors or
# self-signed certificates.
#
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
#
# Example:
@@ -740,7 +683,7 @@ jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 1024, \
# During SSL/TLS security parameters negotiation, legacy algorithms will
# not be negotiated unless there are no other candidates.
#
-# The syntax of the disabled algorithm string is described as this Java
+# The syntax of the legacy algorithms string is described as this Java
# BNF-style:
# LegacyAlgorithms:
# " LegacyAlgorithm { , LegacyAlgorithm } "
@@ -776,7 +719,7 @@ jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 1024, \
# javax.net.ssl.SSLParameters.setAlgorithmConstraints()),
# then the algorithm is completely disabled and will not be negotiated.
#
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
# There is no guarantee the property will continue to exist or be of the
# same syntax in future releases.
@@ -789,7 +732,8 @@ jdk.tls.legacyAlgorithms= \
DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \
DH_RSA_EXPORT, RSA_EXPORT, \
DH_anon, ECDH_anon, \
- RC4_128, RC4_40, DES_CBC, DES40_CBC
+ RC4_128, RC4_40, DES_CBC, DES40_CBC, \
+ 3DES_EDE_CBC
# The pre-defined default finite field Diffie-Hellman ephemeral (DHE)
# parameters for Transport Layer Security (SSL/TLS/DTLS) processing.
@@ -912,7 +856,7 @@ crypto.policy=crypto.policydir-tbd
# Constraint {"," Constraint }
# Constraint:
# AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint |
-# ReferenceUriSchemeConstraint | OtherConstraint
+# ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint
# AlgConstraint
# "disallowAlg" Uri
# MaxTransformsConstraint:
@@ -921,12 +865,16 @@ crypto.policy=crypto.policydir-tbd
# "maxReferences" Integer
# ReferenceUriSchemeConstraint:
# "disallowReferenceUriSchemes" String { String }
+# KeySizeConstraint:
+# "minKeySize" KeyAlg Integer
# OtherConstraint:
# "noDuplicateIds" | "noRetrievalMethodLoops"
#
# For AlgConstraint, Uri is the algorithm URI String that is not allowed.
# See the XML Signature Recommendation for more information on algorithm
-# URI Identifiers. If the MaxTransformsConstraint or MaxReferencesConstraint is
+# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm
+# name of the key type (ex: "RSA"). If the MaxTransformsConstraint,
+# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is
# specified more than once, only the last entry is enforced.
#
# Note: This property is currently used by the JDK Reference implementation. It
@@ -940,6 +888,8 @@ jdk.xml.dsig.secureValidationPolicy=\
maxTransforms 5,\
maxReferences 30,\
disallowReferenceUriSchemes file http https,\
+ minKeySize RSA 1024,\
+ minKeySize DSA 1024,\
noDuplicateIds,\
noRetrievalMethodLoops
diff --git a/jdk/src/java.base/share/lib/security/default.policy b/jdk/src/java.base/share/lib/security/default.policy
index 0c1798fbe9b..ae4a1e2db54 100644
--- a/jdk/src/java.base/share/lib/security/default.policy
+++ b/jdk/src/java.base/share/lib/security/default.policy
@@ -81,6 +81,8 @@ grant codeBase "jrt:/java.xml.bind" {
};
grant codeBase "jrt:/java.xml.crypto" {
+ permission java.lang.RuntimePermission
+ "accessClassInPackage.sun.security.util";
permission java.util.PropertyPermission "*", "read";
permission java.security.SecurityPermission "putProviderProperty.XMLDSig";
permission java.security.SecurityPermission
@@ -91,9 +93,19 @@ grant codeBase "jrt:/java.xml.crypto" {
"com.sun.org.apache.xml.internal.security.register";
permission java.security.SecurityPermission
"getProperty.jdk.xml.dsig.secureValidationPolicy";
+ permission java.lang.RuntimePermission
+ "accessClassInPackage.com.sun.org.apache.xml.internal.*";
+ permission java.lang.RuntimePermission
+ "accessClassInPackage.com.sun.org.apache.xpath.internal";
+ permission java.lang.RuntimePermission
+ "accessClassInPackage.com.sun.org.apache.xpath.internal.*";
};
grant codeBase "jrt:/java.xml.ws" {
+ permission java.lang.RuntimePermission
+ "accessClassInPackage.com.sun.org.apache.xml.internal.resolver";
+ permission java.lang.RuntimePermission
+ "accessClassInPackage.com.sun.org.apache.xml.internal.resolver.tools";
permission java.lang.RuntimePermission
"accessClassInPackage.com.sun.xml.internal.*";
permission java.lang.RuntimePermission
@@ -186,3 +198,18 @@ grant codeBase "jrt:/jdk.zipfs" {
permission java.util.PropertyPermission "os.name", "read";
};
+grant codeBase "jrt:/jdk.accessibility" {
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.awt";
+};
+
+grant codeBase "jrt:/jdk.desktop" {
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.awt";
+};
+
+// permissions needed by applications using java.desktop module
+grant {
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.beans";
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.beans.*";
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.java.swing.plaf.*";
+ permission java.lang.RuntimePermission "accessClassInPackage.com.apple.*";
+};
diff --git a/jdk/src/java.base/share/native/libnet/net_util.c b/jdk/src/java.base/share/native/libnet/net_util.c
index 02bf588ddc9..f6cbb353200 100644
--- a/jdk/src/java.base/share/native/libnet/net_util.c
+++ b/jdk/src/java.base/share/native/libnet/net_util.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -64,10 +64,10 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
preferIPv4Stack = (*env)->CallStaticBooleanMethod(env, iCls, mid, s);
/*
- Since we have initialized and loaded the Socket library we will
- check now to whether we have IPv6 on this platform and if the
- supporting socket APIs are available
- */
+ * Since we have initialized and loaded the socket library we will
+ * check now whether we have IPv6 on this platform and if the
+ * supporting socket APIs are available
+ */
IPv6_available = IPv6_supported() & (!preferIPv4Stack);
/* check if SO_REUSEPORT is supported on this platform */
@@ -120,16 +120,16 @@ jboolean setInet6Address_scopeifname(JNIEnv *env, jobject iaObj, jobject scopeif
return JNI_TRUE;
}
-int getInet6Address_scopeid_set(JNIEnv *env, jobject iaObj) {
+jboolean getInet6Address_scopeid_set(JNIEnv *env, jobject iaObj) {
jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
- CHECK_NULL_RETURN(holder, -1);
+ CHECK_NULL_RETURN(holder, JNI_FALSE);
return (*env)->GetBooleanField(env, holder, ia6_scopeidsetID);
}
-int getInet6Address_scopeid(JNIEnv *env, jobject iaObj) {
+unsigned int getInet6Address_scopeid(JNIEnv *env, jobject iaObj) {
jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
- CHECK_NULL_RETURN(holder, -1);
- return (*env)->GetIntField(env, holder, ia6_scopeidID);
+ CHECK_NULL_RETURN(holder, 0);
+ return (unsigned int)(*env)->GetIntField(env, holder, ia6_scopeidID);
}
jboolean setInet6Address_scopeid(JNIEnv *env, jobject iaObj, int scopeid) {
@@ -201,11 +201,10 @@ jobject getInetAddress_hostName(JNIEnv *env, jobject iaObj) {
}
JNIEXPORT jobject JNICALL
-NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
+NET_SockaddrToInetAddress(JNIEnv *env, SOCKETADDRESS *sa, int *port) {
jobject iaObj;
- if (him->sa_family == AF_INET6) {
- struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
- jbyte *caddr = (jbyte *)&(him6->sin6_addr);
+ if (sa->sa.sa_family == AF_INET6) {
+ jbyte *caddr = (jbyte *)&sa->sa6.sin6_addr;
if (NET_IsIPv4Mapped(caddr)) {
int address;
iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
@@ -214,42 +213,35 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
setInetAddress_addr(env, iaObj, address);
setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);
} else {
- jint scope;
jboolean ret;
iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
CHECK_NULL_RETURN(iaObj, NULL);
- ret = setInet6Address_ipaddress(env, iaObj, (char *)&(him6->sin6_addr));
+ ret = setInet6Address_ipaddress(env, iaObj, (char *)&sa->sa6.sin6_addr);
if (ret == JNI_FALSE)
return NULL;
setInetAddress_family(env, iaObj, java_net_InetAddress_IPv6);
- scope = getScopeID(him);
- setInet6Address_scopeid(env, iaObj, scope);
+ setInet6Address_scopeid(env, iaObj, sa->sa6.sin6_scope_id);
}
- *port = ntohs(him6->sin6_port);
+ *port = ntohs(sa->sa6.sin6_port);
} else {
- 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, java_net_InetAddress_IPv4);
- setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr));
- *port = ntohs(him4->sin_port);
+ setInetAddress_addr(env, iaObj, ntohl(sa->sa4.sin_addr.s_addr));
+ *port = ntohs(sa->sa4.sin_port);
}
return iaObj;
}
-JNIEXPORT jint JNICALL
-NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
+JNIEXPORT jboolean JNICALL
+NET_SockaddrEqualsInetAddress(JNIEnv *env, SOCKETADDRESS *sa, jobject iaObj)
{
- jint family = AF_INET;
-
- family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
- AF_INET : AF_INET6;
- if (him->sa_family == AF_INET6) {
- struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
- jbyte *caddrNew = (jbyte *)&(him6->sin6_addr);
+ jint family = getInetAddress_family(env, iaObj) ==
+ java_net_InetAddress_IPv4 ? AF_INET : AF_INET6;
+ if (sa->sa.sa_family == AF_INET6) {
+ jbyte *caddrNew = (jbyte *)&sa->sa6.sin6_addr;
if (NET_IsIPv4Mapped(caddrNew)) {
- int addrNew;
- int addrCur;
+ int addrNew, addrCur;
if (family == AF_INET6) {
return JNI_FALSE;
}
@@ -262,26 +254,24 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
}
} else {
jbyte caddrCur[16];
- int scope;
-
if (family == AF_INET) {
return JNI_FALSE;
}
- scope = getInet6Address_scopeid(env, iaObj);
getInet6Address_ipaddress(env, iaObj, (char *)caddrCur);
- if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) {
+ if (NET_IsEqual(caddrNew, caddrCur) &&
+ sa->sa6.sin6_scope_id == getInet6Address_scopeid(env, iaObj))
+ {
return JNI_TRUE;
} else {
return JNI_FALSE;
}
}
} else {
- struct sockaddr_in *him4 = (struct sockaddr_in *)him;
int addrNew, addrCur;
if (family != AF_INET) {
return JNI_FALSE;
}
- addrNew = ntohl(him4->sin_addr.s_addr);
+ addrNew = ntohl(sa->sa4.sin_addr.s_addr);
addrCur = getInetAddress_addr(env, iaObj);
if (addrNew == addrCur) {
return JNI_TRUE;
@@ -291,6 +281,15 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
}
}
+JNIEXPORT jint JNICALL
+NET_GetPortFromSockaddr(SOCKETADDRESS *sa) {
+ if (sa->sa.sa_family == AF_INET6) {
+ return ntohs(sa->sa6.sin6_port);
+ } else {
+ return ntohs(sa->sa4.sin_port);
+ }
+}
+
unsigned short
in_cksum(unsigned short *addr, int len) {
int nleft = len;
diff --git a/jdk/src/java.base/share/native/libnet/net_util.h b/jdk/src/java.base/share/native/libnet/net_util.h
index c625d60c27f..1acaff9bec3 100644
--- a/jdk/src/java.base/share/native/libnet/net_util.h
+++ b/jdk/src/java.base/share/native/libnet/net_util.h
@@ -63,8 +63,8 @@ JNIEXPORT void JNICALL initInetAddressIDs(JNIEnv *env);
*/
extern jobject getInet6Address_scopeifname(JNIEnv *env, jobject ia6Obj);
extern jboolean setInet6Address_scopeifname(JNIEnv *env, jobject ia6Obj, jobject scopeifname);
-extern int getInet6Address_scopeid_set(JNIEnv *env, jobject ia6Obj);
-extern int getInet6Address_scopeid(JNIEnv *env, jobject ia6Obj);
+extern jboolean getInet6Address_scopeid_set(JNIEnv *env, jobject ia6Obj);
+extern unsigned int getInet6Address_scopeid(JNIEnv *env, jobject ia6Obj);
extern jboolean setInet6Address_scopeid(JNIEnv *env, jobject ia6Obj, int scopeid);
extern jboolean getInet6Address_ipaddress(JNIEnv *env, jobject ia6Obj, char *dest);
extern jboolean setInet6Address_ipaddress(JNIEnv *env, jobject ia6Obj, char *address);
@@ -132,24 +132,41 @@ JNIEXPORT jint JNICALL ipv6_available();
JNIEXPORT jint JNICALL reuseport_available();
+/**
+ * This function will fill a SOCKETADDRESS structure from an InetAddress
+ * object.
+ *
+ * The parameter 'sa' must point to valid storage of size
+ * 'sizeof(SOCKETADDRESS)'.
+ *
+ * The parameter 'len' is a pointer to an int and is used for returning
+ * the actual sockaddr length, e.g. 'sizeof(struct sockaddr_in)' or
+ * 'sizeof(struct sockaddr_in6)'.
+ *
+ * If the type of the InetAddress object is IPv6, the function will fill a
+ * sockaddr_in6 structure. IPv6 must be available in that case, otherwise an
+ * exception is thrown.
+ * In the case of an IPv4 InetAddress, when IPv6 is available and
+ * v4MappedAddress is TRUE, this method will fill a sockaddr_in6 structure
+ * containing an IPv4 mapped IPv6 address. Otherwise a sockaddr_in
+ * structure will be filled.
+ */
JNIEXPORT int JNICALL
NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port,
- struct sockaddr *him, int *len,
+ SOCKETADDRESS *sa, int *len,
jboolean v4MappedAddress);
JNIEXPORT jobject JNICALL
-NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port);
+NET_SockaddrToInetAddress(JNIEnv *env, SOCKETADDRESS *sa, int *port);
void platformInit();
void parseExclusiveBindProperty(JNIEnv *env);
-void NET_SetTrafficClass(struct sockaddr *him, int trafficClass);
+JNIEXPORT jint JNICALL NET_GetPortFromSockaddr(SOCKETADDRESS *sa);
-JNIEXPORT jint JNICALL NET_GetPortFromSockaddr(struct sockaddr *him);
-
-JNIEXPORT jint JNICALL
-NET_SockaddrEqualsInetAddress(JNIEnv *env,struct sockaddr *him, jobject iaObj);
+JNIEXPORT jboolean JNICALL
+NET_SockaddrEqualsInetAddress(JNIEnv *env, SOCKETADDRESS *sa, jobject iaObj);
int NET_IsIPv4Mapped(jbyte* caddr);
@@ -172,7 +189,7 @@ JNIEXPORT int JNICALL
NET_SetSockOpt(int fd, int level, int opt, const void *arg, int len);
JNIEXPORT int JNICALL
-NET_Bind(int fd, struct sockaddr *him, int len);
+NET_Bind(int fd, SOCKETADDRESS *sa, int len);
JNIEXPORT int JNICALL
NET_MapSocketOption(jint cmd, int *level, int *optname);
@@ -183,10 +200,6 @@ NET_MapSocketOptionV6(jint cmd, int *level, int *optname);
JNIEXPORT jint JNICALL
NET_EnableFastTcpLoopback(int fd);
-int getScopeID(struct sockaddr *);
-
-int cmpScopeID(unsigned int, struct sockaddr *);
-
unsigned short in_cksum(unsigned short *addr, int len);
jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout);
diff --git a/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c b/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c
index f4b961d943b..15f984ebd34 100644
--- a/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c
+++ b/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c
@@ -211,7 +211,8 @@ lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6)
{
int port;
int index = (family == AF_INET) ? i++ : j++;
- jobject o = NET_SockaddrToInetAddress(env, iter->ifa_addr, &port);
+ jobject o = NET_SockaddrToInetAddress(env,
+ (SOCKETADDRESS *)iter->ifa_addr, &port);
if (!o) {
freeifaddrs(ifa);
if (!(*env)->ExceptionCheck(env))
diff --git a/jdk/src/java.base/unix/native/libnet/NetworkInterface.c b/jdk/src/java.base/unix/native/libnet/NetworkInterface.c
index 80571100666..88c27955ac8 100644
--- a/jdk/src/java.base/unix/native/libnet/NetworkInterface.c
+++ b/jdk/src/java.base/unix/native/libnet/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -791,7 +791,7 @@ static netif *enumInterfaces(JNIEnv *env) {
int sock;
sock = openSocket(env, AF_INET);
- if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+ if (sock < 0) {
return NULL;
}
@@ -809,7 +809,7 @@ static netif *enumInterfaces(JNIEnv *env) {
// so we have to call ipv6_available()
if (ipv6_available()) {
sock = openSocket(env, AF_INET6);
- if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+ if (sock < 0) {
freeif(ifs);
return NULL;
}
diff --git a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c
index a7fddecedd5..12357330ffe 100644
--- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c
+++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c
@@ -99,7 +99,7 @@ static jobject createInteger(JNIEnv *env, int i) {
CHECK_NULL_RETURN(i_class, NULL);
}
- return ( (*env)->NewObject(env, i_class, i_ctrID, i) );
+ return (*env)->NewObject(env, i_class, i_ctrID, i);
}
/*
@@ -118,10 +118,9 @@ static jobject createBoolean(JNIEnv *env, int b) {
CHECK_NULL_RETURN(b_class, NULL);
}
- return( (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b!=0)) );
+ return (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b != 0));
}
-
/*
* Returns the fd for a PlainDatagramSocketImpl or -1
* if closed.
@@ -134,7 +133,6 @@ static int getFD(JNIEnv *env, jobject this) {
return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
}
-
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: init
@@ -166,7 +164,6 @@ Java_java_net_PlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) {
initInetAddressIDs(env);
JNU_CHECK_EXCEPTION(env);
Java_java_net_NetworkInterface_init(env, 0);
-
}
/*
@@ -176,13 +173,13 @@ Java_java_net_PlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) {
*/
JNIEXPORT void JNICALL
Java_java_net_PlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
- jint localport, jobject iaObj) {
+ jint localport, jobject iaObj) {
/* fdObj is the FileDescriptor field on this */
jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
/* fd is an int field on fdObj */
int fd;
int len = 0;
- SOCKETADDRESS him;
+ SOCKETADDRESS sa;
socklen_t slen = sizeof(SOCKETADDRESS);
if (IS_NULL(fdObj)) {
@@ -199,12 +196,13 @@ Java_java_net_PlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
}
/* bind */
- if (NET_InetAddressToSockaddr(env, iaObj, localport, &him.sa, &len, JNI_TRUE) != 0) {
+ if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa, &len,
+ JNI_TRUE) != 0) {
return;
}
- setDefaultScopeID(env, &him.sa);
+ setDefaultScopeID(env, &sa.sa);
- if (NET_Bind(fd, &him.sa, len) < 0) {
+ if (NET_Bind(fd, &sa, len) < 0) {
if (errno == EADDRINUSE || errno == EADDRNOTAVAIL ||
errno == EPERM || errno == EACCES) {
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",
@@ -221,13 +219,13 @@ Java_java_net_PlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
/* Now that we're a connected socket, let's extract the port number
* that the system chose for us and store it in the Socket object.
*/
- if (getsockname(fd, &him.sa, &slen) == -1) {
+ if (getsockname(fd, &sa.sa, &slen) == -1) {
JNU_ThrowByNameWithMessageAndLastError
(env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
return;
}
- localport = NET_GetPortFromSockaddr(&him.sa);
+ localport = NET_GetPortFromSockaddr(&sa);
(*env)->SetIntField(env, this, pdsi_localPortID, localport);
} else {
@@ -263,7 +261,8 @@ Java_java_net_PlainDatagramSocketImpl_connect0(JNIEnv *env, jobject this,
return;
}
- if (NET_InetAddressToSockaddr(env, address, port, &rmtaddr.sa, &len, JNI_TRUE) != 0) {
+ if (NET_InetAddressToSockaddr(env, address, port, &rmtaddr, &len,
+ JNI_TRUE) != 0) {
return;
}
@@ -290,6 +289,9 @@ Java_java_net_PlainDatagramSocketImpl_disconnect0(JNIEnv *env, jobject this, jin
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
SOCKETADDRESS addr;
socklen_t len;
+#if defined(__linux__)
+ int localPort = 0;
+#endif
#endif
if (IS_NULL(fdObj)) {
@@ -298,32 +300,31 @@ Java_java_net_PlainDatagramSocketImpl_disconnect0(JNIEnv *env, jobject this, jin
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
- memset(&addr, 0, sizeof(addr));
- if (ipv6_available()) {
- addr.sa6.sin6_family = AF_UNSPEC;
- len = sizeof(struct sockaddr_in6);
+ memset(&addr, 0, sizeof(addr));
+ if (ipv6_available()) {
+ addr.sa6.sin6_family = AF_UNSPEC;
+ len = sizeof(struct sockaddr_in6);
+ } else {
+ addr.sa4.sin_family = AF_UNSPEC;
+ len = sizeof(struct sockaddr_in);
+ }
+ NET_Connect(fd, &addr.sa, len);
+
+#if defined(__linux__)
+ if (getsockname(fd, &addr.sa, &len) == -1)
+ return;
+
+ localPort = NET_GetPortFromSockaddr(&addr);
+ if (localPort == 0) {
+ localPort = (*env)->GetIntField(env, this, pdsi_localPortID);
+ if (addr.sa.sa_family == AF_INET6) {
+ addr.sa6.sin6_port = htons(localPort);
} else {
- addr.sa4.sin_family = AF_UNSPEC;
- len = sizeof(struct sockaddr_in);
+ addr.sa4.sin_port = htons(localPort);
}
- NET_Connect(fd, &addr.sa, len);
-#ifdef __linux__
- int localPort = 0;
- if (getsockname(fd, &addr.sa, &len) == -1)
- return;
-
- localPort = NET_GetPortFromSockaddr(&addr.sa);
- if (localPort == 0) {
- localPort = (*env)->GetIntField(env, this, pdsi_localPortID);
- if (addr.sa.sa_family == AF_INET6) {
- addr.sa6.sin6_port = htons(localPort);
- } else {
- addr.sa4.sin_port = htons(localPort);
- }
-
- NET_Bind(fd, &addr.sa, len);
- }
+ NET_Bind(fd, &addr, len);
+ }
#endif
#else
@@ -355,8 +356,9 @@ Java_java_net_PlainDatagramSocketImpl_send(JNIEnv *env, jobject this,
/* The fdObj'fd */
jint fd;
- SOCKETADDRESS rmtaddr, *rmtaddrP = &rmtaddr;
- int len;
+ SOCKETADDRESS rmtaddr;
+ struct sockaddr *rmtaddrP = 0;
+ int len = 0;
if (IS_NULL(fdObj)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
@@ -382,15 +384,14 @@ Java_java_net_PlainDatagramSocketImpl_send(JNIEnv *env, jobject this,
packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID);
packetBufferLen = (*env)->GetIntField(env, packet, dp_lengthID);
- if (connected) {
- /* arg to NET_Sendto () null in this case */
- len = 0;
- rmtaddrP = 0;
- } else {
+ // arg to NET_Sendto() null, if connected
+ if (!connected) {
packetPort = (*env)->GetIntField(env, packet, dp_portID);
- if (NET_InetAddressToSockaddr(env, packetAddress, packetPort, &rmtaddr.sa, &len, JNI_TRUE) != 0) {
+ if (NET_InetAddressToSockaddr(env, packetAddress, packetPort, &rmtaddr,
+ &len, JNI_TRUE) != 0) {
return;
}
+ rmtaddrP = &rmtaddr.sa;
}
setDefaultScopeID(env, &rmtaddr.sa);
@@ -427,7 +428,7 @@ Java_java_net_PlainDatagramSocketImpl_send(JNIEnv *env, jobject this,
(*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset, packetBufferLen,
(jbyte *)fullPacket);
if (trafficClass != 0 && ipv6_available()) {
- NET_SetTrafficClass(&rmtaddr.sa, trafficClass);
+ NET_SetTrafficClass(&rmtaddr, trafficClass);
}
/*
@@ -437,8 +438,7 @@ Java_java_net_PlainDatagramSocketImpl_send(JNIEnv *env, jobject this,
* ECONNREFUSED indicating that an ICMP port unreachable has
* received.
*/
- ret = NET_SendTo(fd, fullPacket, packetBufferLen, 0,
- (struct sockaddr *)rmtaddrP, len);
+ ret = NET_SendTo(fd, fullPacket, packetBufferLen, 0, rmtaddrP, len);
if (ret < 0) {
if (errno == ECONNREFUSED) {
@@ -510,7 +510,7 @@ Java_java_net_PlainDatagramSocketImpl_peek(JNIEnv *env, jobject this,
#ifdef __solaris__
if (errno == ECONNREFUSED) {
int orig_errno = errno;
- (void) recv(fd, buf, 1, 0);
+ recv(fd, buf, 1, 0);
errno = orig_errno;
}
#endif
@@ -528,7 +528,7 @@ Java_java_net_PlainDatagramSocketImpl_peek(JNIEnv *env, jobject this,
return 0;
}
- iaObj = NET_SockaddrToInetAddress(env, &rmtaddr.sa, &port);
+ iaObj = NET_SockaddrToInetAddress(env, &rmtaddr, &port);
family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
AF_INET : AF_INET6;
if (family == AF_INET) { /* this API can't handle IPV6 addresses */
@@ -676,18 +676,18 @@ Java_java_net_PlainDatagramSocketImpl_peekData(JNIEnv *env, jobject this,
*/
packetAddress = (*env)->GetObjectField(env, packet, dp_addressID);
if (packetAddress != NULL) {
- if (!NET_SockaddrEqualsInetAddress(env, &rmtaddr.sa, packetAddress)) {
+ if (!NET_SockaddrEqualsInetAddress(env, &rmtaddr, packetAddress)) {
/* force a new InetAddress to be created */
packetAddress = NULL;
}
}
if (packetAddress == NULL) {
- packetAddress = NET_SockaddrToInetAddress(env, &rmtaddr.sa, &port);
+ packetAddress = NET_SockaddrToInetAddress(env, &rmtaddr, &port);
/* stuff the new Inetaddress in the packet */
(*env)->SetObjectField(env, packet, dp_addressID, packetAddress);
} else {
/* only get the new port number */
- port = NET_GetPortFromSockaddr(&rmtaddr.sa);
+ port = NET_GetPortFromSockaddr(&rmtaddr);
}
/* and fill in the data, remote address/port and such */
(*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n,
@@ -857,18 +857,19 @@ Java_java_net_PlainDatagramSocketImpl_receive0(JNIEnv *env, jobject this,
*/
packetAddress = (*env)->GetObjectField(env, packet, dp_addressID);
if (packetAddress != NULL) {
- if (!NET_SockaddrEqualsInetAddress(env, &rmtaddr.sa, packetAddress)) {
+ if (!NET_SockaddrEqualsInetAddress(env, &rmtaddr,
+ packetAddress)) {
/* force a new InetAddress to be created */
packetAddress = NULL;
}
}
if (packetAddress == NULL) {
- packetAddress = NET_SockaddrToInetAddress(env, &rmtaddr.sa, &port);
+ packetAddress = NET_SockaddrToInetAddress(env, &rmtaddr, &port);
/* stuff the new Inetaddress in the packet */
(*env)->SetObjectField(env, packet, dp_addressID, packetAddress);
} else {
/* only get the new port number */
- port = NET_GetPortFromSockaddr(&rmtaddr.sa);
+ port = NET_GetPortFromSockaddr(&rmtaddr);
}
/* and fill in the data, remote address/port and such */
(*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n,
@@ -1040,6 +1041,7 @@ static void mcast_set_if_by_if_v4(JNIEnv *env, jobject this, int fd, jobject val
/*
* We need an ipv4 address here
*/
+ in.s_addr = 0;
for (i = 0; i < len; i++) {
addr = (*env)->GetObjectArrayElement(env, addrArray, i);
if (getInetAddress_family(env, addr) == java_net_InetAddress_IPv4) {
@@ -1049,7 +1051,7 @@ static void mcast_set_if_by_if_v4(JNIEnv *env, jobject this, int fd, jobject val
}
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
- (const char*)&in, sizeof(in)) < 0) {
+ (const char *)&in, sizeof(in)) < 0) {
JNU_ThrowByNameWithMessageAndLastError
(env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
}
@@ -1670,17 +1672,17 @@ Java_java_net_PlainDatagramSocketImpl_socketGetOption
*/
if (opt == java_net_SocketOptions_SO_BINDADDR) {
/* find out local IP address */
- SOCKETADDRESS him;
+ SOCKETADDRESS sa;
socklen_t len = sizeof(SOCKETADDRESS);
int port;
jobject iaObj;
- if (getsockname(fd, &him.sa, &len) == -1) {
+ if (getsockname(fd, &sa.sa, &len) == -1) {
JNU_ThrowByNameWithMessageAndLastError
(env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
return NULL;
}
- iaObj = NET_SockaddrToInetAddress(env, &him.sa, &port);
+ iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
return iaObj;
}
@@ -1969,6 +1971,7 @@ static void mcast_join_leave(JNIEnv *env, jobject this,
mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj));
#ifdef __linux__
mname.imr_address.s_addr = htonl(getInetAddress_addr(env, addr));
+ mname.imr_ifindex = 0;
#else
mname.imr_interface.s_addr = htonl(getInetAddress_addr(env, addr));
#endif
@@ -2023,7 +2026,7 @@ static void mcast_join_leave(JNIEnv *env, jobject this,
#ifdef __linux__
mname.imr_address.s_addr = in.s_addr;
-
+ mname.imr_ifindex = 0;
#else
mname.imr_interface.s_addr = in.s_addr;
#endif
diff --git a/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c b/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c
index b5af3466ada..1985085abb4 100644
--- a/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c
+++ b/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c
@@ -244,7 +244,7 @@ Java_java_net_PlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
/* fd is an int field on iaObj */
jint fd;
- SOCKETADDRESS him;
+ SOCKETADDRESS sa;
/* The result of the connection */
int connect_rv = -1;
@@ -260,17 +260,18 @@ Java_java_net_PlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
}
/* connect */
- if (NET_InetAddressToSockaddr(env, iaObj, port, &him.sa, &len, JNI_TRUE) != 0) {
+ if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, &len,
+ JNI_TRUE) != 0) {
return;
}
- setDefaultScopeID(env, &him.sa);
+ setDefaultScopeID(env, &sa.sa);
if (trafficClass != 0 && ipv6_available()) {
- NET_SetTrafficClass(&him.sa, trafficClass);
+ NET_SetTrafficClass(&sa, trafficClass);
}
if (timeout <= 0) {
- connect_rv = NET_Connect(fd, &him.sa, len);
+ connect_rv = NET_Connect(fd, &sa.sa, len);
#ifdef __solaris__
if (connect_rv == -1 && errno == EINPROGRESS ) {
@@ -319,7 +320,7 @@ Java_java_net_PlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
SET_NONBLOCKING(fd);
/* no need to use NET_Connect as non-blocking */
- connect_rv = connect(fd, &him.sa, len);
+ connect_rv = connect(fd, &sa.sa, len);
/* connection not established immediately */
if (connect_rv != 0) {
@@ -467,11 +468,11 @@ Java_java_net_PlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
* that the system chose for us and store it in the Socket object.
*/
socklen_t slen = sizeof(SOCKETADDRESS);
- if (getsockname(fd, &him.sa, &slen) == -1) {
+ if (getsockname(fd, &sa.sa, &slen) == -1) {
JNU_ThrowByNameWithMessageAndLastError
(env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
} else {
- localport = NET_GetPortFromSockaddr(&him.sa);
+ localport = NET_GetPortFromSockaddr(&sa);
(*env)->SetIntField(env, this, psi_localportID, localport);
}
}
@@ -490,8 +491,8 @@ Java_java_net_PlainSocketImpl_socketBind(JNIEnv *env, jobject this,
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
/* fd is an int field on fdObj */
int fd;
- int len;
- SOCKETADDRESS him;
+ int len = 0;
+ SOCKETADDRESS sa;
if (IS_NULL(fdObj)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
@@ -506,13 +507,13 @@ Java_java_net_PlainSocketImpl_socketBind(JNIEnv *env, jobject this,
}
/* bind */
- if (NET_InetAddressToSockaddr(env, iaObj, localport, &him.sa,
+ if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa,
&len, JNI_TRUE) != 0) {
return;
}
- setDefaultScopeID(env, &him.sa);
+ setDefaultScopeID(env, &sa.sa);
- if (NET_Bind(fd, &him.sa, len) < 0) {
+ if (NET_Bind(fd, &sa, len) < 0) {
if (errno == EADDRINUSE || errno == EADDRNOTAVAIL ||
errno == EPERM || errno == EACCES) {
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",
@@ -533,12 +534,12 @@ Java_java_net_PlainSocketImpl_socketBind(JNIEnv *env, jobject this,
/* Now that we're a connected socket, let's extract the port number
* that the system chose for us and store it in the Socket object.
*/
- if (getsockname(fd, &him.sa, &slen) == -1) {
+ if (getsockname(fd, &sa.sa, &slen) == -1) {
JNU_ThrowByNameWithMessageAndLastError
(env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
return;
}
- localport = NET_GetPortFromSockaddr(&him.sa);
+ localport = NET_GetPortFromSockaddr(&sa);
(*env)->SetIntField(env, this, psi_localportID, localport);
} else {
(*env)->SetIntField(env, this, psi_localportID, localport);
@@ -606,7 +607,7 @@ Java_java_net_PlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
/* accepted fd */
jint newfd;
- SOCKETADDRESS him;
+ SOCKETADDRESS sa;
socklen_t slen = sizeof(SOCKETADDRESS);
if (IS_NULL(fdObj)) {
@@ -661,7 +662,7 @@ Java_java_net_PlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
return;
}
- newfd = NET_Accept(fd, &him.sa, &slen);
+ newfd = NET_Accept(fd, &sa.sa, &slen);
/* connection accepted */
if (newfd >= 0) {
@@ -709,7 +710,7 @@ Java_java_net_PlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
/*
* fill up the remote peer port and address in the new socket structure.
*/
- socketAddressObj = NET_SockaddrToInetAddress(env, &him.sa, &port);
+ socketAddressObj = NET_SockaddrToInetAddress(env, &sa, &port);
if (socketAddressObj == NULL) {
/* should be pending exception */
close(newfd);
@@ -944,19 +945,19 @@ Java_java_net_PlainSocketImpl_socketGetOption
* SO_BINDADDR isn't a socket option
*/
if (cmd == java_net_SocketOptions_SO_BINDADDR) {
- SOCKETADDRESS him;
+ SOCKETADDRESS sa;
socklen_t len = sizeof(SOCKETADDRESS);
int port;
jobject iaObj;
jclass iaCntrClass;
jfieldID iaFieldID;
- if (getsockname(fd, &him.sa, &len) < 0) {
+ if (getsockname(fd, &sa.sa, &len) < 0) {
JNU_ThrowByNameWithMessageAndLastError
(env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
return -1;
}
- iaObj = NET_SockaddrToInetAddress(env, &him.sa, &port);
+ iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
CHECK_NULL_RETURN(iaObj, -1);
iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
diff --git a/jdk/src/java.base/unix/native/libnet/SocketOutputStream.c b/jdk/src/java.base/unix/native/libnet/SocketOutputStream.c
index 17afe8b8d46..ba3a907ae67 100644
--- a/jdk/src/java.base/unix/native/libnet/SocketOutputStream.c
+++ b/jdk/src/java.base/unix/native/libnet/SocketOutputStream.c
@@ -98,27 +98,31 @@ Java_java_net_SocketOutputStream_socketWrite0(JNIEnv *env, jobject this,
int llen = chunkLen;
(*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
- while(llen > 0) {
- int n = NET_Send(fd, bufP + loff, llen, 0);
- if (n > 0) {
- llen -= n;
- loff += n;
- continue;
+ if ((*env)->ExceptionCheck(env)) {
+ break;
+ } else {
+ while(llen > 0) {
+ int n = NET_Send(fd, bufP + loff, llen, 0);
+ if (n > 0) {
+ llen -= n;
+ loff += n;
+ continue;
+ }
+ if (errno == ECONNRESET) {
+ JNU_ThrowByName(env, "sun/net/ConnectionResetException",
+ "Connection reset");
+ } else {
+ JNU_ThrowByNameWithMessageAndLastError
+ (env, "java/net/SocketException", "Write failed");
+ }
+ if (bufP != BUF) {
+ free(bufP);
+ }
+ return;
}
- if (errno == ECONNRESET) {
- JNU_ThrowByName(env, "sun/net/ConnectionResetException",
- "Connection reset");
- } else {
- JNU_ThrowByNameWithMessageAndLastError
- (env, "java/net/SocketException", "Write failed");
- }
- if (bufP != BUF) {
- free(bufP);
- }
- return;
+ len -= chunkLen;
+ off += chunkLen;
}
- len -= chunkLen;
- off += chunkLen;
}
if (bufP != BUF) {
diff --git a/jdk/src/java.base/unix/native/libnet/net_util_md.c b/jdk/src/java.base/unix/native/libnet/net_util_md.c
index ee518088277..744fc2f6298 100644
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.c
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c
@@ -234,29 +234,6 @@ int kernelIsV24 () {
}
return kernelV24;
}
-
-int getScopeID (struct sockaddr *him) {
- struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him;
- return hext->sin6_scope_id;
-}
-
-int cmpScopeID (unsigned int scope, struct sockaddr *him) {
- struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him;
- return hext->sin6_scope_id == scope;
-}
-
-#else
-
-int getScopeID (struct sockaddr *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;
- return him6->sin6_scope_id == scope;
-}
-
#endif
void
@@ -775,30 +752,32 @@ NET_EnableFastTcpLoopback(int fd) {
return 0;
}
-/* In the case of an IPv4 Inetaddress this method will return an
- * IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE.
- * Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress.
-*/
+/**
+ * See net_util.h for documentation
+ */
JNIEXPORT int JNICALL
-NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him,
- int *len, jboolean v4MappedAddress) {
- jint family;
- family = getInetAddress_family(env, iaObj);
- /* needs work. 1. family 2. clean up him6 etc deallocate memory */
- if (ipv6_available() && !(family == java_net_InetAddress_IPv4 &&
- v4MappedAddress == JNI_FALSE)) {
- struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
+NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port,
+ SOCKETADDRESS *sa, int *len,
+ jboolean v4MappedAddress)
+{
+ jint family = getInetAddress_family(env, iaObj);
+ memset((char *)sa, 0, sizeof(SOCKETADDRESS));
+
+ if (ipv6_available() &&
+ !(family == java_net_InetAddress_IPv4 &&
+ v4MappedAddress == JNI_FALSE))
+ {
jbyte caddr[16];
jint address;
if (family == java_net_InetAddress_IPv4) {
// convert to IPv4-mapped address
- memset((char *) caddr, 0, 16);
+ memset((char *)caddr, 0, 16);
address = getInetAddress_addr(env, iaObj);
if (address == INADDR_ANY) {
/* we would always prefer IPv6 wildcard address
- caddr[10] = 0xff;
- caddr[11] = 0xff; */
+ * caddr[10] = 0xff;
+ * caddr[11] = 0xff; */
} else {
caddr[10] = 0xff;
caddr[11] = 0xff;
@@ -810,22 +789,19 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr
} else {
getInet6Address_ipaddress(env, iaObj, (char *)caddr);
}
- memset((char *)him6, 0, sizeof(struct sockaddr_in6));
- him6->sin6_port = htons(port);
- memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );
- him6->sin6_family = AF_INET6;
- *len = sizeof(struct sockaddr_in6);
-
-#if defined(_ALLBSD_SOURCE)
-// XXXBSD: should we do something with scope id here ? see below linux comment
-/* MMM: Come back to this! */
-#endif
+ sa->sa6.sin6_port = htons(port);
+ memcpy((void *)&sa->sa6.sin6_addr, caddr, sizeof(struct in6_addr));
+ sa->sa6.sin6_family = AF_INET6;
+ if (len != NULL) {
+ *len = sizeof(struct sockaddr_in6);
+ }
+#ifdef __linux__
/*
* On Linux if we are connecting to a link-local address
* we need to specify the interface in the scope_id (2.4 kernel only)
*
- * If the scope was cached the we use the cached value. If not cached but
+ * If the scope was cached then we use the cached value. If not cached but
* specified in the Inet6Address we use that, but we first check if the
* address needs to be routed via the loopback interface. In this case,
* we override the specified value with that of the loopback interface.
@@ -833,9 +809,8 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr
* we try to determine a value from the routing table. In all these
* cases the used value is cached for further use.
*/
-#ifdef __linux__
- if (IN6_IS_ADDR_LINKLOCAL(&(him6->sin6_addr))) {
- int cached_scope_id = 0, scope_id = 0;
+ if (IN6_IS_ADDR_LINKLOCAL(&sa->sa6.sin6_addr)) {
+ unsigned int cached_scope_id = 0, scope_id = 0;
if (ia6_cachedscopeidID) {
cached_scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID);
@@ -850,7 +825,7 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr
/* check user-specified value for loopback case
* that needs to be overridden
*/
- if (kernelIsV24() && needsLoopbackRoute (&him6->sin6_addr)) {
+ if (kernelIsV24() && needsLoopbackRoute(&sa->sa6.sin6_addr)) {
cached_scope_id = lo_scope_id;
(*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
}
@@ -860,11 +835,11 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr
* try determine the appropriate interface.
*/
if (kernelIsV24()) {
- cached_scope_id = getDefaultIPv6Interface(&(him6->sin6_addr));
+ cached_scope_id = getDefaultIPv6Interface(&sa->sa6.sin6_addr);
} else {
- cached_scope_id = getLocalScopeID((char *)&(him6->sin6_addr));
+ cached_scope_id = getLocalScopeID((char *)&(sa->sa6.sin6_addr));
if (cached_scope_id == 0) {
- cached_scope_id = getDefaultIPv6Interface(&(him6->sin6_addr));
+ cached_scope_id = getDefaultIPv6Interface(&sa->sa6.sin6_addr);
}
}
(*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
@@ -876,53 +851,37 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr
* If we have a scope_id use the extended form
* of sockaddr_in6.
*/
-
- struct sockaddr_in6 *him6 =
- (struct sockaddr_in6 *)him;
- him6->sin6_scope_id = cached_scope_id != 0 ?
- cached_scope_id : scope_id;
- *len = sizeof(struct sockaddr_in6);
+ sa->sa6.sin6_scope_id = cached_scope_id == 0 ? scope_id : cached_scope_id;
}
#else
- /* handle scope_id for solaris */
-
+ /* handle scope_id */
if (family != java_net_InetAddress_IPv4) {
if (ia6_scopeidID) {
- him6->sin6_scope_id = getInet6Address_scopeid(env, iaObj);
+ sa->sa6.sin6_scope_id = getInet6Address_scopeid(env, iaObj);
}
}
#endif
} else {
- struct sockaddr_in *him4 = (struct sockaddr_in *)him;
jint address;
- if (family == java_net_InetAddress_IPv6) {
+ if (family != java_net_InetAddress_IPv4) {
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 = htonl(address);
- him4->sin_family = AF_INET;
- *len = sizeof(struct sockaddr_in);
+ sa->sa4.sin_port = htons(port);
+ sa->sa4.sin_addr.s_addr = htonl(address);
+ sa->sa4.sin_family = AF_INET;
+ if (len != NULL) {
+ *len = sizeof(struct sockaddr_in);
+ }
}
return 0;
}
void
-NET_SetTrafficClass(struct sockaddr *him, int trafficClass) {
- if (him->sa_family == AF_INET6) {
- struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
- him6->sin6_flowinfo = htonl((trafficClass & 0xff) << 20);
- }
-}
-
-JNIEXPORT jint JNICALL
-NET_GetPortFromSockaddr(struct sockaddr *him) {
- if (him->sa_family == AF_INET6) {
- return ntohs(((struct sockaddr_in6*)him)->sin6_port);
- } else {
- return ntohs(((struct sockaddr_in*)him)->sin_port);
+NET_SetTrafficClass(SOCKETADDRESS *sa, int trafficClass) {
+ if (sa->sa.sa_family == AF_INET6) {
+ sa->sa6.sin6_flowinfo = htonl((trafficClass & 0xff) << 20);
}
}
@@ -1488,7 +1447,7 @@ NET_SetSockOpt(int fd, int level, int opt, const void *arg,
*
*/
int
-NET_Bind(int fd, struct sockaddr *him, int len)
+NET_Bind(int fd, SOCKETADDRESS *sa, int len)
{
#if defined(__solaris__)
int level = -1;
@@ -1503,9 +1462,8 @@ NET_Bind(int fd, struct sockaddr *him, int len)
* ## When IPv6 is enabled this will be an IPv4-mapped
* ## with family set to AF_INET6
*/
- if (him->sa_family == AF_INET) {
- struct sockaddr_in *sa = (struct sockaddr_in *)him;
- if ((ntohl(sa->sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {
+ if (sa->sa.sa_family == AF_INET) {
+ if ((ntohl(sa->sa4.sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {
errno = EADDRNOTAVAIL;
return -1;
}
@@ -1524,8 +1482,9 @@ NET_Bind(int fd, struct sockaddr *him, int len)
*/
alen = sizeof(arg);
- if (useExclBind || getsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- (char *)&arg, &alen) == 0) {
+ if (useExclBind ||
+ getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg, &alen) == 0)
+ {
if (useExclBind || arg == 0) {
/*
* SO_REUSEADDR is disabled or sun.net.useExclusiveBind
@@ -1533,8 +1492,8 @@ NET_Bind(int fd, struct sockaddr *him, int len)
* UDP_EXCLBIND
*/
alen = sizeof(arg);
- if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg,
- &alen) == 0) {
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg, &alen) == 0)
+ {
if (arg == SOCK_STREAM) {
level = IPPROTO_TCP;
exclbind = TCP_EXCLBIND;
@@ -1545,14 +1504,13 @@ NET_Bind(int fd, struct sockaddr *him, int len)
}
arg = 1;
- setsockopt(fd, level, exclbind, (char *)&arg,
- sizeof(arg));
+ setsockopt(fd, level, exclbind, (char *)&arg, sizeof(arg));
}
}
#endif
- rv = bind(fd, him, len);
+ rv = bind(fd, &sa->sa, len);
#if defined(__solaris__)
if (rv < 0) {
diff --git a/jdk/src/java.base/unix/native/libnet/net_util_md.h b/jdk/src/java.base/unix/native/libnet/net_util_md.h
index 48503d2efbe..15e08c48ae9 100644
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.h
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h
@@ -30,32 +30,6 @@
#include
#include
-int NET_Timeout(int s, long timeout);
-int NET_Timeout0(int s, long timeout, long currentTime);
-int NET_Read(int s, void* buf, size_t len);
-int NET_NonBlockingRead(int s, void* buf, size_t len);
-int NET_TimeoutWithCurrentTime(int s, long timeout, long currentTime);
-long NET_GetCurrentTime();
-int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, socklen_t *fromlen);
-int NET_ReadV(int s, const struct iovec * vector, int count);
-int NET_Send(int s, void *msg, int len, unsigned int flags);
-int NET_SendTo(int s, const void *msg, int len, unsigned int
- flags, const struct sockaddr *to, int tolen);
-int NET_Writev(int s, const struct iovec * vector, int count);
-int NET_Connect(int s, struct sockaddr *addr, int addrlen);
-int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen);
-int NET_SocketClose(int s);
-int NET_Dup2(int oldfd, int newfd);
-int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout);
-int NET_SocketAvailable(int s, jint *pbytes);
-
-void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
- const char* hostname,
- int gai_error);
-void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
- const char *defaultDetail);
-
/************************************************************************
* Macros and constants
*/
@@ -91,9 +65,36 @@ typedef union {
} SOCKETADDRESS;
/************************************************************************
- * Utilities
+ * Functions
*/
+int NET_Timeout(int s, long timeout);
+int NET_Timeout0(int s, long timeout, long currentTime);
+int NET_Read(int s, void* buf, size_t len);
+int NET_NonBlockingRead(int s, void* buf, size_t len);
+int NET_TimeoutWithCurrentTime(int s, long timeout, long currentTime);
+long NET_GetCurrentTime();
+int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
+ struct sockaddr *from, socklen_t *fromlen);
+int NET_ReadV(int s, const struct iovec * vector, int count);
+int NET_Send(int s, void *msg, int len, unsigned int flags);
+int NET_SendTo(int s, const void *msg, int len, unsigned int
+ flags, const struct sockaddr *to, int tolen);
+int NET_Writev(int s, const struct iovec * vector, int count);
+int NET_Connect(int s, struct sockaddr *addr, int addrlen);
+int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+int NET_SocketClose(int s);
+int NET_Dup2(int oldfd, int newfd);
+int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout);
+int NET_SocketAvailable(int s, jint *pbytes);
+
+void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
+ const char* hostname,
+ int gai_error);
+void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
+ const char *defaultDetail);
+void NET_SetTrafficClass(SOCKETADDRESS *sa, int trafficClass);
+
#ifdef __linux__
int kernelIsV24();
int getDefaultIPv6Interface(struct in6_addr *target_addr);
diff --git a/jdk/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c b/jdk/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c
index 9159d3bc38d..ef512a1a1f9 100644
--- a/jdk/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c
+++ b/jdk/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c
@@ -181,11 +181,11 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
*/
senderAddr = (*env)->GetObjectField(env, this, dci_senderAddrID);
if (senderAddr != NULL) {
- if (!NET_SockaddrEqualsInetAddress(env, &sa.sa, senderAddr)) {
+ if (!NET_SockaddrEqualsInetAddress(env, &sa, senderAddr)) {
senderAddr = NULL;
} else {
jint port = (*env)->GetIntField(env, this, dci_senderPortID);
- if (port != NET_GetPortFromSockaddr(&sa.sa)) {
+ if (port != NET_GetPortFromSockaddr(&sa)) {
senderAddr = NULL;
}
}
@@ -193,7 +193,7 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
if (senderAddr == NULL) {
jobject isa = NULL;
int port = 0;
- jobject ia = NET_SockaddrToInetAddress(env, &sa.sa, &port);
+ jobject ia = NET_SockaddrToInetAddress(env, &sa, &port);
if (ia != NULL) {
isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
}
@@ -201,7 +201,7 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
(*env)->SetObjectField(env, this, dci_senderAddrID, ia);
(*env)->SetIntField(env, this, dci_senderPortID,
- NET_GetPortFromSockaddr(&sa.sa));
+ NET_GetPortFromSockaddr(&sa));
(*env)->SetObjectField(env, this, dci_senderID, isa);
}
return n;
@@ -215,14 +215,14 @@ Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this,
jint fd = fdval(env, fdo);
void *buf = (void *)jlong_to_ptr(address);
SOCKETADDRESS sa;
- int sa_len = sizeof(SOCKETADDRESS);
+ int sa_len = 0;
jint n = 0;
if (len > MAX_PACKET_LEN) {
len = MAX_PACKET_LEN;
}
- if (NET_InetAddressToSockaddr(env, destAddress, destPort, &sa.sa,
+ if (NET_InetAddressToSockaddr(env, destAddress, destPort, &sa,
&sa_len, preferIPv6) != 0) {
return IOS_THROWN;
}
diff --git a/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c b/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c
index 72eae0d606e..37ed11a8937 100644
--- a/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c
+++ b/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c
@@ -64,7 +64,7 @@ Java_sun_nio_ch_InheritedChannel_peerAddress0(JNIEnv *env, jclass cla, jint fd)
if (getpeername(fd, &sa.sa, &len) == 0) {
if (matchFamily(&sa.sa)) {
- remote_ia = NET_SockaddrToInetAddress(env, &sa.sa, (int *)&remote_port);
+ remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
}
}
@@ -81,7 +81,7 @@ Java_sun_nio_ch_InheritedChannel_peerPort0(JNIEnv *env, jclass cla, jint fd)
if (getpeername(fd, &sa.sa, &len) == 0) {
if (matchFamily(&sa.sa)) {
- NET_SockaddrToInetAddress(env, &sa.sa, (int *)&remote_port);
+ NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
}
}
diff --git a/jdk/src/java.base/unix/native/libnio/ch/Net.c b/jdk/src/java.base/unix/native/libnio/ch/Net.c
index 33d08fbd808..dd9aedccdfa 100644
--- a/jdk/src/java.base/unix/native/libnio/ch/Net.c
+++ b/jdk/src/java.base/unix/native/libnio/ch/Net.c
@@ -274,15 +274,15 @@ Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jobject fdo, jboolean prefe
jboolean useExclBind, jobject iao, int port)
{
SOCKETADDRESS sa;
- int sa_len = sizeof(SOCKETADDRESS);
+ int sa_len = 0;
int rv = 0;
- if (NET_InetAddressToSockaddr(env, iao, port, &sa.sa, &sa_len,
+ if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len,
preferIPv6) != 0) {
return;
}
- rv = NET_Bind(fdval(env, fdo), &sa.sa, sa_len);
+ rv = NET_Bind(fdval(env, fdo), &sa, sa_len);
if (rv != 0) {
handleSocketError(env, errno);
}
@@ -300,10 +300,10 @@ Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
jobject fdo, jobject iao, jint port)
{
SOCKETADDRESS sa;
- int sa_len = sizeof(SOCKETADDRESS);
+ int sa_len = 0;
int rv;
- if (NET_InetAddressToSockaddr(env, iao, port, &sa.sa, &sa_len,
+ if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len,
preferIPv6) != 0) {
return IOS_THROWN;
}
@@ -349,7 +349,7 @@ Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
return -1;
#endif /* _ALLBSD_SOURCE */
}
- return NET_GetPortFromSockaddr(&sa.sa);
+ return NET_GetPortFromSockaddr(&sa);
}
JNIEXPORT jobject JNICALL
@@ -382,7 +382,7 @@ Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
return NULL;
#endif /* _ALLBSD_SOURCE */
}
- return NET_SockaddrToInetAddress(env, &sa.sa, &port);
+ return NET_SockaddrToInetAddress(env, &sa, &port);
}
JNIEXPORT jint JNICALL
diff --git a/jdk/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c b/jdk/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c
index 915b70c0c59..f9f6e8f3cc8 100644
--- a/jdk/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c
+++ b/jdk/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c
@@ -112,7 +112,7 @@ Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv *env, jobject this,
}
(*env)->SetIntField(env, newfdo, fd_fdID, newfd);
- remote_ia = NET_SockaddrToInetAddress(env, &sa.sa, (int *)&remote_port);
+ remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port);
CHECK_NULL_RETURN(isa, IOS_THROWN);
diff --git a/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java b/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java
index e6b13bba7b1..9cd515075fa 100644
--- a/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java
+++ b/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -233,11 +233,14 @@ class WinNTFileSystem extends FileSystem {
int childStart = 0;
int parentEnd = pn;
+ boolean isDirectoryRelative =
+ pn == 2 && isLetter(parent.charAt(0)) && parent.charAt(1) == ':';
+
if ((cn > 1) && (c.charAt(0) == slash)) {
if (c.charAt(1) == slash) {
/* Drop prefix when child is a UNC pathname */
childStart = 2;
- } else {
+ } else if (!isDirectoryRelative) {
/* Drop prefix when child is drive-relative */
childStart = 1;
@@ -254,7 +257,7 @@ class WinNTFileSystem extends FileSystem {
int strlen = parentEnd + cn - childStart;
char[] theChars = null;
- if (child.charAt(childStart) == slash) {
+ if (child.charAt(childStart) == slash || isDirectoryRelative) {
theChars = new char[strlen];
parent.getChars(0, parentEnd, theChars, 0);
child.getChars(childStart, cn, theChars, parentEnd);
diff --git a/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c b/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c
index d834ef9bf11..90f3c1f7318 100644
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c
@@ -53,7 +53,7 @@ static jboolean purgeOutstandingICMP(JNIEnv *env, jint fd)
break;
}
if (recvfrom(fd, buf, 1, MSG_PEEK,
- (struct sockaddr *)&rmtaddr, &addrlen) != SOCKET_ERROR) {
+ &rmtaddr.sa, &addrlen) != SOCKET_ERROR) {
break;
}
if (WSAGetLastError() != WSAECONNRESET) {
@@ -61,7 +61,7 @@ static jboolean purgeOutstandingICMP(JNIEnv *env, jint fd)
break;
}
- recvfrom(fd, buf, 1, 0, (struct sockaddr *)&rmtaddr, &addrlen);
+ recvfrom(fd, buf, 1, 0, &rmtaddr.sa, &addrlen);
got_icmp = JNI_TRUE;
}
@@ -134,14 +134,13 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketCrea
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketBind
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port, jboolean exclBind) {
SOCKETADDRESS sa;
- int rv;
- int sa_len = sizeof(sa);
+ int rv, sa_len = 0;
- if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
+ if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
&sa_len, JNI_TRUE) != 0) {
return;
}
- rv = NET_WinBind(fd, (struct sockaddr *)&sa, sa_len, exclBind);
+ rv = NET_WinBind(fd, &sa, sa_len, exclBind);
if (rv == SOCKET_ERROR) {
if (WSAGetLastError() == WSAEACCES) {
@@ -159,17 +158,15 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketBind
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketConnect
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
SOCKETADDRESS sa;
- int rv;
- int sa_len = sizeof(sa);
+ int rv, sa_len = 0, t = TRUE;
DWORD x1, x2; /* ignored result codes */
- int t = TRUE;
- if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
+ if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
&sa_len, JNI_TRUE) != 0) {
return;
}
- rv = connect(fd, (struct sockaddr *)&sa, sa_len);
+ rv = connect(fd, &sa.sa, sa_len);
if (rv == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "connect");
return;
@@ -192,7 +189,7 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketDisc
int t = FALSE;
memset(&sa, 0, sa_len);
- connect(fd, (struct sockaddr *)&sa, sa_len);
+ connect(fd, &sa.sa, sa_len);
/* see comment in socketCreate */
WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
@@ -219,7 +216,7 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLoca
SOCKETADDRESS sa;
int len = sizeof(sa);
- if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
+ if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "getsockname");
return -1;
}
@@ -238,12 +235,12 @@ JNIEXPORT jobject JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketL
jobject iaObj;
int port;
- if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
+ if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
return NULL;
}
- iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
+ iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
return iaObj;
}
@@ -316,7 +313,7 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketRece
/* receive the packet */
rv = recvfrom(fd, fullPacket, packetBufferLen, flags,
- (struct sockaddr *)&sa, &sa_len);
+ &sa.sa, &sa_len);
if (rv == SOCKET_ERROR && (WSAGetLastError() == WSAECONNRESET)) {
/* An icmp port unreachable - we must receive this as Windows
@@ -383,15 +380,13 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketRece
*/
packetAddress = (*env)->GetObjectField(env, dpObj, dp_addressID);
if (packetAddress != NULL) {
- if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&sa,
- packetAddress)) {
+ if (!NET_SockaddrEqualsInetAddress(env, &sa, packetAddress)) {
/* force a new InetAddress to be created */
packetAddress = NULL;
}
}
if (packetAddress == NULL) {
- packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa,
- &port);
+ packetAddress = NET_SockaddrToInetAddress(env, &sa, &port);
if (packetAddress != NULL) {
/* stuff the new Inetaddress into the packet */
(*env)->SetObjectField(env, dpObj, dp_addressID, packetAddress);
@@ -422,20 +417,18 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSend
(JNIEnv *env, jclass clazz, jint fd, jbyteArray data, jint offset, jint length,
jobject iaObj, jint port, jboolean connected) {
SOCKETADDRESS sa;
- int sa_len = sizeof(sa);
- SOCKETADDRESS *sap = &sa;
+ int rv, sa_len = 0;
+ struct sockaddr *sap = 0;
char BUF[MAX_BUFFER_LEN];
char *fullPacket;
- int rv;
- if (connected) {
- sap = 0; /* arg to sendto () null in this case */
- sa_len = 0;
- } else {
- if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
- &sa_len, JNI_TRUE) != 0) {
+ // if already connected, sap arg to sendto() is null
+ if (!connected) {
+ if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
+ &sa_len, JNI_TRUE) != 0) {
return;
}
+ sap = &sa.sa;
}
if (length > MAX_BUFFER_LEN) {
@@ -456,7 +449,7 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSend
(*env)->GetByteArrayRegion(env, data, offset, length,
(jbyte *)fullPacket);
- rv = sendto(fd, fullPacket, length, 0, (struct sockaddr *)sap, sa_len);
+ rv = sendto(fd, fullPacket, length, 0, sap, sa_len);
if (rv == SOCKET_ERROR) {
if (rv == -1) {
NET_ThrowNew(env, WSAGetLastError(), "Datagram send failed");
diff --git a/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c b/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c
index 39178408823..f5a310148ae 100644
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c
@@ -89,15 +89,14 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_bind0
jboolean exclBind)
{
SOCKETADDRESS sa;
- int rv;
- int sa_len = sizeof(sa);
+ int rv, sa_len = 0;
- if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
- &sa_len, JNI_TRUE) != 0) {
+ if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
+ &sa_len, JNI_TRUE) != 0) {
return;
}
- rv = NET_WinBind(fd, (struct sockaddr *)&sa, sa_len, exclBind);
+ rv = NET_WinBind(fd, &sa, sa_len, exclBind);
if (rv == SOCKET_ERROR)
NET_ThrowNew(env, WSAGetLastError(), "NET_Bind");
@@ -111,15 +110,14 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_bind0
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_connect0
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
SOCKETADDRESS sa;
- int rv;
- int sa_len = sizeof(sa);
+ int rv, sa_len = 0;
- if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
- &sa_len, JNI_TRUE) != 0) {
+ if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
+ &sa_len, JNI_TRUE) != 0) {
return -1;
}
- rv = connect(fd, (struct sockaddr *)&sa, sa_len);
+ rv = connect(fd, &sa.sa, sa_len);
if (rv == SOCKET_ERROR) {
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK) {
@@ -217,7 +215,7 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_localPort0
SOCKETADDRESS sa;
int len = sizeof(sa);
- if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
+ if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
if (WSAGetLastError() == WSAENOTSOCK) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Socket closed");
@@ -243,11 +241,11 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_localAddress
jclass iaContainerClass;
jfieldID iaFieldID;
- if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
+ if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
return;
}
- iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
+ iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
CHECK_NULL(iaObj);
iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj);
@@ -283,7 +281,7 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_accept0
int len = sizeof(sa);
memset((char *)&sa, 0, len);
- newfd = accept(fd, (struct sockaddr *)&sa, &len);
+ newfd = accept(fd, &sa.sa, &len);
if (newfd == INVALID_SOCKET) {
if (WSAGetLastError() == -2) {
@@ -298,7 +296,7 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_accept0
SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
- ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
+ ia = NET_SockaddrToInetAddress(env, &sa, &port);
isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
(*env)->SetObjectArrayElement(env, isaa, 0, isa);
diff --git a/jdk/src/java.base/windows/native/libnet/SocketOutputStream.c b/jdk/src/java.base/windows/native/libnet/SocketOutputStream.c
index 9894cb0e596..dcb533b753e 100644
--- a/jdk/src/java.base/windows/native/libnet/SocketOutputStream.c
+++ b/jdk/src/java.base/windows/native/libnet/SocketOutputStream.c
@@ -92,66 +92,69 @@ Java_java_net_SocketOutputStream_socketWrite0(JNIEnv *env, jobject this,
int retry = 0;
(*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
-
- while(llen > 0) {
- int n = send(fd, bufP + loff, llen, 0);
- if (n > 0) {
- llen -= n;
- loff += n;
- continue;
- }
-
- /*
- * Due to a bug in Windows Sockets (observed on NT and Windows
- * 2000) it may be necessary to retry the send. The issue is that
- * on blocking sockets send/WSASend is supposed to block if there
- * is insufficient buffer space available. If there are a large
- * number of threads blocked on write due to congestion then it's
- * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS.
- * The workaround we use is to retry the send. If we have a
- * large buffer to send (>2k) then we retry with a maximum of
- * 2k buffer. If we hit the issue with <=2k buffer then we backoff
- * for 1 second and retry again. We repeat this up to a reasonable
- * limit before bailing out and throwing an exception. In load
- * conditions we've observed that the send will succeed after 2-3
- * attempts but this depends on network buffers associated with
- * other sockets draining.
- */
- if (WSAGetLastError() == WSAENOBUFS) {
- if (llen > MAX_BUFFER_LEN) {
- buflen = MAX_BUFFER_LEN;
- chunkLen = MAX_BUFFER_LEN;
- llen = MAX_BUFFER_LEN;
+ if ((*env)->ExceptionCheck(env)) {
+ break;
+ } else {
+ while(llen > 0) {
+ int n = send(fd, bufP + loff, llen, 0);
+ if (n > 0) {
+ llen -= n;
+ loff += n;
continue;
}
- if (retry >= 30) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "No buffer space available - exhausted attempts to queue buffer");
- if (bufP != BUF) {
- free(bufP);
- }
- return;
- }
- Sleep(1000);
- retry++;
- continue;
- }
- /*
- * Send failed - can be caused by close or write error.
- */
- if (WSAGetLastError() == WSAENOTSOCK) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
- } else {
- NET_ThrowCurrent(env, "socket write error");
+ /*
+ * Due to a bug in Windows Sockets (observed on NT and Windows
+ * 2000) it may be necessary to retry the send. The issue is that
+ * on blocking sockets send/WSASend is supposed to block if there
+ * is insufficient buffer space available. If there are a large
+ * number of threads blocked on write due to congestion then it's
+ * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS.
+ * The workaround we use is to retry the send. If we have a
+ * large buffer to send (>2k) then we retry with a maximum of
+ * 2k buffer. If we hit the issue with <=2k buffer then we backoff
+ * for 1 second and retry again. We repeat this up to a reasonable
+ * limit before bailing out and throwing an exception. In load
+ * conditions we've observed that the send will succeed after 2-3
+ * attempts but this depends on network buffers associated with
+ * other sockets draining.
+ */
+ if (WSAGetLastError() == WSAENOBUFS) {
+ if (llen > MAX_BUFFER_LEN) {
+ buflen = MAX_BUFFER_LEN;
+ chunkLen = MAX_BUFFER_LEN;
+ llen = MAX_BUFFER_LEN;
+ continue;
+ }
+ if (retry >= 30) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "No buffer space available - exhausted attempts to queue buffer");
+ if (bufP != BUF) {
+ free(bufP);
+ }
+ return;
+ }
+ Sleep(1000);
+ retry++;
+ continue;
+ }
+
+ /*
+ * Send failed - can be caused by close or write error.
+ */
+ if (WSAGetLastError() == WSAENOTSOCK) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ } else {
+ NET_ThrowCurrent(env, "socket write error");
+ }
+ if (bufP != BUF) {
+ free(bufP);
+ }
+ return;
}
- if (bufP != BUF) {
- free(bufP);
- }
- return;
+ len -= chunkLen;
+ off += chunkLen;
}
- len -= chunkLen;
- off += chunkLen;
}
if (bufP != BUF) {
diff --git a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c
index d382267742c..46cc779d402 100644
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c
@@ -420,18 +420,13 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
jboolean exclBind) {
jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
-
- int fd, fd1 = -1, family;
int ipv6_supported = ipv6_available();
-
+ int fd, fd1 = -1, lcladdrlen = 0;
SOCKETADDRESS lcladdr;
- int lcladdrlen = sizeof(SOCKETADDRESS);
- int address;
- memset((char *)&lcladdr, 0, sizeof(lcladdr));
-
- family = getInetAddress_family(env, addressObj);
- if (family == java_net_InetAddress_IPv6 && !ipv6_supported) {
+ if (getInetAddress_family(env, addressObj) == java_net_InetAddress_IPv6 &&
+ !ipv6_supported)
+ {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported");
return;
@@ -446,14 +441,13 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
}
}
+
if (IS_NULL(addressObj)) {
JNU_ThrowNullPointerException(env, "argument address");
return;
- } else {
- address = getInetAddress_addr(env, addressObj);
}
- if (NET_InetAddressToSockaddr(env, addressObj, port, &lcladdr.sa,
+ if (NET_InetAddressToSockaddr(env, addressObj, port, &lcladdr,
&lcladdrlen, JNI_FALSE) != 0) {
return;
}
@@ -493,7 +487,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
return;
}
} else {
- if (NET_WinBind(fd, &lcladdr.sa, lcladdrlen, exclBind) == -1) {
+ if (NET_WinBind(fd, &lcladdr, lcladdrlen, exclBind) == -1) {
if (WSAGetLastError() == WSAEACCES) {
WSASetLastError(WSAEADDRINUSE);
}
@@ -507,7 +501,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
NET_ThrowCurrent(env, "getsockname");
return;
}
- port = ntohs((u_short) GET_PORT (&lcladdr));
+ port = ntohs((u_short)GET_PORT(&lcladdr));
}
(*env)->SetIntField(env, this, pdsi_localPortID, port);
}
@@ -520,27 +514,25 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
*/
JNIEXPORT void JNICALL
-Java_java_net_TwoStacksPlainDatagramSocketImpl_connect0(JNIEnv *env, jobject this,
- jobject address, jint port) {
- /* The object's field */
+Java_java_net_TwoStacksPlainDatagramSocketImpl_connect0
+ (JNIEnv *env, jobject this, jobject address, jint port)
+{
jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
- /* The fdObj'fd */
- jint fd=-1, fd1=-1, fdc;
- /* The packetAddress address, family and port */
- jint addr, family;
+ jint fd = -1, fd1 = -1, fdc, family;
SOCKETADDRESS rmtaddr;
- int rmtaddrlen;
- int ipv6_supported = ipv6_available();
+ int rmtaddrlen = 0;
if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Socket closed");
return;
}
+
if (!IS_NULL(fdObj)) {
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
}
+
if (!IS_NULL(fd1Obj)) {
fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
}
@@ -550,10 +542,8 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_connect0(JNIEnv *env, jobject thi
return;
}
- addr = getInetAddress_addr(env, address);
-
family = getInetAddress_family(env, address);
- if (family == java_net_InetAddress_IPv6 && !ipv6_supported) {
+ if (family == java_net_InetAddress_IPv6 && !ipv6_available()) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported");
return;
@@ -572,12 +562,12 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_connect0(JNIEnv *env, jobject thi
res = WSAIoctl(fdc,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0);
}
- if (NET_InetAddressToSockaddr(env, address, port, &rmtaddr.sa,
+ if (NET_InetAddressToSockaddr(env, address, port, &rmtaddr,
&rmtaddrlen, JNI_FALSE) != 0) {
return;
}
- if (connect(fdc, &rmtaddr.sa, sizeof(rmtaddr)) == -1) {
+ if (connect(fdc, &rmtaddr.sa, rmtaddrlen) == -1) {
NET_ThrowCurrent(env, "connect");
return;
}
@@ -631,9 +621,9 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_disconnect0(JNIEnv *env, jobject
* Signature: (Ljava/net/DatagramPacket;)V
*/
JNIEXPORT void JNICALL
-Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this,
- jobject packet) {
-
+Java_java_net_TwoStacksPlainDatagramSocketImpl_send
+ (JNIEnv *env, jobject this, jobject packet)
+{
char BUF[MAX_BUFFER_LEN];
char *fullPacket;
jobject fdObj;
@@ -647,11 +637,10 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this,
jbyteArray packetBuffer;
jboolean connected;
- SOCKETADDRESS rmtaddr, *addrp = &rmtaddr;
+ SOCKETADDRESS rmtaddr;
+ struct sockaddr *addrp = 0;
int addrlen = 0;
- memset((char *)&rmtaddr, 0, sizeof(rmtaddr));
-
if (IS_NULL(packet)) {
JNU_ThrowNullPointerException(env, "null packet");
return;
@@ -696,14 +685,13 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this,
packetBufferLen = MAX_PACKET_LEN;
}
- if (connected) {
- addrp = 0; /* arg to sendto () null in this case */
- addrlen = 0;
- } else {
- if (NET_InetAddressToSockaddr(env, iaObj, packetPort, &rmtaddr.sa,
+ // sockaddr arg to sendto() is null if already connected
+ if (!connected) {
+ if (NET_InetAddressToSockaddr(env, iaObj, packetPort, &rmtaddr,
&addrlen, JNI_FALSE) != 0) {
return;
}
+ addrp = &rmtaddr.sa;
}
if (packetBufferLen > MAX_BUFFER_LEN) {
@@ -753,11 +741,12 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this,
fullPacket = &(BUF[0]);
}
- (*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset, packetBufferLen,
- (jbyte *)fullPacket);
- if (sendto(fd, fullPacket, packetBufferLen, 0,
- (struct sockaddr *)addrp, addrlen) == SOCKET_ERROR) {
- NET_ThrowCurrent(env, "Datagram send failed");
+ (*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset,
+ packetBufferLen, (jbyte *)fullPacket);
+ if (sendto(fd, fullPacket, packetBufferLen, 0, addrp,
+ addrlen) == SOCKET_ERROR)
+ {
+ NET_ThrowCurrent(env, "Datagram send failed");
}
if (packetBufferLen > MAX_BUFFER_LEN) {
@@ -1147,14 +1136,14 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_peekData(JNIEnv *env, jobject thi
*/
packetAddress = (*env)->GetObjectField(env, packet, dp_addressID);
if (packetAddress != NULL) {
- if (!NET_SockaddrEqualsInetAddress(env, &remote_addr.sa,
+ if (!NET_SockaddrEqualsInetAddress(env, &remote_addr,
packetAddress)) {
/* force a new InetAddress to be created */
packetAddress = NULL;
}
}
if (packetAddress == NULL) {
- packetAddress = NET_SockaddrToInetAddress(env, &remote_addr.sa,
+ packetAddress = NET_SockaddrToInetAddress(env, &remote_addr,
&port);
/* stuff the new Inetaddress in the packet */
(*env)->SetObjectField(env, packet, dp_addressID, packetAddress);
@@ -1431,20 +1420,21 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0(JNIEnv *env, jobject thi
* can't update any existing InetAddress because it is immutable
*/
packetAddress = (*env)->GetObjectField(env, packet, dp_addressID);
-
if (packetAddress != NULL) {
- if (!NET_SockaddrEqualsInetAddress(env, &remote_addr.sa, packetAddress)) {
+ if (!NET_SockaddrEqualsInetAddress(env, &remote_addr,
+ packetAddress)) {
/* force a new InetAddress to be created */
packetAddress = NULL;
}
}
if (packetAddress == NULL) {
- packetAddress = NET_SockaddrToInetAddress(env, &remote_addr.sa, &port);
+ packetAddress = NET_SockaddrToInetAddress(env, &remote_addr,
+ &port);
/* stuff the new Inetaddress in the packet */
(*env)->SetObjectField(env, packet, dp_addressID, packetAddress);
} else {
/* only get the new port number */
- port = NET_GetPortFromSockaddr(&remote_addr.sa);
+ port = NET_GetPortFromSockaddr(&remote_addr);
}
/* populate the packet */
(*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n,
@@ -1528,7 +1518,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_datagramSocketClose(JNIEnv *env,
jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
int ipv6_supported = ipv6_available();
- int fd=-1, fd1=-1;
+ int fd = -1, fd1 = -1;
if (IS_NULL(fdObj) && (!ipv6_supported || IS_NULL(fd1Obj))) {
return;
@@ -1799,7 +1789,7 @@ JNIEXPORT void JNICALL
Java_java_net_TwoStacksPlainDatagramSocketImpl_socketNativeSetOption
(JNIEnv *env,jobject this, jint opt,jobject value)
{
- int fd=-1, fd1=-1;
+ int fd = -1, fd1 = -1;
int levelv4 = 0, levelv6 = 0, optnamev4 = 0, optnamev6 = 0, optlen = 0;
union {
int i;
@@ -2167,7 +2157,7 @@ JNIEXPORT jobject JNICALL
Java_java_net_TwoStacksPlainDatagramSocketImpl_socketGetOption
(JNIEnv *env, jobject this, jint opt)
{
- int fd=-1, fd1=-1;
+ int fd = -1, fd1 = -1;
int level, optname, optlen;
union {
int i;
@@ -2255,7 +2245,7 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_socketLocalAddress
(JNIEnv *env, jobject this, jint family)
{
int fd = -1, fd1 = -1;
- SOCKETADDRESS him;
+ SOCKETADDRESS sa;
int len = 0;
int port;
jobject iaObj;
@@ -2288,12 +2278,12 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_socketLocalAddress
return NULL;
}
- if (getsockname(fd, &him.sa, &len) == -1) {
+ if (getsockname(fd, &sa.sa, &len) == -1) {
JNU_ThrowByNameWithMessageAndLastError
(env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
return NULL;
}
- iaObj = NET_SockaddrToInetAddress(env, &him.sa, &port);
+ iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
return iaObj;
}
@@ -2430,7 +2420,7 @@ static void mcast_join_leave(JNIEnv *env, jobject this,
int len, family;
int ipv6_supported = ipv6_available();
- int cmd ;
+ int cmd;
memset((char *)&in, 0, sizeof(in));
memset((char *)&name, 0, sizeof(name));
@@ -2452,7 +2442,7 @@ static void mcast_join_leave(JNIEnv *env, jobject this,
return;
}
- if (NET_InetAddressToSockaddr(env, iaObj, 0, &name.sa, &len, JNI_FALSE) != 0) {
+ if (NET_InetAddressToSockaddr(env, iaObj, 0, &name, &len, JNI_FALSE) != 0) {
return;
}
@@ -2473,7 +2463,7 @@ static void mcast_join_leave(JNIEnv *env, jobject this,
return;
}
if (IS_NULL(niObj)) {
- len = sizeof (in);
+ len = sizeof(in);
if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF,
(char *)&in, &len) < 0) {
NET_ThrowCurrent(env, "get IP_MULTICAST_IF failed");
diff --git a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c
index f8f1063c904..0df5be632dd 100644
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c
@@ -175,8 +175,8 @@ Java_java_net_TwoStacksPlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
*/
JNIEXPORT void JNICALL
Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
- jobject iaObj, jint port,
- jint timeout)
+ jobject iaObj, jint port,
+ jint timeout)
{
jint localport = (*env)->GetIntField(env, this, psi_localportID);
@@ -193,11 +193,11 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
- SOCKETADDRESS him;
+ SOCKETADDRESS sa;
/* The result of the connection */
int connect_res;
- memset((char *)&him, 0, sizeof(him));
+ memset((char *)&sa, 0, sizeof(sa));
if (!IS_NULL(fdObj)) {
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
@@ -212,11 +212,12 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
return;
}
- if (NET_InetAddressToSockaddr(env, iaObj, port, &him.sa, &len, JNI_FALSE) != 0) {
- return;
+ if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, &len,
+ JNI_FALSE) != 0) {
+ return;
}
- family = him.sa.sa_family;
+ family = sa.sa.sa_family;
if (family == AF_INET6) {
if (!ipv6_supported) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
@@ -248,7 +249,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
(*env)->SetObjectField(env, this, psi_fd1ID, NULL);
if (timeout <= 0) {
- connect_res = connect(fd, &him.sa, sizeof(SOCKETADDRESS));
+ connect_res = connect(fd, &sa.sa, sizeof(SOCKETADDRESS));
if (connect_res == SOCKET_ERROR) {
connect_res = WSAGetLastError();
}
@@ -261,7 +262,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
ioctlsocket(fd, FIONBIO, &optval);
/* initiate the connect */
- connect_res = connect(fd, &him.sa, sizeof(SOCKETADDRESS));
+ connect_res = connect(fd, &sa.sa, sizeof(SOCKETADDRESS));
if (connect_res == SOCKET_ERROR) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
connect_res = WSAGetLastError();
@@ -362,7 +363,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
*/
u_short port;
int len = sizeof(SOCKETADDRESS);
- if (getsockname(fd, &him.sa, &len) == -1) {
+ if (getsockname(fd, &sa.sa, &len) == -1) {
if (WSAGetLastError() == WSAENOTSOCK) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Socket closed");
@@ -371,7 +372,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
}
return;
}
- port = ntohs((u_short)GET_PORT(&him));
+ port = ntohs((u_short)GET_PORT(&sa));
(*env)->SetIntField(env, this, psi_localportID, (int) port);
}
}
@@ -396,7 +397,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
int family;
int rv;
- SOCKETADDRESS him;
+ SOCKETADDRESS sa;
fdObj = (*env)->GetObjectField(env, this, psi_fdID);
fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
@@ -424,13 +425,13 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
return;
}
- if (NET_InetAddressToSockaddr(env, iaObj, localport, &him.sa, &len,
+ if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa, &len,
JNI_FALSE) != 0) {
return;
}
if (ipv6_supported) {
struct ipv6bind v6bind;
- v6bind.addr = &him;
+ v6bind.addr = &sa.sa;
v6bind.ipv4_fd = fd;
v6bind.ipv6_fd = fd1;
rv = NET_BindV6(&v6bind, exclBind);
@@ -462,7 +463,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
(*env)->SetObjectField(env, this, psi_fd1ID, NULL);
}
} else {
- rv = NET_WinBind(fd, &him.sa, len, exclBind);
+ rv = NET_WinBind(fd, &sa, len, exclBind);
}
if (rv == -1) {
@@ -481,11 +482,11 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
int len = sizeof(SOCKETADDRESS);
u_short port;
- if (getsockname(him.sa.sa_family == AF_INET ? fd: fd1, &him.sa, &len) == -1) {
+ if (getsockname(sa.sa.sa_family == AF_INET ? fd : fd1, &sa.sa, &len) == -1) {
NET_ThrowCurrent(env, "getsockname in plain socketBind");
return;
}
- port = ntohs((u_short) GET_PORT (&him));
+ port = ntohs((u_short) GET_PORT (&sa));
(*env)->SetIntField(env, this, psi_localportID, (int)port);
} else {
@@ -529,7 +530,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketListen
JNU_ThrowNullPointerException(env, "socket address");
return;
}
- if (NET_InetAddressToSockaddr(env, address, 0, &addr.sa, &addrlen,
+ if (NET_InetAddressToSockaddr(env, address, 0, &addr, &addrlen,
JNI_FALSE) != 0) {
return;
}
@@ -585,7 +586,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
/* the fd int field on fdObj */
jint fd=-1, fd1=-1;
- SOCKETADDRESS him;
+ SOCKETADDRESS sa;
jint len;
if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
@@ -676,7 +677,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
}
}
}
- fd = accept(fd, &him.sa, &len);
+ fd = accept(fd, &sa.sa, &len);
if (fd < 0) {
/* REMIND: SOCKET CLOSED PROBLEM */
if (fd == -2) {
@@ -691,7 +692,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, 0);
(*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd);
- if (him.sa.sa_family == AF_INET) {
+ if (sa.sa.sa_family == AF_INET) {
if (inet4Cls == NULL) {
jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
if (c != NULL) {
@@ -717,7 +718,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
return;
}
- setInetAddress_addr(env, socketAddressObj, ntohl(him.sa4.sin_addr.s_addr));
+ setInetAddress_addr(env, socketAddressObj, ntohl(sa.sa4.sin_addr.s_addr));
setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv4);
(*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
} else {
@@ -743,14 +744,14 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
NET_SocketClose(fd);
return;
}
- setInet6Address_ipaddress(env, socketAddressObj, (char *)&him.sa6.sin6_addr);
+ setInet6Address_ipaddress(env, socketAddressObj, (char *)&sa.sa6.sin6_addr);
setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv6);
- setInet6Address_scopeid(env, socketAddressObj, him.sa6.sin6_scope_id);
+ setInet6Address_scopeid(env, socketAddressObj, sa.sa6.sin6_scope_id);
}
/* fields common to AF_INET and AF_INET6 */
- port = ntohs ((u_short) GET_PORT (&him));
+ port = ntohs ((u_short)GET_PORT(&sa));
(*env)->SetIntField(env, socket, psi_portID, (int)port);
port = (*env)->GetIntField(env, this, psi_localportID);
(*env)->SetIntField(env, socket, psi_localportID, port);
@@ -1025,14 +1026,14 @@ Java_java_net_TwoStacksPlainSocketImpl_socketGetOption
* SO_BINDADDR isn't a socket option
*/
if (opt == java_net_SocketOptions_SO_BINDADDR) {
- SOCKETADDRESS him;
+ SOCKETADDRESS sa;
int len = sizeof(SOCKETADDRESS);
int port;
jobject iaObj;
jclass iaCntrClass;
jfieldID iaFieldID;
- memset((char *)&him, 0, len);
+ memset((char *)&sa, 0, len);
if (fd == -1) {
/* must be an IPV6 only socket. Case where both sockets are != -1
@@ -1041,12 +1042,12 @@ Java_java_net_TwoStacksPlainSocketImpl_socketGetOption
fd = getFD1 (env, this);
}
- if (getsockname(fd, &him.sa, &len) < 0) {
+ if (getsockname(fd, &sa.sa, &len) < 0) {
JNU_ThrowByNameWithMessageAndLastError
(env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
return -1;
}
- iaObj = NET_SockaddrToInetAddress(env, &him.sa, &port);
+ iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
CHECK_NULL_RETURN(iaObj, -1);
iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
diff --git a/jdk/src/java.base/windows/native/libnet/net_util_md.c b/jdk/src/java.base/windows/native/libnet/net_util_md.c
index e0bd5681e33..e9ad96f37ac 100644
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.c
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c
@@ -488,10 +488,10 @@ void setExclusiveBind(int fd) {
* Should be only called by the wrapper method NET_WinBind
*/
JNIEXPORT int JNICALL
-NET_Bind(int s, struct sockaddr *him, int len)
+NET_Bind(int s, SOCKETADDRESS *sa, int len)
{
int rv = 0;
- rv = bind(s, him, len);
+ rv = bind(s, &sa->sa, len);
if (rv == SOCKET_ERROR) {
/*
@@ -511,11 +511,11 @@ NET_Bind(int s, struct sockaddr *him, int len)
* if required, and then calls NET_BIND
*/
JNIEXPORT int JNICALL
-NET_WinBind(int s, struct sockaddr *him, int len, jboolean exclBind)
+NET_WinBind(int s, SOCKETADDRESS *sa, int len, jboolean exclBind)
{
if (exclBind == JNI_TRUE)
setExclusiveBind(s);
- return NET_Bind(s, him, len);
+ return NET_Bind(s, sa, len);
}
JNIEXPORT int JNICALL
@@ -677,8 +677,8 @@ NET_BindV6(struct ipv6bind *b, jboolean exclBind) {
if (family == AF_INET && (b->addr->sa4.sin_addr.s_addr != INADDR_ANY)) {
/* bind to v4 only */
int ret;
- ret = NET_WinBind((int)b->ipv4_fd, (struct sockaddr *)b->addr,
- sizeof(SOCKETADDRESS), exclBind);
+ ret = NET_WinBind((int)b->ipv4_fd, b->addr,
+ sizeof(SOCKETADDRESS), exclBind);
if (ret == SOCKET_ERROR) {
CLOSE_SOCKETS_AND_RETURN;
}
@@ -689,7 +689,7 @@ NET_BindV6(struct ipv6bind *b, jboolean exclBind) {
if (family == AF_INET6 && (!IN6_IS_ADDR_ANY(&b->addr->sa6.sin6_addr))) {
/* bind to v6 only */
int ret;
- ret = NET_WinBind((int)b->ipv6_fd, (struct sockaddr *)b->addr,
+ ret = NET_WinBind((int)b->ipv6_fd, b->addr,
sizeof(SOCKETADDRESS), exclBind);
if (ret == SOCKET_ERROR) {
CLOSE_SOCKETS_AND_RETURN;
@@ -719,7 +719,7 @@ NET_BindV6(struct ipv6bind *b, jboolean exclBind) {
oaddr.sa4.sin_addr.s_addr = INADDR_ANY;
}
- rv = NET_WinBind(fd, (struct sockaddr *)b->addr, sizeof(SOCKETADDRESS), exclBind);
+ rv = NET_WinBind(fd, b->addr, sizeof(SOCKETADDRESS), exclBind);
if (rv == SOCKET_ERROR) {
CLOSE_SOCKETS_AND_RETURN;
}
@@ -731,7 +731,7 @@ NET_BindV6(struct ipv6bind *b, jboolean exclBind) {
}
bound_port = GET_PORT (b->addr);
SET_PORT (&oaddr, bound_port);
- if ((rv = NET_WinBind(ofd, &oaddr.sa,
+ if ((rv = NET_WinBind(ofd, &oaddr,
sizeof(SOCKETADDRESS), exclBind)) == SOCKET_ERROR) {
int retries;
int sotype, arglen=sizeof(sotype);
@@ -768,7 +768,7 @@ NET_BindV6(struct ipv6bind *b, jboolean exclBind) {
/* bind random port on first socket */
SET_PORT (&oaddr, 0);
- rv = NET_WinBind(ofd, &oaddr.sa, sizeof(SOCKETADDRESS), exclBind);
+ rv = NET_WinBind(ofd, &oaddr, sizeof(SOCKETADDRESS), exclBind);
if (rv == SOCKET_ERROR) {
CLOSE_SOCKETS_AND_RETURN;
}
@@ -784,8 +784,7 @@ NET_BindV6(struct ipv6bind *b, jboolean exclBind) {
}
bound_port = GET_PORT (&oaddr);
SET_PORT (b->addr, bound_port);
- rv = NET_WinBind(fd, (struct sockaddr *)b->addr,
- sizeof(SOCKETADDRESS), exclBind);
+ rv = NET_WinBind(fd, b->addr, sizeof(SOCKETADDRESS), exclBind);
if (rv != SOCKET_ERROR) {
if (family == AF_INET) {
@@ -853,31 +852,33 @@ NET_EnableFastTcpLoopback(int fd) {
return result == SOCKET_ERROR ? WSAGetLastError() : 0;
}
-/* If address types is IPv6, then IPv6 must be available. Otherwise
- * no address can be generated. In the case of an IPv4 Inetaddress this
- * method will return an IPv4 mapped address where IPv6 is available and
- * v4MappedAddress is TRUE. Otherwise it will return a sockaddr_in
- * structure for an IPv4 InetAddress.
-*/
+/**
+ * See net_util.h for documentation
+ */
JNIEXPORT int JNICALL
-NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him,
- int *len, jboolean v4MappedAddress) {
- jint family, iafam;
- iafam = getInetAddress_family(env, iaObj);
- 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;
- jbyte caddr[16];
- jint address, scopeid = 0;
- jint cached_scope_id = 0;
+NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port,
+ SOCKETADDRESS *sa, int *len,
+ jboolean v4MappedAddress)
+{
+ jint family = getInetAddress_family(env, iaObj);
+ memset((char *)sa, 0, sizeof(SOCKETADDRESS));
- if (family == AF_INET) { /* will convert to IPv4-mapped address */
- memset((char *) caddr, 0, 16);
+ if (ipv6_available() &&
+ !(family == java_net_InetAddress_IPv4 &&
+ v4MappedAddress == JNI_FALSE))
+ {
+ jbyte caddr[16];
+ jint address;
+ unsigned int scopeid = 0, cached_scope_id = 0;
+
+ 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) {
/* we would always prefer IPv6 wildcard address
- caddr[10] = 0xff;
- caddr[11] = 0xff; */
+ * caddr[10] = 0xff;
+ * caddr[11] = 0xff; */
} else {
caddr[10] = 0xff;
caddr[11] = 0xff;
@@ -889,46 +890,39 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr
} else {
getInet6Address_ipaddress(env, iaObj, (char *)caddr);
scopeid = getInet6Address_scopeid(env, iaObj);
- cached_scope_id = (jint)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID);
+ cached_scope_id = (unsigned int)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID);
}
-
- 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;
- if ((family == AF_INET6) && IN6_IS_ADDR_LINKLOCAL( &(him6->sin6_addr) )
- && (!scopeid && !cached_scope_id)) {
- cached_scope_id = getDefaultIPv6Interface(env, him6);
+ sa->sa6.sin6_port = (u_short)htons((u_short)port);
+ memcpy((void *)&sa->sa6.sin6_addr, caddr, sizeof(struct in6_addr));
+ sa->sa6.sin6_family = AF_INET6;
+ if ((family == java_net_InetAddress_IPv6) &&
+ IN6_IS_ADDR_LINKLOCAL(&sa->sa6.sin6_addr) &&
+ (!scopeid && !cached_scope_id))
+ {
+ cached_scope_id = getDefaultIPv6Interface(env, &sa->sa6);
(*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
}
- him6->sin6_scope_id = scopeid != 0 ? scopeid : cached_scope_id;
- *len = sizeof(struct sockaddr_in6) ;
- } else {
- struct sockaddr_in *him4 = (struct sockaddr_in *)him;
- jint address;
- if (family != AF_INET) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");
- return -1;
+ sa->sa6.sin6_scope_id = scopeid == 0 ? cached_scope_id : scopeid;
+ if (len != NULL) {
+ *len = sizeof(struct sockaddr_in6);
+ }
+ } else {
+ jint address;
+ if (family != java_net_InetAddress_IPv4) {
+ 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 = (u_long) htonl(address);
- him4->sin_family = AF_INET;
- *len = sizeof(struct sockaddr_in);
+ sa->sa4.sin_port = htons((short)port);
+ sa->sa4.sin_addr.s_addr = (u_long)htonl(address);
+ sa->sa4.sin_family = AF_INET;
+ if (len != NULL) {
+ *len = sizeof(struct sockaddr_in);
+ }
}
return 0;
}
-JNIEXPORT jint JNICALL
-NET_GetPortFromSockaddr(struct sockaddr *him) {
- if (him->sa_family == AF_INET6) {
- return ntohs(((struct sockaddr_in6 *)him)->sin6_port);
- } else {
- return ntohs(((struct sockaddr_in *)him)->sin_port);
- }
-}
-
int
NET_IsIPv4Mapped(jbyte* caddr) {
int i;
@@ -961,16 +955,6 @@ NET_IsEqual(jbyte* caddr1, jbyte* caddr2) {
return 1;
}
-int getScopeID(struct sockaddr *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;
- return him6->sin6_scope_id == scope;
-}
-
/**
* Wrapper for select/poll with timeout on a single file descriptor.
*
diff --git a/jdk/src/java.base/windows/native/libnet/net_util_md.h b/jdk/src/java.base/windows/native/libnet/net_util_md.h
index 96c122b33c5..26a9e38022a 100644
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.h
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.h
@@ -121,7 +121,7 @@ JNIEXPORT int JNICALL NET_Timeout2(int fd, int fd1, long timeout, int *fdret);
JNIEXPORT int JNICALL NET_BindV6(struct ipv6bind *b, jboolean exclBind);
-JNIEXPORT int JNICALL NET_WinBind(int s, struct sockaddr *him, int len,
+JNIEXPORT int JNICALL NET_WinBind(int s, SOCKETADDRESS *sa, int len,
jboolean exclBind);
/* XP versions of the native routines */
diff --git a/jdk/src/java.base/windows/native/libnio/ch/DatagramChannelImpl.c b/jdk/src/java.base/windows/native/libnio/ch/DatagramChannelImpl.c
index ecc96a1d8bb..0355c88ff79 100644
--- a/jdk/src/java.base/windows/native/libnio/ch/DatagramChannelImpl.c
+++ b/jdk/src/java.base/windows/native/libnio/ch/DatagramChannelImpl.c
@@ -96,7 +96,7 @@ jboolean purgeOutstandingICMP(JNIEnv *env, jclass clazz, jint fd)
break;
}
if (recvfrom(fd, buf, 1, MSG_PEEK,
- (struct sockaddr *)&sa, &addrlen) != SOCKET_ERROR) {
+ &sa.sa, &addrlen) != SOCKET_ERROR) {
break;
}
if (WSAGetLastError() != WSAECONNRESET) {
@@ -104,7 +104,7 @@ jboolean purgeOutstandingICMP(JNIEnv *env, jclass clazz, jint fd)
break;
}
- recvfrom(fd, buf, 1, 0, (struct sockaddr *)&sa, &addrlen);
+ recvfrom(fd, buf, 1, 0, &sa.sa, &addrlen);
got_icmp = JNI_TRUE;
}
@@ -122,7 +122,7 @@ Java_sun_nio_ch_DatagramChannelImpl_disconnect0(JNIEnv *env, jobject this,
memset(&sa, 0, sa_len);
- rv = connect((SOCKET)fd, (struct sockaddr *)&sa, sa_len);
+ rv = connect((SOCKET)fd, &sa.sa, sa_len);
if (rv == SOCKET_ERROR) {
handleSocketError(env, WSAGetLastError());
} else {
@@ -153,7 +153,7 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
(char *)buf,
len,
0,
- (struct sockaddr *)&sa,
+ &sa.sa,
&sa_len);
if (n == SOCKET_ERROR) {
@@ -182,12 +182,11 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
*/
senderAddr = (*env)->GetObjectField(env, this, dci_senderAddrID);
if (senderAddr != NULL) {
- if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&sa,
- senderAddr)) {
+ if (!NET_SockaddrEqualsInetAddress(env, &sa, senderAddr)) {
senderAddr = NULL;
} else {
jint port = (*env)->GetIntField(env, this, dci_senderPortID);
- if (port != NET_GetPortFromSockaddr((struct sockaddr *)&sa)) {
+ if (port != NET_GetPortFromSockaddr(&sa)) {
senderAddr = NULL;
}
}
@@ -195,7 +194,7 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
if (senderAddr == NULL) {
jobject isa = NULL;
int port;
- jobject ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
+ jobject ia = NET_SockaddrToInetAddress(env, &sa, &port);
if (ia != NULL) {
isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
}
@@ -204,7 +203,7 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
// update cachedSenderInetAddress/cachedSenderPort
(*env)->SetObjectField(env, this, dci_senderAddrID, ia);
(*env)->SetIntField(env, this, dci_senderPortID,
- NET_GetPortFromSockaddr((struct sockaddr *)&sa));
+ NET_GetPortFromSockaddr(&sa));
(*env)->SetObjectField(env, this, dci_senderID, isa);
}
return n;
@@ -219,21 +218,15 @@ Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this,
jint fd = fdval(env, fdo);
void *buf = (void *)jlong_to_ptr(address);
SOCKETADDRESS sa;
- int sa_len;
+ int sa_len = 0;
jint rv = 0;
- if (NET_InetAddressToSockaddr(env, destAddress, destPort,
- (struct sockaddr *)&sa,
- &sa_len, preferIPv6) != 0) {
+ if (NET_InetAddressToSockaddr(env, destAddress, destPort, &sa,
+ &sa_len, preferIPv6) != 0) {
return IOS_THROWN;
}
- rv = sendto((SOCKET)fd,
- buf,
- len,
- 0,
- (struct sockaddr *)&sa,
- sa_len);
+ rv = sendto((SOCKET)fd, buf, len, 0, &sa.sa, sa_len);
if (rv == SOCKET_ERROR) {
int theErr = (jint)WSAGetLastError();
if (theErr == WSAEWOULDBLOCK) {
diff --git a/jdk/src/java.base/windows/native/libnio/ch/Net.c b/jdk/src/java.base/windows/native/libnio/ch/Net.c
index c7702006d27..cae8ef03bf8 100644
--- a/jdk/src/java.base/windows/native/libnio/ch/Net.c
+++ b/jdk/src/java.base/windows/native/libnio/ch/Net.c
@@ -168,13 +168,13 @@ Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jobject fdo, jboolean prefe
{
SOCKETADDRESS sa;
int rv;
- int sa_len;
+ int sa_len = 0;
- if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
- return;
+ if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, preferIPv6) != 0) {
+ return;
}
- rv = NET_WinBind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len, isExclBind);
+ rv = NET_WinBind(fdval(env, fdo), &sa, sa_len, isExclBind);
if (rv == SOCKET_ERROR)
NET_ThrowNew(env, WSAGetLastError(), "bind");
}
@@ -194,14 +194,14 @@ Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6, job
{
SOCKETADDRESS sa;
int rv;
- int sa_len;
+ int sa_len = 0;
SOCKET s = (SOCKET)fdval(env, fdo);
- if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
+ if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, preferIPv6) != 0) {
return IOS_THROWN;
}
- rv = connect(s, (struct sockaddr *)&sa, sa_len);
+ rv = connect(s, &sa.sa, sa_len);
if (rv != 0) {
int err = WSAGetLastError();
if (err == WSAEINPROGRESS || err == WSAEWOULDBLOCK) {
@@ -226,7 +226,7 @@ Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
SOCKETADDRESS sa;
int sa_len = sizeof(sa);
- if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
+ if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
int error = WSAGetLastError();
if (error == WSAEINVAL) {
return 0;
@@ -234,7 +234,7 @@ Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
NET_ThrowNew(env, error, "getsockname");
return IOS_THROWN;
}
- return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
+ return NET_GetPortFromSockaddr(&sa);
}
JNIEXPORT jobject JNICALL
@@ -244,11 +244,11 @@ Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
int sa_len = sizeof(sa);
int port;
- if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
+ if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
NET_ThrowNew(env, WSAGetLastError(), "getsockname");
return NULL;
}
- return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
+ return NET_SockaddrToInetAddress(env, &sa, &port);
}
JNIEXPORT jint JNICALL
@@ -257,7 +257,7 @@ Java_sun_nio_ch_Net_remotePort(JNIEnv *env, jclass clazz, jobject fdo)
SOCKETADDRESS sa;
int sa_len = sizeof(sa);
- if (getpeername(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
+ if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
int error = WSAGetLastError();
if (error == WSAEINVAL) {
return 0;
@@ -265,7 +265,7 @@ Java_sun_nio_ch_Net_remotePort(JNIEnv *env, jclass clazz, jobject fdo)
NET_ThrowNew(env, error, "getsockname");
return IOS_THROWN;
}
- return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
+ return NET_GetPortFromSockaddr(&sa);
}
JNIEXPORT jobject JNICALL
@@ -275,11 +275,11 @@ Java_sun_nio_ch_Net_remoteInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
int sa_len = sizeof(sa);
int port;
- if (getpeername(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
+ if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
NET_ThrowNew(env, WSAGetLastError(), "getsockname");
return NULL;
}
- return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
+ return NET_SockaddrToInetAddress(env, &sa, &port);
}
JNIEXPORT jint JNICALL
diff --git a/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c b/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c
index 8cd94eadaa9..83469c463c1 100644
--- a/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c
+++ b/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c
@@ -95,7 +95,7 @@ Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv *env, jobject this,
int addrlen = sizeof(sa);
memset((char *)&sa, 0, sizeof(sa));
- newfd = (jint)accept(ssfd, (struct sockaddr *)&sa, &addrlen);
+ newfd = (jint)accept(ssfd, &sa.sa, &addrlen);
if (newfd == INVALID_SOCKET) {
int theErr = (jint)WSAGetLastError();
if (theErr == WSAEWOULDBLOCK) {
@@ -107,7 +107,7 @@ Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv *env, jobject this,
SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
(*env)->SetIntField(env, newfdo, fd_fdID, newfd);
- remote_ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, (int *)&remote_port);
+ remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port);
diff --git a/jdk/src/java.base/windows/native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c b/jdk/src/java.base/windows/native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c
index b78f443937b..40b8d8ba8dc 100644
--- a/jdk/src/java.base/windows/native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c
+++ b/jdk/src/java.base/windows/native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c
@@ -88,26 +88,21 @@ JNIEXPORT jint JNICALL
Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_connect0(JNIEnv* env, jclass this,
jlong socket, jboolean preferIPv6, jobject iao, jint port, jlong ov)
{
- SOCKET s = (SOCKET) jlong_to_ptr(socket);
- OVERLAPPED* lpOverlapped = (OVERLAPPED*) jlong_to_ptr(ov);
+ SOCKET s = (SOCKET)jlong_to_ptr(socket);
+ OVERLAPPED *lpOverlapped = (OVERLAPPED *)jlong_to_ptr(ov);
SOCKETADDRESS sa;
- int sa_len;
+ int sa_len = 0;
BOOL res;
- if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
+ if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len,
+ preferIPv6) != 0) {
return IOS_THROWN;
}
ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED));
- res = (*ConnectEx_func)(s,
- (struct sockaddr *)&sa,
- sa_len,
- NULL,
- 0,
- NULL,
- lpOverlapped);
+ res = (*ConnectEx_func)(s, &sa.sa, sa_len, NULL, 0, NULL, lpOverlapped);
if (res == 0) {
int error = GetLastError();
if (error == ERROR_IO_PENDING) {
diff --git a/jdk/src/java.base/windows/native/libnio/ch/WindowsSelectorImpl.c b/jdk/src/java.base/windows/native/libnio/ch/WindowsSelectorImpl.c
index 7d5e1e77875..c6b5fa9b368 100644
--- a/jdk/src/java.base/windows/native/libnio/ch/WindowsSelectorImpl.c
+++ b/jdk/src/java.base/windows/native/libnio/ch/WindowsSelectorImpl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
#define FD_SETSIZE 1024
+#include
#include
#include
@@ -74,9 +75,19 @@ Java_sun_nio_ch_WindowsSelectorImpl_00024SubSelector_poll0(JNIEnv *env, jobject
} else if (timeout < 0) {
tv = NULL;
} else {
+ jlong sec = timeout / 1000;
tv = &timevalue;
- tv->tv_sec = (long)(timeout / 1000);
- tv->tv_usec = (long)((timeout % 1000) * 1000);
+ //
+ // struct timeval members are signed 32-bit integers so the
+ // signed 64-bit jlong needs to be clamped
+ //
+ if (sec > INT_MAX) {
+ tv->tv_sec = INT_MAX;
+ tv->tv_usec = 0;
+ } else {
+ tv->tv_sec = (long)sec;
+ tv->tv_usec = (long)((timeout % 1000) * 1000);
+ }
}
/* Set FD_SET structures required for select */
diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java
index 027cbcf67e6..e017b32538a 100644
--- a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java
@@ -123,7 +123,7 @@ class _AppMenuBarHandler {
}
// grab the pointer to the CMenuBar, and retain it in native
- nativeSetDefaultMenuBar(((CMenuBar)peer).getModel());
+ ((CMenuBar) peer).execute(_AppMenuBarHandler::nativeSetDefaultMenuBar);
}
void setAboutMenuItemVisible(final boolean present) {
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java
index da53c302ad5..d21de341fb4 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java
@@ -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
@@ -26,29 +26,28 @@
package sun.lwawt.macosx;
import java.awt.CheckboxMenuItem;
-import java.awt.EventQueue;
import java.awt.event.ItemEvent;
import java.awt.peer.CheckboxMenuItemPeer;
import sun.awt.SunToolkit;
public class CCheckboxMenuItem extends CMenuItem implements CheckboxMenuItemPeer {
- boolean fAutoToggle = true;
- boolean fIsIndeterminate = false;
+ volatile boolean fAutoToggle = true;
+ volatile boolean fIsIndeterminate = false;
private native void nativeSetState(long modelPtr, boolean state);
private native void nativeSetIsCheckbox(long modelPtr);
- CCheckboxMenuItem(CheckboxMenuItem target) {
+ CCheckboxMenuItem(final CheckboxMenuItem target) {
super(target);
- nativeSetIsCheckbox(getModel());
+ execute(this::nativeSetIsCheckbox);
setState(target.getState());
}
// MenuItemPeer implementation
@Override
- public void setState(boolean state) {
- nativeSetState(getModel(), state);
+ public void setState(final boolean state) {
+ execute(ptr -> nativeSetState(ptr, state));
}
public void handleAction(final boolean state) {
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java
index cec76f5c897..f69ad201ef8 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java
@@ -23,7 +23,6 @@
* questions.
*/
-
package sun.lwawt.macosx;
/**
@@ -34,6 +33,7 @@ public class CFRetainedResource {
private static native void nativeCFRelease(final long ptr, final boolean disposeOnAppKitThread);
private final boolean disposeOnAppKitThread;
+ // TODO this pointer should be private and accessed via CFNativeAction class
protected volatile long ptr;
/**
@@ -70,8 +70,72 @@ public class CFRetainedResource {
nativeCFRelease(oldPtr, disposeOnAppKitThread); // perform outside of the synchronized block
}
+ /**
+ * The interface which allows to execute some native operations with
+ * assumption that the native pointer will be valid till the end.
+ */
+ public interface CFNativeAction {
+
+ /**
+ * The native operation should be called from this method.
+ *
+ * @param ptr the pointer to the native data
+ */
+ void run(long ptr);
+ }
+
+ /**
+ * The interface which allows to execute some native operations and get a
+ * result with assumption that the native pointer will be valid till the
+ * end.
+ */
+ interface CFNativeActionGet {
+
+ /**
+ * The native operation should be called from this method.
+ *
+ * @param ptr the pointer to the native data
+ * @return result of the native operation
+ */
+ long run(long ptr);
+ }
+
+ /**
+ * This is utility method which should be used instead of the direct access
+ * to the {@link #ptr}, because this method guaranteed that the pointer will
+ * not be zero and will be valid till the end of the operation.It is highly
+ * recomended to not use any external lock in action. If the current
+ * {@link #ptr} is {@code 0} then action will be ignored.
+ *
+ * @param action The native operation
+ */
+ public final synchronized void execute(final CFNativeAction action) {
+ if (ptr != 0) {
+ action.run(ptr);
+ }
+ }
+
+ /**
+ * This is utility method which should be used instead of the direct access
+ * to the {@link #ptr}, because this method guaranteed that the pointer will
+ * not be zero and will be valid till the end of the operation. It is highly
+ * recomended to not use any external lock in action. If the current
+ * {@link #ptr} is {@code 0} then action will be ignored and {@code} is
+ * returned.
+ *
+ * @param action the native operation
+ * @return result of the native operation, usually the native pointer to
+ * some other data
+ */
+ final synchronized long executeGet(final CFNativeActionGet action) {
+ if (ptr != 0) {
+ return action.run(ptr);
+ }
+ return 0;
+ }
+
@Override
- protected void finalize() throws Throwable {
+ protected final void finalize() throws Throwable {
dispose();
}
}
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenu.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenu.java
index 9e1499b8de9..4f2fc96ad8a 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenu.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenu.java
@@ -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
@@ -25,7 +25,9 @@
package sun.lwawt.macosx;
-import java.awt.*;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
import java.awt.peer.MenuItemPeer;
import java.awt.peer.MenuPeer;
@@ -37,7 +39,7 @@ public class CMenu extends CMenuItem implements MenuPeer {
// This way we avoiding invocation of the setters twice
@Override
- protected void initialize(MenuItem target) {
+ protected final void initialize(MenuItem target) {
setLabel(target.getLabel());
setEnabled(target.isEnabled());
}
@@ -57,52 +59,50 @@ public class CMenu extends CMenuItem implements MenuPeer {
}
@Override
- protected long createModel() {
+ long createModel() {
CMenuComponent parent = (CMenuComponent)
LWCToolkit.targetToPeer(getTarget().getParent());
- if (parent instanceof CMenu ||
- parent instanceof CPopupMenu)
- {
- return nativeCreateSubMenu(parent.getModel());
- } else if (parent instanceof CMenuBar) {
+ if (parent instanceof CMenu) {
+ return parent.executeGet(this::nativeCreateSubMenu);
+ }
+ if (parent instanceof CMenuBar) {
MenuBar parentContainer = (MenuBar)getTarget().getParent();
boolean isHelpMenu = parentContainer.getHelpMenu() == getTarget();
int insertionLocation = ((CMenuBar)parent).getNextInsertionIndex();
- return nativeCreateMenu(parent.getModel(),
- isHelpMenu, insertionLocation);
- } else {
- throw new InternalError("Parent must be CMenu or CMenuBar");
+ return parent.executeGet(ptr -> nativeCreateMenu(ptr, isHelpMenu,
+ insertionLocation));
}
+ throw new InternalError("Parent must be CMenu or CMenuBar");
}
@Override
- public void addItem(MenuItem item) {
+ public final void addItem(MenuItem item) {
// Nothing to do here -- we added it when we created the
// menu item's peer.
}
@Override
- public void delItem(int index) {
- nativeDeleteItem(getModel(), index);
+ public final void delItem(final int index) {
+ execute(ptr -> nativeDeleteItem(ptr, index));
}
@Override
- public void setLabel(String label) {
- nativeSetMenuTitle(getModel(), label);
+ public final void setLabel(final String label) {
+ execute(ptr->nativeSetMenuTitle(ptr, label));
super.setLabel(label);
}
// Note that addSeparator is never called directly from java.awt.Menu,
// though it is required in the MenuPeer interface.
@Override
- public void addSeparator() {
- nativeAddSeparator(getModel());
+ public final void addSeparator() {
+ execute(this::nativeAddSeparator);
}
// Used by ScreenMenuBar to get to the native menu for event handling.
- public long getNativeMenu() {
- return nativeGetNSMenu(getModel());
+ public final long getNativeMenu() {
+ return executeGet(this::nativeGetNSMenu);
}
private native long nativeCreateMenu(long parentMenuPtr,
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuBar.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuBar.java
index 7d2aa7b7beb..3dd64a97422 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuBar.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuBar.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, 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
@@ -31,7 +31,7 @@ import java.awt.peer.MenuBarPeer;
import sun.awt.AWTAccessor;
-public class CMenuBar extends CMenuComponent implements MenuBarPeer {
+public final class CMenuBar extends CMenuComponent implements MenuBarPeer {
private int nextInsertionIndex = -1;
@@ -40,14 +40,15 @@ public class CMenuBar extends CMenuComponent implements MenuBarPeer {
}
@Override
- protected long createModel() {
+ long createModel() {
return nativeCreateMenuBar();
}
@Override
- public void addHelpMenu(Menu m) {
- CMenu cMenu = AWTAccessor.getMenuComponentAccessor().getPeer(m);
- nativeSetHelpMenu(getModel(), cMenu.getModel());
+ public void addHelpMenu(final Menu m) {
+ final CMenu cMenu = AWTAccessor.getMenuComponentAccessor().getPeer(m);
+ execute(parentPtr -> cMenu.execute(
+ menuPtr -> nativeSetHelpMenu(parentPtr, menuPtr)));
}
public int getNextInsertionIndex() {
@@ -65,8 +66,8 @@ public class CMenuBar extends CMenuComponent implements MenuBarPeer {
}
@Override
- public void delMenu(int index) {
- nativeDelMenu(getModel(), index);
+ public void delMenu(final int index) {
+ execute(ptr -> nativeDelMenu(ptr, index));
}
private native long nativeCreateMenuBar();
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuComponent.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuComponent.java
index 2dbc923859c..6100916be3e 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuComponent.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuComponent.java
@@ -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
@@ -29,36 +29,32 @@ import java.awt.Font;
import java.awt.MenuComponent;
import java.awt.peer.MenuComponentPeer;
-public abstract class CMenuComponent implements MenuComponentPeer {
+abstract class CMenuComponent extends CFRetainedResource
+ implements MenuComponentPeer {
- private MenuComponent target;
- private long modelPtr;
+ private final MenuComponent target;
- CMenuComponent(MenuComponent target) {
+ CMenuComponent(final MenuComponent target) {
+ super(0, true);
this.target = target;
- this.modelPtr = createModel();
+ setPtr(createModel());
}
- MenuComponent getTarget() {
+ final MenuComponent getTarget() {
return target;
}
- public long getModel() {
- return modelPtr;
- }
+ abstract long createModel();
- protected abstract long createModel();
-
- public void dispose() {
+ @Override
+ public final void dispose() {
+ super.dispose();
LWCToolkit.targetDisposedPeer(target, this);
- nativeDispose(modelPtr);
- target = null;
}
- private native void nativeDispose(long modelPtr);
-
// 1.5 peer method
- public void setFont(Font f) {
+ @Override
+ public final void setFont(final Font f) {
// no-op, as we don't currently support menu fonts
// c.f. radar 4032912
}
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuItem.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuItem.java
index 2fca524922b..0230c4e842f 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuItem.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CMenuItem.java
@@ -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
@@ -25,16 +25,17 @@
package sun.lwawt.macosx;
-import sun.awt.SunToolkit;
-import sun.lwawt.LWToolkit;
-
-import java.awt.MenuContainer;
import java.awt.MenuItem;
import java.awt.MenuShortcut;
-import java.awt.event.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
import java.awt.peer.MenuItemPeer;
import java.util.concurrent.atomic.AtomicBoolean;
+import sun.awt.SunToolkit;
+import sun.lwawt.LWToolkit;
+
public class CMenuItem extends CMenuComponent implements MenuItemPeer {
private final AtomicBoolean enabled = new AtomicBoolean(true);
@@ -58,9 +59,9 @@ public class CMenuItem extends CMenuComponent implements MenuItemPeer {
}
@Override
- protected long createModel() {
+ long createModel() {
CMenuComponent parent = (CMenuComponent)LWToolkit.targetToPeer(getTarget().getParent());
- return nativeCreate(parent.getModel(), isSeparator());
+ return parent.executeGet(ptr->nativeCreate(ptr, isSeparator()));
}
public void setLabel(String label, char keyChar, int keyCode, int modifiers) {
@@ -90,7 +91,12 @@ public class CMenuItem extends CMenuComponent implements MenuItemPeer {
keyChar = 0;
}
- nativeSetLabel(getModel(), label, keyChar, keyCode, keyMask);
+ final String finalLabel = label;
+ final char finalKeyChar = keyChar;
+ final int finalKeyCode = keyCode;
+ final int finalKeyMask = keyMask;
+ execute(ptr -> nativeSetLabel(ptr, finalLabel, finalKeyChar,
+ finalKeyCode, finalKeyMask));
}
@Override
@@ -105,16 +111,16 @@ public class CMenuItem extends CMenuComponent implements MenuItemPeer {
* There isn't a need to expose this except in a instanceof because
* it isn't defined in the peer api.
*/
- public void setImage(java.awt.Image img) {
+ public final void setImage(final java.awt.Image img) {
CImage cimg = CImage.getCreator().createFromImage(img);
- nativeSetImage(getModel(), cimg == null ? 0L : cimg.ptr);
+ execute(ptr -> nativeSetImage(ptr, cimg == null ? 0L : cimg.ptr));
}
/**
* New API for tooltips
*/
- public void setToolTipText(String text) {
- nativeSetTooltip(getModel(), text);
+ public final void setToolTipText(final String text) {
+ execute(ptr -> nativeSetTooltip(ptr, text));
}
// @Override
@@ -138,7 +144,8 @@ public class CMenuItem extends CMenuComponent implements MenuItemPeer {
b &= ((CMenuItem) parent).isEnabled();
}
if (enabled.compareAndSet(!b, b)) {
- nativeSetEnabled(getModel(), b);
+ final boolean finalB = b;
+ execute(ptr->nativeSetEnabled(ptr, finalB));
}
}
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java
index d0c8275dc7c..102851f3b87 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java
@@ -231,6 +231,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
private boolean isFullScreenAnimationOn;
private volatile boolean isInFullScreen;
+ private volatile boolean isIconifyAnimationActive;
private Window target;
private LWWindowPeer peer;
@@ -448,7 +449,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
final long nsWindowPtr = getNSWindowPtr();
CMenuBar mbPeer = (CMenuBar)LWToolkit.targetToPeer(mb);
if (mbPeer != null) {
- nativeSetNSWindowMenuBar(nsWindowPtr, mbPeer.getModel());
+ mbPeer.execute(ptr -> nativeSetNSWindowMenuBar(nsWindowPtr, ptr));
} else {
nativeSetNSWindowMenuBar(nsWindowPtr, 0);
}
@@ -997,6 +998,9 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
if (peer != null) {
peer.notifyIconify(iconify);
}
+ if (iconify) {
+ isIconifyAnimationActive = false;
+ }
}
private void deliverZoom(final boolean isZoomed) {
@@ -1071,6 +1075,17 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
return true;
}
+ private boolean isIconified() {
+ boolean isIconified = false;
+ if (target instanceof Frame) {
+ int state = ((Frame)target).getExtendedState();
+ if ((state & Frame.ICONIFIED) != 0) {
+ isIconified = true;
+ }
+ }
+ return isIconifyAnimationActive || isIconified;
+ }
+
private boolean isOneOfOwnersOrSelf(CPlatformWindow window) {
while (window != null) {
if (this == window) {
@@ -1094,11 +1109,14 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
// the windows are ordered above their nearest owner; ancestors of the window,
// which is going to become 'main window', are placed above their siblings.
CPlatformWindow rootOwner = getRootOwner();
- if (rootOwner.isVisible()) {
+ if (rootOwner.isVisible() && !rootOwner.isIconified()) {
CWrapper.NSWindow.orderFront(rootOwner.getNSWindowPtr());
}
- final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
- orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target));
+ // Do not order child windows of iconified owner.
+ if (!rootOwner.isIconified()) {
+ final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
+ orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target));
+ }
}
private void orderAboveSiblingsImpl(Window[] windows) {
@@ -1109,10 +1127,12 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
// Go through the list of windows and perform ordering.
for (Window w : windows) {
+ boolean iconified = false;
final Object p = componentAccessor.getPeer(w);
if (p instanceof LWWindowPeer) {
CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow();
- if (pw != null && pw.isVisible()) {
+ iconified = isIconified();
+ if (pw != null && pw.isVisible() && !iconified) {
// If the window is one of ancestors of 'main window' or is going to become main by itself,
// the window should be ordered above its siblings; otherwise the window is just ordered
// above its nearest parent.
@@ -1125,10 +1145,13 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
pw.applyWindowLevel(w);
}
}
- // Retrieve the child windows for each window from the list and store them for future use.
+ // Retrieve the child windows for each window from the list except iconified ones
+ // and store them for future use.
// Note: we collect data about child windows even for invisible owners, since they may have
// visible children.
- childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w)));
+ if (!iconified) {
+ childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w)));
+ }
}
// If some windows, which have just been ordered, have any child windows, let's start new iteration
// and order these child windows.
@@ -1149,6 +1172,10 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
// NATIVE CALLBACKS
// ----------------------------------------------------------------------
+ private void windowWillMiniaturize() {
+ isIconifyAnimationActive = true;
+ }
+
private void windowDidBecomeMain() {
if (checkBlockingAndOrder()) return;
// If it's not blocked, make sure it's above its siblings
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPopupMenu.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPopupMenu.java
index 67ddf91471a..b73f67a0f79 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPopupMenu.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPopupMenu.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, 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
@@ -25,18 +25,20 @@
package sun.lwawt.macosx;
-import java.awt.*;
+import java.awt.Component;
+import java.awt.Event;
+import java.awt.Point;
+import java.awt.PopupMenu;
import java.awt.peer.PopupMenuPeer;
-import sun.lwawt.LWWindowPeer;
+final class CPopupMenu extends CMenu implements PopupMenuPeer {
-public class CPopupMenu extends CMenu implements PopupMenuPeer {
CPopupMenu(PopupMenu target) {
super(target);
}
@Override
- protected long createModel() {
+ long createModel() {
return nativeCreatePopupMenu();
}
@@ -50,7 +52,7 @@ public class CPopupMenu extends CMenu implements PopupMenuPeer {
Point loc = origin.getLocationOnScreen();
e.x += loc.x;
e.y += loc.y;
- nativeShowPopupMenu(getModel(), e.x, e.y);
+ execute(ptr -> nativeShowPopupMenu(ptr, e.x, e.y));
}
}
}
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java
index abd092b8be9..bcbb242f949 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, 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
@@ -118,7 +118,10 @@ public class CTrayIcon extends CFRetainedResource implements TrayIconPeer {
}
}
- return checkAndCreatePopupPeer().getModel();
+ // This method is executed on Appkit, so if ptr is not zero means that,
+ // it is still not deallocated(even if we call NSApp postRunnableEvent)
+ // and sent CFRelease to the native queue
+ return checkAndCreatePopupPeer().ptr;
}
/**
diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m
index ca983d031c1..03829b3dc1a 100644
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m
@@ -327,10 +327,43 @@ AWT_ASSERT_APPKIT_THREAD;
return [window isKindOfClass: [AWTWindow_Panel class]] || [window isKindOfClass: [AWTWindow_Normal class]];
}
+// Retrieves the list of possible window layers (levels)
++ (NSArray*) getWindowLayers {
+ static NSArray *windowLayers;
+ static dispatch_once_t token;
+
+ // Initialize the list of possible window layers
+ dispatch_once(&token, ^{
+ // The layers are ordered from front to back, (i.e. the toppest one is the first)
+ windowLayers = [NSArray arrayWithObjects:
+ [NSNumber numberWithInt:CGWindowLevelForKey(kCGPopUpMenuWindowLevelKey)],
+ [NSNumber numberWithInt:CGWindowLevelForKey(kCGFloatingWindowLevelKey)],
+ [NSNumber numberWithInt:CGWindowLevelForKey(kCGNormalWindowLevelKey)],
+ nil
+ ];
+ [windowLayers retain];
+ });
+ return windowLayers;
+}
+
// returns id for the topmost window under mouse
+ (NSInteger) getTopmostWindowUnderMouseID {
NSInteger result = -1;
+ NSArray *windowLayers = [AWTWindow getWindowLayers];
+ // Looking for the window under mouse starting from the toppest layer
+ for (NSNumber *layer in windowLayers) {
+ result = [AWTWindow getTopmostWindowUnderMouseIDImpl:[layer integerValue]];
+ if (result != -1) {
+ break;
+ }
+ }
+ return result;
+}
+
++ (NSInteger) getTopmostWindowUnderMouseIDImpl:(NSInteger)windowLayer {
+ NSInteger result = -1;
+
NSRect screenRect = [[NSScreen mainScreen] frame];
NSPoint nsMouseLocation = [NSEvent mouseLocation];
CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y);
@@ -339,7 +372,7 @@ AWT_ASSERT_APPKIT_THREAD;
for (NSDictionary *window in windows) {
NSInteger layer = [[window objectForKey:(id)kCGWindowLayer] integerValue];
- if (layer == 0) {
+ if (layer == windowLayer) {
CGRect rect;
CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect);
if (CGRectContainsPoint(rect, cgMouseLocation)) {
@@ -639,6 +672,14 @@ AWT_ASSERT_APPKIT_THREAD;
AWT_ASSERT_APPKIT_THREAD;
self.isMinimizing = YES;
+
+ JNIEnv *env = [ThreadUtilities getJNIEnv];
+ jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
+ if (platformWindow != NULL) {
+ static JNF_MEMBER_CACHE(jm_windowWillMiniaturize, jc_CPlatformWindow, "windowWillMiniaturize", "()V");
+ JNFCallVoidMethod(env, platformWindow, jm_windowWillMiniaturize);
+ (*env)->DeleteLocalRef(env, platformWindow);
+ }
// Excplicitly make myself a key window to avoid possible
// negative visual effects during iconify operation
[self.nsWindow makeKeyAndOrderFront:self.nsWindow];
diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenu.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenu.m
index 43b08f09d2c..fe42ac75247 100644
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenu.m
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenu.m
@@ -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
@@ -38,7 +38,7 @@
- (id)initWithPeer:(jobject)peer {
AWT_ASSERT_APPKIT_THREAD;
// Create the new NSMenu
- self = [super initWithPeer:peer asSeparator:[NSNumber numberWithBool:NO]];
+ self = [super initWithPeer:peer asSeparator:NO];
if (self) {
fMenu = [NSMenu javaMenuWithTitle:@""];
[fMenu retain];
@@ -133,14 +133,13 @@ AWT_ASSERT_APPKIT_THREAD;
CMenu * createCMenu (jobject cPeerObjGlobal) {
- CMenu *aCMenu = nil;
+ __block CMenu *aCMenu = nil;
- // We use an array here only to be able to get a return value
- NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil];
+ [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
- [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenu alloc] withObject:args waitUntilDone:YES];
-
- aCMenu = (CMenu *)[args objectAtIndex: 0];
+ aCMenu = [[CMenu alloc] initWithPeer:cPeerObjGlobal];
+ // the aCMenu is released in CMenuComponent.dispose()
+ }];
if (aCMenu == nil) {
return 0L;
diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuBar.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuBar.m
index 34ba099331b..2de86be755b 100644
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuBar.m
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuBar.m
@@ -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
@@ -383,27 +383,20 @@ JNIEXPORT jlong JNICALL
Java_sun_lwawt_macosx_CMenuBar_nativeCreateMenuBar
(JNIEnv *env, jobject peer)
{
- CMenuBar *aCMenuBar = nil;
+ __block CMenuBar *aCMenuBar = nil;
JNF_COCOA_ENTER(env);
jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);
- // We use an array here only to be able to get a return value
- NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil];
-
- [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenuBar alloc] withObject:args waitUntilDone:YES];
-
- aCMenuBar = (CMenuBar *)[args objectAtIndex: 0];
+ [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
+ aCMenuBar = [[CMenuBar alloc] initWithPeer:cPeerObjGlobal];
+ // the aCMenuBar is released in CMenuComponent.dispose()
+ }];
if (aCMenuBar == nil) {
return 0L;
}
- // [args release];
-
- // A strange memory managment after that.
-
-
JNF_COCOA_EXIT(env);
return ptr_to_jlong(aCMenuBar);
}
diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuComponent.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuComponent.m
index c3bff14241c..cf093cd650c 100644
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuComponent.m
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuComponent.m
@@ -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
@@ -41,45 +41,11 @@
return self;
}
--(void) cleanup {
- // Used by subclasses
-}
-
--(void) disposer {
+- (void)dealloc {
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
JNFDeleteGlobalRef(env, fPeer);
fPeer = NULL;
- [self cleanup];
- [self release];
+ [super dealloc];
}
-
-// The method is used by all subclasses, since the process of the creation
-// is the same. The only exception is the CMenuItem class.
-- (void) _create_OnAppKitThread: (NSMutableArray *)argValue {
- jobject cPeerObjGlobal = (jobject)[[argValue objectAtIndex: 0] pointerValue];
- CMenuItem *aCMenuItem = [self initWithPeer:cPeerObjGlobal];
- [argValue removeAllObjects];
- [argValue addObject: aCMenuItem];
-}
-
@end
-
-/*
- * Class: sun_lwawt_macosx_CMenuComponent
- * Method: nativeDispose
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL
-Java_sun_lwawt_macosx_CMenuComponent_nativeDispose
-(JNIEnv *env, jobject peer, jlong menuItemObj)
-{
-JNF_COCOA_ENTER(env);
-
- [ThreadUtilities performOnMainThread:@selector(disposer)
- on:((id)jlong_to_ptr(menuItemObj))
- withObject:nil
- waitUntilDone:NO];
-
-JNF_COCOA_EXIT(env);
-}
diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.h b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.h
index 60a0565f3f6..e2c72f2e539 100644
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.h
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, 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
@@ -32,7 +32,7 @@
}
// Setup
-- (id) initWithPeer:(jobject)peer asSeparator: (NSNumber *) asSeparator;
+- (id) initWithPeer:(jobject)peer asSeparator: (BOOL) asSeparator;
- (void) setIsCheckbox;
// Events
diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m
index bcf7893005c..c9cc97ae21e 100644
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014, 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
@@ -39,11 +39,11 @@
@implementation CMenuItem
-- (id) initWithPeer:(jobject)peer asSeparator: (NSNumber *) asSeparator{
+- (id) initWithPeer:(jobject)peer asSeparator: (BOOL) asSeparator{
AWT_ASSERT_APPKIT_THREAD;
self = [super initWithPeer:peer];
if (self) {
- if ([asSeparator boolValue]) {
+ if (asSeparator) {
fMenuItem = (NSMenuItem*)[NSMenuItem separatorItem];
[fMenuItem retain];
} else {
@@ -204,12 +204,9 @@
}];
}
-- (void)cleanup {
+- (void)dealloc {
[fMenuItem setAction:NULL];
[fMenuItem setTarget:nil];
-}
-
-- (void)dealloc {
[fMenuItem release];
fMenuItem = nil;
@@ -228,14 +225,6 @@
fIsCheckbox = YES;
}
-- (void) _createMenuItem_OnAppKitThread: (NSMutableArray *)argValue {
- jobject cPeerObjGlobal = (jobject)[[argValue objectAtIndex: 0] pointerValue];
- NSNumber * asSeparator = (NSNumber *)[argValue objectAtIndex: 1];
- CMenuItem *aCMenuItem = [self initWithPeer: cPeerObjGlobal asSeparator: asSeparator];
- [argValue removeAllObjects];
- [argValue addObject: aCMenuItem];
-}
-
- (NSString *)description {
return [NSString stringWithFormat:@"CMenuItem[ %@ ]", fMenuItem];
}
@@ -397,24 +386,18 @@ Java_sun_lwawt_macosx_CMenuItem_nativeCreate
(JNIEnv *env, jobject peer, jlong parentCMenuObj, jboolean isSeparator)
{
- CMenuItem *aCMenuItem = nil;
+ __block CMenuItem *aCMenuItem = nil;
+ BOOL asSeparator = (isSeparator == JNI_TRUE) ? YES: NO;
CMenu *parentCMenu = (CMenu *)jlong_to_ptr(parentCMenuObj);
JNF_COCOA_ENTER(env);
jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);
-
- NSMutableArray *args = nil;
-
- // Create a new item....
- if (isSeparator == JNI_TRUE) {
- args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:YES], nil];
- } else {
- args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:NO], nil];
- }
-
- [ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) on:[CMenuItem alloc] withObject:args waitUntilDone:YES];
-
- aCMenuItem = (CMenuItem *)[args objectAtIndex: 0];
+
+ [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
+ aCMenuItem = [[CMenuItem alloc] initWithPeer: cPeerObjGlobal
+ asSeparator: asSeparator];
+ // the CMenuItem is released in CMenuComponent.dispose()
+ }];
if (aCMenuItem == nil) {
return 0L;
diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
index 79a31fd71b0..a2d7e7ecafc 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
@@ -735,7 +735,11 @@ public class PNGImageReader extends ImageReader {
parse_iCCP_chunk(chunkLength);
break;
case iTXt_TYPE:
- parse_iTXt_chunk(chunkLength);
+ if (ignoreMetadata) {
+ stream.skipBytes(chunkLength);
+ } else {
+ parse_iTXt_chunk(chunkLength);
+ }
break;
case pHYs_TYPE:
parse_pHYs_chunk();
@@ -759,7 +763,11 @@ public class PNGImageReader extends ImageReader {
parse_tRNS_chunk(chunkLength);
break;
case zTXt_TYPE:
- parse_zTXt_chunk(chunkLength);
+ if (ignoreMetadata) {
+ stream.skipBytes(chunkLength);
+ } else {
+ parse_zTXt_chunk(chunkLength);
+ }
break;
default:
// Read an unknown chunk
diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java
index 3ccc3cd9233..8f95e5502f6 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -730,18 +730,47 @@ public class TIFFImageReader extends ImageReader {
// to use it if the data layout is component type.
if (iccProfileField != null
&& itsRaw.getColorModel() instanceof ComponentColorModel) {
- // Create a ColorSpace from the profile.
- byte[] iccProfileValue = iccProfileField.getAsBytes();
- ICC_Profile iccProfile
- = ICC_Profile.getInstance(iccProfileValue);
- ICC_ColorSpace iccColorSpace
- = new ICC_ColorSpace(iccProfile);
-
// Get the raw sample and color information.
ColorModel cmRaw = itsRaw.getColorModel();
ColorSpace csRaw = cmRaw.getColorSpace();
SampleModel smRaw = itsRaw.getSampleModel();
+ ColorSpace iccColorSpace = null;
+ try {
+ // Create a ColorSpace from the profile.
+ byte[] iccProfileValue = iccProfileField.getAsBytes();
+ ICC_Profile iccProfile
+ = ICC_Profile.getInstance(iccProfileValue);
+ iccColorSpace = new ICC_ColorSpace(iccProfile);
+
+ // Workaround for JDK-8145241: test a conversion and fall
+ // back to a standard ColorSpace if it fails. This
+ // workaround could be removed if JDK-8145241 is fixed.
+ float[] rgb =
+ iccColorSpace.toRGB(new float[] {1.0F, 1.0F, 1.0F});
+ } catch (Exception iccProfileException) {
+ processWarningOccurred("Superseding bad ICC profile: "
+ + iccProfileException.getMessage());
+
+ if (iccColorSpace != null) {
+ switch (iccColorSpace.getType()) {
+ case ColorSpace.TYPE_GRAY:
+ iccColorSpace =
+ ColorSpace.getInstance(ColorSpace.CS_GRAY);
+ break;
+ case ColorSpace.TYPE_RGB:
+ iccColorSpace =
+ ColorSpace.getInstance(ColorSpace.CS_sRGB);
+ break;
+ default:
+ iccColorSpace = csRaw;
+ break;
+ }
+ } else {
+ iccColorSpace = csRaw;
+ }
+ }
+
// Get the number of samples per pixel and the number
// of color components.
int numBands = smRaw.getNumBands();
diff --git a/jdk/src/java.desktop/share/classes/java/beans/AppletInitializer.java b/jdk/src/java.desktop/share/classes/java/beans/AppletInitializer.java
index 50c54643209..1e2a99b357c 100644
--- a/jdk/src/java.desktop/share/classes/java/beans/AppletInitializer.java
+++ b/jdk/src/java.desktop/share/classes/java/beans/AppletInitializer.java
@@ -30,21 +30,20 @@ import java.applet.Applet;
import java.beans.beancontext.BeanContext;
/**
- *
* This interface is designed to work in collusion with java.beans.Beans.instantiate.
* The interface is intended to provide mechanism to allow the proper
* initialization of JavaBeans that are also Applets, during their
* instantiation by java.beans.Beans.instantiate().
- *
*
* @see java.beans.Beans#instantiate
*
* @since 1.2
*
+ * @deprecated The Applet API is deprecated. See the
+ * java.applet package
+ * documentation for further information.
*/
-
-
-@SuppressWarnings("deprecation")
+@Deprecated(since = "9")
public interface AppletInitializer {
/**
@@ -74,7 +73,6 @@ public interface AppletInitializer {
* @param bCtxt The BeanContext intended for this Applet, or
* null.
*/
-
void initialize(Applet newAppletBean, BeanContext bCtxt);
/**
@@ -86,6 +84,5 @@ public interface AppletInitializer {
*
* @param newApplet The newly instantiated JavaBean
*/
-
void activate(Applet newApplet);
}
diff --git a/jdk/src/java.desktop/share/classes/java/beans/Beans.java b/jdk/src/java.desktop/share/classes/java/beans/Beans.java
index 43e5c42ffd0..c8b820bb4dc 100644
--- a/jdk/src/java.desktop/share/classes/java/beans/Beans.java
+++ b/jdk/src/java.desktop/share/classes/java/beans/Beans.java
@@ -97,8 +97,10 @@ public class Beans {
* @exception IOException if an I/O error occurs.
* @since 1.2
*/
-
- public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext) throws IOException, ClassNotFoundException {
+ @SuppressWarnings("deprecation")
+ public static Object instantiate(ClassLoader cls, String beanName,
+ BeanContext beanContext)
+ throws IOException, ClassNotFoundException {
return Beans.instantiate(cls, beanName, beanContext, null);
}
@@ -153,10 +155,18 @@ public class Beans {
* object could not be found.
* @exception IOException if an I/O error occurs.
* @since 1.2
+ *
+ * @deprecated It is recommended to use
+ * {@link #instantiate(ClassLoader, String, BeanContext)},
+ * because the Applet API is deprecated. See the
+ * java.applet package
+ * documentation for further information.
*/
- @SuppressWarnings("deprecation")
- public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext, AppletInitializer initializer)
- throws IOException, ClassNotFoundException {
+ @Deprecated(since = "9")
+ public static Object instantiate(ClassLoader cls, String beanName,
+ BeanContext beanContext,
+ AppletInitializer initializer)
+ throws IOException, ClassNotFoundException {
InputStream ins;
ObjectInputStream oins = null;
@@ -501,7 +511,7 @@ class ObjectInputStreamWithLoader extends ObjectInputStream
* Package private support class. This provides a default AppletContext
* for beans which are applets.
*/
-@SuppressWarnings("deprecation")
+@Deprecated(since = "9")
class BeansAppletContext implements AppletContext {
Applet target;
Hashtable imageCache = new Hashtable<>();
@@ -586,7 +596,7 @@ class BeansAppletContext implements AppletContext {
* Package private support class. This provides an AppletStub
* for beans which are applets.
*/
-@SuppressWarnings("deprecation")
+@Deprecated(since = "9")
class BeansAppletStub implements AppletStub {
transient boolean active;
transient Applet target;
diff --git a/jdk/src/java.desktop/share/classes/javax/swing/PopupFactory.java b/jdk/src/java.desktop/share/classes/javax/swing/PopupFactory.java
index d45390709cc..4343ae15984 100644
--- a/jdk/src/java.desktop/share/classes/javax/swing/PopupFactory.java
+++ b/jdk/src/java.desktop/share/classes/javax/swing/PopupFactory.java
@@ -260,6 +260,7 @@ public class PopupFactory {
* Obtains the appropriate Popup based on
* popupType.
*/
+ @SuppressWarnings("deprecation")
private Popup getPopup(Component owner, Component contents,
int ownerX, int ownerY, int popupType) {
if (GraphicsEnvironment.isHeadless()) {
diff --git a/jdk/src/java.desktop/share/classes/javax/swing/RepaintManager.java b/jdk/src/java.desktop/share/classes/javax/swing/RepaintManager.java
index 8737b6bb760..93bae569daa 100644
--- a/jdk/src/java.desktop/share/classes/javax/swing/RepaintManager.java
+++ b/jdk/src/java.desktop/share/classes/javax/swing/RepaintManager.java
@@ -525,8 +525,12 @@ public class RepaintManager
* @param h Height of the region to repaint
* @see JApplet#repaint
* @since 1.6
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * java.applet package
+ * documentation for further information.
*/
- @SuppressWarnings("deprecation")
+ @Deprecated(since = "9")
public void addDirtyRegion(Applet applet, int x, int y, int w, int h) {
addDirtyRegion0(applet, x, y, w, h);
}
diff --git a/jdk/src/java.desktop/share/classes/javax/swing/TablePrintable.java b/jdk/src/java.desktop/share/classes/javax/swing/TablePrintable.java
index b47f8696662..4c8eb0529ab 100644
--- a/jdk/src/java.desktop/share/classes/javax/swing/TablePrintable.java
+++ b/jdk/src/java.desktop/share/classes/javax/swing/TablePrintable.java
@@ -380,6 +380,12 @@ class TablePrintable implements Printable {
// print the current section of the table
g2d.translate(-clip.x, -clip.y);
g2d.clip(clip);
+
+ // set a property so that BasicTableUI#paint can know JTable printMode
+ // is FIT_WIDTH since TablePrintable.printMode is not accessible from BasicTableUI
+ if (printMode == JTable.PrintMode.FIT_WIDTH) {
+ table.putClientProperty("Table.printMode", JTable.PrintMode.FIT_WIDTH);
+ }
table.print(g2d);
// restore the original transform and clip
@@ -407,8 +413,18 @@ class TablePrintable implements Printable {
for(int visrow = rMin; visrow < rMax; visrow++) {
rowHeight += table.getRowHeight(visrow);
}
- g2d.drawRect(0, 0, visibleBounds.width, hclip.height + rowHeight);
+ // If PrintMode is FIT_WIDTH, then draw rect for entire column width while
+ // printing irrespective of how many columns are visible in console
+ if (printMode == JTable.PrintMode.FIT_WIDTH) {
+ g2d.drawRect(0, 0, clip.width, hclip.height + rowHeight);
+ } else {
+ g2d.drawRect(0, 0, visibleBounds.width, hclip.height + rowHeight);
+ }
+ // clear the property
+ if (printMode == JTable.PrintMode.FIT_WIDTH) {
+ table.putClientProperty("Table.printMode", null);
+ }
// dispose the graphics copy
g2d.dispose();
@@ -534,5 +550,4 @@ class TablePrintable implements Printable {
} while (clip.width + colWidth <= pw);
}
-
}
diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java
index ffa4e603950..b80d7efa54a 100644
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java
@@ -1812,12 +1812,12 @@ public class BasicTableUI extends TableUI
}
boolean ltr = table.getComponentOrientation().isLeftToRight();
-
+ Point upperLeft, lowerRight;
// compute the visible part of table which needs to be painted
Rectangle visibleBounds = clip.intersection(bounds);
- Point upperLeft = visibleBounds.getLocation();
- Point lowerRight = new Point(visibleBounds.x + visibleBounds.width - 1,
- visibleBounds.y + visibleBounds.height - 1);
+ upperLeft = visibleBounds.getLocation();
+ lowerRight = new Point(visibleBounds.x + visibleBounds.width - 1,
+ visibleBounds.y + visibleBounds.height - 1);
int rMin = table.rowAtPoint(upperLeft);
int rMax = table.rowAtPoint(lowerRight);
@@ -1834,6 +1834,18 @@ public class BasicTableUI extends TableUI
rMax = table.getRowCount()-1;
}
+ // For FIT_WIDTH, all columns should be printed irrespective of
+ // how many columns are visible. So, we used clip which is already set to
+ // total col width instead of visible region
+ // Since JTable.PrintMode is not accessible
+ // from here, we aet "Table.printMode" in TablePrintable#print and
+ // access from here.
+ Object printMode = table.getClientProperty("Table.printMode");
+ if ((printMode == JTable.PrintMode.FIT_WIDTH)) {
+ upperLeft = clip.getLocation();
+ lowerRight = new Point(clip.x + clip.width - 1,
+ clip.y + clip.height - 1);
+ }
int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);
int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);
// This should never happen.
@@ -2018,7 +2030,7 @@ public class BasicTableUI extends TableUI
int y = damagedArea.y;
for (int row = rMin; row <= rMax; row++) {
y += table.getRowHeight(row);
- g.drawLine(damagedArea.x, y - 1, tableWidth - 1, y - 1);
+ SwingUtilities2.drawHLine(g, damagedArea.x, tableWidth - 1, y - 1);
}
}
if (table.getShowVerticalLines()) {
@@ -2030,14 +2042,14 @@ public class BasicTableUI extends TableUI
for (int column = cMin; column <= cMax; column++) {
int w = cm.getColumn(column).getWidth();
x += w;
- g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
+ SwingUtilities2.drawVLine(g, x - 1, 0, tableHeight - 1);
}
} else {
x = damagedArea.x;
for (int column = cMax; column >= cMin; column--) {
int w = cm.getColumn(column).getWidth();
x += w;
- g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
+ SwingUtilities2.drawVLine(g, x - 1, 0, tableHeight - 1);
}
}
}
diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/PasswordView.java b/jdk/src/java.desktop/share/classes/javax/swing/text/PasswordView.java
index 7da3fa313b2..38bb0eec13e 100644
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/PasswordView.java
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/PasswordView.java
@@ -27,10 +27,7 @@ package javax.swing.text;
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
@@ -332,22 +329,6 @@ public class PasswordView extends FieldView {
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() {
- @Override
- public Boolean run() {
- Class>[] intTypes = {Graphics.class, INT, INT, CHAR};
- Class>[] fpTypes = {Graphics2D.class, FP, FP, CHAR};
- return isFPMethodOverriden("drawEchoCharacter", CLS, intTypes, fpTypes);
- }
- });
- }
+ private final boolean drawEchoCharacterOverridden =
+ getFPMethodOverridden(getClass(), "drawEchoCharacter", FPMethodArgs.GNNC);
}
diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/PlainView.java b/jdk/src/java.desktop/share/classes/javax/swing/text/PlainView.java
index e04c95aecd6..4430b4e1c89 100644
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/PlainView.java
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/PlainView.java
@@ -32,6 +32,8 @@ import java.security.PrivilegedAction;
import java.util.Objects;
import javax.swing.event.*;
import java.lang.reflect.Module;
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
/**
* Implements View interface for a simple multi-line text view
@@ -818,10 +820,45 @@ public class PlainView extends View implements TabExpander {
return w;
}
- static boolean isFPMethodOverriden(String method,
- Class> cls,
- Class>[] intTypes,
- Class>[] fpTypes)
+ static boolean getFPMethodOverridden(Class> cls, String method,
+ FPMethodArgs methodArgs) {
+ HashMap map = null;
+ boolean initialized = methodsOverriddenMapRef != null
+ && (map = methodsOverriddenMapRef.get()) != null;
+
+ if (!initialized) {
+ map = new HashMap<>();
+ methodsOverriddenMapRef = new SoftReference<>(map);
+ }
+
+ FPMethodItem key = new FPMethodItem(cls, method);
+ Boolean isFPMethodOverridden = map.get(key);
+ if (isFPMethodOverridden == null) {
+ isFPMethodOverridden = checkFPMethodOverridden(cls, method, methodArgs);
+ map.put(key, isFPMethodOverridden);
+ }
+ return isFPMethodOverridden;
+ }
+
+ private static boolean checkFPMethodOverridden(final Class> className,
+ final String methodName,
+ final FPMethodArgs methodArgs) {
+
+ return AccessController
+ .doPrivileged(new PrivilegedAction() {
+ @Override
+ public Boolean run() {
+ return isFPMethodOverridden(methodName, className,
+ methodArgs.getMethodArguments(false),
+ methodArgs.getMethodArguments(true));
+ }
+ });
+ }
+
+ private static boolean isFPMethodOverridden(String method,
+ Class> cls,
+ Class>[] intTypes,
+ Class>[] fpTypes)
{
Module thisModule = PlainView.class.getModule();
while (!thisModule.equals(cls.getModule())) {
@@ -840,6 +877,57 @@ public class PlainView extends View implements TabExpander {
return true;
}
+ enum FPMethodArgs {
+
+ IGNN,
+ IIGNN,
+ GNNII,
+ GNNC;
+
+ public Class>[] getMethodArguments(boolean isFPType) {
+ Class> N = (isFPType) ? Float.TYPE : Integer.TYPE;
+ Class> G = (isFPType) ? Graphics2D.class : Graphics.class;
+ switch (this) {
+ case IGNN:
+ return new Class>[]{Integer.TYPE, G, N, N};
+ case IIGNN:
+ return new Class>[]{Integer.TYPE, Integer.TYPE, G, N, N};
+ case GNNII:
+ return new Class>[]{G, N, N, Integer.TYPE, Integer.TYPE};
+ case GNNC:
+ return new Class>[]{G, N, N, Character.TYPE};
+ default:
+ throw new RuntimeException("Unknown method arguments!");
+ }
+ }
+ }
+
+ private static class FPMethodItem {
+
+ final Class> className;
+ final String methodName;
+
+ public FPMethodItem(Class> className, String methodName) {
+ this.className = className;
+ this.methodName = methodName;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof FPMethodItem) {
+ FPMethodItem that = (FPMethodItem) obj;
+ return this.className.equals(that.className)
+ && this.methodName.equals(that.methodName);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * methodName.hashCode() + className.hashCode();
+ }
+ }
+
// --- member variables -----------------------------------------------
/**
@@ -878,46 +966,13 @@ public class PlainView extends View implements TabExpander {
*/
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() {
- @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() {
- @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() {
- @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;
- }
+ private static SoftReference> methodsOverriddenMapRef;
+ final boolean drawLineOverridden =
+ getFPMethodOverridden(getClass(), "drawLine", FPMethodArgs.IGNN);
+ final boolean drawSelectedTextOverridden =
+ getFPMethodOverridden(getClass(), "drawSelectedText", FPMethodArgs.GNNII);
+ final boolean drawUnselectedTextOverridden =
+ getFPMethodOverridden(getClass(), "drawUnselectedText", FPMethodArgs.GNNII);
+ final boolean useFloatingPointAPI =
+ drawUnselectedTextOverridden || drawSelectedTextOverridden;
}
diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java b/jdk/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java
index dde3437adf4..7cb83f755c2 100644
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java
@@ -28,10 +28,9 @@ import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.lang.ref.SoftReference;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import javax.swing.event.*;
-import static javax.swing.text.PlainView.isFPMethodOverriden;
+import static javax.swing.text.PlainView.FPMethodArgs.*;
+import static javax.swing.text.PlainView.getFPMethodOverridden;
/**
* View of plain text (text with only one font and color)
@@ -989,46 +988,12 @@ public class WrappedPlainView extends BoxView implements TabExpander {
SoftReference 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() {
- @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() {
- @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() {
- @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;
- }
+ private final boolean drawLineOverridden =
+ getFPMethodOverridden(getClass(), "drawLine", IIGNN);
+ private final boolean drawSelectedTextOverridden =
+ getFPMethodOverridden(getClass(), "drawSelectedText", GNNII);
+ private final boolean drawUnselectedTextOverridden =
+ getFPMethodOverridden(getClass(), "drawUnselectedText", GNNII);
+ private final boolean useFloatingPointAPI =
+ drawUnselectedTextOverridden || drawSelectedTextOverridden;
}
diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletEvent.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletEvent.java
index 9b7e9c25526..6a1a5880fc8 100644
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletEvent.java
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletEvent.java
@@ -32,8 +32,13 @@ import java.util.EventObject;
* AppletEvent class.
*
* @author Sunita Mani
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * java.applet package
+ * documentation for further information.
*/
@SuppressWarnings("serial") // JDK-implementation class
+@Deprecated(since = "9")
public class AppletEvent extends EventObject {
private Object arg;
diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletEventMulticaster.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletEventMulticaster.java
index 6889240a1c4..31542d0665b 100644
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletEventMulticaster.java
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletEventMulticaster.java
@@ -36,7 +36,12 @@ import java.io.IOException;
* responsible for dispatching events to them.
*
* @author Sunita Mani
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * java.applet package
+ * documentation for further information.
*/
+@Deprecated(since = "9")
public class AppletEventMulticaster implements AppletListener {
private final AppletListener a, b;
diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletIOException.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletIOException.java
index de435906e17..e8bd4e0bf75 100644
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletIOException.java
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletIOException.java
@@ -31,10 +31,14 @@ import java.io.IOException;
* An applet IO exception.
*
* @author Koji Uno
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * java.applet package
+ * documentation for further information.
*/
@SuppressWarnings("serial") // JDK implementation class
-public
-class AppletIOException extends IOException {
+@Deprecated(since = "9")
+public class AppletIOException extends IOException {
private String key = null;
private Object msgobj = null;
diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletIllegalArgumentException.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletIllegalArgumentException.java
index 292bd957053..750d09d3113 100644
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletIllegalArgumentException.java
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletIllegalArgumentException.java
@@ -29,10 +29,14 @@ package sun.applet;
* An applet security exception.
*
* @author Arthur van Hoff
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * java.applet package
+ * documentation for further information.
*/
@SuppressWarnings("serial") // JDK implementation class
-public
-class AppletIllegalArgumentException extends IllegalArgumentException {
+@Deprecated(since = "9")
+public class AppletIllegalArgumentException extends IllegalArgumentException {
private String key = null;
public AppletIllegalArgumentException(String key) {
diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletImageRef.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletImageRef.java
index e3eb5a26fb1..bdda032a8ff 100644
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletImageRef.java
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletImageRef.java
@@ -31,6 +31,7 @@ import java.lang.ref.SoftReference;
import sun.awt.image.URLImageSource;
import java.net.URL;
+@Deprecated(since = "9")
class AppletImageRef {
private SoftReference soft = null;
diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletListener.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletListener.java
index 00664938251..728060326ad 100644
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletListener.java
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletListener.java
@@ -32,8 +32,12 @@ import java.util.EventListener;
* by objects interested in AppletEvents.
*
* @author Sunita Mani
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * java.applet package
+ * documentation for further information.
*/
-
+@Deprecated(since = "9")
public interface AppletListener extends EventListener {
public void appletStateChanged(AppletEvent e);
}
diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletObjectInputStream.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletObjectInputStream.java
index 0906136bfec..689529b77e0 100644
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletObjectInputStream.java
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletObjectInputStream.java
@@ -34,8 +34,12 @@ import java.lang.reflect.Array;
/**
* This subclass of ObjectInputStream delegates loading of classes to
* an existing ClassLoader.
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * java.applet package
+ * documentation for further information.
*/
-
+@Deprecated(since = "9")
class AppletObjectInputStream extends ObjectInputStream
{
private AppletClassLoader loader;
diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java
index fc8eaac0845..221314ad04d 100644
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java
@@ -52,9 +52,14 @@ import sun.security.util.SecurityConstants;
* thread group to call the applet's init(), start(), stop(), and
* destroy() methods.
*
+ * @deprecated The Applet API is deprecated. See the
+ * java.applet package
+ * documentation for further information.
+ *
* @author Arthur van Hoff
*/
-@SuppressWarnings({"serial", "deprecation"}) // JDK implementation class
+@SuppressWarnings({"serial"}) // JDK implementation class
+@Deprecated(since = "9")
public
abstract class AppletPanel extends Panel implements AppletStub, Runnable {
diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletProps.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletProps.java
index f78e4160209..bb30abe9897 100644
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletProps.java
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletProps.java
@@ -36,6 +36,7 @@ import java.security.PrivilegedActionException;
import sun.security.action.*;
@SuppressWarnings("serial") // JDK implementation class
+@Deprecated(since = "9")
class AppletProps extends Frame {
TextField proxyHost;
@@ -197,6 +198,7 @@ class AppletProps extends Frame {
/* 4066432 */
/* Dialog class to display property-related errors to user */
@SuppressWarnings("serial") // JDK implementation class
+@Deprecated(since = "9")
class AppletPropsErrorDialog extends Dialog {
@SuppressWarnings("deprecation")
public AppletPropsErrorDialog(Frame parent, String title, String message,
diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java
index f11804dddab..c64971b4fb0 100644
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java
@@ -43,6 +43,7 @@ import sun.awt.AppContext;
* A frame to show the applet tag in.
*/
@SuppressWarnings("serial") // JDK-implementation class
+@Deprecated(since = "9")
final class TextFrame extends Frame {
/**
@@ -91,6 +92,7 @@ final class TextFrame extends Frame {
/**
* Lets us construct one using unix-style one shot behaviors.
*/
+@Deprecated(since = "9")
final class StdAppletViewerFactory implements AppletViewerFactory {
@Override
@@ -116,8 +118,13 @@ final class StdAppletViewerFactory implements AppletViewerFactory {
* AppletViewer Tags.
* (The document named appletviewertags.html in the JDK's docs/tooldocs directory,
* once the JDK docs have been installed.)
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * java.applet package
+ * documentation for further information.
*/
-@SuppressWarnings({"serial", "deprecation"}) // JDK-implementation class
+@SuppressWarnings({"serial"}) // JDK-implementation class
+@Deprecated(since = "9")
public class AppletViewer extends Frame implements AppletContext, Printable {
/**
@@ -146,7 +153,7 @@ public class AppletViewer extends Frame implements AppletContext, Printable {
*/
AppletViewerFactory factory;
-
+ @Deprecated(since = "9")
private final class UserActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent evt) {
@@ -219,6 +226,7 @@ public class AppletViewer extends Frame implements AppletContext, Printable {
}
};
+ @Deprecated(since = "9")
class AppletEventListener implements AppletListener
{
final Frame frame;
diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletViewerFactory.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletViewerFactory.java
index 16b6db4679d..7cf319f6941 100644
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletViewerFactory.java
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletViewerFactory.java
@@ -33,8 +33,8 @@ import java.util.Hashtable;
import java.net.URL;
import java.awt.MenuBar;
-public
-interface AppletViewerFactory {
+@Deprecated(since = "9")
+public interface AppletViewerFactory {
public AppletViewer createAppletViewer(int x, int y, URL doc,
Hashtable atts);
public MenuBar getBaseMenuBar();
diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletViewerPanel.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletViewerPanel.java
index c0aaf07ad03..86ef3671df0 100644
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletViewerPanel.java
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletViewerPanel.java
@@ -40,7 +40,12 @@ import java.applet.*;
* destroy() methods.
*
* @author Arthur van Hoff
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * java.applet package
+ * documentation for further information.
*/
+@Deprecated(since = "9")
class AppletViewerPanel extends AppletPanel {
/* Are we debugging? */
diff --git a/jdk/src/java.desktop/share/classes/sun/applet/Main.java b/jdk/src/java.desktop/share/classes/sun/applet/Main.java
index 6c28c8f9d11..6f5d0c178d7 100644
--- a/jdk/src/java.desktop/share/classes/sun/applet/Main.java
+++ b/jdk/src/java.desktop/share/classes/sun/applet/Main.java
@@ -39,7 +39,12 @@ import sun.net.www.ParseUtil;
/**
* The main entry point into AppletViewer.
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * java.applet package
+ * documentation for further information.
*/
+@Deprecated(since = "9")
public class Main {
/**
* The file which contains all of the AppletViewer specific properties.
diff --git a/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java b/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java
index 38060aa55a6..704a8619591 100644
--- a/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java
+++ b/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java
@@ -496,10 +496,14 @@ public abstract class EmbeddedFrame extends Frame
* Checks if the component is in an EmbeddedFrame. If so,
* returns the applet found in the hierarchy or null if
* not found.
- * @return the parent applet or {@ null}
+ * @return the parent applet or {@code null}
* @since 1.6
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * java.applet package
+ * documentation for further information.
*/
- @SuppressWarnings("deprecation")
+ @Deprecated(since = "9")
public static Applet getAppletIfAncestorOf(Component comp) {
Container parent = comp.getParent();
Applet applet = null;
diff --git a/jdk/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c b/jdk/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c
index 15c705a5fec..0a934d5fff7 100644
--- a/jdk/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c
+++ b/jdk/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c
@@ -2419,7 +2419,7 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
case sun_awt_image_IntegerComponentRaster_TYPE_INT_8BIT_SAMPLES:
if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 4)) &&
SAFE_TO_ALLOC_2(width, 4) &&
- SAFE_TO_ALLOC_3(height, rasterP->scanlineStride, 4)))
+ SAFE_TO_ALLOC_3(rasterP->scanlineStride, height, 4)))
{
return -1;
}
@@ -2428,7 +2428,7 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
if (offset < 0 || offset >= dataSize ||
width > rasterP->scanlineStride ||
- height * rasterP->scanlineStride * 4 > dataSize - offset)
+ ((width + (height - 1) * rasterP->scanlineStride) * 4) > dataSize - offset)
{
// raster data buffer is too short
return -1;
@@ -2446,7 +2446,7 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
return 0;
case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_SAMPLES:
if (!(SAFE_TO_ALLOC_2(width, rasterP->numBands) &&
- SAFE_TO_ALLOC_2(height, rasterP->scanlineStride)))
+ SAFE_TO_ALLOC_2(rasterP->scanlineStride, height)))
{
return -1;
}
@@ -2455,7 +2455,8 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
if (offset < 0 || offset >= dataSize ||
width * rasterP->numBands > rasterP->scanlineStride ||
- height * rasterP->scanlineStride > dataSize - offset)
+ ((width * rasterP->numBands) +
+ (height - 1) * rasterP->scanlineStride) > dataSize - offset)
{
// raster data buffer is too short
return -1;
@@ -2474,7 +2475,7 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_SAMPLES:
if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 2)) &&
SAFE_TO_ALLOC_3(width, rasterP->numBands, 2) &&
- SAFE_TO_ALLOC_3(height, rasterP->scanlineStride, 2)))
+ SAFE_TO_ALLOC_3(rasterP->scanlineStride, height, 2)))
{
return -1;
}
@@ -2483,7 +2484,8 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
if (offset < 0 || offset >= dataSize ||
width * rasterP->numBands > rasterP->scanlineStride ||
- height * rasterP->scanlineStride * 2 > dataSize - offset)
+ (((width * rasterP->numBands) +
+ (height - 1) * rasterP->scanlineStride)) * 2 > dataSize - offset)
{
// raster data buffer is too short
return -1;
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.cc b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.cc
index 5068dc14d9a..02c60253bfc 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.cc
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.cc
@@ -247,7 +247,7 @@ hb_blob_destroy (hb_blob_t *blob)
* @destroy: callback to call when @data is not needed anymore.
* @replace: whether to replace an existing data with the same key.
*
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -266,9 +266,9 @@ hb_blob_set_user_data (hb_blob_t *blob,
* @blob: a blob.
* @key: key for data to get.
*
+ *
*
- *
- * Return value: (transfer none):
+ * Return value: (transfer none):
*
* Since: 0.9.2
**/
@@ -284,7 +284,7 @@ hb_blob_get_user_data (hb_blob_t *blob,
* hb_blob_make_immutable:
* @blob: a blob.
*
- *
+ *
*
* Since: 0.9.2
**/
@@ -301,7 +301,7 @@ hb_blob_make_immutable (hb_blob_t *blob)
* hb_blob_is_immutable:
* @blob: a blob.
*
- *
+ *
*
* Return value: TODO
*
@@ -318,7 +318,7 @@ hb_blob_is_immutable (hb_blob_t *blob)
* hb_blob_get_length:
* @blob: a blob.
*
- *
+ *
*
* Return value: the length of blob data in bytes.
*
@@ -335,9 +335,9 @@ hb_blob_get_length (hb_blob_t *blob)
* @blob: a blob.
* @length: (out):
*
+ *
*
- *
- * Returns: (transfer none) (array length=length):
+ * Returns: (transfer none) (array length=length):
*
* Since: 0.9.2
**/
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-json.hh b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-json.hh
index 5d4387149ac..7581c2cd739 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-json.hh
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-json.hh
@@ -34,397 +34,397 @@
#line 36 "hb-buffer-deserialize-json.hh"
static const unsigned char _deserialize_json_trans_keys[] = {
- 0u, 0u, 9u, 123u, 9u, 34u, 97u, 103u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u,
- 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u,
- 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u,
- 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u,
- 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
+ 0u, 0u, 9u, 123u, 9u, 34u, 97u, 103u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u,
+ 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u,
+ 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u,
+ 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u,
+ 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
65u, 122u, 34u, 122u, 9u, 125u, 9u, 125u, 9u, 93u, 9u, 123u, 0u, 0u, 0
};
static const char _deserialize_json_key_spans[] = {
- 0, 115, 26, 7, 2, 1, 50, 49,
- 10, 117, 117, 117, 1, 50, 49, 10,
- 117, 117, 1, 1, 50, 49, 117, 117,
- 2, 1, 50, 49, 10, 117, 117, 1,
- 50, 49, 10, 117, 117, 1, 50, 49,
+ 0, 115, 26, 7, 2, 1, 50, 49,
+ 10, 117, 117, 117, 1, 50, 49, 10,
+ 117, 117, 1, 1, 50, 49, 117, 117,
+ 2, 1, 50, 49, 10, 117, 117, 1,
+ 50, 49, 10, 117, 117, 1, 50, 49,
58, 89, 117, 117, 85, 115, 0
};
static const short _deserialize_json_index_offsets[] = {
- 0, 0, 116, 143, 151, 154, 156, 207,
- 257, 268, 386, 504, 622, 624, 675, 725,
- 736, 854, 972, 974, 976, 1027, 1077, 1195,
- 1313, 1316, 1318, 1369, 1419, 1430, 1548, 1666,
- 1668, 1719, 1769, 1780, 1898, 2016, 2018, 2069,
+ 0, 0, 116, 143, 151, 154, 156, 207,
+ 257, 268, 386, 504, 622, 624, 675, 725,
+ 736, 854, 972, 974, 976, 1027, 1077, 1195,
+ 1313, 1316, 1318, 1369, 1419, 1430, 1548, 1666,
+ 1668, 1719, 1769, 1780, 1898, 2016, 2018, 2069,
2119, 2178, 2268, 2386, 2504, 2590, 2706
};
static const char _deserialize_json_indicies[] = {
- 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 2, 1, 3, 3, 3,
- 3, 3, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 3, 1, 4, 1,
- 5, 1, 6, 7, 1, 1, 8, 1,
- 9, 10, 1, 11, 1, 11, 11, 11,
- 11, 11, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 11, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 12, 1,
- 12, 12, 12, 12, 12, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 12,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 13, 1, 1, 14,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 1, 16, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 1, 18, 18, 18,
- 18, 18, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 18, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 19, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 20, 1, 21, 21, 21, 21, 21,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 21, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 3, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 22,
- 1, 18, 18, 18, 18, 18, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 18, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 19, 1, 1, 1,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 20, 1, 23,
- 1, 23, 23, 23, 23, 23, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 23, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 24, 1, 24, 24, 24, 24,
- 24, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 24, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 25, 1, 1, 26, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 1, 28, 29,
- 29, 29, 29, 29, 29, 29, 29, 29,
- 1, 30, 30, 30, 30, 30, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 30, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 31, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 32, 1, 30,
- 30, 30, 30, 30, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 30, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 31, 1, 1, 1, 29, 29,
- 29, 29, 29, 29, 29, 29, 29, 29,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 32, 1, 33, 1, 34,
- 1, 34, 34, 34, 34, 34, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 34, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 35, 1, 35, 35, 35, 35,
- 35, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 35, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 36, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 1, 38, 38,
- 38, 38, 38, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 38, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 39, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 40, 1, 38, 38, 38, 38,
- 38, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 38, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 39,
- 1, 1, 1, 41, 41, 41, 41, 41,
- 41, 41, 41, 41, 41, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 40, 1, 42, 43, 1, 44, 1, 44,
- 44, 44, 44, 44, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 44, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 45, 1, 45, 45, 45, 45, 45, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 45, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 46, 1,
- 1, 47, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 1, 49, 50, 50, 50,
- 50, 50, 50, 50, 50, 50, 1, 51,
- 51, 51, 51, 51, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 51, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 52, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 53, 1, 51, 51, 51,
- 51, 51, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 51, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 52, 1, 1, 1, 50, 50, 50, 50,
- 50, 50, 50, 50, 50, 50, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 53, 1, 54, 1, 54, 54, 54,
- 54, 54, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 54, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 55, 1,
- 55, 55, 55, 55, 55, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 55,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 56, 1, 1, 57,
- 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 1, 59, 60, 60, 60, 60, 60,
- 60, 60, 60, 60, 1, 61, 61, 61,
- 61, 61, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 61, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 62, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 63, 1, 61, 61, 61, 61, 61,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 61, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 62, 1,
- 1, 1, 60, 60, 60, 60, 60, 60,
- 60, 60, 60, 60, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 63,
- 1, 64, 1, 64, 64, 64, 64, 64,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 64, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 65, 1, 65, 65,
- 65, 65, 65, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 65, 1, 66,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 67, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 1,
- 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 1, 1, 1, 1, 1, 1,
- 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 1, 70, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 71, 71,
- 1, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 1, 1, 1, 1, 1,
- 1, 1, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 1, 1, 1, 1,
- 71, 1, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 1, 72, 72, 72,
- 72, 72, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 72, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 73, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 74, 1, 72, 72, 72, 72, 72,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 72, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 73, 1,
- 1, 1, 75, 75, 75, 75, 75, 75,
- 75, 75, 75, 75, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 74,
- 1, 76, 76, 76, 76, 76, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 76, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 77, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 78, 1, 0,
- 0, 0, 0, 0, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 0, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 2, 1, 3, 3, 3,
+ 3, 3, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 3, 1, 4, 1,
+ 5, 1, 6, 7, 1, 1, 8, 1,
+ 9, 10, 1, 11, 1, 11, 11, 11,
+ 11, 11, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 11, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 12, 1,
+ 12, 12, 12, 12, 12, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 12,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 13, 1, 1, 14,
+ 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 1, 16, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 1, 18, 18, 18,
+ 18, 18, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 18, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 19, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 20, 1, 21, 21, 21, 21, 21,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 21, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 3, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 22,
+ 1, 18, 18, 18, 18, 18, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 18, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 19, 1, 1, 1,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 20, 1, 23,
+ 1, 23, 23, 23, 23, 23, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 23, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 24, 1, 24, 24, 24, 24,
+ 24, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 24, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 25, 1, 1, 26, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 1, 28, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29,
+ 1, 30, 30, 30, 30, 30, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 30, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 31, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 32, 1, 30,
+ 30, 30, 30, 30, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 30, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 31, 1, 1, 1, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 32, 1, 33, 1, 34,
+ 1, 34, 34, 34, 34, 34, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 34, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 35, 1, 35, 35, 35, 35,
+ 35, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 35, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 36, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 1, 38, 38,
+ 38, 38, 38, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 38, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 39, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 40, 1, 38, 38, 38, 38,
+ 38, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 38, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 39,
+ 1, 1, 1, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 40, 1, 42, 43, 1, 44, 1, 44,
+ 44, 44, 44, 44, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 44, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 45, 1, 45, 45, 45, 45, 45, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 45, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 46, 1,
+ 1, 47, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 1, 49, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 1, 51,
+ 51, 51, 51, 51, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 51, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 52, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 53, 1, 51, 51, 51,
+ 51, 51, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 51, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 52, 1, 1, 1, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 53, 1, 54, 1, 54, 54, 54,
+ 54, 54, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 54, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 55, 1,
+ 55, 55, 55, 55, 55, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 55,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 56, 1, 1, 57,
+ 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 1, 59, 60, 60, 60, 60, 60,
+ 60, 60, 60, 60, 1, 61, 61, 61,
+ 61, 61, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 61, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 62, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 63, 1, 61, 61, 61, 61, 61,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 61, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 62, 1,
+ 1, 1, 60, 60, 60, 60, 60, 60,
+ 60, 60, 60, 60, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 63,
+ 1, 64, 1, 64, 64, 64, 64, 64,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 64, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 65, 1, 65, 65,
+ 65, 65, 65, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 65, 1, 66,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 67, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 1,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 1, 1, 1, 1, 1, 1,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 1, 70, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 71, 71,
+ 1, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 1, 1, 1, 1, 1,
+ 1, 1, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 1, 1, 1, 1,
+ 71, 1, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 1, 72, 72, 72,
+ 72, 72, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 72, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 73, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 74, 1, 72, 72, 72, 72, 72,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 72, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 73, 1,
+ 1, 1, 75, 75, 75, 75, 75, 75,
+ 75, 75, 75, 75, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 74,
+ 1, 76, 76, 76, 76, 76, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 76, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 77, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 78, 1, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 1, 1, 0
};
static const char _deserialize_json_trans_targs[] = {
- 1, 0, 2, 2, 3, 4, 18, 24,
- 37, 5, 12, 6, 7, 8, 9, 11,
- 9, 11, 10, 2, 44, 10, 44, 13,
- 14, 15, 16, 17, 16, 17, 10, 2,
- 44, 19, 20, 21, 22, 23, 10, 2,
- 44, 23, 25, 31, 26, 27, 28, 29,
- 30, 29, 30, 10, 2, 44, 32, 33,
- 34, 35, 36, 35, 36, 10, 2, 44,
- 38, 39, 40, 42, 43, 41, 10, 41,
+ 1, 0, 2, 2, 3, 4, 18, 24,
+ 37, 5, 12, 6, 7, 8, 9, 11,
+ 9, 11, 10, 2, 44, 10, 44, 13,
+ 14, 15, 16, 17, 16, 17, 10, 2,
+ 44, 19, 20, 21, 22, 23, 10, 2,
+ 44, 23, 25, 31, 26, 27, 28, 29,
+ 30, 29, 30, 10, 2, 44, 32, 33,
+ 34, 35, 36, 35, 36, 10, 2, 44,
+ 38, 39, 40, 42, 43, 41, 10, 41,
10, 2, 44, 43, 44, 45, 46
};
static const char _deserialize_json_trans_actions[] = {
- 0, 0, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 2, 2, 2,
- 0, 0, 3, 3, 4, 0, 5, 0,
- 0, 2, 2, 2, 0, 0, 6, 6,
- 7, 0, 0, 0, 2, 2, 8, 8,
- 9, 0, 0, 0, 0, 0, 2, 2,
- 2, 0, 0, 10, 10, 11, 0, 0,
- 2, 2, 2, 0, 0, 12, 12, 13,
- 0, 0, 0, 2, 2, 2, 14, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 2, 2,
+ 0, 0, 3, 3, 4, 0, 5, 0,
+ 0, 2, 2, 2, 0, 0, 6, 6,
+ 7, 0, 0, 0, 2, 2, 8, 8,
+ 9, 0, 0, 0, 0, 0, 2, 2,
+ 2, 0, 0, 10, 10, 11, 0, 0,
+ 2, 2, 2, 0, 0, 12, 12, 13,
+ 0, 0, 0, 2, 2, 2, 14, 0,
15, 15, 16, 0, 0, 0, 0
};
@@ -461,7 +461,7 @@ _hb_buffer_deserialize_glyphs_json (hb_buffer_t *buffer,
int cs;
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
-
+
#line 466 "hb-buffer-deserialize-json.hh"
{
cs = deserialize_json_start;
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-text.hh b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-text.hh
index c45442c0274..259719c1fea 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-text.hh
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-text.hh
@@ -34,274 +34,274 @@
#line 36 "hb-buffer-deserialize-text.hh"
static const unsigned char _deserialize_text_trans_keys[] = {
- 0u, 0u, 9u, 122u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u,
- 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 9u, 124u, 9u, 124u, 0u, 0u,
- 9u, 122u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u,
+ 0u, 0u, 9u, 122u, 45u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 48u, 57u, 45u, 57u,
+ 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, 9u, 124u, 9u, 124u, 0u, 0u,
+ 9u, 122u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u,
9u, 124u, 9u, 124u, 9u, 124u, 0
};
static const char _deserialize_text_key_spans[] = {
- 0, 114, 13, 10, 13, 10, 10, 13,
- 10, 1, 13, 10, 14, 116, 116, 0,
- 114, 116, 116, 116, 116, 116, 116, 116,
+ 0, 114, 13, 10, 13, 10, 10, 13,
+ 10, 1, 13, 10, 14, 116, 116, 0,
+ 114, 116, 116, 116, 116, 116, 116, 116,
116, 116, 116
};
static const short _deserialize_text_index_offsets[] = {
- 0, 0, 115, 129, 140, 154, 165, 176,
- 190, 201, 203, 217, 228, 243, 360, 477,
- 478, 593, 710, 827, 944, 1061, 1178, 1295,
+ 0, 0, 115, 129, 140, 154, 165, 176,
+ 190, 201, 203, 217, 228, 243, 360, 477,
+ 478, 593, 710, 827, 944, 1061, 1178, 1295,
1412, 1529, 1646
};
static const char _deserialize_text_indicies[] = {
- 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 1, 1, 1, 1, 1, 1,
- 1, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 1, 1, 1, 1, 1,
- 1, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 1, 5, 1, 1, 6,
- 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 1, 8, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 1, 10, 1, 1,
- 11, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 1, 13, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 1, 15, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 1, 17, 1, 1, 18, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 1, 20,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 1, 22, 1, 23, 1, 1, 24,
- 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 1, 26, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 1, 22, 1, 1,
- 1, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 1, 28, 28, 28, 28,
- 28, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 28, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 29, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 30, 1, 1, 31, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 32, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 33,
- 1, 34, 34, 34, 34, 34, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 34, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 35, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 36, 1, 1, 0,
- 0, 0, 0, 0, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 0, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 2, 3,
- 3, 3, 3, 3, 3, 3, 3, 3,
- 1, 1, 1, 1, 1, 1, 1, 4,
- 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 1, 1, 1, 1, 1, 1, 4,
- 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 1, 28, 28, 28, 28, 28, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 28, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 29, 1, 1, 1,
- 1, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 1, 1, 1, 30, 1,
- 1, 31, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 32, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 33, 1, 38,
- 38, 38, 38, 38, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 38, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 39, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 40, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 41, 1, 42, 42, 42, 42,
- 42, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 42, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 43, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 44,
- 1, 42, 42, 42, 42, 42, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 42, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 43, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 44, 1, 38, 38,
- 38, 38, 38, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 38, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 39, 1, 1, 1, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 40, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 41, 1, 45, 45, 45, 45, 45,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 45, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 46, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 47, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 48,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 49, 1,
- 50, 50, 50, 50, 50, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 50,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 51, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 52, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 53, 1, 50, 50, 50,
- 50, 50, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 50, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 51,
- 1, 1, 1, 1, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 52, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 53, 1, 45, 45, 45, 45, 45, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 45, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 46, 1, 1, 1,
- 1, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 1, 1, 1, 1, 1,
- 1, 47, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 48, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 49, 1, 28,
- 28, 28, 28, 28, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 28, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 29, 1, 55, 55, 1, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55,
- 1, 1, 1, 30, 1, 1, 31, 55,
- 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 1, 1, 32, 1, 55, 1, 55,
- 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 1, 1, 1, 1, 1, 1,
+ 1, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 1, 1, 1, 1, 1,
+ 1, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 1, 5, 1, 1, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 1, 8, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 1, 10, 1, 1,
+ 11, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 1, 13, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 1, 15, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 1, 17, 1, 1, 18, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 1, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 1, 22, 1, 23, 1, 1, 24,
+ 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 1, 26, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 1, 22, 1, 1,
+ 1, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 1, 28, 28, 28, 28,
+ 28, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 28, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 29, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 30, 1, 1, 31, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 32, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 33,
+ 1, 34, 34, 34, 34, 34, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 34, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 35, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 36, 1, 1, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 2, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 1, 1, 1, 1, 1, 1, 1, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 1, 1, 1, 1, 1, 1, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 1, 28, 28, 28, 28, 28, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 28, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 29, 1, 1, 1,
+ 1, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 1, 1, 1, 30, 1,
+ 1, 31, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 32, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 33, 1, 38,
+ 38, 38, 38, 38, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 38, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 39, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 40, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 41, 1, 42, 42, 42, 42,
+ 42, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 42, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 43, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 44,
+ 1, 42, 42, 42, 42, 42, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 42, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 43, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 44, 1, 38, 38,
+ 38, 38, 38, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 38, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 39, 1, 1, 1, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 40, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 41, 1, 45, 45, 45, 45, 45,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 45, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 46, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 47, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 48,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 49, 1,
+ 50, 50, 50, 50, 50, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 50,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 51, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 52, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 53, 1, 50, 50, 50,
+ 50, 50, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 50, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 51,
+ 1, 1, 1, 1, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 52, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 53, 1, 45, 45, 45, 45, 45, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 45, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 46, 1, 1, 1,
+ 1, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 1, 1, 1, 1, 1,
+ 1, 47, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 48, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 49, 1, 28,
+ 28, 28, 28, 28, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 28, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 29, 1, 55, 55, 1, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55,
+ 1, 1, 1, 30, 1, 1, 31, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 1, 1, 32, 1, 55, 1, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55,
55, 1, 33, 1, 0
};
static const char _deserialize_text_trans_targs[] = {
- 1, 0, 13, 17, 26, 3, 18, 21,
- 18, 21, 5, 19, 20, 19, 20, 22,
- 25, 8, 9, 12, 9, 12, 10, 11,
- 23, 24, 23, 24, 14, 2, 6, 7,
- 15, 16, 14, 15, 16, 17, 14, 4,
- 15, 16, 14, 15, 16, 14, 2, 7,
+ 1, 0, 13, 17, 26, 3, 18, 21,
+ 18, 21, 5, 19, 20, 19, 20, 22,
+ 25, 8, 9, 12, 9, 12, 10, 11,
+ 23, 24, 23, 24, 14, 2, 6, 7,
+ 15, 16, 14, 15, 16, 17, 14, 4,
+ 15, 16, 14, 15, 16, 14, 2, 7,
15, 16, 14, 2, 15, 16, 25, 26
};
static const char _deserialize_text_trans_actions[] = {
- 0, 0, 1, 1, 1, 2, 2, 2,
- 0, 0, 2, 2, 2, 0, 0, 2,
- 2, 2, 2, 2, 0, 0, 3, 2,
- 2, 2, 0, 0, 4, 5, 5, 5,
- 4, 4, 0, 0, 0, 0, 6, 7,
- 6, 6, 8, 8, 8, 9, 10, 10,
+ 0, 0, 1, 1, 1, 2, 2, 2,
+ 0, 0, 2, 2, 2, 0, 0, 2,
+ 2, 2, 2, 2, 0, 0, 3, 2,
+ 2, 2, 0, 0, 4, 5, 5, 5,
+ 4, 4, 0, 0, 0, 0, 6, 7,
+ 6, 6, 8, 8, 8, 9, 10, 10,
9, 9, 11, 12, 11, 11, 0, 0
};
static const char _deserialize_text_eof_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 4, 0, 0,
- 0, 4, 6, 8, 8, 6, 9, 11,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 4, 0, 0,
+ 0, 4, 6, 8, 8, 6, 9, 11,
11, 9, 4
};
@@ -338,7 +338,7 @@ _hb_buffer_deserialize_glyphs_text (hb_buffer_t *buffer,
int cs;
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
-
+
#line 343 "hb-buffer-deserialize-text.hh"
{
cs = deserialize_text_start;
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-private.hh b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-private.hh
index 1fc2252d12c..b92b67b7e26 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-private.hh
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-private.hh
@@ -134,7 +134,7 @@ struct hb_buffer_t {
#ifndef HB_NDEBUG
unsigned int end = start + count;
assert (end <= 8);
- unsigned int bits = (1<> value_bits) != (key >> cache_bits))
return false;
- *value = v & ((1<> key_bits) || (value >> value_bits)))
return false; /* Overflows */
- unsigned int k = key & ((1<>cache_bits)< hb_cmap_cache_t;
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.cc b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.cc
index d7b75ac1b1e..aae6351cc5f 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.cc
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.cc
@@ -57,12 +57,12 @@ _hb_options_init (void)
/**
* hb_tag_from_string:
- * @str: (array length=len) (element-type uint8_t):
- * @len:
+ * @str: (array length=len) (element-type uint8_t):
+ * @len:
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -87,10 +87,10 @@ hb_tag_from_string (const char *str, int len)
/**
* hb_tag_to_string:
- * @tag:
- * @buf: (out caller-allocates) (array fixed-size=4) (element-type uint8_t):
- *
+ * @tag:
+ * @buf: (out caller-allocates) (array fixed-size=4) (element-type uint8_t):
*
+ *
*
* Since: 0.9.5
**/
@@ -115,12 +115,12 @@ const char direction_strings[][4] = {
/**
* hb_direction_from_string:
- * @str: (array length=len) (element-type uint8_t):
- * @len:
+ * @str: (array length=len) (element-type uint8_t):
+ * @len:
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -143,11 +143,11 @@ hb_direction_from_string (const char *str, int len)
/**
* hb_direction_to_string:
- * @direction:
+ * @direction:
*
+ *
*
- *
- * Return value: (transfer none):
+ * Return value: (transfer none):
*
* Since: 0.9.2
**/
@@ -337,7 +337,7 @@ hb_language_to_string (hb_language_t language)
/**
* hb_language_get_default:
*
- *
+ *
*
* Return value: (transfer none):
*
@@ -366,7 +366,7 @@ hb_language_get_default (void)
*
* Converts an ISOÂ 15924 script tag to a corresponding #hb_script_t.
*
- * Return value:
+ * Return value:
* An #hb_script_t corresponding to the ISOÂ 15924 tag.
*
* Since: 0.9.2
@@ -415,7 +415,7 @@ hb_script_from_iso15924_tag (hb_tag_t tag)
* corresponding #hb_script_t. Shorthand for hb_tag_from_string() then
* hb_script_from_iso15924_tag().
*
- * Return value:
+ * Return value:
* An #hb_script_t corresponding to the ISOÂ 15924 tag.
*
* Since: 0.9.2
@@ -445,11 +445,11 @@ hb_script_to_iso15924_tag (hb_script_t script)
/**
* hb_script_get_horizontal_direction:
- * @script:
+ * @script:
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -588,13 +588,13 @@ hb_version_string (void)
/**
* hb_version_atleast:
- * @major:
- * @minor:
- * @micro:
+ * @major:
+ * @minor:
+ * @micro:
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.30
**/
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-coretext.cc b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-coretext.cc
index bd769a04aa8..01e3a23f2b1 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-coretext.cc
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-coretext.cc
@@ -145,6 +145,22 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size)
DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed");
return NULL;
}
+
+ /* crbug.com/576941 and crbug.com/625902 and the investigation in the latter
+ * bug indicate that the cascade list reconfiguration occasionally causes
+ * crashes in CoreText on OS X 10.9, thus let's skip this step on older
+ * operating system versions. Except for the emoji font, where _not_
+ * reconfiguring the cascade list causes CoreText crashes. For details, see
+ * crbug.com/549610 */
+ // 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h
+ if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() < 0x00070000) {
+ CFStringRef fontName = CTFontCopyPostScriptName (ct_font);
+ bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo;
+ CFRelease (fontName);
+ if (!isEmojiFont)
+ return ct_font;
+ }
+
CFURLRef original_url = (CFURLRef)CTFontCopyAttribute(ct_font, kCTFontURLAttribute);
/* Create font copy with cascade list that has LastResort first; this speeds up CoreText
@@ -272,7 +288,9 @@ struct hb_coretext_shaper_shape_plan_data_t {};
hb_coretext_shaper_shape_plan_data_t *
_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
- unsigned int num_user_features HB_UNUSED)
+ unsigned int num_user_features HB_UNUSED,
+ const int *coords HB_UNUSED,
+ unsigned int num_coords HB_UNUSED)
{
return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
@@ -717,7 +735,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
pchars[chars_len++] = 0xFFFDu;
else {
pchars[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
- pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1 << 10) - 1));
+ pchars[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1));
}
}
@@ -1264,7 +1282,9 @@ struct hb_coretext_aat_shaper_shape_plan_data_t {};
hb_coretext_aat_shaper_shape_plan_data_t *
_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
- unsigned int num_user_features HB_UNUSED)
+ unsigned int num_user_features HB_UNUSED,
+ const int *coords HB_UNUSED,
+ unsigned int num_coords HB_UNUSED)
{
return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.cc b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.cc
index b5019a122de..bb6673cdf2b 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.cc
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.cc
@@ -35,8 +35,6 @@
#include "hb-ot-head-table.hh"
#include "hb-ot-maxp-table.hh"
-#include "hb-cache-private.hh"
-
#include
@@ -70,10 +68,10 @@ const hb_face_t _hb_face_nil = {
/**
* hb_face_create_for_tables:
* @reference_table_func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
+ * @user_data:
+ * @destroy:
*
+ *
*
* Return value: (transfer full)
*
@@ -150,10 +148,10 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
/**
* hb_face_create: (Xconstructor)
- * @blob:
- * @index:
- *
+ * @blob:
+ * @index:
*
+ *
*
* Return value: (transfer full):
*
@@ -185,7 +183,7 @@ hb_face_create (hb_blob_t *blob,
/**
* hb_face_get_empty:
*
- *
+ *
*
* Return value: (transfer full)
*
@@ -202,9 +200,9 @@ hb_face_get_empty (void)
* hb_face_reference: (skip)
* @face: a face.
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -218,7 +216,7 @@ hb_face_reference (hb_face_t *face)
* hb_face_destroy: (skip)
* @face: a face.
*
- *
+ *
*
* Since: 0.9.2
**/
@@ -248,14 +246,14 @@ hb_face_destroy (hb_face_t *face)
/**
* hb_face_set_user_data: (skip)
* @face: a face.
- * @key:
- * @data:
- * @destroy:
- * @replace:
+ * @key:
+ * @data:
+ * @destroy:
+ * @replace:
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -272,9 +270,9 @@ hb_face_set_user_data (hb_face_t *face,
/**
* hb_face_get_user_data: (skip)
* @face: a face.
- * @key:
- *
+ * @key:
*
+ *
*
* Return value: (transfer none):
*
@@ -291,7 +289,7 @@ hb_face_get_user_data (hb_face_t *face,
* hb_face_make_immutable:
* @face: a face.
*
- *
+ *
*
* Since: 0.9.2
**/
@@ -308,9 +306,9 @@ hb_face_make_immutable (hb_face_t *face)
* hb_face_is_immutable:
* @face: a face.
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -324,9 +322,9 @@ hb_face_is_immutable (hb_face_t *face)
/**
* hb_face_reference_table:
* @face: a face.
- * @tag:
- *
+ * @tag:
*
+ *
*
* Return value: (transfer full):
*
@@ -343,7 +341,7 @@ hb_face_reference_table (hb_face_t *face,
* hb_face_reference_blob:
* @face: a face.
*
- *
+ *
*
* Return value: (transfer full):
*
@@ -358,9 +356,9 @@ hb_face_reference_blob (hb_face_t *face)
/**
* hb_face_set_index:
* @face: a face.
- * @index:
- *
+ * @index:
*
+ *
*
* Since: 0.9.2
**/
@@ -378,9 +376,9 @@ hb_face_set_index (hb_face_t *face,
* hb_face_get_index:
* @face: a face.
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -393,9 +391,9 @@ hb_face_get_index (hb_face_t *face)
/**
* hb_face_set_upem:
* @face: a face.
- * @upem:
- *
+ * @upem:
*
+ *
*
* Since: 0.9.2
**/
@@ -413,9 +411,9 @@ hb_face_set_upem (hb_face_t *face,
* hb_face_get_upem:
* @face: a face.
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -437,9 +435,9 @@ hb_face_t::load_upem (void) const
/**
* hb_face_set_glyph_count:
* @face: a face.
- * @glyph_count:
- *
+ * @glyph_count:
*
+ *
*
* Since: 0.9.7
**/
@@ -457,9 +455,9 @@ hb_face_set_glyph_count (hb_face_t *face,
* hb_face_get_glyph_count:
* @face: a face.
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.7
**/
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-fallback-shape.cc b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-fallback-shape.cc
index dee7d7d12eb..9f40c911c5f 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-fallback-shape.cc
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-fallback-shape.cc
@@ -73,7 +73,9 @@ struct hb_fallback_shaper_shape_plan_data_t {};
hb_fallback_shaper_shape_plan_data_t *
_hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
const hb_feature_t *user_features HB_UNUSED,
- unsigned int num_user_features HB_UNUSED)
+ unsigned int num_user_features HB_UNUSED,
+ const int *coords HB_UNUSED,
+ unsigned int num_coords HB_UNUSED)
{
return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font-private.hh b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font-private.hh
index d7b48776e1e..9254cd0f4e5 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font-private.hh
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font-private.hh
@@ -108,6 +108,10 @@ struct hb_font_t {
unsigned int x_ppem;
unsigned int y_ppem;
+ /* Font variation coordinates. */
+ unsigned int num_coords;
+ int *coords;
+
hb_font_funcs_t *klass;
void *user_data;
hb_destroy_func_t destroy;
@@ -116,8 +120,14 @@ struct hb_font_t {
/* Convert from font-space to user-space */
- inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); }
- inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); }
+ inline int dir_scale (hb_direction_t direction)
+ { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
+ inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
+ inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
+ inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
+ inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
+ inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
+ { return em_scale (v, dir_scale (direction)); }
/* Convert from parent-font user-space to our user-space */
inline hb_position_t parent_scale_x_distance (hb_position_t v) {
@@ -292,24 +302,32 @@ struct hb_font_t {
/* A bit higher-level, and with fallback */
+ inline void get_h_extents_with_fallback (hb_font_extents_t *extents)
+ {
+ if (!get_font_h_extents (extents))
+ {
+ extents->ascender = y_scale * .8;
+ extents->descender = extents->ascender - y_scale;
+ extents->line_gap = 0;
+ }
+ }
+ inline void get_v_extents_with_fallback (hb_font_extents_t *extents)
+ {
+ if (!get_font_v_extents (extents))
+ {
+ extents->ascender = x_scale / 2;
+ extents->descender = extents->ascender - x_scale;
+ extents->line_gap = 0;
+ }
+ }
+
inline void get_extents_for_direction (hb_direction_t direction,
hb_font_extents_t *extents)
{
- if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
- if (!get_font_h_extents (extents))
- {
- extents->ascender = y_scale * .8;
- extents->descender = y_scale - extents->ascender;
- extents->line_gap = 0;
- }
- } else {
- if (!get_font_v_extents (extents))
- {
- extents->ascender = x_scale / 2;
- extents->descender = x_scale - extents->ascender;
- extents->line_gap = 0;
- }
- }
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+ get_h_extents_with_fallback (extents);
+ else
+ get_v_extents_with_fallback (extents);
}
inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
@@ -325,14 +343,38 @@ struct hb_font_t {
}
}
- /* Internal only */
inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
hb_position_t *x, hb_position_t *y)
{
*x = get_glyph_h_advance (glyph) / 2;
- /* TODO use font_extents.ascender */
- *y = y_scale;
+ /* TODO cache this somehow?! */
+ hb_font_extents_t extents;
+ get_h_extents_with_fallback (&extents);
+ *y = extents.ascender;
+ }
+
+ inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
+ hb_position_t *x, hb_position_t *y)
+ {
+ if (!get_glyph_h_origin (glyph, x, y) &&
+ get_glyph_v_origin (glyph, x, y))
+ {
+ hb_position_t dx, dy;
+ guess_v_origin_minus_h_origin (glyph, &dx, &dy);
+ *x -= dx; *y -= dy;
+ }
+ }
+ inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
+ hb_position_t *x, hb_position_t *y)
+ {
+ if (!get_glyph_v_origin (glyph, x, y) &&
+ get_glyph_h_origin (glyph, x, y))
+ {
+ hb_position_t dx, dy;
+ guess_v_origin_minus_h_origin (glyph, &dx, &dy);
+ *x += dx; *y += dy;
+ }
}
inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
@@ -340,25 +382,9 @@ struct hb_font_t {
hb_position_t *x, hb_position_t *y)
{
if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
- {
- if (!get_glyph_h_origin (glyph, x, y) &&
- get_glyph_v_origin (glyph, x, y))
- {
- hb_position_t dx, dy;
- guess_v_origin_minus_h_origin (glyph, &dx, &dy);
- *x -= dx; *y -= dy;
- }
- }
+ get_glyph_h_origin_with_fallback (glyph, x, y);
else
- {
- if (!get_glyph_v_origin (glyph, x, y) &&
- get_glyph_h_origin (glyph, x, y))
- {
- hb_position_t dx, dy;
- guess_v_origin_minus_h_origin (glyph, &dx, &dy);
- *x += dx; *y += dy;
- }
- }
+ get_glyph_v_origin_with_fallback (glyph, x, y);
}
inline void add_glyph_h_origin (hb_codepoint_t glyph,
@@ -366,7 +392,7 @@ struct hb_font_t {
{
hb_position_t origin_x, origin_y;
- get_glyph_h_origin (glyph, &origin_x, &origin_y);
+ get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
*x += origin_x;
*y += origin_y;
@@ -376,7 +402,7 @@ struct hb_font_t {
{
hb_position_t origin_x, origin_y;
- get_glyph_v_origin (glyph, &origin_x, &origin_y);
+ get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
*x += origin_x;
*y += origin_y;
@@ -398,7 +424,7 @@ struct hb_font_t {
{
hb_position_t origin_x, origin_y;
- get_glyph_h_origin (glyph, &origin_x, &origin_y);
+ get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
*x -= origin_x;
*y -= origin_y;
@@ -408,7 +434,7 @@ struct hb_font_t {
{
hb_position_t origin_x, origin_y;
- get_glyph_v_origin (glyph, &origin_x, &origin_y);
+ get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
*x -= origin_x;
*y -= origin_y;
@@ -504,7 +530,6 @@ struct hb_font_t {
return false;
}
- private:
inline hb_position_t em_scale (int16_t v, int scale)
{
int upem = face->get_upem ();
@@ -512,6 +537,10 @@ struct hb_font_t {
scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
return (hb_position_t) (scaled / upem);
}
+ inline hb_position_t em_scalef (float v, int scale)
+ {
+ return (hb_position_t) (v * scale / face->get_upem ());
+ }
};
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.cc b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.cc
index eb0f9fcfd09..b81c46e51d1 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.cc
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.cc
@@ -35,8 +35,6 @@
#include "hb-ot-head-table.hh"
#include "hb-ot-maxp-table.hh"
-#include "hb-cache-private.hh"
-
#include
@@ -401,9 +399,9 @@ static const hb_font_funcs_t _hb_font_funcs_parent = {
/**
* hb_font_funcs_create: (Xconstructor)
*
+ *
*
- *
- * Return value: (transfer full):
+ * Return value: (transfer full):
*
* Since: 0.9.2
**/
@@ -423,9 +421,9 @@ hb_font_funcs_create (void)
/**
* hb_font_funcs_get_empty:
*
+ *
*
- *
- * Return value: (transfer full):
+ * Return value: (transfer full):
*
* Since: 0.9.2
**/
@@ -439,9 +437,9 @@ hb_font_funcs_get_empty (void)
* hb_font_funcs_reference: (skip)
* @ffuncs: font functions.
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -455,7 +453,7 @@ hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
* hb_font_funcs_destroy: (skip)
* @ffuncs: font functions.
*
- *
+ *
*
* Since: 0.9.2
**/
@@ -475,14 +473,14 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
/**
* hb_font_funcs_set_user_data: (skip)
* @ffuncs: font functions.
- * @key:
- * @data:
- * @destroy:
- * @replace:
+ * @key:
+ * @data:
+ * @destroy:
+ * @replace:
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -499,11 +497,11 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
/**
* hb_font_funcs_get_user_data: (skip)
* @ffuncs: font functions.
- * @key:
+ * @key:
*
+ *
*
- *
- * Return value: (transfer none):
+ * Return value: (transfer none):
*
* Since: 0.9.2
**/
@@ -519,7 +517,7 @@ hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
* hb_font_funcs_make_immutable:
* @ffuncs: font functions.
*
- *
+ *
*
* Since: 0.9.2
**/
@@ -536,9 +534,9 @@ hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
* hb_font_funcs_is_immutable:
* @ffuncs: font functions.
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -629,13 +627,13 @@ hb_font_get_v_extents (hb_font_t *font,
/**
* hb_font_get_glyph:
* @font: a font.
- * @unicode:
- * @variation_selector:
- * @glyph: (out):
+ * @unicode:
+ * @variation_selector:
+ * @glyph: (out):
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -652,12 +650,12 @@ hb_font_get_glyph (hb_font_t *font,
/**
* hb_font_get_nominal_glyph:
* @font: a font.
- * @unicode:
- * @glyph: (out):
+ * @unicode:
+ * @glyph: (out):
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 1.2.3
**/
@@ -672,13 +670,13 @@ hb_font_get_nominal_glyph (hb_font_t *font,
/**
* hb_font_get_variation_glyph:
* @font: a font.
- * @unicode:
- * @variation_selector:
- * @glyph: (out):
+ * @unicode:
+ * @variation_selector:
+ * @glyph: (out):
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 1.2.3
**/
@@ -693,11 +691,11 @@ hb_font_get_variation_glyph (hb_font_t *font,
/**
* hb_font_get_glyph_h_advance:
* @font: a font.
- * @glyph:
+ * @glyph:
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -711,11 +709,11 @@ hb_font_get_glyph_h_advance (hb_font_t *font,
/**
* hb_font_get_glyph_v_advance:
* @font: a font.
- * @glyph:
+ * @glyph:
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -729,13 +727,13 @@ hb_font_get_glyph_v_advance (hb_font_t *font,
/**
* hb_font_get_glyph_h_origin:
* @font: a font.
- * @glyph:
- * @x: (out):
- * @y: (out):
+ * @glyph:
+ * @x: (out):
+ * @y: (out):
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -750,13 +748,13 @@ hb_font_get_glyph_h_origin (hb_font_t *font,
/**
* hb_font_get_glyph_v_origin:
* @font: a font.
- * @glyph:
- * @x: (out):
- * @y: (out):
+ * @glyph:
+ * @x: (out):
+ * @y: (out):
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -771,12 +769,12 @@ hb_font_get_glyph_v_origin (hb_font_t *font,
/**
* hb_font_get_glyph_h_kerning:
* @font: a font.
- * @left_glyph:
- * @right_glyph:
+ * @left_glyph:
+ * @right_glyph:
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -790,12 +788,12 @@ hb_font_get_glyph_h_kerning (hb_font_t *font,
/**
* hb_font_get_glyph_v_kerning:
* @font: a font.
- * @top_glyph:
- * @bottom_glyph:
+ * @top_glyph:
+ * @bottom_glyph:
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -809,12 +807,12 @@ hb_font_get_glyph_v_kerning (hb_font_t *font,
/**
* hb_font_get_glyph_extents:
* @font: a font.
- * @glyph:
- * @extents: (out):
+ * @glyph:
+ * @extents: (out):
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -829,14 +827,14 @@ hb_font_get_glyph_extents (hb_font_t *font,
/**
* hb_font_get_glyph_contour_point:
* @font: a font.
- * @glyph:
- * @point_index:
- * @x: (out):
- * @y: (out):
+ * @glyph:
+ * @point_index:
+ * @x: (out):
+ * @y: (out):
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -851,13 +849,13 @@ hb_font_get_glyph_contour_point (hb_font_t *font,
/**
* hb_font_get_glyph_name:
* @font: a font.
- * @glyph:
- * @name: (array length=size):
- * @size:
+ * @glyph:
+ * @name: (array length=size):
+ * @size:
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -872,13 +870,13 @@ hb_font_get_glyph_name (hb_font_t *font,
/**
* hb_font_get_glyph_from_name:
* @font: a font.
- * @name: (array length=len):
- * @len:
- * @glyph: (out):
+ * @name: (array length=len):
+ * @len:
+ * @glyph: (out):
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -913,12 +911,12 @@ hb_font_get_extents_for_direction (hb_font_t *font,
/**
* hb_font_get_glyph_advance_for_direction:
* @font: a font.
- * @glyph:
- * @direction:
- * @x: (out):
- * @y: (out):
- *
+ * @glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
*
+ *
*
* Since: 0.9.2
**/
@@ -934,12 +932,12 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font,
/**
* hb_font_get_glyph_origin_for_direction:
* @font: a font.
- * @glyph:
- * @direction:
- * @x: (out):
- * @y: (out):
- *
+ * @glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
*
+ *
*
* Since: 0.9.2
**/
@@ -955,12 +953,12 @@ hb_font_get_glyph_origin_for_direction (hb_font_t *font,
/**
* hb_font_add_glyph_origin_for_direction:
* @font: a font.
- * @glyph:
- * @direction:
- * @x: (out):
- * @y: (out):
- *
+ * @glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
*
+ *
*
* Since: 0.9.2
**/
@@ -976,12 +974,12 @@ hb_font_add_glyph_origin_for_direction (hb_font_t *font,
/**
* hb_font_subtract_glyph_origin_for_direction:
* @font: a font.
- * @glyph:
- * @direction:
- * @x: (out):
- * @y: (out):
- *
+ * @glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
*
+ *
*
* Since: 0.9.2
**/
@@ -997,13 +995,13 @@ hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
/**
* hb_font_get_glyph_kerning_for_direction:
* @font: a font.
- * @first_glyph:
- * @second_glyph:
- * @direction:
- * @x: (out):
- * @y: (out):
- *
+ * @first_glyph:
+ * @second_glyph:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
*
+ *
*
* Since: 0.9.2
**/
@@ -1019,13 +1017,13 @@ hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
/**
* hb_font_get_glyph_extents_for_origin:
* @font: a font.
- * @glyph:
- * @direction:
- * @extents: (out):
+ * @glyph:
+ * @direction:
+ * @extents: (out):
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -1041,15 +1039,15 @@ hb_font_get_glyph_extents_for_origin (hb_font_t *font,
/**
* hb_font_get_glyph_contour_point_for_origin:
* @font: a font.
- * @glyph:
- * @point_index:
- * @direction:
- * @x: (out):
- * @y: (out):
+ * @glyph:
+ * @point_index:
+ * @direction:
+ * @x: (out):
+ * @y: (out):
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -1066,11 +1064,11 @@ hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
/**
* hb_font_glyph_to_string:
* @font: a font.
- * @glyph:
- * @s: (array length=size):
- * @size:
- *
+ * @glyph:
+ * @s: (array length=size):
+ * @size:
*
+ *
*
* Since: 0.9.2
**/
@@ -1086,13 +1084,13 @@ hb_font_glyph_to_string (hb_font_t *font,
/**
* hb_font_glyph_from_string:
* @font: a font.
- * @s: (array length=len) (element-type uint8_t):
- * @len:
- * @glyph: (out):
+ * @s: (array length=len) (element-type uint8_t):
+ * @len:
+ * @glyph: (out):
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -1113,9 +1111,9 @@ hb_font_glyph_from_string (hb_font_t *font,
* hb_font_create: (Xconstructor)
* @face: a face.
*
+ *
*
- *
- * Return value: (transfer full):
+ * Return value: (transfer full):
*
* Since: 0.9.2
**/
@@ -1143,9 +1141,9 @@ hb_font_create (hb_face_t *face)
* hb_font_create_sub_font:
* @parent: parent font.
*
+ *
*
- *
- * Return value: (transfer full):
+ * Return value: (transfer full):
*
* Since: 0.9.2
**/
@@ -1167,13 +1165,15 @@ hb_font_create_sub_font (hb_font_t *parent)
font->x_ppem = parent->x_ppem;
font->y_ppem = parent->y_ppem;
+ /* TODO: copy variation coordinates. */
+
return font;
}
/**
* hb_font_get_empty:
*
- *
+ *
*
* Return value: (transfer full)
*
@@ -1196,6 +1196,9 @@ hb_font_get_empty (void)
0, /* x_ppem */
0, /* y_ppem */
+ 0, /* num_coords */
+ NULL, /* coords */
+
const_cast (&_hb_font_funcs_nil), /* klass */
NULL, /* user_data */
NULL, /* destroy */
@@ -1214,9 +1217,9 @@ hb_font_get_empty (void)
* hb_font_reference: (skip)
* @font: a font.
*
+ *
*
- *
- * Return value: (transfer full):
+ * Return value: (transfer full):
*
* Since: 0.9.2
**/
@@ -1230,7 +1233,7 @@ hb_font_reference (hb_font_t *font)
* hb_font_destroy: (skip)
* @font: a font.
*
- *
+ *
*
* Since: 0.9.2
**/
@@ -1250,20 +1253,22 @@ hb_font_destroy (hb_font_t *font)
hb_face_destroy (font->face);
hb_font_funcs_destroy (font->klass);
+ free (font->coords);
+
free (font);
}
/**
* hb_font_set_user_data: (skip)
* @font: a font.
- * @key:
- * @data:
- * @destroy:
- * @replace:
+ * @key:
+ * @data:
+ * @destroy:
+ * @replace:
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -1280,11 +1285,11 @@ hb_font_set_user_data (hb_font_t *font,
/**
* hb_font_get_user_data: (skip)
* @font: a font.
- * @key:
+ * @key:
*
+ *
*
- *
- * Return value: (transfer none):
+ * Return value: (transfer none):
*
* Since: 0.9.2
**/
@@ -1299,7 +1304,7 @@ hb_font_get_user_data (hb_font_t *font,
* hb_font_make_immutable:
* @font: a font.
*
- *
+ *
*
* Since: 0.9.2
**/
@@ -1319,9 +1324,9 @@ hb_font_make_immutable (hb_font_t *font)
* hb_font_is_immutable:
* @font: a font.
*
+ *
*
- *
- * Return value:
+ * Return value:
*
* Since: 0.9.2
**/
@@ -1361,9 +1366,9 @@ hb_font_set_parent (hb_font_t *font,
* hb_font_get_parent:
* @font: a font.
*
+ *
*
- *
- * Return value: (transfer none):
+ * Return value: (transfer none):
*
* Since: 0.9.2
**/
@@ -1377,9 +1382,9 @@ hb_font_get_parent (hb_font_t *font)
* hb_font_get_face:
* @font: a font.
*
+ *
*
- *
- * Return value: (transfer none):
+ * Return value: (transfer none):
*
* Since: 0.9.2
**/
@@ -1394,10 +1399,10 @@ hb_font_get_face (hb_font_t *font)
* hb_font_set_funcs:
* @font: a font.
* @klass: (closure font_data) (destroy destroy) (scope notified):
- * @font_data:
- * @destroy:
- *
+ * @font_data:
+ * @destroy:
*
+ *
*
* Since: 0.9.2
**/
@@ -1430,9 +1435,9 @@ hb_font_set_funcs (hb_font_t *font,
* hb_font_set_funcs_data:
* @font: a font.
* @font_data: (destroy destroy) (scope notified):
- * @destroy:
- *
+ * @destroy:
*
+ *
*
* Since: 0.9.2
**/
@@ -1459,10 +1464,10 @@ hb_font_set_funcs_data (hb_font_t *font,
/**
* hb_font_set_scale:
* @font: a font.
- * @x_scale:
- * @y_scale:
- *
+ * @x_scale:
+ * @y_scale:
*
+ *
*
* Since: 0.9.2
**/
@@ -1481,10 +1486,10 @@ hb_font_set_scale (hb_font_t *font,
/**
* hb_font_get_scale:
* @font: a font.
- * @x_scale: (out):
- * @y_scale: (out):
- *
+ * @x_scale: (out):
+ * @y_scale: (out):
*
+ *
*
* Since: 0.9.2
**/
@@ -1500,10 +1505,10 @@ hb_font_get_scale (hb_font_t *font,
/**
* hb_font_set_ppem:
* @font: a font.
- * @x_ppem:
- * @y_ppem:
- *
+ * @x_ppem:
+ * @y_ppem:
*
+ *
*
* Since: 0.9.2
**/
@@ -1522,10 +1527,10 @@ hb_font_set_ppem (hb_font_t *font,
/**
* hb_font_get_ppem:
* @font: a font.
- * @x_ppem: (out):
- * @y_ppem: (out):
- *
+ * @x_ppem: (out):
+ * @y_ppem: (out):
*
+ *
*
* Since: 0.9.2
**/
@@ -1539,6 +1544,32 @@ hb_font_get_ppem (hb_font_t *font,
}
+void
+hb_font_set_var_coords_normalized (hb_font_t *font,
+ int *coords, /* XXX 2.14 normalized */
+ unsigned int coords_length)
+{
+ if (font->immutable)
+ return;
+
+ /* Skip tail zero entries. */
+ while (coords_length && !coords[coords_length - 1])
+ coords_length--;
+
+ int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : NULL;
+ if (unlikely (coords_length && !copy))
+ return;
+
+ free (font->coords);
+
+ if (coords_length)
+ memcpy (copy, coords, coords_length * sizeof (coords[0]));
+
+ font->coords = copy;
+ font->num_coords = coords_length;
+}
+
+
#ifndef HB_DISABLE_DEPRECATED
/*
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.h b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.h
index da9a3a7543c..ff5d88f642c 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.h
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.h
@@ -604,6 +604,11 @@ hb_font_get_ppem (hb_font_t *font,
unsigned int *y_ppem);
+HB_EXTERN void
+hb_font_set_var_coords_normalized (hb_font_t *font,
+ int *coords, /* XXX 2.14 normalized */
+ unsigned int coords_length);
+
HB_END_DECLS
#endif /* HB_FONT_H */
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ft.cc b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ft.cc
index fb3c1dfbcf0..fda781623fd 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ft.cc
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ft.cc
@@ -33,7 +33,10 @@
#include "hb-font-private.hh"
+#include "hb-cache-private.hh" // Maybe use in the future?
+
#include FT_ADVANCES_H
+#include FT_MULTIPLE_MASTERS_H
#include FT_TRUETYPE_TABLES_H
@@ -111,7 +114,7 @@ _hb_ft_font_destroy (hb_ft_font_t *ft_font)
* @font:
* @load_flags:
*
- *
+ *
*
* Since: 1.0.5
**/
@@ -133,7 +136,7 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
* hb_ft_font_get_load_flags:
* @font:
*
- *
+ *
*
* Return value:
* Since: 1.0.5
@@ -504,12 +507,12 @@ reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
/**
* hb_ft_face_create:
- * @ft_face: (destroy destroy) (scope notified):
+ * @ft_face: (destroy destroy) (scope notified):
* @destroy:
*
+ *
*
- *
- * Return value: (transfer full):
+ * Return value: (transfer full):
* Since: 0.9.2
**/
hb_face_t *
@@ -541,9 +544,9 @@ hb_ft_face_create (FT_Face ft_face,
* hb_ft_face_create_referenced:
* @ft_face:
*
+ *
*
- *
- * Return value: (transfer full):
+ * Return value: (transfer full):
* Since: 0.9.38
**/
hb_face_t *
@@ -561,11 +564,11 @@ hb_ft_face_finalize (FT_Face ft_face)
/**
* hb_ft_face_create_cached:
- * @ft_face:
+ * @ft_face:
*
+ *
*
- *
- * Return value: (transfer full):
+ * Return value: (transfer full):
* Since: 0.9.2
**/
hb_face_t *
@@ -586,12 +589,12 @@ hb_ft_face_create_cached (FT_Face ft_face)
/**
* hb_ft_font_create:
- * @ft_face: (destroy destroy) (scope notified):
+ * @ft_face: (destroy destroy) (scope notified):
* @destroy:
*
+ *
*
- *
- * Return value: (transfer full):
+ * Return value: (transfer full):
* Since: 0.9.2
**/
hb_font_t *
@@ -606,14 +609,31 @@ hb_ft_font_create (FT_Face ft_face,
hb_face_destroy (face);
_hb_ft_font_set_funcs (font, ft_face, false);
hb_font_set_scale (font,
- (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16),
- (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16));
+ (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16),
+ (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1u<<15)) >> 16));
#if 0 /* hb-ft works in no-hinting model */
hb_font_set_ppem (font,
ft_face->size->metrics.x_ppem,
ft_face->size->metrics.y_ppem);
#endif
+#ifdef HAVE_FT_GET_VAR_BLEND_COORDINATES
+ FT_MM_Var *mm_var = NULL;
+ if (!FT_Get_MM_Var (ft_face, &mm_var))
+ {
+ FT_Fixed coords[mm_var->num_axis];
+ int hbCoords[mm_var->num_axis];
+ if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, coords))
+ {
+ for (int i = 0; i < mm_var->num_axis; ++i)
+ hbCoords[i] = coords[i] >> 2;
+
+ hb_font_set_var_coords_normalized (font, hbCoords, mm_var->num_axis);
+ }
+ }
+ free (mm_var);
+#endif
+
return font;
}
@@ -621,9 +641,9 @@ hb_ft_font_create (FT_Face ft_face,
* hb_ft_font_create_referenced:
* @ft_face:
*
+ *
*
- *
- * Return value: (transfer full):
+ * Return value: (transfer full):
* Since: 0.9.38
**/
hb_font_t *
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type-private.hh b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type-private.hh
index 27c5f1703cd..15e927dcd8f 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type-private.hh
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type-private.hh
@@ -105,7 +105,7 @@ static inline Type& StructAfter(TObject &X)
inline unsigned int get_size (void) const { return (size); }
#define DEFINE_SIZE_UNION(size, _member) \
- DEFINE_INSTANCE_ASSERTION (this->u._member.static_size == (size)); \
+ DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \
static const unsigned int min_size = (size)
#define DEFINE_SIZE_MIN(size) \
@@ -650,7 +650,9 @@ struct IntType
DEFINE_SIZE_STATIC (Size);
};
+typedef IntType CHAR; /* 8-bit signed integer. */
typedef IntType BYTE; /* 8-bit unsigned integer. */
+typedef IntType INT8; /* 8-bit signed integer. */
typedef IntType USHORT; /* 16-bit unsigned integer. */
typedef IntType SHORT; /* 16-bit signed integer. */
typedef IntType ULONG; /* 32-bit unsigned integer. */
@@ -805,6 +807,7 @@ struct OffsetTo : Offset
if (unlikely (!c->check_struct (this))) return_trace (false);
unsigned int offset = *this;
if (unlikely (!offset)) return_trace (true);
+ if (unlikely (!c->check_range (base, offset))) return_trace (false);
const Type &obj = StructAtOffset (base, offset);
return_trace (likely (obj.sanitize (c)) || neuter (c));
}
@@ -815,6 +818,7 @@ struct OffsetTo : Offset
if (unlikely (!c->check_struct (this))) return_trace (false);
unsigned int offset = *this;
if (unlikely (!offset)) return_trace (true);
+ if (unlikely (!c->check_range (base, offset))) return_trace (false);
const Type &obj = StructAtOffset (base, offset);
return_trace (likely (obj.sanitize (c, user_data)) || neuter (c));
}
@@ -948,8 +952,8 @@ struct ArrayOf
};
/* Array of Offset's */
-template
-struct OffsetArrayOf : ArrayOf > {};
+template
+struct OffsetArrayOf : ArrayOf > {};
/* Array of offsets relative to the beginning of the array itself. */
template
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cbdt-table.hh b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cbdt-table.hh
new file mode 100644
index 00000000000..52897abd3a3
--- /dev/null
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cbdt-table.hh
@@ -0,0 +1,384 @@
+/*
+ * Copyright © 2016 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Seigo Nonaka
+ */
+
+#ifndef HB_OT_CBDT_TABLE_HH
+#define HB_OT_CBDT_TABLE_HH
+
+#include "hb-open-type-private.hh"
+
+namespace OT {
+
+struct SmallGlyphMetrics
+{
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ inline void get_extents (hb_glyph_extents_t *extents) const
+ {
+ extents->x_bearing = bearingX;
+ extents->y_bearing = bearingY;
+ extents->width = width;
+ extents->height = -height;
+ }
+
+ BYTE height;
+ BYTE width;
+ CHAR bearingX;
+ CHAR bearingY;
+ BYTE advance;
+
+ DEFINE_SIZE_STATIC(5);
+};
+
+struct BigGlyphMetrics : SmallGlyphMetrics
+{
+ CHAR vertBearingX;
+ CHAR vertBearingY;
+ BYTE vertAdvance;
+
+ DEFINE_SIZE_STATIC(8);
+};
+
+struct SBitLineMetrics
+{
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ CHAR ascender;
+ CHAR decender;
+ BYTE widthMax;
+ CHAR caretSlopeNumerator;
+ CHAR caretSlopeDenominator;
+ CHAR caretOffset;
+ CHAR minOriginSB;
+ CHAR minAdvanceSB;
+ CHAR maxBeforeBL;
+ CHAR minAfterBL;
+ CHAR padding1;
+ CHAR padding2;
+
+ DEFINE_SIZE_STATIC(12);
+};
+
+
+/*
+ * Index Subtables.
+ */
+
+struct IndexSubtableHeader
+{
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ USHORT indexFormat;
+ USHORT imageFormat;
+ ULONG imageDataOffset;
+
+ DEFINE_SIZE_STATIC(8);
+};
+
+template
+struct IndexSubtableFormat1Or3
+{
+ inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ c->check_array (offsetArrayZ, offsetArrayZ[0].static_size, glyph_count + 1));
+ }
+
+ bool get_image_data (unsigned int idx,
+ unsigned int *offset,
+ unsigned int *length) const
+ {
+ if (unlikely (offsetArrayZ[idx + 1] <= offsetArrayZ[idx]))
+ return false;
+
+ *offset = header.imageDataOffset + offsetArrayZ[idx];
+ *length = offsetArrayZ[idx + 1] - offsetArrayZ[idx];
+ return true;
+ }
+
+ IndexSubtableHeader header;
+ Offset offsetArrayZ[VAR];
+
+ DEFINE_SIZE_ARRAY(8, offsetArrayZ);
+};
+
+struct IndexSubtableFormat1 : IndexSubtableFormat1Or3 {};
+struct IndexSubtableFormat3 : IndexSubtableFormat1Or3 {};
+
+struct IndexSubtable
+{
+ inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
+ {
+ TRACE_SANITIZE (this);
+ if (!u.header.sanitize (c)) return_trace (false);
+ switch (u.header.indexFormat) {
+ case 1: return_trace (u.format1.sanitize (c, glyph_count));
+ case 3: return_trace (u.format3.sanitize (c, glyph_count));
+ default:return_trace (true);
+ }
+ }
+
+ inline bool get_extents (hb_glyph_extents_t *extents) const
+ {
+ switch (u.header.indexFormat) {
+ case 2: case 5: /* TODO */
+ case 1: case 3: case 4: /* Variable-metrics formats do not have metrics here. */
+ default:return (false);
+ }
+ }
+
+ bool get_image_data (unsigned int idx,
+ unsigned int *offset,
+ unsigned int *length,
+ unsigned int *format) const
+ {
+ *format = u.header.imageFormat;
+ switch (u.header.indexFormat) {
+ case 1: return u.format1.get_image_data (idx, offset, length);
+ case 3: return u.format3.get_image_data (idx, offset, length);
+ default: return false;
+ }
+ }
+
+ protected:
+ union {
+ IndexSubtableHeader header;
+ IndexSubtableFormat1 format1;
+ IndexSubtableFormat3 format3;
+ /* TODO: Format 2, 4, 5. */
+ } u;
+ public:
+ DEFINE_SIZE_UNION (8, header);
+};
+
+struct IndexSubtableRecord
+{
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ firstGlyphIndex <= lastGlyphIndex &&
+ offsetToSubtable.sanitize (c, this, lastGlyphIndex - firstGlyphIndex + 1));
+ }
+
+ inline bool get_extents (hb_glyph_extents_t *extents) const
+ {
+ return (this+offsetToSubtable).get_extents (extents);
+ }
+
+ bool get_image_data (unsigned int gid,
+ unsigned int *offset,
+ unsigned int *length,
+ unsigned int *format) const
+ {
+ if (gid < firstGlyphIndex || gid > lastGlyphIndex)
+ {
+ return false;
+ }
+ return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
+ offset, length, format);
+ }
+
+ USHORT firstGlyphIndex;
+ USHORT lastGlyphIndex;
+ OffsetTo offsetToSubtable;
+
+ DEFINE_SIZE_STATIC(8);
+};
+
+struct IndexSubtableArray
+{
+ inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+ {
+ TRACE_SANITIZE (this);
+ if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, count)))
+ return_trace (false);
+ for (unsigned int i = 0; i < count; i++)
+ if (unlikely (!indexSubtablesZ[i].sanitize (c, this)))
+ return_trace (false);
+ return_trace (true);
+ }
+
+ public:
+ const IndexSubtableRecord* find_table (hb_codepoint_t glyph, unsigned int numTables) const
+ {
+ for (unsigned int i = 0; i < numTables; ++i)
+ {
+ unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex;
+ unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex;
+ if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) {
+ return &indexSubtablesZ[i];
+ }
+ }
+ return NULL;
+ }
+
+ protected:
+ IndexSubtableRecord indexSubtablesZ[VAR];
+
+ public:
+ DEFINE_SIZE_ARRAY(0, indexSubtablesZ);
+};
+
+struct BitmapSizeTable
+{
+ friend struct CBLC;
+
+ inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ indexSubtableArrayOffset.sanitize (c, base, numberOfIndexSubtables) &&
+ c->check_range (&(base+indexSubtableArrayOffset), indexTablesSize) &&
+ horizontal.sanitize (c) &&
+ vertical.sanitize (c));
+ }
+
+ const IndexSubtableRecord *find_table (hb_codepoint_t glyph, const void *base) const
+ {
+ return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables);
+ }
+
+ protected:
+ OffsetTo indexSubtableArrayOffset;
+ ULONG indexTablesSize;
+ ULONG numberOfIndexSubtables;
+ ULONG colorRef;
+ SBitLineMetrics horizontal;
+ SBitLineMetrics vertical;
+ USHORT startGlyphIndex;
+ USHORT endGlyphIndex;
+ BYTE ppemX;
+ BYTE ppemY;
+ BYTE bitDepth;
+ CHAR flags;
+
+public:
+ DEFINE_SIZE_STATIC(48);
+};
+
+
+/*
+ * Glyph Bitmap Data Formats.
+ */
+
+struct GlyphBitmapDataFormat17
+{
+ SmallGlyphMetrics glyphMetrics;
+ ULONG dataLen;
+ BYTE dataZ[VAR];
+
+ DEFINE_SIZE_ARRAY(9, dataZ);
+};
+
+
+/*
+ * CBLC -- Color Bitmap Location Table
+ */
+
+#define HB_OT_TAG_CBLC HB_TAG('C','B','L','C')
+
+struct CBLC
+{
+ static const hb_tag_t tableTag = HB_OT_TAG_CBLC;
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ likely (version.major == 2 || version.major == 3) &&
+ sizeTables.sanitize (c, this));
+ }
+
+ public:
+ const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
+ unsigned int *x_ppem, unsigned int *y_ppem) const
+ {
+ /* TODO: Make it possible to select strike. */
+
+ unsigned int count = sizeTables.len;
+ for (uint32_t i = 0; i < count; ++i)
+ {
+ unsigned int startGlyphIndex = sizeTables.array[i].startGlyphIndex;
+ unsigned int endGlyphIndex = sizeTables.array[i].endGlyphIndex;
+ if (startGlyphIndex <= glyph && glyph <= endGlyphIndex)
+ {
+ *x_ppem = sizeTables[i].ppemX;
+ *y_ppem = sizeTables[i].ppemY;
+ return sizeTables[i].find_table (glyph, this);
+ }
+ }
+
+ return NULL;
+ }
+
+ protected:
+ FixedVersion<>version;
+ ArrayOf sizeTables;
+
+ public:
+ DEFINE_SIZE_ARRAY(8, sizeTables);
+};
+
+/*
+ * CBDT -- Color Bitmap Data Table
+ */
+#define HB_OT_TAG_CBDT HB_TAG('C','B','D','T')
+
+struct CBDT
+{
+ static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ likely (version.major == 2 || version.major == 3));
+ }
+
+ protected:
+ FixedVersion<>version;
+ BYTE dataZ[VAR];
+
+ public:
+ DEFINE_SIZE_ARRAY(4, dataZ);
+};
+
+} /* namespace OT */
+
+#endif /* HB_OT_CBDT_TABLE_HH */
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-font.cc b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-font.cc
index 3c63f336a6b..3b3122b69a3 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-font.cc
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-font.cc
@@ -31,6 +31,7 @@
#include "hb-font-private.hh"
#include "hb-ot-cmap-table.hh"
+#include "hb-ot-cbdt-table.hh"
#include "hb-ot-glyf-table.hh"
#include "hb-ot-head-table.hh"
#include "hb-ot-hhea-table.hh"
@@ -47,6 +48,7 @@ struct hb_ot_face_metrics_accelerator_t
unsigned short ascender;
unsigned short descender;
unsigned short line_gap;
+ bool has_font_extents;
const OT::_mtx *table;
hb_blob_t *blob;
@@ -54,9 +56,10 @@ struct hb_ot_face_metrics_accelerator_t
inline void init (hb_face_t *face,
hb_tag_t _hea_tag,
hb_tag_t _mtx_tag,
- hb_tag_t os2_tag)
+ hb_tag_t os2_tag,
+ unsigned int default_advance = 0)
{
- this->default_advance = face->get_upem ();
+ this->default_advance = default_advance ? default_advance : face->get_upem ();
bool got_font_extents = false;
if (os2_tag)
@@ -82,9 +85,12 @@ struct hb_ot_face_metrics_accelerator_t
this->ascender = _hea->ascender;
this->descender = _hea->descender;
this->line_gap = _hea->lineGap;
+ got_font_extents = (this->ascender | this->descender) != 0;
}
hb_blob_destroy (_hea_blob);
+ this->has_font_extents = got_font_extents;
+
this->blob = OT::Sanitizer::sanitize (face->reference_table (_mtx_tag));
/* Cap num_metrics() and num_advances() based on table length. */
@@ -202,6 +208,91 @@ struct hb_ot_face_glyf_accelerator_t
}
};
+struct hb_ot_face_cbdt_accelerator_t
+{
+ hb_blob_t *cblc_blob;
+ hb_blob_t *cbdt_blob;
+ const OT::CBLC *cblc;
+ const OT::CBDT *cbdt;
+
+ unsigned int cbdt_len;
+ float upem;
+
+ inline void init (hb_face_t *face)
+ {
+ upem = face->get_upem();
+
+ cblc_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_CBLC));
+ cbdt_blob = OT::Sanitizer::sanitize (face->reference_table (HB_OT_TAG_CBDT));
+ cbdt_len = hb_blob_get_length (cbdt_blob);
+
+ if (hb_blob_get_length (cblc_blob) == 0) {
+ cblc = NULL;
+ cbdt = NULL;
+ return; /* Not a bitmap font. */
+ }
+ cblc = OT::Sanitizer::lock_instance (cblc_blob);
+ cbdt = OT::Sanitizer::lock_instance (cbdt_blob);
+
+ }
+
+ inline void fini (void)
+ {
+ hb_blob_destroy (this->cblc_blob);
+ hb_blob_destroy (this->cbdt_blob);
+ }
+
+ inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+ {
+ unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */
+
+ if (cblc == NULL)
+ return false; // Not a color bitmap font.
+
+ const OT::IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem);
+ if (subtable_record == NULL)
+ return false;
+
+ if (subtable_record->get_extents (extents))
+ return true;
+
+ unsigned int image_offset = 0, image_length = 0, image_format = 0;
+ if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format))
+ return false;
+
+ {
+ /* TODO Move the following into CBDT struct when adding more formats. */
+
+ if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
+ return false;
+
+ switch (image_format)
+ {
+ case 17: {
+ if (unlikely (image_length < OT::GlyphBitmapDataFormat17::min_size))
+ return false;
+
+ const OT::GlyphBitmapDataFormat17& glyphFormat17 =
+ OT::StructAtOffset (this->cbdt, image_offset);
+ glyphFormat17.glyphMetrics.get_extents (extents);
+ }
+ break;
+ default:
+ // TODO: Support other image formats.
+ return false;
+ }
+ }
+
+ /* Convert to the font units. */
+ extents->x_bearing *= upem / (float) x_ppem;
+ extents->y_bearing *= upem / (float) y_ppem;
+ extents->width *= upem / (float) x_ppem;
+ extents->height *= upem / (float) y_ppem;
+
+ return true;
+ }
+};
+
typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
hb_codepoint_t codepoint,
hb_codepoint_t *glyph);
@@ -264,7 +355,11 @@ struct hb_ot_face_cmap_accelerator_t
if (!subtable) subtable = cmap->find_subtable (0, 2);
if (!subtable) subtable = cmap->find_subtable (0, 1);
if (!subtable) subtable = cmap->find_subtable (0, 0);
- if (!subtable)(subtable = cmap->find_subtable (3, 0)) && (symbol = true);
+ if (!subtable)
+ {
+ subtable = cmap->find_subtable (3, 0);
+ if (subtable) symbol = true;
+ }
/* Meh. */
if (!subtable) subtable = &OT::Null(OT::CmapSubtable);
@@ -374,6 +469,7 @@ struct hb_ot_font_t
hb_ot_face_metrics_accelerator_t h_metrics;
hb_ot_face_metrics_accelerator_t v_metrics;
hb_lazy_loader_t glyf;
+ hb_lazy_loader_t cbdt;
};
@@ -387,8 +483,10 @@ _hb_ot_font_create (hb_face_t *face)
ot_font->cmap.init (face);
ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_os2);
- ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE); /* TODO Can we do this lazily? */
+ ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE,
+ ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
ot_font->glyf.init (face);
+ ot_font->cbdt.init (face);
return ot_font;
}
@@ -400,6 +498,7 @@ _hb_ot_font_destroy (hb_ot_font_t *ot_font)
ot_font->h_metrics.fini ();
ot_font->v_metrics.fini ();
ot_font->glyf.fini ();
+ ot_font->cbdt.fini ();
free (ot_font);
}
@@ -458,6 +557,8 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
{
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
bool ret = ot_font->glyf->get_extents (glyph, extents);
+ if (!ret)
+ ret = ot_font->cbdt->get_extents (glyph, extents);
extents->x_bearing = font->em_scale_x (extents->x_bearing);
extents->y_bearing = font->em_scale_y (extents->y_bearing);
extents->width = font->em_scale_x (extents->width);
@@ -475,7 +576,7 @@ hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED,
metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender);
metrics->descender = font->em_scale_y (ot_font->h_metrics.descender);
metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap);
- return true;
+ return ot_font->h_metrics.has_font_extents;
}
static hb_bool_t
@@ -488,7 +589,7 @@ hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED,
metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender);
metrics->descender = font->em_scale_x (ot_font->v_metrics.descender);
metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap);
- return true;
+ return ot_font->v_metrics.has_font_extents;
}
static hb_font_funcs_t *static_ot_funcs = NULL;
diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-common-private.hh b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-common-private.hh
index f6d966cc97d..80dc44eb1d8 100644
--- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-common-private.hh
+++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-common-private.hh
@@ -507,7 +507,7 @@ struct Feature
{ return this+featureParams; }
inline bool sanitize (hb_sanitize_context_t *c,
- const Record::sanitize_closure_t *closure) const
+ const Record::sanitize_closure_t *closure = NULL) const
{
TRACE_SANITIZE (this);
if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
@@ -731,8 +731,8 @@ struct CoverageFormat1
inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
inline bool more (void) { return i < c->glyphArray.len; }
inline void next (void) { i++; }
- inline uint16_t get_glyph (void) { return c->glyphArray[i]; }
- inline uint16_t get_coverage (void) { return i; }
+ inline hb_codepoint_t get_glyph (void) { return c->glyphArray[i]; }
+ inline unsigned int get_coverage (void) { return i; }
private:
const struct CoverageFormat1 *c;
@@ -829,26 +829,33 @@ struct CoverageFormat2
public:
/* Older compilers need this to be public. */
- struct Iter {
- inline void init (const CoverageFormat2 &c_) {
+ struct Iter
+ {
+ inline void init (const CoverageFormat2 &c_)
+ {
c = &c_;
coverage = 0;
i = 0;
j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0;
}
inline bool more (void) { return i < c->rangeRecord.len; }
- inline void next (void) {
- coverage++;
- if (j == c->rangeRecord[i].end) {
+ inline void next (void)
+ {
+ if (j >= c->rangeRecord[i].end)
+ {
i++;
if (more ())
+ {
j = c->rangeRecord[i].start;
+ coverage = c->rangeRecord[i].value;
+ }
return;
}
+ coverage++;
j++;
}
- inline uint16_t get_glyph (void) { return j; }
- inline uint16_t get_coverage (void) { return coverage; }
+ inline hb_codepoint_t get_glyph (void) { return j; }
+ inline unsigned int get_coverage (void) { return coverage; }
private:
const struct CoverageFormat2 *c;
@@ -957,14 +964,14 @@ struct Coverage
default: break;
}
}
- inline uint16_t get_glyph (void) {
+ inline hb_codepoint_t get_glyph (void) {
switch (format) {
case 1: return u.format1.get_glyph ();
case 2: return u.format2.get_glyph ();
default:return 0;
}
}
- inline uint16_t get_coverage (void) {
+ inline unsigned int get_coverage (void) {
switch (format) {
case 1: return u.format1.get_coverage ();
case 2: return u.format2.get_coverage ();
@@ -1161,12 +1168,381 @@ struct ClassDef
};
+/*
+ * Item Variation Store
+ */
+
+struct VarRegionAxis
+{
+ inline float evaluate (int coord) const
+ {
+ int start = startCoord, peak = peakCoord, end = endCoord;
+
+ /* TODO Move these to sanitize(). */
+ if (unlikely (start > peak || peak > end))
+ return 1.;
+ if (unlikely (start < 0 && end > 0 && peak != 0))
+ return 1.;
+
+ if (peak == 0 || coord == peak)
+ return 1.;
+
+ if (coord <= start || end <= coord)
+ return 0.;
+
+ /* Interpolate */
+ if (coord < peak)
+ return float (coord - start) / (peak - start);
+ else
+ return float (end - coord) / (end - peak);
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ /* TODO Handle invalid start/peak/end configs, so we don't
+ * have to do that at runtime. */
+ }
+
+ public:
+ F2DOT14 startCoord;
+ F2DOT14 peakCoord;
+ F2DOT14 endCoord;
+ public:
+ DEFINE_SIZE_STATIC (6);
+};
+
+struct VarRegionList
+{
+ inline float evaluate (unsigned int region_index,
+ int *coords, unsigned int coord_len) const
+ {
+ if (unlikely (region_index >= regionCount))
+ return 0.;
+
+ const VarRegionAxis *axes = axesZ + (region_index * axisCount);
+
+ float v = 1.;
+ unsigned int count = MIN (coord_len, (unsigned int) axisCount);
+ for (unsigned int i = 0; i < count; i++)
+ {
+ float factor = axes[i].evaluate (coords[i]);
+ if (factor == 0.)
+ return 0.;
+ v *= factor;
+ }
+ return v;
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ c->check_array (axesZ, axesZ[0].static_size,
+ (unsigned int) axisCount * (unsigned int) regionCount));
+ }
+
+ protected:
+ USHORT axisCount;
+ USHORT regionCount;
+ VarRegionAxis axesZ[VAR];
+ public:
+ DEFINE_SIZE_ARRAY (4, axesZ);
+};
+
+struct VarData
+{
+ inline unsigned int get_row_size (void) const
+ { return shortCount + regionIndices.len; }
+
+ inline unsigned int get_size (void) const
+ { return itemCount * get_row_size (); }
+
+ inline float get_delta (unsigned int inner,
+ int *coords, unsigned int coord_count,
+ const VarRegionList ®ions) const
+ {
+ if (unlikely (inner >= itemCount))
+ return 0.;
+
+ unsigned int count = regionIndices.len;
+ unsigned int scount = shortCount;
+
+ const BYTE *bytes = &StructAfter (regionIndices);
+ const BYTE *row = bytes + inner * (scount + count);
+
+ float delta = 0.;
+ unsigned int i = 0;
+
+ const SHORT *scursor = reinterpret_cast |