--- a/jdk/.hgtags Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/.hgtags Tue Jan 17 11:35:28 2017 -0800
@@ -394,3 +394,4 @@
5a846396a24c7aff01d6a8feaa7afc0a6369f04d jdk-9+149
71e198ef3839045e829a879af1d709be16ab0f88 jdk-9+150
d27bab22ff62823902d93d1d35ca397cfd50d059 jdk-9+151
+a20f2cf90762673e1bc4980fd6597e70a2578045 jdk-9+152
--- a/jdk/src/java.base/share/classes/java/io/File.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/io/File.java Tue Jan 17 11:35:28 2017 -0800
@@ -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 @@
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)
--- a/jdk/src/java.base/share/classes/java/util/Date.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/share/classes/java/util/Date.java Tue Jan 17 11:35:28 2017 -0800
@@ -82,17 +82,19 @@
* well; for example, the time scale used by the satellite-based
* global positioning system (GPS) is synchronized to UTC but is
* <i>not</i> 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):
* <blockquote><pre>
- * <a href="http://www.usno.navy.mil">http://www.usno.navy.mil</a>
+ * <a href="http://www.usno.navy.mil/USNO">http://www.usno.navy.mil/USNO</a>
* </pre></blockquote>
* <p>
- * and their definitions of "Systems of Time" at:
+ * and the material regarding "Systems of Time" at:
* <blockquote><pre>
* <a href="http://www.usno.navy.mil/USNO/time/master-clock/systems-of-time">http://www.usno.navy.mil/USNO/time/master-clock/systems-of-time</a>
* </pre></blockquote>
* <p>
+ * which has descriptions of various different time systems including
+ * UT, UT1, and UTC.
+ * <p>
* In all methods of class {@code Date} that accept or return
* year, month, date, hours, minutes, and seconds values, the
* following representations are used:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java Tue Jan 17 11:35:28 2017 -0800
@@ -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<String> 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<String> 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<String, ModuleHashes> computeHashes(Set<String> roots) {
+ // build a graph containing the the packaged modules and
+ // its transitive dependences matching --hash-modules
+ Graph.Builder<String> builder = new Graph.Builder<>();
+ Deque<ResolvedModule> deque = new ArrayDeque<>(configuration.modules());
+ Set<ResolvedModule> 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<String> 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<String> mods = new HashSet<>();
+ Map<String, ModuleHashes> 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<String> 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<String, Path> 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<T> {
+ private final Set<T> nodes;
+ private final Map<T, Set<T>> edges;
+
+ public Graph(Set<T> nodes, Map<T, Set<T>> edges) {
+ this.nodes = Collections.unmodifiableSet(nodes);
+ this.edges = Collections.unmodifiableMap(edges);
+ }
+
+ public Set<T> nodes() {
+ return nodes;
+ }
+
+ public Map<T, Set<T>> edges() {
+ return edges;
+ }
+
+ public Set<T> adjacentNodes(T u) {
+ return edges.get(u);
+ }
+
+ public boolean contains(T u) {
+ return nodes.contains(u);
+ }
+
+ /**
+ * Returns nodes sorted in topological order.
+ */
+ public Stream<T> orderedNodes() {
+ TopoSorter<T> sorter = new TopoSorter<>(this);
+ return sorter.result.stream();
+ }
+
+ /**
+ * Traverse this graph and performs the given action in topological order
+ */
+ public void ordered(Consumer<T> action) {
+ TopoSorter<T> sorter = new TopoSorter<>(this);
+ sorter.ordered(action);
+ }
+
+ /**
+ * Traverses this graph and performs the given action in reverse topological order
+ */
+ public void reverse(Consumer<T> action) {
+ TopoSorter<T> sorter = new TopoSorter<>(this);
+ sorter.reverse(action);
+ }
+
+ /**
+ * Returns a transposed graph from this graph
+ */
+ public Graph<T> transpose() {
+ Builder<T> 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<T> dfs(T root) {
+ return dfs(Set.of(root));
+ }
+
+ /**
+ * Returns all nodes reachable from the given set of roots.
+ */
+ public Set<T> dfs(Set<T> roots) {
+ Deque<T> deque = new LinkedList<>(roots);
+ Set<T> 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<T> {
+ final Set<T> nodes = new HashSet<>();
+ final Map<T, Set<T>> 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<T> build() {
+ return new Graph<T>(nodes, edges);
+ }
+ }
+ }
+
+ /**
+ * Topological sort
+ */
+ private static class TopoSorter<T> {
+ final Deque<T> result = new LinkedList<>();
+ final Deque<T> nodes;
+ final Graph<T> graph;
+
+ TopoSorter(Graph<T> graph) {
+ this.graph = graph;
+ this.nodes = new LinkedList<>(graph.nodes);
+ sort();
+ }
+
+ public void ordered(Consumer<T> action) {
+ result.iterator().forEachRemaining(action);
+ }
+
+ public void reverse(Consumer<T> action) {
+ result.descendingIterator().forEachRemaining(action);
+ }
+
+ private void sort() {
+ Deque<T> visited = new LinkedList<>();
+ Deque<T> done = new LinkedList<>();
+ T node;
+ while ((node = nodes.poll()) != null) {
+ if (!visited.contains(node)) {
+ visit(node, visited, done);
+ }
+ }
+ }
+
+ private void visit(T node, Deque<T> visited, Deque<T> 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);
+ }
+ }
+}
--- a/jdk/src/java.base/share/native/libnet/net_util.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/share/native/libnet/net_util.c Tue Jan 17 11:35:28 2017 -0800
@@ -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 @@
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 @@
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 @@
}
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 @@
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 @@
}
} 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 @@
}
}
+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;
--- a/jdk/src/java.base/share/native/libnet/net_util.h Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/share/native/libnet/net_util.h Tue Jan 17 11:35:28 2017 -0800
@@ -63,8 +63,8 @@
*/
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 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 @@
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 @@
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);
--- a/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c Tue Jan 17 11:35:28 2017 -0800
@@ -211,7 +211,8 @@
{
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))
--- a/jdk/src/java.base/unix/native/libnet/NetworkInterface.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/unix/native/libnet/NetworkInterface.c Tue Jan 17 11:35:28 2017 -0800
@@ -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 @@
int sock;
sock = openSocket(env, AF_INET);
- if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+ if (sock < 0) {
return NULL;
}
@@ -809,7 +809,7 @@
// 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;
}
--- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Tue Jan 17 11:35:28 2017 -0800
@@ -99,7 +99,7 @@
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 @@
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 @@
return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
}
-
/*
* Class: java_net_PlainDatagramSocketImpl
* Method: init
@@ -166,7 +164,6 @@
initInetAddressIDs(env);
JNU_CHECK_EXCEPTION(env);
Java_java_net_NetworkInterface_init(env, 0);
-
}
/*
@@ -176,13 +173,13 @@
*/
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 @@
}
/* 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 @@
/* 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 @@
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 @@
#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 @@
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);
- } else {
- addr.sa4.sin_family = AF_UNSPEC;
- len = sizeof(struct sockaddr_in);
- }
- NET_Connect(fd, &addr.sa, len);
+ 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);
-#ifdef __linux__
- int localPort = 0;
- if (getsockname(fd, &addr.sa, &len) == -1)
- return;
+#if defined(__linux__)
+ 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);
- }
+ 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_port = htons(localPort);
+ }
- NET_Bind(fd, &addr.sa, len);
- }
+ NET_Bind(fd, &addr, len);
+ }
#endif
#else
@@ -355,8 +356,9 @@
/* 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 @@
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 @@
(*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 @@
* 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 @@
#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 @@
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 @@
*/
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 @@
*/
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 @@
/*
* 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 @@
}
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 @@
*/
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 @@
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 @@
#ifdef __linux__
mname.imr_address.s_addr = in.s_addr;
-
+ mname.imr_ifindex = 0;
#else
mname.imr_interface.s_addr = in.s_addr;
#endif
--- a/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c Tue Jan 17 11:35:28 2017 -0800
@@ -244,7 +244,7 @@
/* 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 @@
}
/* 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 @@
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 @@
* 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 @@
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 @@
}
/* 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 @@
/* 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 @@
/* accepted fd */
jint newfd;
- SOCKETADDRESS him;
+ SOCKETADDRESS sa;
socklen_t slen = sizeof(SOCKETADDRESS);
if (IS_NULL(fdObj)) {
@@ -661,7 +662,7 @@
return;
}
- newfd = NET_Accept(fd, &him.sa, &slen);
+ newfd = NET_Accept(fd, &sa.sa, &slen);
/* connection accepted */
if (newfd >= 0) {
@@ -709,7 +710,7 @@
/*
* 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 @@
* 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);
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c Tue Jan 17 11:35:28 2017 -0800
@@ -234,29 +234,6 @@
}
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 @@
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 @@
} 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);
+ 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);
+ }
-#if defined(_ALLBSD_SOURCE)
-// XXXBSD: should we do something with scope id here ? see below linux comment
-/* MMM: Come back to this! */
-#endif
-
+#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 @@
* 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 @@
/* 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 @@
* 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 @@
* 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 @@
*
*/
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 @@
* ## 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 @@
*/
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 @@
* 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 @@
}
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) {
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.h Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h Tue Jan 17 11:35:28 2017 -0800
@@ -30,32 +30,6 @@
#include <sys/poll.h>
#include <sys/socket.h>
-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 @@
} 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);
--- a/jdk/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c Tue Jan 17 11:35:28 2017 -0800
@@ -181,11 +181,11 @@
*/
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 @@
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 @@
(*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 @@
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;
}
--- a/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c Tue Jan 17 11:35:28 2017 -0800
@@ -64,7 +64,7 @@
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 @@
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);
}
}
--- a/jdk/src/java.base/unix/native/libnio/ch/Net.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/unix/native/libnio/ch/Net.c Tue Jan 17 11:35:28 2017 -0800
@@ -274,15 +274,15 @@
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 @@
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 @@
return -1;
#endif /* _ALLBSD_SOURCE */
}
- return NET_GetPortFromSockaddr(&sa.sa);
+ return NET_GetPortFromSockaddr(&sa);
}
JNIEXPORT jobject JNICALL
@@ -382,7 +382,7 @@
return NULL;
#endif /* _ALLBSD_SOURCE */
}
- return NET_SockaddrToInetAddress(env, &sa.sa, &port);
+ return NET_SockaddrToInetAddress(env, &sa, &port);
}
JNIEXPORT jint JNICALL
--- a/jdk/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c Tue Jan 17 11:35:28 2017 -0800
@@ -112,7 +112,7 @@
}
(*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);
--- a/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java Tue Jan 17 11:35:28 2017 -0800
@@ -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 @@
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 @@
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);
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c Tue Jan 17 11:35:28 2017 -0800
@@ -53,7 +53,7 @@
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 @@
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 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_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 @@
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 @@
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 @@
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 @@
/* 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 @@
*/
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 @@
(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 @@
(*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");
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Tue Jan 17 11:35:28 2017 -0800
@@ -89,15 +89,14 @@
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 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 @@
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 @@
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 @@
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 @@
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);
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c Tue Jan 17 11:35:28 2017 -0800
@@ -420,18 +420,13 @@
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 @@
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 @@
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 @@
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 @@
*/
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 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
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 @@
*/
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 @@
* 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 @@
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 @@
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 @@
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 @@
(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 @@
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 @@
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 @@
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 @@
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");
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c Tue Jan 17 11:35:28 2017 -0800
@@ -175,8 +175,8 @@
*/
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 @@
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 @@
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 @@
(*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 @@
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 @@
*/
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 @@
}
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 @@
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 @@
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 @@
(*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 @@
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 @@
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 @@
/* 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 @@
}
}
}
- 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 @@
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 @@
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 @@
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 @@
* 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 @@
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);
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c Tue Jan 17 11:35:28 2017 -0800
@@ -488,10 +488,10 @@
* 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 @@
* 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 @@
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 @@
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 @@
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 @@
}
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 @@
/* 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 @@
}
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 @@
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;
+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, scopeid = 0;
- jint cached_scope_id = 0;
+ jint address;
+ unsigned int scopeid = 0, cached_scope_id = 0;
- if (family == AF_INET) { /* will convert to IPv4-mapped address */
- memset((char *) caddr, 0, 16);
+ 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 @@
} 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) ;
+ sa->sa6.sin6_scope_id = scopeid == 0 ? cached_scope_id : scopeid;
+ if (len != NULL) {
+ *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;
+ 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 @@
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.
*
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.h Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.h Tue Jan 17 11:35:28 2017 -0800
@@ -121,7 +121,7 @@
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 */
--- a/jdk/src/java.base/windows/native/libnio/ch/DatagramChannelImpl.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/windows/native/libnio/ch/DatagramChannelImpl.c Tue Jan 17 11:35:28 2017 -0800
@@ -96,7 +96,7 @@
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 @@
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 @@
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 @@
(char *)buf,
len,
0,
- (struct sockaddr *)&sa,
+ &sa.sa,
&sa_len);
if (n == SOCKET_ERROR) {
@@ -182,12 +182,11 @@
*/
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 @@
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 @@
// 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 @@
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) {
--- a/jdk/src/java.base/windows/native/libnio/ch/Net.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/windows/native/libnio/ch/Net.c Tue Jan 17 11:35:28 2017 -0800
@@ -168,13 +168,13 @@
{
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 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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
--- a/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c Tue Jan 17 11:35:28 2017 -0800
@@ -95,7 +95,7 @@
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 @@
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);
--- a/jdk/src/java.base/windows/native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/java.base/windows/native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c Tue Jan 17 11:35:28 2017 -0800
@@ -88,26 +88,21 @@
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) {
--- a/jdk/src/jdk.internal.le/windows/native/lible/WindowsTerminal.cpp Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.internal.le/windows/native/lible/WindowsTerminal.cpp Tue Jan 17 11:35:28 2017 -0800
@@ -102,26 +102,26 @@
JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getWindowsTerminalWidth
(JNIEnv *, jobject) {
- HANDLE hStdIn;
- if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
+ HANDLE hStdOut;
+ if ((hStdOut = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
return -1;
}
CONSOLE_SCREEN_BUFFER_INFO info;
- if (! GetConsoleScreenBufferInfo(hStdIn, &info)) {
+ if (! GetConsoleScreenBufferInfo(hStdOut, &info)) {
return -1;
}
- return info.dwSize.X;
+ return info.srWindow.Right - info.srWindow.Left;
}
JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getWindowsTerminalHeight
(JNIEnv *, jobject) {
- HANDLE hStdIn;
- if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
+ HANDLE hStdOut;
+ if ((hStdOut = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
return -1;
}
CONSOLE_SCREEN_BUFFER_INFO info;
- if (! GetConsoleScreenBufferInfo(hStdIn, &info)) {
+ if (! GetConsoleScreenBufferInfo(hStdOut, &info)) {
return -1;
}
- return info.dwSize.Y;
+ return info.srWindow.Bottom - info.srWindow.Top + 1;
}
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java Tue Jan 17 11:35:28 2017 -0800
@@ -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
@@ -34,6 +34,8 @@
import java.nio.file.Paths;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
+
+import jdk.internal.module.ModulePath;
import jdk.internal.module.ModuleResolution;
/**
@@ -155,8 +157,8 @@
for (String dir : dirs) {
paths[i++] = Paths.get(dir);
}
- jartool.moduleFinder = ModuleFinder.compose(jartool.moduleFinder,
- ModuleFinder.of(paths));
+ jartool.moduleFinder =
+ new ModulePath(Runtime.version(), true, paths);
}
},
new Option(false, OptionType.CREATE_UPDATE, "--do-not-resolve-by-default") {
@@ -169,9 +171,9 @@
new Option(true, OptionType.CREATE_UPDATE, "--warn-if-resolved") {
void process(Main jartool, String opt, String arg) throws BadArgs {
ModuleResolution mres = ModuleResolution.empty();
- if (jartool.moduleResolution.doNotResolveByDefault())
+ if (jartool.moduleResolution.doNotResolveByDefault()) {
mres.withDoNotResolveByDefault();
-
+ }
if (arg.equals("deprecated")) {
jartool.moduleResolution = mres.withDeprecated();
} else if (arg.equals("deprecated-for-removal")) {
@@ -201,26 +203,27 @@
// Other options
new Option(true, true, OptionType.OTHER, "--help", "-h") {
void process(Main jartool, String opt, String arg) throws BadArgs {
- if (arg == null) {
- jartool.info = Main.Info.HELP;
- return;
+ if (jartool.info == null) {
+ if (arg == null) {
+ jartool.info = GNUStyleOptions::printHelp; // Main.Info.HELP;
+ return;
+ }
+ if (!arg.equals("compat"))
+ throw new BadArgs("error.illegal.option", arg).showUsage(true);
+ // jartool.info = Main.Info.COMPAT_HELP;
+ jartool.info = GNUStyleOptions::printCompatHelp;
}
-
- if (!arg.equals("compat"))
- throw new BadArgs("error.illegal.option", arg).showUsage(true);
-
- jartool.info = Main.Info.COMPAT_HELP;
}
},
new Option(false, OptionType.OTHER, "--help-extra") {
void process(Main jartool, String opt, String arg) throws BadArgs {
- jartool.info = Main.Info.HELP_EXTRA;
+ jartool.info = GNUStyleOptions::printHelpExtra;
}
},
new Option(false, OptionType.OTHER, "--version") {
void process(Main jartool, String opt, String arg) {
if (jartool.info == null)
- jartool.info = Main.Info.VERSION;
+ jartool.info = GNUStyleOptions::printVersion;
}
}
};
@@ -279,14 +282,14 @@
static int parseOptions(Main jartool, String[] args) throws BadArgs {
int count = 0;
if (args.length == 0) {
- jartool.info = Main.Info.USAGE_TRYHELP;
+ jartool.info = GNUStyleOptions::printUsageTryHelp; // never be here
return 0;
}
// process options
for (; count < args.length; count++) {
- if (args[count].charAt(0) != '-' || args[count].equals("-C")
- || args[count].equals("--release"))
+ if (args[count].charAt(0) != '-' || args[count].equals("-C") ||
+ args[count].equals("--release"))
break;
String name = args[count];
@@ -322,15 +325,15 @@
throw new BadArgs("error.unrecognized.option", name).showUsage(true);
}
- static void printHelp(PrintWriter out) {
- printHelp(out, false);
+ static void printHelpExtra(PrintWriter out) {
+ printHelp0(out, true);
}
- static void printHelpExtra(PrintWriter out) {
- printHelp(out, true);
+ static void printHelp(PrintWriter out) {
+ printHelp0(out, false);
}
- private static void printHelp(PrintWriter out, boolean printExtra) {
+ private static void printHelp0(PrintWriter out, boolean printExtra) {
out.format("%s%n", Main.getMsg("main.help.preopt"));
for (OptionType type : OptionType.values()) {
boolean typeHeadingWritten = false;
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Tue Jan 17 11:35:28 2017 -0800
@@ -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
@@ -27,6 +27,7 @@
import java.io.*;
import java.lang.module.Configuration;
+import java.lang.module.InvalidModuleDescriptorException;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Provides;
@@ -46,7 +47,7 @@
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.function.Consumer;
-import java.util.function.Function;
+import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -58,6 +59,7 @@
import jdk.internal.module.Checks;
import jdk.internal.module.ModuleHashes;
+import jdk.internal.module.ModuleHashesBuilder;
import jdk.internal.module.ModuleInfo;
import jdk.internal.module.ModuleInfoExtender;
import jdk.internal.module.ModuleResolution;
@@ -66,7 +68,6 @@
import static jdk.internal.util.jar.JarIndex.INDEX_NAME;
import static java.util.jar.JarFile.MANIFEST_NAME;
import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toSet;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
/**
@@ -74,58 +75,24 @@
* (Java Archive) file format. The JAR format is based on the ZIP file
* format, with optional meta-information stored in a MANIFEST entry.
*/
-public
-class Main {
+public class Main {
String program;
PrintWriter out, err;
String fname, mname, ename;
String zname = "";
String rootjar = null;
- Set<String> concealedPackages = new HashSet<>(); // used by Validator
private static final int BASE_VERSION = 0;
- class Entry {
- final String basename;
- final String entryname;
+ private static class Entry {
+ final String name;
final File file;
final boolean isDir;
- Entry(File file, String basename, String entryname) {
- this.file = file;
- this.isDir = file.isDirectory();
- this.basename = basename;
- this.entryname = entryname;
- }
-
- Entry(int version, File file) {
+ Entry(File file, String name, boolean isDir) {
this.file = file;
- String path = file.getPath();
- if (file.isDirectory()) {
- isDir = true;
- path = path.endsWith(File.separator) ? path :
- path + File.separator;
- } else {
- isDir = false;
- }
- EntryName en = new EntryName(path, version);
- basename = en.baseName;
- entryname = en.entryName;
- }
-
- /**
- * Returns a new Entry that trims the versions directory.
- *
- * This entry should be a valid entry matching the given version.
- */
- Entry toVersionedEntry(int version) {
- assert isValidVersionedEntry(this, version);
-
- if (version == BASE_VERSION)
- return this;
-
- EntryName en = new EntryName(trimVersionsDir(basename, version), version);
- return new Entry(this.file, en.baseName, en.entryName);
+ this.isDir = isDir;
+ this.name = name;
}
@Override
@@ -141,32 +108,6 @@
}
}
- class EntryName {
- final String baseName;
- final String entryName;
-
- EntryName(String name, int version) {
- name = name.replace(File.separatorChar, '/');
- String matchPath = "";
- for (String path : pathsMap.get(version)) {
- if (name.startsWith(path)
- && (path.length() > matchPath.length())) {
- matchPath = path;
- }
- }
- name = safeName(name.substring(matchPath.length()));
- // the old implementaton doesn't remove
- // "./" if it was led by "/" (?)
- if (name.startsWith("./")) {
- name = name.substring(2);
- }
- baseName = name;
- entryName = (version > BASE_VERSION)
- ? VERSIONS_DIR + version + "/" + baseName
- : baseName;
- }
- }
-
// An entryName(path)->Entry map generated during "expand", it helps to
// decide whether or not an existing entry in a jar file needs to be
// replaced, during the "update" operation.
@@ -175,11 +116,8 @@
// All entries need to be added/updated.
Set<Entry> entries = new LinkedHashSet<>();
- // All packages.
- Set<String> packages = new HashSet<>();
- // All actual entries added, or existing, in the jar file ( excl manifest
- // and module-info.class ). Populated during create or update.
- Set<String> jarEntries = new HashSet<>();
+ // module-info.class entries need to be added/updated.
+ Map<String,byte[]> moduleInfos = new HashMap<>();
// A paths Set for each version, where each Set contains directories
// specified by the "-C" operation.
@@ -208,19 +146,7 @@
boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag, pflag, dflag;
/* To support additional GNU Style informational options */
- enum Info {
- HELP(GNUStyleOptions::printHelp),
- HELP_EXTRA(GNUStyleOptions::printHelpExtra),
- COMPAT_HELP(GNUStyleOptions::printCompatHelp),
- USAGE_TRYHELP(GNUStyleOptions::printUsageTryHelp),
- VERSION(GNUStyleOptions::printVersion);
-
- private Consumer<PrintWriter> printFunction;
- Info(Consumer<PrintWriter> f) { this.printFunction = f; }
- void print(PrintWriter out) { printFunction.accept(out); }
- };
- Info info;
-
+ Consumer<PrintWriter> info;
/* Modular jar related options */
Version moduleVersion;
@@ -228,8 +154,7 @@
ModuleResolution moduleResolution = ModuleResolution.empty();
ModuleFinder moduleFinder = ModuleFinder.of();
- private static final String MODULE_INFO = "module-info.class";
-
+ static final String MODULE_INFO = "module-info.class";
static final String MANIFEST_DIR = "META-INF/";
static final String VERSIONS_DIR = MANIFEST_DIR + "versions/";
static final String VERSION = "1.0";
@@ -324,7 +249,6 @@
}
}
}
-
if (cflag) {
Manifest manifest = null;
if (!Mflag) {
@@ -347,72 +271,60 @@
addMultiRelease(manifest);
}
}
-
- Map<String,Path> moduleInfoPaths = new HashMap<>();
- for (int version : filesMap.keySet()) {
- String[] files = filesMap.get(version);
- expand(null, files, false, moduleInfoPaths, version);
- }
-
- Map<String,byte[]> moduleInfos = new LinkedHashMap<>();
- if (!moduleInfoPaths.isEmpty()) {
- if (!checkModuleInfos(moduleInfoPaths))
- return false;
-
- // root module-info first
- byte[] b = readModuleInfo(moduleInfoPaths.get(MODULE_INFO));
- moduleInfos.put(MODULE_INFO, b);
- for (Map.Entry<String,Path> e : moduleInfoPaths.entrySet())
- moduleInfos.putIfAbsent(e.getKey(), readModuleInfo(e.getValue()));
-
- if (!addExtendedModuleAttributes(moduleInfos))
- return false;
+ expand();
+ if (!moduleInfos.isEmpty()) {
+ // All actual file entries (excl manifest and module-info.class)
+ Set<String> jentries = new HashSet<>();
+ // all packages if it's a class or resource
+ Set<String> packages = new HashSet<>();
+ entries.stream()
+ .filter(e -> !e.isDir)
+ .forEach( e -> {
+ addPackageIfNamed(packages, e.name);
+ jentries.add(e.name);
+ });
+ addExtendedModuleAttributes(moduleInfos, packages);
// Basic consistency checks for modular jars.
- if (!checkServices(moduleInfos.get(MODULE_INFO)))
+ if (!checkModuleInfo(moduleInfos.get(MODULE_INFO), jentries))
return false;
} else if (moduleVersion != null || modulesToHash != null) {
error(getMsg("error.module.options.without.info"));
return false;
}
-
if (vflag && fname == null) {
// Disable verbose output so that it does not appear
// on stdout along with file data
// error("Warning: -v option ignored");
vflag = false;
}
-
final String tmpbase = (fname == null)
? "tmpjar"
: fname.substring(fname.indexOf(File.separatorChar) + 1);
+
File tmpfile = createTemporaryFile(tmpbase, ".jar");
-
try (OutputStream out = new FileOutputStream(tmpfile)) {
- create(new BufferedOutputStream(out, 4096), manifest, moduleInfos);
+ create(new BufferedOutputStream(out, 4096), manifest);
}
-
if (nflag) {
File packFile = createTemporaryFile(tmpbase, ".pack");
try {
Packer packer = Pack200.newPacker();
Map<String, String> p = packer.properties();
p.put(Packer.EFFORT, "1"); // Minimal effort to conserve CPU
- try (
- JarFile jarFile = new JarFile(tmpfile.getCanonicalPath());
- OutputStream pack = new FileOutputStream(packFile)
- ) {
+ try (JarFile jarFile = new JarFile(tmpfile.getCanonicalPath());
+ OutputStream pack = new FileOutputStream(packFile))
+ {
packer.pack(jarFile, pack);
}
if (tmpfile.exists()) {
tmpfile.delete();
}
tmpfile = createTemporaryFile(tmpbase, ".jar");
- try (
- OutputStream out = new FileOutputStream(tmpfile);
- JarOutputStream jos = new JarOutputStream(out)
- ) {
+ try (OutputStream out = new FileOutputStream(tmpfile);
+ JarOutputStream jos = new JarOutputStream(out))
+ {
Unpacker unpacker = Pack200.newUnpacker();
unpacker.unpack(packFile, jos);
}
@@ -420,9 +332,7 @@
Files.deleteIfExists(packFile.toPath());
}
}
-
validateAndClose(tmpfile);
-
} else if (uflag) {
File inputFile = null, tmpFile = null;
if (fname != null) {
@@ -432,39 +342,20 @@
vflag = false;
tmpFile = createTemporaryFile("tmpjar", ".jar");
}
-
- Map<String,Path> moduleInfoPaths = new HashMap<>();
- for (int version : filesMap.keySet()) {
- String[] files = filesMap.get(version);
- expand(null, files, true, moduleInfoPaths, version);
+ expand();
+ try (FileInputStream in = (fname != null) ? new FileInputStream(inputFile)
+ : new FileInputStream(FileDescriptor.in);
+ FileOutputStream out = new FileOutputStream(tmpFile);
+ InputStream manifest = (!Mflag && (mname != null)) ?
+ (new FileInputStream(mname)) : null;
+ ) {
+ boolean updateOk = update(in, new BufferedOutputStream(out),
+ manifest, moduleInfos, null);
+ if (ok) {
+ ok = updateOk;
+ }
}
-
- Map<String,byte[]> moduleInfos = new HashMap<>();
- for (Map.Entry<String,Path> e : moduleInfoPaths.entrySet())
- moduleInfos.put(e.getKey(), readModuleInfo(e.getValue()));
-
- try (
- FileInputStream in = (fname != null) ? new FileInputStream(inputFile)
- : new FileInputStream(FileDescriptor.in);
- FileOutputStream out = new FileOutputStream(tmpFile);
- InputStream manifest = (!Mflag && (mname != null)) ?
- (new FileInputStream(mname)) : null;
- ) {
- boolean updateOk = update(in, new BufferedOutputStream(out),
- manifest, moduleInfos, null);
- if (ok) {
- ok = updateOk;
- }
- }
-
- // Consistency checks for modular jars.
- if (!moduleInfos.isEmpty()) {
- if(!checkServices(moduleInfos.get(MODULE_INFO)))
- return false;
- }
-
validateAndClose(tmpFile);
-
} else if (tflag) {
replaceFSC(filesMap);
// For the "list table contents" action, access using the
@@ -542,12 +433,15 @@
private void validateAndClose(File tmpfile) throws IOException {
if (ok && isMultiRelease) {
- ok = validate(tmpfile.getCanonicalPath());
- if (!ok) {
- error(formatMsg("error.validator.jarfile.invalid", fname));
+ try (JarFile jf = new JarFile(tmpfile)) {
+ ok = Validator.validate(this, jf);
+ if (!ok) {
+ error(formatMsg("error.validator.jarfile.invalid", fname));
+ }
+ } catch (IOException e) {
+ error(formatMsg2("error.validator.jarfile.exception", fname, e.getMessage()));
}
}
-
Path path = tmpfile.toPath();
try {
if (ok) {
@@ -572,78 +466,9 @@
Stream<String> filesToEntryNames(Map.Entry<Integer,String[]> fileEntries) {
int version = fileEntries.getKey();
+ Set<String> cpaths = pathsMap.get(version);
return Stream.of(fileEntries.getValue())
- .map(f -> (new EntryName(f, version)).entryName);
- }
-
- // sort base entries before versioned entries, and sort entry classes with
- // nested classes so that the top level class appears before the associated
- // nested class
- private Comparator<JarEntry> entryComparator = (je1, je2) -> {
- String s1 = je1.getName();
- String s2 = je2.getName();
- if (s1.equals(s2)) return 0;
- boolean b1 = s1.startsWith(VERSIONS_DIR);
- boolean b2 = s2.startsWith(VERSIONS_DIR);
- if (b1 && !b2) return 1;
- if (!b1 && b2) return -1;
- int n = 0; // starting char for String compare
- if (b1 && b2) {
- // normally strings would be sorted so "10" goes before "9", but
- // version number strings need to be sorted numerically
- n = VERSIONS_DIR.length(); // skip the common prefix
- int i1 = s1.indexOf('/', n);
- int i2 = s1.indexOf('/', n);
- if (i1 == -1) throw new InvalidJarException(s1);
- if (i2 == -1) throw new InvalidJarException(s2);
- // shorter version numbers go first
- if (i1 != i2) return i1 - i2;
- // otherwise, handle equal length numbers below
- }
- int l1 = s1.length();
- int l2 = s2.length();
- int lim = Math.min(l1, l2);
- for (int k = n; k < lim; k++) {
- char c1 = s1.charAt(k);
- char c2 = s2.charAt(k);
- if (c1 != c2) {
- // change natural ordering so '.' comes before '$'
- // i.e. top level classes come before nested classes
- if (c1 == '$' && c2 == '.') return 1;
- if (c1 == '.' && c2 == '$') return -1;
- return c1 - c2;
- }
- }
- return l1 - l2;
- };
-
- private boolean validate(String fname) {
- boolean valid;
-
- try (JarFile jf = new JarFile(fname)) {
- Validator validator = new Validator(this, jf);
- jf.stream()
- .filter(e -> !e.isDirectory())
- .filter(e -> !e.getName().equals(MANIFEST_NAME))
- .filter(e -> !e.getName().endsWith(MODULE_INFO))
- .sorted(entryComparator)
- .forEachOrdered(validator);
- valid = validator.isValid();
- } catch (IOException e) {
- error(formatMsg2("error.validator.jarfile.exception", fname, e.getMessage()));
- valid = false;
- } catch (InvalidJarException e) {
- error(formatMsg("error.validator.bad.entry.name", e.getMessage()));
- valid = false;
- }
- return valid;
- }
-
- private static class InvalidJarException extends RuntimeException {
- private static final long serialVersionUID = -3642329147299217726L;
- InvalidJarException(String msg) {
- super(msg);
- }
+ .map(f -> toVersionedName(toEntryName(f, cpaths, false), version));
}
/**
@@ -668,20 +493,22 @@
// Note: flags.length == 2 can be treated as the short version of
// the GNU option since the there cannot be any other options,
// excluding -C, as per the old way.
- if (flags.startsWith("--")
- || (flags.startsWith("-") && flags.length() == 2)) {
+ if (flags.startsWith("--") ||
+ (flags.startsWith("-") && flags.length() == 2)) {
try {
count = GNUStyleOptions.parseOptions(this, args);
} catch (GNUStyleOptions.BadArgs x) {
if (info == null) {
- error(x.getMessage());
- if (x.showUsage)
- Info.USAGE_TRYHELP.print(err);
+ if (x.showUsage) {
+ usageError(x.getMessage());
+ } else {
+ error(x.getMessage());
+ }
return false;
}
}
if (info != null) {
- info.print(out);
+ info.accept(out);
return true;
}
} else {
@@ -851,19 +678,55 @@
* Add the package of the given resource name if it's a .class
* or a resource in a named package.
*/
- boolean addPackageIfNamed(String name) {
+ void addPackageIfNamed(Set<String> packages, String name) {
if (name.startsWith(VERSIONS_DIR)) {
- throw new InternalError(name);
+ // trim the version dir prefix
+ int i0 = VERSIONS_DIR.length();
+ int i = name.indexOf('/', i0);
+ if (i <= 0) {
+ warn(formatMsg("warn.release.unexpected.versioned.entry", name));
+ return;
+ }
+ while (i0 < i) {
+ char c = name.charAt(i0);
+ if (c < '0' || c > '9') {
+ warn(formatMsg("warn.release.unexpected.versioned.entry", name));
+ return;
+ }
+ i0++;
+ }
+ name = name.substring(i + 1, name.length());
}
-
String pn = toPackageName(name);
// add if this is a class or resource in a package
if (Checks.isJavaIdentifier(pn)) {
packages.add(pn);
- return true;
+ }
+ }
+
+ private String toEntryName(String name, Set<String> cpaths, boolean isDir) {
+ name = name.replace(File.separatorChar, '/');
+ if (isDir) {
+ name = name.endsWith("/") ? name : name + "/";
}
+ String matchPath = "";
+ for (String path : cpaths) {
+ if (name.startsWith(path) && path.length() > matchPath.length()) {
+ matchPath = path;
+ }
+ }
+ name = safeName(name.substring(matchPath.length()));
+ // the old implementaton doesn't remove
+ // "./" if it was led by "/" (?)
+ if (name.startsWith("./")) {
+ name = name.substring(2);
+ }
+ return name;
+ }
- return false;
+ private static String toVersionedName(String name, int version) {
+ return version > BASE_VERSION
+ ? VERSIONS_DIR + version + "/" + name : name;
}
private static String toPackageName(String path) {
@@ -875,57 +738,23 @@
}
}
- /*
- * Returns true if the given entry is a valid entry of the given version.
- */
- private boolean isValidVersionedEntry(Entry entry, int version) {
- String name = entry.basename;
- if (name.startsWith(VERSIONS_DIR) && version != BASE_VERSION) {
- int i = name.indexOf('/', VERSIONS_DIR.length());
- // name == -1 -> not a versioned directory, something else
- if (i == -1)
- return false;
- try {
- String v = name.substring(VERSIONS_DIR.length(), i);
- return Integer.valueOf(v) == version;
- } catch (NumberFormatException x) {
- return false;
- }
+ private void expand() throws IOException {
+ for (int version : filesMap.keySet()) {
+ String[] files = filesMap.get(version);
+ expand(null, files, pathsMap.get(version), version);
}
- return true;
- }
-
- /*
- * Trim META-INF/versions/$version/ from the given name if the
- * given name is a versioned entry of the given version; or
- * of any version if the given version is BASE_VERSION
- */
- private String trimVersionsDir(String name, int version) {
- if (name.startsWith(VERSIONS_DIR)) {
- int i = name.indexOf('/', VERSIONS_DIR.length());
- if (i >= 0) {
- try {
- String v = name.substring(VERSIONS_DIR.length(), i);
- if (version == BASE_VERSION || Integer.valueOf(v) == version) {
- return name.substring(i + 1, name.length());
- }
- } catch (NumberFormatException x) {}
- }
- throw new InternalError("unexpected versioned entry: " +
- name + " version " + version);
- }
- return name;
}
/**
* Expands list of files to process into full list of all files that
* can be found by recursively descending directories.
+ *
+ * @param dir parent directory
+ * @param file s list of files to expand
+ * @param cpaths set of directories specified by -C option for the files
+ * @throws IOException if an I/O error occurs
*/
- void expand(File dir,
- String[] files,
- boolean isUpdate,
- Map<String,Path> moduleInfoPaths,
- int version)
+ private void expand(File dir, String[] files, Set<String> cpaths, int version)
throws IOException
{
if (files == null)
@@ -938,47 +767,48 @@
else
f = new File(dir, files[i]);
- Entry e = new Entry(version, f);
- String entryName = e.entryname;
- Entry entry = e;
- if (e.basename.startsWith(VERSIONS_DIR) && isValidVersionedEntry(e, version)) {
- entry = e.toVersionedEntry(version);
- }
- if (f.isFile()) {
- if (entryName.endsWith(MODULE_INFO)) {
- moduleInfoPaths.put(entryName, f.toPath());
- if (isUpdate)
- entryMap.put(entryName, entry);
- } else if (isValidVersionedEntry(entry, version)) {
- if (entries.add(entry)) {
- jarEntries.add(entryName);
- // add the package if it's a class or resource
- addPackageIfNamed(trimVersionsDir(entry.basename, version));
- if (isUpdate)
- entryMap.put(entryName, entry);
- }
- } else {
+ boolean isDir = f.isDirectory();
+ String name = toEntryName(f.getPath(), cpaths, isDir);
+
+ if (version != BASE_VERSION) {
+ if (name.startsWith(VERSIONS_DIR)) {
+ // the entry starts with VERSIONS_DIR and version != BASE_VERSION,
+ // which means the "[dirs|files]" in --release v [dirs|files]
+ // includes VERSIONS_DIR-ed entries --> warning and skip (?)
error(formatMsg2("error.release.unexpected.versioned.entry",
- entry.basename, String.valueOf(version)));
+ name, String.valueOf(version)));
ok = false;
+ return;
}
- } else if (f.isDirectory()) {
- if (isValidVersionedEntry(entry, version)) {
- if (entries.add(entry)) {
- if (isUpdate) {
- entryMap.put(entryName, entry);
- }
+ name = toVersionedName(name, version);
+ }
+
+ if (f.isFile()) {
+ Entry e = new Entry(f, name, false);
+ if (isModuleInfoEntry(name)) {
+ moduleInfos.putIfAbsent(name, Files.readAllBytes(f.toPath()));
+ if (uflag)
+ entryMap.put(name, e);
+ } else if (entries.add(e)) {
+ if (uflag)
+ entryMap.put(name, e);
+ }
+ } else if (isDir) {
+ Entry e = new Entry(f, name, true);
+ if (entries.add(e)) {
+ // utilize entryMap for the duplicate dir check even in
+ // case of cflag == true.
+ // dir name confilict/duplicate could happen with -C option.
+ // just remove the last "e" from the "entries" (zos will fail
+ // with "duplicated" entries), but continue expanding the
+ // sub tree
+ if (entryMap.containsKey(name)) {
+ entries.remove(e);
+ } else {
+ entryMap.put(name, e);
}
- } else if (entry.basename.equals(VERSIONS_DIR)) {
- if (vflag) {
- output(formatMsg("out.ignore.entry", entry.basename));
- }
- } else {
- error(formatMsg2("error.release.unexpected.versioned.entry",
- entry.basename, String.valueOf(version)));
- ok = false;
+ expand(f, f.list(), cpaths, version);
}
- expand(f, f.list(), isUpdate, moduleInfoPaths, version);
} else {
error(formatMsg("error.nosuch.fileordir", String.valueOf(f)));
ok = false;
@@ -989,52 +819,36 @@
/**
* Creates a new JAR file.
*/
- void create(OutputStream out, Manifest manifest, Map<String,byte[]> moduleInfos)
- throws IOException
+ void create(OutputStream out, Manifest manifest) throws IOException
{
- ZipOutputStream zos = new JarOutputStream(out);
- if (flag0) {
- zos.setMethod(ZipOutputStream.STORED);
- }
- // TODO: check module-info attributes against manifest ??
- if (manifest != null) {
- if (vflag) {
- output(getMsg("out.added.manifest"));
- }
- ZipEntry e = new ZipEntry(MANIFEST_DIR);
- e.setTime(System.currentTimeMillis());
- e.setSize(0);
- e.setCrc(0);
- zos.putNextEntry(e);
- e = new ZipEntry(MANIFEST_NAME);
- e.setTime(System.currentTimeMillis());
+ try (ZipOutputStream zos = new JarOutputStream(out)) {
if (flag0) {
- crc32Manifest(e, manifest);
+ zos.setMethod(ZipOutputStream.STORED);
}
- zos.putNextEntry(e);
- manifest.write(zos);
- zos.closeEntry();
- }
- for (Map.Entry<String,byte[]> mi : moduleInfos.entrySet()) {
- String entryName = mi.getKey();
- byte[] miBytes = mi.getValue();
- if (vflag) {
- output(formatMsg("out.added.module-info", entryName));
+ // TODO: check module-info attributes against manifest ??
+ if (manifest != null) {
+ if (vflag) {
+ output(getMsg("out.added.manifest"));
+ }
+ ZipEntry e = new ZipEntry(MANIFEST_DIR);
+ e.setTime(System.currentTimeMillis());
+ e.setSize(0);
+ e.setCrc(0);
+ zos.putNextEntry(e);
+ e = new ZipEntry(MANIFEST_NAME);
+ e.setTime(System.currentTimeMillis());
+ if (flag0) {
+ crc32Manifest(e, manifest);
+ }
+ zos.putNextEntry(e);
+ manifest.write(zos);
+ zos.closeEntry();
}
- ZipEntry e = new ZipEntry(mi.getKey());
- e.setTime(System.currentTimeMillis());
- if (flag0) {
- crc32ModuleInfo(e, miBytes);
+ updateModuleInfo(moduleInfos, zos);
+ for (Entry entry : entries) {
+ addFile(zos, entry);
}
- zos.putNextEntry(e);
- ByteArrayInputStream in = new ByteArrayInputStream(miBytes);
- in.transferTo(zos);
- zos.closeEntry();
}
- for (Entry entry : entries) {
- addFile(zos, entry);
- }
- zos.close();
}
private char toUpperCaseASCII(char c) {
@@ -1062,30 +876,6 @@
}
/**
- * Returns true of the given module-info's are located in acceptable
- * locations. Otherwise, outputs an appropriate message and returns false.
- */
- private boolean checkModuleInfos(Map<String,?> moduleInfos) {
- // there must always be, at least, a root module-info
- if (!moduleInfos.containsKey(MODULE_INFO)) {
- error(getMsg("error.versioned.info.without.root"));
- return false;
- }
-
- // module-info can only appear in the root, or a versioned section
- Optional<String> other = moduleInfos.keySet().stream()
- .filter(x -> !x.equals(MODULE_INFO))
- .filter(x -> !x.startsWith(VERSIONS_DIR))
- .findFirst();
-
- if (other.isPresent()) {
- error(formatMsg("error.unexpected.module-info", other.get()));
- return false;
- }
- return true;
- }
-
- /**
* Updates an existing jar file.
*/
boolean update(InputStream in, OutputStream out,
@@ -1099,6 +889,10 @@
boolean foundManifest = false;
boolean updateOk = true;
+ // All actual entries added/updated/existing, in the jar file (excl manifest
+ // and module-info.class ).
+ Set<String> jentries = new HashSet<>();
+
if (jarIndex != null) {
addIndex(jarIndex, zos);
}
@@ -1108,7 +902,7 @@
String name = e.getName();
boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME);
- boolean isModuleInfoEntry = name.endsWith(MODULE_INFO);
+ boolean isModuleInfoEntry = isModuleInfoEntry(name);
if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME))
|| (Mflag && isManifestEntry)) {
@@ -1127,7 +921,6 @@
return false;
}
}
-
// Update the manifest.
Manifest old = new Manifest(zis);
if (newManifest != null) {
@@ -1137,7 +930,7 @@
return false;
}
} else if (moduleInfos != null && isModuleInfoEntry) {
- moduleInfos.putIfAbsent(name, readModuleInfo(zis));
+ moduleInfos.putIfAbsent(name, zis.readAllBytes());
} else {
boolean isDir = e.isDirectory();
if (!entryMap.containsKey(name)) { // copy the old stuff
@@ -1160,11 +953,8 @@
entries.remove(ent);
isDir = ent.isDir;
}
-
- jarEntries.add(name);
if (!isDir) {
- // add the package if it's a class or resource
- addPackageIfNamed(trimVersionsDir(name, BASE_VERSION));
+ jentries.add(name);
}
}
}
@@ -1172,6 +962,9 @@
// add the remaining new files
for (Entry entry : entries) {
addFile(zos, entry);
+ if (!entry.isDir) {
+ jentries.add(entry.name);
+ }
}
if (!foundManifest) {
if (newManifest != null) {
@@ -1188,35 +981,24 @@
}
}
}
-
- if (moduleInfos != null && !moduleInfos.isEmpty()) {
- if (!checkModuleInfos(moduleInfos))
+ if (updateOk) {
+ if (moduleInfos != null && !moduleInfos.isEmpty()) {
+ Set<String> pkgs = new HashSet<>();
+ jentries.forEach( je -> addPackageIfNamed(pkgs, je));
+ addExtendedModuleAttributes(moduleInfos, pkgs);
+ updateOk = checkModuleInfo(moduleInfos.get(MODULE_INFO), jentries);
+ updateModuleInfo(moduleInfos, zos);
+ // TODO: check manifest main classes, etc
+ } else if (moduleVersion != null || modulesToHash != null) {
+ error(getMsg("error.module.options.without.info"));
updateOk = false;
-
- if (updateOk) {
- if (!addExtendedModuleAttributes(moduleInfos))
- updateOk = false;
}
-
- // TODO: check manifest main classes, etc
-
- if (updateOk) {
- for (Map.Entry<String,byte[]> mi : moduleInfos.entrySet()) {
- if (!updateModuleInfo(mi.getValue(), zos, mi.getKey()))
- updateOk = false;
- }
- }
- } else if (moduleVersion != null || modulesToHash != null) {
- error(getMsg("error.module.options.without.info"));
- updateOk = false;
}
-
zis.close();
zos.close();
return updateOk;
}
-
private void addIndex(JarIndex index, ZipOutputStream zos)
throws IOException
{
@@ -1232,20 +1014,25 @@
zos.closeEntry();
}
- private boolean updateModuleInfo(byte[] moduleInfoBytes, ZipOutputStream zos, String entryName)
+ private void updateModuleInfo(Map<String,byte[]> moduleInfos, ZipOutputStream zos)
throws IOException
{
- ZipEntry e = new ZipEntry(entryName);
- e.setTime(System.currentTimeMillis());
- if (flag0) {
- crc32ModuleInfo(e, moduleInfoBytes);
+ String fmt = uflag ? "out.update.module-info": "out.added.module-info";
+ for (Map.Entry<String,byte[]> mi : moduleInfos.entrySet()) {
+ String name = mi.getKey();
+ byte[] bytes = mi.getValue();
+ ZipEntry e = new ZipEntry(name);
+ e.setTime(System.currentTimeMillis());
+ if (flag0) {
+ crc32ModuleInfo(e, bytes);
+ }
+ zos.putNextEntry(e);
+ zos.write(bytes);
+ zos.closeEntry();
+ if (vflag) {
+ output(formatMsg(fmt, name));
+ }
}
- zos.putNextEntry(e);
- zos.write(moduleInfoBytes);
- if (vflag) {
- output(formatMsg("out.update.module-info", entryName));
- }
- return true;
}
private boolean updateManifest(Manifest m, ZipOutputStream zos)
@@ -1358,11 +1145,9 @@
* Adds a new file entry to the ZIP output stream.
*/
void addFile(ZipOutputStream zos, Entry entry) throws IOException {
- // skip the generation of directory entries for META-INF/versions/*/
- if (entry.basename.isEmpty()) return;
File file = entry.file;
- String name = entry.entryname;
+ String name = entry.name;
boolean isDir = entry.isDir;
if (name.equals("") || name.equals(".") || name.equals(zname)) {
@@ -1444,11 +1229,8 @@
* @throws IOException if an I/O error occurs
*/
private void copy(File from, OutputStream to) throws IOException {
- InputStream in = new FileInputStream(from);
- try {
+ try (InputStream in = new FileInputStream(from)) {
copy(in, to);
- } finally {
- in.close();
}
}
@@ -1461,11 +1243,8 @@
* @throws IOException if an I/O error occurs
*/
private void copy(InputStream from, File to) throws IOException {
- OutputStream out = new FileOutputStream(to);
- try {
+ try (OutputStream out = new FileOutputStream(to)) {
copy(from, out);
- } finally {
- out.close();
}
}
@@ -1825,7 +1604,7 @@
*/
void usageError(String s) {
err.println(s);
- Info.USAGE_TRYHELP.print(err);
+ err.println(getMsg("main.usage.summary.try"));
}
/**
@@ -1934,16 +1713,6 @@
return tmpfile;
}
- private static byte[] readModuleInfo(InputStream zis) throws IOException {
- return zis.readAllBytes();
- }
-
- private static byte[] readModuleInfo(Path path) throws IOException {
- try (InputStream is = Files.newInputStream(path)) {
- return is.readAllBytes();
- }
- }
-
// Modular jar support
static <T> String toString(Collection<T> c,
@@ -1951,7 +1720,6 @@
CharSequence suffix ) {
if (c.isEmpty())
return "";
-
return c.stream().map(e -> e.toString())
.collect(joining(", ", prefix, suffix));
}
@@ -2045,136 +1813,84 @@
md.osVersion().ifPresent(v -> sb.append("\n operating-system-version " + v));
- if (hashes != null) {
- hashes.names().stream().sorted().forEach(
- mod -> sb.append("\n hashes ").append(mod).append(" ")
- .append(hashes.algorithm()).append(" ")
- .append(toHex(hashes.hashFor(mod))));
+ if (hashes != null) {
+ hashes.names().stream().sorted().forEach(
+ mod -> sb.append("\n hashes ").append(mod).append(" ")
+ .append(hashes.algorithm()).append(" ")
+ .append(toHex(hashes.hashFor(mod))));
}
output(sb.toString());
}
private static String toHex(byte[] ba) {
- StringBuilder sb = new StringBuilder(ba.length);
+ StringBuilder sb = new StringBuilder(ba.length << 1);
for (byte b: ba) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
}
- private static String toBinaryName(String classname) {
+ static String toBinaryName(String classname) {
return (classname.replace('.', '/')) + ".class";
}
- /* A module must have the implementation class of the services it 'provides'. */
- private boolean checkServices(byte[] moduleInfoBytes)
+ private boolean checkModuleInfo(byte[] moduleInfoBytes, Set<String> entries)
throws IOException
{
- ModuleDescriptor md = ModuleDescriptor.read(ByteBuffer.wrap(moduleInfoBytes));
- Set<String> missing = md.provides()
- .stream()
- .map(Provides::providers)
- .flatMap(List::stream)
- .filter(p -> !jarEntries.contains(toBinaryName(p)))
- .collect(Collectors.toSet());
- if (missing.size() > 0) {
- missing.stream().forEach(s -> fatalError(formatMsg("error.missing.provider", s)));
- return false;
+ boolean ok = true;
+ if (moduleInfoBytes != null) { // no root module-info.class if null
+ try {
+ // ModuleDescriptor.read() checks open/exported pkgs vs packages
+ ModuleDescriptor md = ModuleDescriptor.read(ByteBuffer.wrap(moduleInfoBytes));
+ // A module must have the implementation class of the services it 'provides'.
+ if (md.provides().stream().map(Provides::providers).flatMap(List::stream)
+ .filter(p -> !entries.contains(toBinaryName(p)))
+ .peek(p -> fatalError(formatMsg("error.missing.provider", p)))
+ .count() != 0) {
+ ok = false;
+ }
+ } catch (InvalidModuleDescriptorException x) {
+ fatalError(x.getMessage());
+ ok = false;
+ }
}
- return true;
+ return ok;
}
/**
* Adds extended modules attributes to the given module-info's. The given
* Map values are updated in-place. Returns false if an error occurs.
*/
- private boolean addExtendedModuleAttributes(Map<String,byte[]> moduleInfos)
+ private void addExtendedModuleAttributes(Map<String,byte[]> moduleInfos,
+ Set<String> packages)
throws IOException
{
- assert !moduleInfos.isEmpty() && moduleInfos.get(MODULE_INFO) != null;
-
- ByteBuffer bb = ByteBuffer.wrap(moduleInfos.get(MODULE_INFO));
- ModuleDescriptor rd = ModuleDescriptor.read(bb);
-
- concealedPackages = findConcealedPackages(rd);
-
for (Map.Entry<String,byte[]> e: moduleInfos.entrySet()) {
- ModuleDescriptor vd = ModuleDescriptor.read(ByteBuffer.wrap(e.getValue()));
- if (!(isValidVersionedDescriptor(vd, rd)))
- return false;
- e.setValue(extendedInfoBytes(rd, vd, e.getValue(), packages));
+ ModuleDescriptor md = ModuleDescriptor.read(ByteBuffer.wrap(e.getValue()));
+ e.setValue(extendedInfoBytes(md, e.getValue(), packages));
}
- return true;
- }
-
- private Set<String> findConcealedPackages(ModuleDescriptor md) {
- Objects.requireNonNull(md);
- Set<String> concealed = new HashSet<>(packages);
- md.exports().stream().map(Exports::source).forEach(concealed::remove);
- md.opens().stream().map(Opens::source).forEach(concealed::remove);
- return concealed;
- }
-
- private static boolean isPlatformModule(String name) {
- return name.startsWith("java.") || name.startsWith("jdk.");
}
- /**
- * Tells whether or not the given versioned module descriptor's attributes
- * are valid when compared against the given root module descriptor.
- *
- * A versioned module descriptor must be identical to the root module
- * descriptor, with two exceptions:
- * - A versioned descriptor can have different non-public `requires`
- * clauses of platform ( `java.*` and `jdk.*` ) modules, and
- * - A versioned descriptor can have different `uses` clauses, even of
- * service types defined outside of the platform modules.
- */
- private boolean isValidVersionedDescriptor(ModuleDescriptor vd,
- ModuleDescriptor rd)
- throws IOException
- {
- if (!rd.name().equals(vd.name())) {
- fatalError(getMsg("error.versioned.info.name.notequal"));
- return false;
- }
- if (!rd.requires().equals(vd.requires())) {
- Set<Requires> rootRequires = rd.requires();
- for (Requires r : vd.requires()) {
- if (rootRequires.contains(r)) {
- continue;
- } else if (r.modifiers().contains(Requires.Modifier.TRANSITIVE)) {
- fatalError(getMsg("error.versioned.info.requires.transitive"));
+ static boolean isModuleInfoEntry(String name) {
+ // root or versioned module-info.class
+ if (name.endsWith(MODULE_INFO)) {
+ int end = name.length() - MODULE_INFO.length();
+ if (end == 0)
+ return true;
+ if (name.startsWith(VERSIONS_DIR)) {
+ int off = VERSIONS_DIR.length();
+ if (off == end) // meta-inf/versions/module-info.class
return false;
- } else if (!isPlatformModule(r.name())) {
- fatalError(getMsg("error.versioned.info.requires.added"));
- return false;
+ while (off < end - 1) {
+ char c = name.charAt(off++);
+ if (c < '0' || c > '9')
+ return false;
}
- }
- for (Requires r : rootRequires) {
- Set<Requires> mdRequires = vd.requires();
- if (mdRequires.contains(r)) {
- continue;
- } else if (!isPlatformModule(r.name())) {
- fatalError(getMsg("error.versioned.info.requires.dropped"));
- return false;
- }
+ return name.charAt(off) == '/';
}
}
- if (!rd.exports().equals(vd.exports())) {
- fatalError(getMsg("error.versioned.info.exports.notequal"));
- return false;
- }
- if (!rd.opens().equals(vd.opens())) {
- fatalError(getMsg("error.versioned.info.opens.notequal"));
- return false;
- }
- if (!rd.provides().equals(vd.provides())) {
- fatalError(getMsg("error.versioned.info.provides.notequal"));
- return false;
- }
- return true;
+ return false;
}
/**
@@ -2185,8 +1901,7 @@
* then the corresponding class file attributes are added to the
* module-info here.
*/
- private byte[] extendedInfoBytes(ModuleDescriptor rootDescriptor,
- ModuleDescriptor md,
+ private byte[] extendedInfoBytes(ModuleDescriptor md,
byte[] miBytes,
Set<String> packages)
throws IOException
@@ -2201,14 +1916,10 @@
// --main-class
if (ename != null)
extender.mainClass(ename);
- else if (rootDescriptor.mainClass().isPresent())
- extender.mainClass(rootDescriptor.mainClass().get());
// --module-version
if (moduleVersion != null)
extender.version(moduleVersion);
- else if (rootDescriptor.version().isPresent())
- extender.version(rootDescriptor.version().get());
// --hash-modules
if (modulesToHash != null) {
@@ -2218,8 +1929,7 @@
if (moduleHashes != null) {
extender.hashes(moduleHashes);
} else {
- // should it issue warning or silent?
- System.out.println("warning: no module is recorded in hash in " + mn);
+ warn("warning: no module is recorded in hash in " + mn);
}
}
@@ -2235,10 +1945,9 @@
* Compute and record hashes
*/
private class Hasher {
+ final ModuleHashesBuilder hashesBuilder;
final ModuleFinder finder;
- final Map<String, Path> moduleNameToPath;
final Set<String> modules;
- final Configuration configuration;
Hasher(ModuleDescriptor descriptor, String fname) throws IOException {
// Create a module finder that finds the modular JAR
// being created/updated
@@ -2268,119 +1977,46 @@
}
});
- // Determine the modules that matches the modulesToHash pattern
- this.modules = moduleFinder.findAll().stream()
- .map(moduleReference -> moduleReference.descriptor().name())
+ // Determine the modules that matches the pattern {@code modulesToHash}
+ Set<String> roots = finder.findAll().stream()
+ .map(ref -> ref.descriptor().name())
.filter(mn -> modulesToHash.matcher(mn).find())
.collect(Collectors.toSet());
- // a map from a module name to Path of the modular JAR
- this.moduleNameToPath = moduleFinder.findAll().stream()
- .map(ModuleReference::descriptor)
- .map(ModuleDescriptor::name)
- .collect(Collectors.toMap(Function.identity(), mn -> moduleToPath(mn)));
-
- Configuration config = null;
- try {
- config = Configuration.empty()
- .resolveRequires(ModuleFinder.ofSystem(), finder, modules);
- } catch (ResolutionException e) {
- // should it throw an error? or emit a warning
- System.out.println("warning: " + e.getMessage());
+ // use system module path unless it creates a modular JAR for
+ // a module that is present in the system image e.g. upgradeable
+ // module
+ ModuleFinder system;
+ String name = descriptor.name();
+ if (name != null && ModuleFinder.ofSystem().find(name).isPresent()) {
+ system = ModuleFinder.of();
+ } else {
+ system = ModuleFinder.ofSystem();
}
- this.configuration = config;
- }
+ // get a resolved module graph
+ Configuration config =
+ Configuration.empty().resolveRequires(system, finder, roots);
- /**
- * Compute hashes of the modules that depend upon the specified
- * module directly or indirectly.
- */
- ModuleHashes computeHashes(String name) {
- // the transposed graph includes all modules in the resolved graph
- Map<String, Set<String>> graph = transpose();
+ // filter modules resolved from the system module finder
+ this.modules = config.modules().stream()
+ .map(ResolvedModule::name)
+ .filter(mn -> roots.contains(mn) && !system.find(mn).isPresent())
+ .collect(Collectors.toSet());
- // find the modules that transitively depend upon the specified name
- Deque<String> deque = new ArrayDeque<>();
- deque.add(name);
- Set<String> mods = visitNodes(graph, deque);
-
- // filter modules matching the pattern specified in --hash-modules,
- // as well as the modular jar file that is being created / updated
- Map<String, Path> modulesForHash = mods.stream()
- .filter(mn -> !mn.equals(name) && modules.contains(mn))
- .collect(Collectors.toMap(Function.identity(), moduleNameToPath::get));
-
- if (modulesForHash.isEmpty())
- return null;
-
- return ModuleHashes.generate(modulesForHash, "SHA-256");
+ this.hashesBuilder = new ModuleHashesBuilder(config, modules);
}
/**
- * Returns all nodes traversed from the given roots.
+ * Compute hashes of the specified module.
+ *
+ * It records the hashing modules that depend upon the specified
+ * module directly or indirectly.
*/
- private Set<String> visitNodes(Map<String, Set<String>> graph,
- Deque<String> roots) {
- Set<String> visited = new HashSet<>();
- while (!roots.isEmpty()) {
- String mn = roots.pop();
- if (!visited.contains(mn)) {
- visited.add(mn);
-
- // the given roots may not be part of the graph
- if (graph.containsKey(mn)) {
- for (String dm : graph.get(mn)) {
- if (!visited.contains(dm))
- roots.push(dm);
- }
- }
- }
- }
- return visited;
- }
-
- /**
- * Returns a transposed graph from the resolved module graph.
- */
- private Map<String, Set<String>> transpose() {
- Map<String, Set<String>> transposedGraph = new HashMap<>();
- Deque<String> deque = new ArrayDeque<>(modules);
+ ModuleHashes computeHashes(String name) {
+ if (hashesBuilder == null)
+ return null;
- Set<String> visited = new HashSet<>();
- while (!deque.isEmpty()) {
- String mn = deque.pop();
- if (!visited.contains(mn)) {
- visited.add(mn);
-
- // add an empty set
- transposedGraph.computeIfAbsent(mn, _k -> new HashSet<>());
-
- ResolvedModule resolvedModule = configuration.findModule(mn).get();
- for (ResolvedModule dm : resolvedModule.reads()) {
- String name = dm.name();
- if (!visited.contains(name)) {
- deque.push(name);
- }
- // reverse edge
- transposedGraph.computeIfAbsent(name, _k -> new HashSet<>())
- .add(mn);
- }
- }
- }
- return transposedGraph;
- }
-
- private Path moduleToPath(String name) {
- ModuleReference mref = moduleFinder.find(name).orElseThrow(
- () -> new InternalError(formatMsg2("error.hash.dep",name , name)));
-
- URI uri = mref.location().get();
- Path path = Paths.get(uri);
- String fn = path.getFileName().toString();
- if (!fn.endsWith(".jar")) {
- throw new UnsupportedOperationException(path + " is not a modular JAR");
- }
- return path;
+ return hashesBuilder.computeHashes(Set.of(name)).get(name);
}
}
}
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java Tue Jan 17 11:35:28 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -25,32 +25,120 @@
package sun.tools.jar;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.module.InvalidModuleDescriptorException;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.InvalidModuleDescriptorException;
+import java.lang.module.ModuleDescriptor.Opens;
+import java.lang.module.ModuleDescriptor.Provides;
+import java.lang.module.ModuleDescriptor.Requires;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.function.Consumer;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
-final class Validator implements Consumer<JarEntry> {
+import static java.util.jar.JarFile.MANIFEST_NAME;
+import static sun.tools.jar.Main.VERSIONS_DIR;
+import static sun.tools.jar.Main.MODULE_INFO;
+import static sun.tools.jar.Main.getMsg;
+import static sun.tools.jar.Main.formatMsg;
+import static sun.tools.jar.Main.formatMsg2;
+import static sun.tools.jar.Main.toBinaryName;
+import static sun.tools.jar.Main.isModuleInfoEntry;
+
+final class Validator {
private final static boolean DEBUG = Boolean.getBoolean("jar.debug");
private final Map<String,FingerPrint> fps = new HashMap<>();
- private final int vdlen = Main.VERSIONS_DIR.length();
+ private static final int vdlen = VERSIONS_DIR.length();
private final Main main;
private final JarFile jf;
private int oldVersion = -1;
private String currentTopLevelName;
private boolean isValid = true;
+ private Set<String> concealedPkgs;
+ private ModuleDescriptor md;
- Validator(Main main, JarFile jf) {
+ private Validator(Main main, JarFile jf) {
this.main = main;
this.jf = jf;
+ loadModuleDescriptor();
+ }
+
+ static boolean validate(Main main, JarFile jf) throws IOException {
+ return new Validator(main, jf).validate();
+ }
+
+ private boolean validate() {
+ try {
+ jf.stream()
+ .filter(e -> !e.isDirectory() &&
+ !e.getName().equals(MANIFEST_NAME))
+ .sorted(entryComparator)
+ .forEachOrdered(e -> validate(e));
+ return isValid;
+ } catch (InvalidJarException e) {
+ error(formatMsg("error.validator.bad.entry.name", e.getMessage()));
+ }
+ return false;
+ }
+
+ private static class InvalidJarException extends RuntimeException {
+ private static final long serialVersionUID = -3642329147299217726L;
+ InvalidJarException(String msg) {
+ super(msg);
+ }
}
- boolean isValid() {
- return isValid;
- }
+ // sort base entries before versioned entries, and sort entry classes with
+ // nested classes so that the top level class appears before the associated
+ // nested class
+ private static Comparator<JarEntry> entryComparator = (je1, je2) -> {
+ String s1 = je1.getName();
+ String s2 = je2.getName();
+ if (s1.equals(s2)) return 0;
+ boolean b1 = s1.startsWith(VERSIONS_DIR);
+ boolean b2 = s2.startsWith(VERSIONS_DIR);
+ if (b1 && !b2) return 1;
+ if (!b1 && b2) return -1;
+ int n = 0; // starting char for String compare
+ if (b1 && b2) {
+ // normally strings would be sorted so "10" goes before "9", but
+ // version number strings need to be sorted numerically
+ n = VERSIONS_DIR.length(); // skip the common prefix
+ int i1 = s1.indexOf('/', n);
+ int i2 = s1.indexOf('/', n);
+ if (i1 == -1) throw new InvalidJarException(s1);
+ if (i2 == -1) throw new InvalidJarException(s2);
+ // shorter version numbers go first
+ if (i1 != i2) return i1 - i2;
+ // otherwise, handle equal length numbers below
+ }
+ int l1 = s1.length();
+ int l2 = s2.length();
+ int lim = Math.min(l1, l2);
+ for (int k = n; k < lim; k++) {
+ char c1 = s1.charAt(k);
+ char c2 = s2.charAt(k);
+ if (c1 != c2) {
+ // change natural ordering so '.' comes before '$'
+ // i.e. top level classes come before nested classes
+ if (c1 == '$' && c2 == '.') return 1;
+ if (c1 == '.' && c2 == '$') return -1;
+ return c1 - c2;
+ }
+ }
+ return l1 - l2;
+ };
/*
* Validator has state and assumes entries provided to accept are ordered
@@ -59,7 +147,7 @@
* classes must be ordered so that the top level class is before the associated
* nested class(es).
*/
- public void accept(JarEntry je) {
+ public void validate(JarEntry je) {
String entryName = je.getName();
// directories are always accepted
@@ -68,13 +156,20 @@
return;
}
+ // validate the versioned module-info
+ if (isModuleInfoEntry(entryName)) {
+ if (entryName.length() != MODULE_INFO.length())
+ checkModuleDescriptor(je);
+ return;
+ }
+
// figure out the version and basename from the JarEntry
int version;
String basename;
- if (entryName.startsWith(Main.VERSIONS_DIR)) {
+ if (entryName.startsWith(VERSIONS_DIR)) {
int n = entryName.indexOf("/", vdlen);
if (n == -1) {
- main.error(Main.formatMsg("error.validator.version.notnumber", entryName));
+ error(formatMsg("error.validator.version.notnumber", entryName));
isValid = false;
return;
}
@@ -82,12 +177,12 @@
try {
version = Integer.parseInt(v);
} catch (NumberFormatException x) {
- main.error(Main.formatMsg("error.validator.version.notnumber", entryName));
+ error(formatMsg("error.validator.version.notnumber", entryName));
isValid = false;
return;
}
if (n == entryName.length()) {
- main.error(Main.formatMsg("error.validator.entryname.tooshort", entryName));
+ error(formatMsg("error.validator.entryname.tooshort", entryName));
isValid = false;
return;
}
@@ -108,7 +203,7 @@
try (InputStream is = jf.getInputStream(je)) {
fp = new FingerPrint(basename, is.readAllBytes());
} catch (IOException x) {
- main.error(x.getMessage());
+ error(x.getMessage());
isValid = false;
return;
}
@@ -123,7 +218,7 @@
fps.put(internalName, fp);
return;
}
- main.error(Main.formatMsg("error.validator.isolated.nested.class", entryName));
+ error(formatMsg("error.validator.isolated.nested.class", entryName));
isValid = false;
return;
}
@@ -153,11 +248,11 @@
}
if (fp.isPublicClass()) {
if (!isConcealed(internalName)) {
- main.error(Main.formatMsg("error.validator.new.public.class", entryName));
+ error(Main.formatMsg("error.validator.new.public.class", entryName));
isValid = false;
return;
}
- main.warn(Main.formatMsg("warn.validator.concealed.public.class", entryName));
+ warn(formatMsg("warn.validator.concealed.public.class", entryName));
debug("%s is a public class entry in a concealed package", entryName);
}
debug("%s is a non-public class entry", entryName);
@@ -173,7 +268,7 @@
// are the two classes/resources identical?
if (fp.isIdentical(matchFp)) {
- main.warn(Main.formatMsg("warn.validator.identical.entry", entryName));
+ warn(formatMsg("warn.validator.identical.entry", entryName));
return; // it's okay, just takes up room
}
debug("sha1 not equal -- different bytes");
@@ -188,12 +283,12 @@
}
debug("%s is a class entry", entryName);
if (!fp.isCompatibleVersion(matchFp)) {
- main.error(Main.formatMsg("error.validator.incompatible.class.version", entryName));
+ error(formatMsg("error.validator.incompatible.class.version", entryName));
isValid = false;
return;
}
if (!fp.isSameAPI(matchFp)) {
- main.error(Main.formatMsg("error.validator.different.api", entryName));
+ error(formatMsg("error.validator.different.api", entryName));
isValid = false;
return;
}
@@ -208,17 +303,118 @@
}
debug("%s is a resource", entryName);
- main.warn(Main.formatMsg("warn.validator.resources.with.same.name", entryName));
+ warn(formatMsg("warn.validator.resources.with.same.name", entryName));
fps.put(internalName, fp);
return;
}
+ private void loadModuleDescriptor() {
+ ZipEntry je = jf.getEntry(MODULE_INFO);
+ if (je != null) {
+ try (InputStream jis = jf.getInputStream(je)) {
+ md = ModuleDescriptor.read(jis);
+ concealedPkgs = new HashSet<>(md.packages());
+ md.exports().stream().map(Exports::source).forEach(concealedPkgs::remove);
+ md.opens().stream().map(Opens::source).forEach(concealedPkgs::remove);
+ return;
+ } catch (Exception x) {
+ error(x.getMessage() + " : " + je.getName());
+ this.isValid = false;
+ }
+ }
+ md = null;
+ concealedPkgs = Collections.emptySet();
+ }
+
+ private static boolean isPlatformModule(String name) {
+ return name.startsWith("java.") || name.startsWith("jdk.");
+ }
+
+ /**
+ * Checks whether or not the given versioned module descriptor's attributes
+ * are valid when compared against the root module descriptor.
+ *
+ * A versioned module descriptor must be identical to the root module
+ * descriptor, with two exceptions:
+ * - A versioned descriptor can have different non-public `requires`
+ * clauses of platform ( `java.*` and `jdk.*` ) modules, and
+ * - A versioned descriptor can have different `uses` clauses, even of
+ * service types defined outside of the platform modules.
+ */
+ private void checkModuleDescriptor(JarEntry je) {
+ try (InputStream is = jf.getInputStream(je)) {
+ ModuleDescriptor root = this.md;
+ ModuleDescriptor md = null;
+ try {
+ md = ModuleDescriptor.read(is);
+ } catch (InvalidModuleDescriptorException x) {
+ error(x.getMessage());
+ isValid = false;
+ return;
+ }
+ if (root == null) {
+ this.md = md;
+ } else {
+ if (!root.name().equals(md.name())) {
+ error(getMsg("error.versioned.info.name.notequal"));
+ isValid = false;
+ }
+ if (!root.requires().equals(md.requires())) {
+ Set<Requires> rootRequires = root.requires();
+ for (Requires r : md.requires()) {
+ if (rootRequires.contains(r))
+ continue;
+ if (r.modifiers().contains(Requires.Modifier.TRANSITIVE)) {
+ error(getMsg("error.versioned.info.requires.transitive"));
+ isValid = false;
+ } else if (!isPlatformModule(r.name())) {
+ error(getMsg("error.versioned.info.requires.added"));
+ isValid = false;
+ }
+ }
+ for (Requires r : rootRequires) {
+ Set<Requires> mdRequires = md.requires();
+ if (mdRequires.contains(r))
+ continue;
+ if (!isPlatformModule(r.name())) {
+ error(getMsg("error.versioned.info.requires.dropped"));
+ isValid = false;
+ }
+ }
+ }
+ if (!root.exports().equals(md.exports())) {
+ error(getMsg("error.versioned.info.exports.notequal"));
+ isValid = false;
+ }
+ if (!root.opens().equals(md.opens())) {
+ error(getMsg("error.versioned.info.opens.notequal"));
+ isValid = false;
+ }
+ if (!root.provides().equals(md.provides())) {
+ error(getMsg("error.versioned.info.provides.notequal"));
+ isValid = false;
+ }
+ if (!root.mainClass().equals(md.mainClass())) {
+ error(formatMsg("error.validator.info.manclass.notequal", je.getName()));
+ isValid = false;
+ }
+ if (!root.version().equals(md.version())) {
+ error(formatMsg("error.validator.info.version.notequal", je.getName()));
+ isValid = false;
+ }
+ }
+ } catch (IOException x) {
+ error(x.getMessage());
+ isValid = false;
+ }
+ }
+
private boolean checkInternalName(String entryName, String basename, String internalName) {
String className = className(basename);
if (internalName.equals(className)) {
return true;
}
- main.error(Main.formatMsg2("error.validator.names.mismatch",
+ error(formatMsg2("error.validator.names.mismatch",
entryName, internalName.replace("/", ".")));
return false;
}
@@ -231,7 +427,7 @@
return true;
}
debug("top level class was not accepted");
- main.error(Main.formatMsg("error.validator.isolated.nested.class", entryName));
+ error(formatMsg("error.validator.isolated.nested.class", entryName));
return false;
}
@@ -240,16 +436,24 @@
}
private boolean isConcealed(String internalName) {
- if (main.concealedPackages.isEmpty()) {
+ if (concealedPkgs.isEmpty()) {
return false;
}
int idx = internalName.lastIndexOf('/');
String pkgName = idx != -1 ? internalName.substring(0, idx).replace('/', '.') : "";
- return main.concealedPackages.contains(pkgName);
+ return concealedPkgs.contains(pkgName);
}
private void debug(String fmt, Object... args) {
if (DEBUG) System.err.format(fmt, args);
}
+
+ private void error(String msg) {
+ main.error(msg);
+ }
+
+ private void warn(String msg) {
+ main.warn(msg);
+ }
+
}
-
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Tue Jan 17 11:35:28 2017 -0800
@@ -66,23 +66,6 @@
Unexpected module descriptor {0}
error.module.descriptor.not.found=\
Module descriptor not found
-error.versioned.info.without.root=\
- module-info.class found in a versioned directory without module-info.class \
- in the root
-error.versioned.info.name.notequal=\
- module-info.class in a versioned directory contains incorrect name
-error.versioned.info.requires.transitive=\
- module-info.class in a versioned directory contains additional "requires transitive"
-error.versioned.info.requires.added=\
- module-info.class in a versioned directory contains additional "requires"
-error.versioned.info.requires.dropped=\
- module-info.class in a versioned directory contains missing "requires"
-error.versioned.info.exports.notequal=\
- module-info.class in a versioned directory contains different "exports"
-error.versioned.info.opens.notequal=\
- module-info.class in a versioned directory contains different "opens"
-error.versioned.info.provides.notequal=\
- module-info.class in a versioned directory contains different "provides"
error.invalid.versioned.module.attribute=\
Invalid module descriptor attribute {0}
error.missing.provider=\
@@ -113,6 +96,24 @@
entry: {0}, contains a class with different api from earlier version
error.validator.names.mismatch=\
entry: {0}, contains a class with internal name {1}, names do not match
+error.validator.info.name.notequal=\
+ module-info.class in a versioned directory contains incorrect name
+error.validator.info.requires.transitive=\
+ module-info.class in a versioned directory contains additional "requires transitive"
+error.validator.info.requires.added=\
+ module-info.class in a versioned directory contains additional "requires"
+error.validator.info.requires.dropped=\
+ module-info.class in a versioned directory contains missing "requires"
+error.validator.info.exports.notequal=\
+ module-info.class in a versioned directory contains different "exports"
+error.validator.info.opens.notequal=\
+ module-info.class in a versioned directory contains different "opens"
+error.validator.info.provides.notequal=\
+ module-info.class in a versioned directory contains different "provides"
+error.validator.info.version.notequal=\
+ {0}: module-info.class in a versioned directory contains different "version"
+error.validator.info.manclass.notequal=\
+ {0}: module-info.class in a versioned directory contains different "main-class"
warn.validator.identical.entry=\
Warning: entry {0} contains a class that\n\
is identical to an entry already in the jar
@@ -122,6 +123,8 @@
Warning: entry {0} is a public class\n\
in a concealed package, placing this jar on the class path will result\n\
in incompatible public interfaces
+warn.release.unexpected.versioned.entry=\
+ unexpected versioned entry {0}
out.added.manifest=\
added manifest
out.added.module-info=\
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties Tue Jan 17 11:35:28 2017 -0800
@@ -42,13 +42,13 @@
error.module.options.without.info=--module-version oder --hash-modules ohne module-info.class
error.unexpected.module-info=Unerwarteter Moduldeskriptor {0}
error.module.descriptor.not.found=Moduldeskriptor nicht gefunden
-error.versioned.info.without.root=module-info.class in einem versionierten Verzeichnis gefunden, in der Root ist module-info.class jedoch nicht vorhanden
-error.versioned.info.name.notequal=module-info.class in einem versionierten Verzeichnis enth\u00E4lt falschen Namen
-error.versioned.info.requires.public=module-info.class in einem versionierten Verzeichnis enth\u00E4lt zus\u00E4tzlichen "requires public"
-error.versioned.info.requires.added=module-info.class in einem versionierten Verzeichnis enth\u00E4lt zus\u00E4tzlichen "requires"
-error.versioned.info.requires.dropped=module-info.class in einem versionierten Verzeichnis enth\u00E4lt fehlenden "requires"
-error.versioned.info.exports.notequal=module-info.class in einem versionierten Verzeichnis enth\u00E4lt unterschiedliche "exports"
-error.versioned.info.provides.notequal=module-info.class in einem versionierten Verzeichnis enth\u00E4lt unterschiedliche "provides"
+error.validator.info.without.root=module-info.class in einem versionierten Verzeichnis gefunden, in der Root ist module-info.class jedoch nicht vorhanden
+error.validator.info.name.notequal=module-info.class in einem versionierten Verzeichnis enth\u00E4lt falschen Namen
+error.validator.info.requires.public=module-info.class in einem versionierten Verzeichnis enth\u00E4lt zus\u00E4tzlichen "requires public"
+error.validator.info.requires.added=module-info.class in einem versionierten Verzeichnis enth\u00E4lt zus\u00E4tzlichen "requires"
+error.validator.info.requires.dropped=module-info.class in einem versionierten Verzeichnis enth\u00E4lt fehlenden "requires"
+error.validator.info.exports.notequal=module-info.class in einem versionierten Verzeichnis enth\u00E4lt unterschiedliche "exports"
+error.validator.info.provides.notequal=module-info.class in einem versionierten Verzeichnis enth\u00E4lt unterschiedliche "provides"
error.invalid.versioned.module.attribute=Ung\u00FCltiges Moduldeskriptorattribut {0}
error.missing.provider=Serviceprovider nicht gefunden: {0}
error.release.value.notnumber=Release {0} nicht g\u00FCltig
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_es.properties Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_es.properties Tue Jan 17 11:35:28 2017 -0800
@@ -42,13 +42,13 @@
error.module.options.without.info=Uno de --module-version o -hash-modules sin module-info.class
error.unexpected.module-info=Descriptor de m\u00F3dulo inesperado {0}
error.module.descriptor.not.found=No se ha encontrado el descriptor de m\u00F3dulo
-error.versioned.info.without.root=Se ha encontrado module-info.class en un directorio con versi\u00F3n sin module-info.class en la ra\u00EDz
-error.versioned.info.name.notequal=module-info.class en un directorio con versi\u00F3n contiene un nombre incorrecto
-error.versioned.info.requires.public=module-info.class en un directorio con versiones contiene "requires public" adicionales
-error.versioned.info.requires.added=module-info.class en un directorio con versi\u00F3n contiene "requires" adicionales
-error.versioned.info.requires.dropped=module-info.class en un directorio con versiones contiene "requires" que faltan
-error.versioned.info.exports.notequal=module-info.class en un directorio con versiones contiene "exports" diferentes
-error.versioned.info.provides.notequal=module-info.class en un directorio con versiones contiene "provides" diferentes
+error.validator.info.without.root=Se ha encontrado module-info.class en un directorio con versi\u00F3n sin module-info.class en la ra\u00EDz
+error.validator.info.name.notequal=module-info.class en un directorio con versi\u00F3n contiene un nombre incorrecto
+error.validator.info.requires.public=module-info.class en un directorio con versiones contiene "requires public" adicionales
+error.validator.info.requires.added=module-info.class en un directorio con versi\u00F3n contiene "requires" adicionales
+error.validator.info.requires.dropped=module-info.class en un directorio con versiones contiene "requires" que faltan
+error.validator.info.exports.notequal=module-info.class en un directorio con versiones contiene "exports" diferentes
+error.validator.info.provides.notequal=module-info.class en un directorio con versiones contiene "provides" diferentes
error.invalid.versioned.module.attribute=Atributo de descriptor de m\u00F3dulo no v\u00E1lido {0}
error.missing.provider=No se ha encontrado el proveedor de servicios: {0}
error.release.value.notnumber=versi\u00F3n {0} no v\u00E1lida
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_fr.properties Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_fr.properties Tue Jan 17 11:35:28 2017 -0800
@@ -42,13 +42,13 @@
error.module.options.without.info=Une des options --module-version ou --hash-modules sans module-info.class
error.unexpected.module-info=Descripteur de module {0} inattendu
error.module.descriptor.not.found=Descripteur de module introuvable
-error.versioned.info.without.root=module-info.class a \u00E9t\u00E9 d\u00E9tect\u00E9 dans un r\u00E9pertoire avec num\u00E9ro de version sans module-info.class dans la racine
-error.versioned.info.name.notequal=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient un nom incorrect
-error.versioned.info.requires.public=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "requires public" suppl\u00E9mentaires
-error.versioned.info.requires.added=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "requires" suppl\u00E9mentaires
-error.versioned.info.requires.dropped=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "requires" manquants
-error.versioned.info.exports.notequal=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "exports" diff\u00E9rents
-error.versioned.info.provides.notequal=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "provides" diff\u00E9rents
+error.validator.info.without.root=module-info.class a \u00E9t\u00E9 d\u00E9tect\u00E9 dans un r\u00E9pertoire avec num\u00E9ro de version sans module-info.class dans la racine
+error.validator.info.name.notequal=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient un nom incorrect
+error.validator.info.requires.public=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "requires public" suppl\u00E9mentaires
+error.validator.info.requires.added=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "requires" suppl\u00E9mentaires
+error.validator.info.requires.dropped=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "requires" manquants
+error.validator.info.exports.notequal=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "exports" diff\u00E9rents
+error.validator.info.provides.notequal=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "provides" diff\u00E9rents
error.invalid.versioned.module.attribute=Attribut de descripteur de module non valide {0}
error.missing.provider=Fournisseur de services introuvable : {0}
error.release.value.notnumber=version {0} non valide
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_it.properties Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_it.properties Tue Jan 17 11:35:28 2017 -0800
@@ -42,13 +42,13 @@
error.module.options.without.info=Una delle opzioni --module-version o --hash-modules non contiene module-info.class
error.unexpected.module-info=Descrittore di modulo {0} imprevisto
error.module.descriptor.not.found=Descrittore di modulo non trovato
-error.versioned.info.without.root=module-info.class trovato in una directory con controllo delle versioni senza module-info.class nella radice
-error.versioned.info.name.notequal=module-info.class in una directory con controllo delle versioni contiene un nome errato
-error.versioned.info.requires.public=module-info.class in una directory con controllo delle versioni contiene valori "requires public" aggiuntivi
-error.versioned.info.requires.added=module-info.class in una directory con controllo delle versioni contiene valori "requires" aggiuntivi
-error.versioned.info.requires.dropped=module-info.class in una directory con controllo delle versioni contiene valori "requires" mancanti
-error.versioned.info.exports.notequal=module-info.class in una directory con controllo delle versioni contiene "exports" differenti
-error.versioned.info.provides.notequal=module-info.class in una directory con controllo delle versioni contiene valori "provides" differenti
+error.validator.info.without.root=module-info.class trovato in una directory con controllo delle versioni senza module-info.class nella radice
+error.validator.info.name.notequal=module-info.class in una directory con controllo delle versioni contiene un nome errato
+error.validator.info.requires.public=module-info.class in una directory con controllo delle versioni contiene valori "requires public" aggiuntivi
+error.validator.info.requires.added=module-info.class in una directory con controllo delle versioni contiene valori "requires" aggiuntivi
+error.validator.info.requires.dropped=module-info.class in una directory con controllo delle versioni contiene valori "requires" mancanti
+error.validator.info.exports.notequal=module-info.class in una directory con controllo delle versioni contiene "exports" differenti
+error.validator.info.provides.notequal=module-info.class in una directory con controllo delle versioni contiene valori "provides" differenti
error.invalid.versioned.module.attribute=Attributo descrittore del modulo {0} non valido.
error.missing.provider=Provider di servizi non trovato: {0}
error.release.value.notnumber=release {0} non valida
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties Tue Jan 17 11:35:28 2017 -0800
@@ -42,13 +42,13 @@
error.module.options.without.info=--module-version\u307E\u305F\u306F--hash-modules\u306E\u3044\u305A\u308C\u304B\u3067module-info.class\u304C\u3042\u308A\u307E\u305B\u3093
error.unexpected.module-info=\u4E88\u671F\u3057\u306A\u3044\u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30C7\u30A3\u30B9\u30AF\u30EA\u30D7\u30BF{0}
error.module.descriptor.not.found=\u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30C7\u30A3\u30B9\u30AF\u30EA\u30D7\u30BF\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
-error.versioned.info.without.root=module-info.class\u304C\u3001\u30EB\u30FC\u30C8\u306Bmodule-info.class\u306E\u306A\u3044\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u898B\u3064\u304B\u308A\u307E\u3057\u305F
-error.versioned.info.name.notequal=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u6B63\u3057\u304F\u306A\u3044\u540D\u524D\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
-error.versioned.info.requires.public=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u8FFD\u52A0\u306E"requires public"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
-error.versioned.info.requires.added=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u8FFD\u52A0\u306E"requires"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
-error.versioned.info.requires.dropped=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u6B20\u843D\u3057\u3066\u3044\u308B"requires"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
-error.versioned.info.exports.notequal=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u7570\u306A\u308B"exports"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
-error.versioned.info.provides.notequal=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u7570\u306A\u308B"provides"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
+error.validator.info.without.root=module-info.class\u304C\u3001\u30EB\u30FC\u30C8\u306Bmodule-info.class\u306E\u306A\u3044\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u898B\u3064\u304B\u308A\u307E\u3057\u305F
+error.validator.info.name.notequal=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u6B63\u3057\u304F\u306A\u3044\u540D\u524D\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
+error.validator.info.requires.public=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u8FFD\u52A0\u306E"requires public"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
+error.validator.info.requires.added=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u8FFD\u52A0\u306E"requires"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
+error.validator.info.requires.dropped=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u6B20\u843D\u3057\u3066\u3044\u308B"requires"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
+error.validator.info.exports.notequal=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u7570\u306A\u308B"exports"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
+error.validator.info.provides.notequal=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u7570\u306A\u308B"provides"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
error.invalid.versioned.module.attribute=\u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30C7\u30A3\u30B9\u30AF\u30EA\u30D7\u30BF\u5C5E\u6027{0}\u304C\u7121\u52B9\u3067\u3059
error.missing.provider=\u30B5\u30FC\u30D3\u30B9\u30FB\u30D7\u30ED\u30D0\u30A4\u30C0\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: {0}
error.release.value.notnumber=\u30EA\u30EA\u30FC\u30B9{0}\u306F\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ko.properties Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ko.properties Tue Jan 17 11:35:28 2017 -0800
@@ -42,13 +42,13 @@
error.module.options.without.info=module-info.class \uC5C6\uC774 --module-version \uB610\uB294 --hash-modules \uC911 \uD558\uB098
error.unexpected.module-info=\uC608\uC0C1\uCE58 \uC54A\uC740 \uBAA8\uB4C8 \uAE30\uC220\uC790 {0}
error.module.descriptor.not.found=\uBAA8\uB4C8 \uAE30\uC220\uC790\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC74C
-error.versioned.info.without.root=\uB8E8\uD2B8\uC5D0\uC11C module-info.class \uC5C6\uC774 \uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C module-info.class\uAC00 \uBC1C\uACAC\uB428
-error.versioned.info.name.notequal=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uC798\uBABB\uB41C \uC774\uB984\uC774 \uD3EC\uD568\uB428
-error.versioned.info.requires.public=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uCD94\uAC00 "requires public" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
-error.versioned.info.requires.added=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uCD94\uAC00 "requires" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
-error.versioned.info.requires.dropped=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uB204\uB77D\uB41C "requires" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
-error.versioned.info.exports.notequal=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uB2E4\uB978 "exports" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
-error.versioned.info.provides.notequal=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uB2E4\uB978 "provides" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
+error.validator.info.without.root=\uB8E8\uD2B8\uC5D0\uC11C module-info.class \uC5C6\uC774 \uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C module-info.class\uAC00 \uBC1C\uACAC\uB428
+error.validator.info.name.notequal=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uC798\uBABB\uB41C \uC774\uB984\uC774 \uD3EC\uD568\uB428
+error.validator.info.requires.public=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uCD94\uAC00 "requires public" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
+error.validator.info.requires.added=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uCD94\uAC00 "requires" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
+error.validator.info.requires.dropped=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uB204\uB77D\uB41C "requires" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
+error.validator.info.exports.notequal=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uB2E4\uB978 "exports" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
+error.validator.info.provides.notequal=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uB2E4\uB978 "provides" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
error.invalid.versioned.module.attribute=\uBD80\uC801\uD569\uD55C \uBAA8\uB4C8 \uAE30\uC220\uC790 \uC18D\uC131 {0}
error.missing.provider=\uC11C\uBE44\uC2A4 \uC81C\uACF5\uC790\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC74C: {0}
error.release.value.notnumber=\uB9B4\uB9AC\uC2A4 {0}\uC774(\uAC00) \uBD80\uC801\uD569\uD568
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_pt_BR.properties Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_pt_BR.properties Tue Jan 17 11:35:28 2017 -0800
@@ -42,13 +42,13 @@
error.module.options.without.info=Um dentre --module-version ou --hash-modules est\u00E1 sem module-info.class
error.unexpected.module-info=Descritor de m\u00F3dulo inesperado {0}
error.module.descriptor.not.found=Descritor de m\u00F3dulo n\u00E3o encontrado
-error.versioned.info.without.root=module-info.class encontrado em um diret\u00F3rio com controle de vers\u00E3o sem module-info.class na raiz
-error.versioned.info.name.notequal=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m nome incorreto
-error.versioned.info.requires.public=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "requires public" adicional
-error.versioned.info.requires.added=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "requires" adicional
-error.versioned.info.requires.dropped=module-info.class em um diret\u00F3rio com controle de vers\u00E3o falta "requires"
-error.versioned.info.exports.notequal=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "exports" diferente
-error.versioned.info.provides.notequal=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "provides" diferente
+error.validator.info.without.root=module-info.class encontrado em um diret\u00F3rio com controle de vers\u00E3o sem module-info.class na raiz
+error.validator.info.name.notequal=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m nome incorreto
+error.validator.info.requires.public=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "requires public" adicional
+error.validator.info.requires.added=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "requires" adicional
+error.validator.info.requires.dropped=module-info.class em um diret\u00F3rio com controle de vers\u00E3o falta "requires"
+error.validator.info.exports.notequal=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "exports" diferente
+error.validator.info.provides.notequal=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "provides" diferente
error.invalid.versioned.module.attribute=Atributo {0} de descritor de m\u00F3dulo inv\u00E1lido
error.missing.provider=Prestador de servi\u00E7os n\u00E3o encontrado: {0}
error.release.value.notnumber=release {0} n\u00E3o v\u00E1lida
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_sv.properties Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_sv.properties Tue Jan 17 11:35:28 2017 -0800
@@ -42,13 +42,13 @@
error.module.options.without.info=--module-version eller --hash-modules utan module-info.class
error.unexpected.module-info=Ov\u00E4ntad moduldeskriptor, {0}
error.module.descriptor.not.found=Moduldeskriptorn hittades inte
-error.versioned.info.without.root=module-info.class hittades i en versionshanterad katalog utan module-info.class i roten
-error.versioned.info.name.notequal=module-info.class i en versionshanterad katalog inneh\u00E5ller ett felaktigt namn
-error.versioned.info.requires.public=module-info.class i en versionshanterad katalog inneh\u00E5ller fler "requires public"
-error.versioned.info.requires.added=module-info.class i en versionshanterad katalog inneh\u00E5ller fler "requires"
-error.versioned.info.requires.dropped=module-info.class i en versionshanterad katalog inneh\u00E5ller saknade "requires"
-error.versioned.info.exports.notequal=module-info.class i en versionshanterad katalog inneh\u00E5ller olika "exports"
-error.versioned.info.provides.notequal=module-info.class i en versionshanterad katalog inneh\u00E5ller olika "provides"
+error.validator.info.without.root=module-info.class hittades i en versionshanterad katalog utan module-info.class i roten
+error.validator.info.name.notequal=module-info.class i en versionshanterad katalog inneh\u00E5ller ett felaktigt namn
+error.validator.info.requires.public=module-info.class i en versionshanterad katalog inneh\u00E5ller fler "requires public"
+error.validator.info.requires.added=module-info.class i en versionshanterad katalog inneh\u00E5ller fler "requires"
+error.validator.info.requires.dropped=module-info.class i en versionshanterad katalog inneh\u00E5ller saknade "requires"
+error.validator.info.exports.notequal=module-info.class i en versionshanterad katalog inneh\u00E5ller olika "exports"
+error.validator.info.provides.notequal=module-info.class i en versionshanterad katalog inneh\u00E5ller olika "provides"
error.invalid.versioned.module.attribute=Ogiltigt attribut f\u00F6r moduldeskriptor, {0}
error.missing.provider=Tj\u00E4nsteleverant\u00F6ren hittades inte: {0}
error.release.value.notnumber=utg\u00E5va {0} \u00E4r inte giltig
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties Tue Jan 17 11:35:28 2017 -0800
@@ -42,13 +42,13 @@
error.module.options.without.info=--module-version \u6216 --hash-modules \u4E4B\u4E00\u6CA1\u6709 module-info.class
error.unexpected.module-info=\u610F\u5916\u7684\u6A21\u5757\u63CF\u8FF0\u7B26 {0}
error.module.descriptor.not.found=\u627E\u4E0D\u5230\u6A21\u5757\u63CF\u8FF0\u7B26
-error.versioned.info.without.root=\u5728\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u627E\u5230\u4E86 module-info.class, \u4F46\u6839\u4E2D\u6CA1\u6709 module-info.class
-error.versioned.info.name.notequal=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u6B63\u786E\u7684\u540D\u79F0
-error.versioned.info.requires.public=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u989D\u5916\u7684 "requires public"
-error.versioned.info.requires.added=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u989D\u5916\u7684 "requires"
-error.versioned.info.requires.dropped=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u7F3A\u5C11\u7684 "requires"
-error.versioned.info.exports.notequal=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "exports"
-error.versioned.info.provides.notequal=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "provides"
+error.validator.info.without.root=\u5728\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u627E\u5230\u4E86 module-info.class, \u4F46\u6839\u4E2D\u6CA1\u6709 module-info.class
+error.validator.info.name.notequal=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u6B63\u786E\u7684\u540D\u79F0
+error.validator.info.requires.public=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u989D\u5916\u7684 "requires public"
+error.validator.info.requires.added=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u989D\u5916\u7684 "requires"
+error.validator.info.requires.dropped=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u7F3A\u5C11\u7684 "requires"
+error.validator.info.exports.notequal=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "exports"
+error.validator.info.provides.notequal=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "provides"
error.invalid.versioned.module.attribute=\u65E0\u6548\u7684\u6A21\u5757\u63CF\u8FF0\u7B26\u5C5E\u6027 {0}
error.missing.provider=\u672A\u627E\u5230\u670D\u52A1\u63D0\u4F9B\u65B9: {0}
error.release.value.notnumber=\u53D1\u884C\u7248 {0} \u65E0\u6548
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_TW.properties Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_TW.properties Tue Jan 17 11:35:28 2017 -0800
@@ -42,13 +42,13 @@
error.module.options.without.info=--module-version \u6216 --hash-modules \u5176\u4E2D\u4E00\u500B\u6C92\u6709 module-info.class
error.unexpected.module-info=\u672A\u9810\u671F\u7684\u6A21\u7D44\u63CF\u8FF0\u5340 {0}
error.module.descriptor.not.found=\u627E\u4E0D\u5230\u6A21\u7D44\u63CF\u8FF0\u5340
-error.versioned.info.without.root=\u5728\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u767C\u73FE module-info.class\uFF0C\u4F46\u662F\u6839\u4E2D\u6C92\u6709 module-info.class
-error.versioned.info.name.notequal=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u6B63\u78BA\u7684\u540D\u7A31
-error.versioned.info.requires.public=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u984D\u5916\u7684 "requires public"
-error.versioned.info.requires.added=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u984D\u5916\u7684 "requires"
-error.versioned.info.requires.dropped=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u907A\u6F0F\u7684 "requires"
-error.versioned.info.exports.notequal=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "exports"
-error.versioned.info.provides.notequal=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "provides"
+error.validator.info.without.root=\u5728\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u767C\u73FE module-info.class\uFF0C\u4F46\u662F\u6839\u4E2D\u6C92\u6709 module-info.class
+error.validator.info.name.notequal=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u6B63\u78BA\u7684\u540D\u7A31
+error.validator.info.requires.public=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u984D\u5916\u7684 "requires public"
+error.validator.info.requires.added=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u984D\u5916\u7684 "requires"
+error.validator.info.requires.dropped=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u907A\u6F0F\u7684 "requires"
+error.validator.info.exports.notequal=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "exports"
+error.validator.info.provides.notequal=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "provides"
error.invalid.versioned.module.attribute=\u6A21\u7D44\u63CF\u8FF0\u5340\u5C6C\u6027 {0} \u7121\u6548
error.missing.provider=\u627E\u4E0D\u5230\u670D\u52D9\u63D0\u4F9B\u8005: {0}
error.release.value.notnumber=\u7248\u672C {0} \u7121\u6548
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java Tue Jan 17 11:35:28 2017 -0800
@@ -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
@@ -58,13 +58,10 @@
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.MessageFormat;
-import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Deque;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
@@ -101,6 +98,7 @@
import jdk.internal.joptsimple.ValueConverter;
import jdk.internal.loader.ResourceHelper;
import jdk.internal.module.ModuleHashes;
+import jdk.internal.module.ModuleHashesBuilder;
import jdk.internal.module.ModuleInfo;
import jdk.internal.module.ModuleInfoExtender;
import jdk.internal.module.ModulePath;
@@ -286,7 +284,27 @@
}
private boolean hashModules() {
- return new Hasher(options.moduleFinder).run();
+ if (options.dryrun) {
+ out.println("Dry run:");
+ }
+
+ Hasher hasher = new Hasher(options.moduleFinder);
+ hasher.computeHashes().forEach((mn, hashes) -> {
+ if (options.dryrun) {
+ out.format("%s%n", mn);
+ hashes.names().stream()
+ .sorted()
+ .forEach(name -> out.format(" hashes %s %s %s%n",
+ name, hashes.algorithm(), toHex(hashes.hashFor(name))));
+ } else {
+ try {
+ hasher.updateModuleInfo(mn, hashes);
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+ });
+ return true;
}
private boolean describe() throws IOException {
@@ -377,7 +395,7 @@
// create jmod with temporary name to avoid it being examined
// when scanning the module path
Path target = options.jmodFile;
- Path tempTarget = target.resolveSibling(target.getFileName() + ".tmp");
+ Path tempTarget = Files.createTempFile(target.getFileName().toString(), ".tmp");
try {
try (JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget)) {
jmod.write(jos);
@@ -411,7 +429,6 @@
final String osArch = options.osArch;
final String osVersion = options.osVersion;
final List<PathMatcher> excludes = options.excludes;
- final Hasher hasher = hasher();
final ModuleResolution moduleResolution = options.moduleResolution;
JmodFileWriter() { }
@@ -514,8 +531,17 @@
if (moduleVersion != null)
extender.version(moduleVersion);
- if (hasher != null) {
- ModuleHashes moduleHashes = hasher.computeHashes(descriptor.name());
+ // --hash-modules
+ if (options.modulesToHash != null) {
+ // To compute hashes, it creates a Configuration to resolve
+ // a module graph. The post-resolution check requires
+ // the packages in ModuleDescriptor be available for validation.
+ ModuleDescriptor md;
+ try (InputStream is = miSupplier.get()) {
+ md = ModuleDescriptor.read(is, () -> packages);
+ }
+
+ ModuleHashes moduleHashes = computeHashes(md);
if (moduleHashes != null) {
extender.hashes(moduleHashes);
} else {
@@ -557,50 +583,34 @@
* The jmod file is being created and does not exist in the
* given modulepath.
*/
- private Hasher hasher() {
- if (options.modulesToHash == null)
- return null;
-
- try {
- Supplier<InputStream> miSupplier = newModuleInfoSupplier();
- if (miSupplier == null) {
- throw new IOException(MODULE_INFO + " not found");
+ private ModuleHashes computeHashes(ModuleDescriptor descriptor) {
+ String mn = descriptor.name();
+ URI uri = options.jmodFile.toUri();
+ ModuleReference mref = new ModuleReference(descriptor, uri) {
+ @Override
+ public ModuleReader open() {
+ throw new UnsupportedOperationException("opening " + mn);
}
+ };
- ModuleDescriptor descriptor;
- try (InputStream in = miSupplier.get()) {
- descriptor = ModuleDescriptor.read(in);
- }
-
- URI uri = options.jmodFile.toUri();
- ModuleReference mref = new ModuleReference(descriptor, uri) {
+ // compose a module finder with the module path and also
+ // a module finder that can find the jmod file being created
+ ModuleFinder finder = ModuleFinder.compose(options.moduleFinder,
+ new ModuleFinder() {
@Override
- public ModuleReader open() {
- throw new UnsupportedOperationException();
+ public Optional<ModuleReference> find(String name) {
+ if (descriptor.name().equals(name))
+ return Optional.of(mref);
+ else return Optional.empty();
}
- };
- // compose a module finder with the module path and also
- // a module finder that can find the jmod file being created
- ModuleFinder finder = ModuleFinder.compose(options.moduleFinder,
- new ModuleFinder() {
- @Override
- public Optional<ModuleReference> find(String name) {
- if (descriptor.name().equals(name))
- return Optional.of(mref);
- else return Optional.empty();
- }
+ @Override
+ public Set<ModuleReference> findAll() {
+ return Collections.singleton(mref);
+ }
+ });
- @Override
- public Set<ModuleReference> findAll() {
- return Collections.singleton(mref);
- }
- });
-
- return new Hasher(finder);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
+ return new Hasher(mn, finder).computeHashes().get(mn);
}
/**
@@ -789,192 +799,93 @@
* Compute and record hashes
*/
private class Hasher {
- final ModuleFinder moduleFinder;
- final Map<String, Path> moduleNameToPath;
+ final Configuration configuration;
+ final ModuleHashesBuilder hashesBuilder;
final Set<String> modules;
- final Configuration configuration;
- final boolean dryrun = options.dryrun;
+ final String moduleName; // a specific module to record hashes, if set
+
+ /**
+ * This constructor is for jmod hash command.
+ *
+ * This Hasher will determine which modules to record hashes, i.e.
+ * the module in a subgraph of modules to be hashed and that
+ * has no outgoing edges. It will record in each of these modules,
+ * say `M`, with the the hashes of modules that depend upon M
+ * directly or indirectly matching the specified --hash-modules pattern.
+ */
Hasher(ModuleFinder finder) {
- this.moduleFinder = finder;
+ this(null, finder);
+ }
+
+ /**
+ * Constructs a Hasher to compute hashes.
+ *
+ * If a module name `M` is specified, it will compute the hashes of
+ * modules that depend upon M directly or indirectly matching the
+ * specified --hash-modules pattern and record in the ModuleHashes
+ * attribute in M's module-info.class.
+ *
+ * @param name name of the module to record hashes
+ * @param finder module finder for the specified --module-path
+ */
+ Hasher(String name, ModuleFinder finder) {
// Determine the modules that matches the pattern {@code modulesToHash}
- this.modules = moduleFinder.findAll().stream()
+ Set<String> roots = finder.findAll().stream()
.map(mref -> mref.descriptor().name())
.filter(mn -> options.modulesToHash.matcher(mn).find())
.collect(Collectors.toSet());
- // a map from a module name to Path of the packaged module
- this.moduleNameToPath = moduleFinder.findAll().stream()
- .map(mref -> mref.descriptor().name())
- .collect(Collectors.toMap(Function.identity(), mn -> moduleToPath(mn)));
-
+ // use system module path unless it creates a JMOD file for
+ // a module that is present in the system image e.g. upgradeable
+ // module
+ ModuleFinder system;
+ if (name != null && ModuleFinder.ofSystem().find(name).isPresent()) {
+ system = ModuleFinder.of();
+ } else {
+ system = ModuleFinder.ofSystem();
+ }
// get a resolved module graph
Configuration config = null;
try {
- config = Configuration.empty()
- .resolveRequires(ModuleFinder.ofSystem(), moduleFinder, modules);
+ config = Configuration.empty().resolveRequires(system, finder, roots);
} catch (ResolutionException e) {
- warning("warn.module.resolution.fail", e.getMessage());
+ throw new CommandException("err.module.resolution.fail", e.getMessage());
}
+
+ this.moduleName = name;
this.configuration = config;
+
+ // filter modules resolved from the system module finder
+ this.modules = config.modules().stream()
+ .map(ResolvedModule::name)
+ .filter(mn -> roots.contains(mn) && !system.find(mn).isPresent())
+ .collect(Collectors.toSet());
+
+ this.hashesBuilder = new ModuleHashesBuilder(config, modules);
}
/**
- * This method is for jmod hash command.
+ * Returns a map of a module M to record hashes of the modules
+ * that depend upon M directly or indirectly.
*
- * Identify the base modules in the module graph, i.e. no outgoing edge
- * to any of the modules to be hashed.
+ * For jmod hash command, the returned map contains one entry
+ * for each module M that has no outgoing edges to any of the
+ * modules matching the specified --hash-modules pattern.
*
- * For each base module M, compute the hashes of all modules that depend
- * upon M directly or indirectly. Then update M's module-info.class
- * to record the hashes.
+ * Each entry represents a leaf node in a connected subgraph containing
+ * M and other candidate modules from the module graph where M's outgoing
+ * edges to any module other than the ones matching the specified
+ * --hash-modules pattern are excluded.
*/
- boolean run() {
- if (configuration == null)
- return false;
-
- // transposed graph containing the the packaged modules and
- // its transitive dependences matching --hash-modules
- Map<String, Set<String>> graph = new HashMap<>();
- for (String root : modules) {
- Deque<String> deque = new ArrayDeque<>();
- deque.add(root);
- Set<String> visited = new HashSet<>();
- while (!deque.isEmpty()) {
- String mn = deque.pop();
- if (!visited.contains(mn)) {
- visited.add(mn);
-
- if (modules.contains(mn))
- graph.computeIfAbsent(mn, _k -> new HashSet<>());
-
- ResolvedModule resolvedModule = configuration.findModule(mn).get();
- for (ResolvedModule dm : resolvedModule.reads()) {
- String name = dm.name();
- if (!visited.contains(name)) {
- deque.push(name);
- }
-
- // reverse edge
- if (modules.contains(name) && modules.contains(mn)) {
- graph.computeIfAbsent(name, _k -> new HashSet<>()).add(mn);
- }
- }
- }
- }
- }
-
- if (dryrun)
- out.println("Dry run:");
-
- // 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.entrySet().stream()
- .filter(e -> !e.getValue().isEmpty())
- .forEach(e -> {
- String mn = e.getKey();
- Map<String, Path> modulesForHash = e.getValue().stream()
- .collect(Collectors.toMap(Function.identity(),
- moduleNameToPath::get));
- ModuleHashes hashes = ModuleHashes.generate(modulesForHash, "SHA-256");
- if (dryrun) {
- out.format("%s%n", mn);
- hashes.names().stream()
- .sorted()
- .forEach(name -> out.format(" hashes %s %s %s%n",
- name, hashes.algorithm(), hashes.hashFor(name)));
- } else {
- try {
- updateModuleInfo(mn, hashes);
- } catch (IOException ex) {
- throw new UncheckedIOException(ex);
- }
- }
- });
- return true;
- }
-
- /**
- * Compute hashes of the specified module.
- *
- * It records the hashing modules that depend upon the specified
- * module directly or indirectly.
- */
- ModuleHashes computeHashes(String name) {
- if (configuration == null)
+ Map<String, ModuleHashes> computeHashes() {
+ if (hashesBuilder == null)
return null;
- // the transposed graph includes all modules in the resolved graph
- Map<String, Set<String>> graph = transpose();
-
- // find the modules that transitively depend upon the specified name
- Deque<String> deque = new ArrayDeque<>();
- deque.add(name);
- Set<String> mods = visitNodes(graph, deque);
-
- // filter modules matching the pattern specified --hash-modules
- // as well as itself as the jmod file is being generated
- Map<String, Path> modulesForHash = mods.stream()
- .filter(mn -> !mn.equals(name) && modules.contains(mn))
- .collect(Collectors.toMap(Function.identity(), moduleNameToPath::get));
-
- if (modulesForHash.isEmpty())
- return null;
-
- return ModuleHashes.generate(modulesForHash, "SHA-256");
- }
-
- /**
- * Returns all nodes traversed from the given roots.
- */
- private Set<String> visitNodes(Map<String, Set<String>> graph,
- Deque<String> roots) {
- Set<String> visited = new HashSet<>();
- while (!roots.isEmpty()) {
- String mn = roots.pop();
- if (!visited.contains(mn)) {
- visited.add(mn);
- // the given roots may not be part of the graph
- if (graph.containsKey(mn)) {
- for (String dm : graph.get(mn)) {
- if (!visited.contains(dm)) {
- roots.push(dm);
- }
- }
- }
- }
+ if (moduleName != null) {
+ return hashesBuilder.computeHashes(Set.of(moduleName));
+ } else {
+ return hashesBuilder.computeHashes(modules);
}
- return visited;
- }
-
- /**
- * Returns a transposed graph from the resolved module graph.
- */
- private Map<String, Set<String>> transpose() {
- Map<String, Set<String>> transposedGraph = new HashMap<>();
- Deque<String> deque = new ArrayDeque<>(modules);
-
- Set<String> visited = new HashSet<>();
- while (!deque.isEmpty()) {
- String mn = deque.pop();
- if (!visited.contains(mn)) {
- visited.add(mn);
-
- transposedGraph.computeIfAbsent(mn, _k -> new HashSet<>());
-
- ResolvedModule resolvedModule = configuration.findModule(mn).get();
- for (ResolvedModule dm : resolvedModule.reads()) {
- String name = dm.name();
- if (!visited.contains(name)) {
- deque.push(name);
- }
-
- // reverse edge
- transposedGraph.computeIfAbsent(name, _k -> new HashSet<>())
- .add(mn);
- }
- }
- }
- return transposedGraph;
}
/**
@@ -993,11 +904,11 @@
extender.write(out);
}
- private void updateModuleInfo(String name, ModuleHashes moduleHashes)
+ void updateModuleInfo(String name, ModuleHashes moduleHashes)
throws IOException
{
- Path target = moduleNameToPath.get(name);
- Path tempTarget = target.resolveSibling(target.getFileName() + ".tmp");
+ Path target = moduleToPath(name);
+ Path tempTarget = Files.createTempFile(target.getFileName().toString(), ".tmp");
try {
if (target.getFileName().toString().endsWith(".jmod")) {
updateJmodFile(target, tempTarget, moduleHashes);
@@ -1075,10 +986,10 @@
}
private Path moduleToPath(String name) {
- ModuleReference mref = moduleFinder.find(name).orElseThrow(
+ ResolvedModule rm = configuration.findModule(name).orElseThrow(
() -> new InternalError("Selected module " + name + " not on module path"));
- URI uri = mref.location().get();
+ URI uri = rm.reference().location().get();
Path path = Paths.get(uri);
String fn = path.getFileName().toString();
if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties Tue Jan 17 11:35:28 2017 -0800
@@ -108,9 +108,9 @@
err.invalid.dryrun.option=--dry-run can only be used with hash mode
err.module.descriptor.not.found=Module descriptor not found
err.missing.export.or.open.packages=Packages that are exported or open in {0} are not present: {1}
+err.module.resolution.fail=Resolution failed: {0}
warn.invalid.arg=Invalid classname or pathname not exist: {0}
warn.no.module.hashes=No hashes recorded: no module specified for hashing depends on {0}
-warn.module.resolution.fail=No hashes recorded: {0}
warn.ignore.entry=ignoring entry {0}, in section {1}
warn.ignore.duplicate.entry=ignoring duplicate entry {0}, in section {1}
--- a/jdk/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c Tue Jan 17 11:35:28 2017 -0800
@@ -418,7 +418,6 @@
(JNIEnv *env, jclass klass, jint fd, jobject resultContainerObj,
jlong address, jint length, jboolean peek) {
SOCKETADDRESS sa;
- int sa_len = sizeof(SOCKETADDRESS);
ssize_t rv = 0;
jlong *addr = jlong_to_ptr(address);
struct iovec iov[1];
@@ -429,7 +428,7 @@
/* Set up the msghdr structure for receiving */
memset(msg, 0, sizeof (*msg));
msg->msg_name = &sa;
- msg->msg_namelen = sa_len;
+ msg->msg_namelen = sizeof(sa);
iov->iov_base = addr;
iov->iov_len = length;
msg->msg_iov = iov;
@@ -538,7 +537,7 @@
jobject targetAddress, jint targetPort, jint assocId, jint streamNumber,
jboolean unordered, jint ppid) {
SOCKETADDRESS sa;
- int sa_len = sizeof(SOCKETADDRESS);
+ int sa_len = 0;
ssize_t rv = 0;
jlong *addr = jlong_to_ptr(address);
struct iovec iov[1];
@@ -555,13 +554,12 @@
* Association already existing, assocId != -1, targetAddress = preferred addr
*/
if (targetAddress != NULL /*&& assocId <= 0*/) {
- if (NET_InetAddressToSockaddr(env, targetAddress, targetPort, &sa.sa,
+ if (NET_InetAddressToSockaddr(env, targetAddress, targetPort, &sa,
&sa_len, JNI_TRUE) != 0) {
return IOS_THROWN;
}
} else {
- memset(&sa, '\x0', sa_len);
- sa_len = 0;
+ memset(&sa, '\x0', sizeof(sa));
}
/* Set up the msghdr structure for sending */
--- a/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c Tue Jan 17 11:35:28 2017 -0800
@@ -211,22 +211,22 @@
(JNIEnv *env, jclass klass, jint fd, jobjectArray addrs, jint port,
jint addrsLength, jboolean add, jboolean preferIPv6) {
SOCKETADDRESS *sap, *tmpSap;
- int i, sa_len = sizeof(SOCKETADDRESS);
+ int i;
jobject ia;
if (addrsLength < 1)
return;
- if ((sap = calloc(addrsLength, sa_len)) == NULL) {
- JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
+ if ((sap = calloc(addrsLength, sizeof(SOCKETADDRESS))) == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
return;
}
tmpSap = sap;
for (i = 0; i < addrsLength; i++) {
ia = (*env)->GetObjectArrayElement(env, addrs, i);
- if (NET_InetAddressToSockaddr(env, ia, port, (struct sockaddr*)tmpSap,
- &sa_len, preferIPv6) != 0) {
+ if (NET_InetAddressToSockaddr(env, ia, port, tmpSap, NULL,
+ preferIPv6) != 0) {
free(sap);
return;
}
@@ -262,11 +262,11 @@
Java_sun_nio_ch_sctp_SctpNet_connect0
(JNIEnv *env, jclass clazz, int fd, 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, JNI_TRUE) != 0) {
+ if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len,
+ JNI_TRUE) != 0) {
return IOS_THROWN;
}
@@ -311,8 +311,7 @@
}
}
-void initializeISA
- (JNIEnv* env) {
+void initializeISA(JNIEnv* env) {
if (isaCls == 0) {
jclass c = (*env)->FindClass(env, "java/net/InetSocketAddress");
CHECK_NULL(c);
@@ -325,8 +324,7 @@
}
}
-jobject SockAddrToInetSocketAddress
- (JNIEnv *env, struct sockaddr* sap) {
+jobject SockAddrToInetSocketAddress(JNIEnv *env, SOCKETADDRESS *sap) {
int port = 0;
jobject ia = NET_SockaddrToInetAddress(env, sap, &port);
@@ -347,9 +345,9 @@
* Signature: (I)[Ljava/net/SocketAddress;
*/
JNIEXPORT jobjectArray JNICALL Java_sun_nio_ch_sctp_SctpNet_getLocalAddresses0
- (JNIEnv *env, jclass klass, jint fd) {
+ (JNIEnv *env, jclass klass, jint fd)
+{
void *addr_buf, *laddr;
- struct sockaddr* sap;
int i, addrCount;
jobjectArray isaa;
@@ -377,38 +375,35 @@
}
laddr = addr_buf;
- for (i=0; i<addrCount; i++) {
+ for (i = 0; i < addrCount; i++) {
int port = 0;
- jobject isa = NULL, ia;
- sap = (struct sockaddr*)addr_buf;
- ia = NET_SockaddrToInetAddress(env, sap, &port);
+ jobject ia, isa = NULL;
+ ia = NET_SockaddrToInetAddress(env, (SOCKETADDRESS *)addr_buf, &port);
if (ia != NULL)
isa = (*env)->NewObject(env, isaCls, isaCtrID, ia, port);
if (isa == NULL)
break;
(*env)->SetObjectArrayElement(env, isaa, i, isa);
- if (sap->sa_family == AF_INET)
- addr_buf = ((struct sockaddr_in*)addr_buf) + 1;
+ if (((struct sockaddr *)addr_buf)->sa_family == AF_INET)
+ addr_buf = ((struct sockaddr_in *)addr_buf) + 1;
else
- addr_buf = ((struct sockaddr_in6*)addr_buf) + 1;
+ addr_buf = ((struct sockaddr_in6 *)addr_buf) + 1;
}
nio_sctp_freeladdrs(laddr);
return isaa;
}
-jobjectArray getRemoteAddresses
- (JNIEnv *env, jint fd, sctp_assoc_t id) {
+jobjectArray getRemoteAddresses(JNIEnv *env, jint fd, sctp_assoc_t id) {
void *addr_buf, *paddr;
- struct sockaddr* sap;
int i, addrCount;
jobjectArray isaa;
#if __solaris__
if ((addrCount = nio_sctp_getpaddrs(fd, id, (void **)&addr_buf)) == -1) {
#else /* __linux__ */
- if ((addrCount = nio_sctp_getpaddrs(fd, id, (struct sockaddr**)&addr_buf)) == -1) {
+ if ((addrCount = nio_sctp_getpaddrs(fd, id, (struct sockaddr **)&addr_buf)) == -1) {
#endif
handleSocketError(env, errno);
return NULL;
@@ -429,25 +424,23 @@
}
paddr = addr_buf;
- for (i=0; i<addrCount; i++) {
- jobject ia, isa = NULL;
+ for (i = 0; i < addrCount; i++) {
int port = 0;
- sap = (struct sockaddr*)addr_buf;
- ia = NET_SockaddrToInetAddress(env, sap, &port);
+ jobject ia, isa = NULL;
+ ia = NET_SockaddrToInetAddress(env, (SOCKETADDRESS *)addr_buf, &port);
if (ia != NULL)
isa = (*env)->NewObject(env, isaCls, isaCtrID, ia, port);
if (isa == NULL)
break;
(*env)->SetObjectArrayElement(env, isaa, i, isa);
- if (sap->sa_family == AF_INET)
- addr_buf = ((struct sockaddr_in*)addr_buf) + 1;
+ if (((struct sockaddr *)addr_buf)->sa_family == AF_INET)
+ addr_buf = ((struct sockaddr_in *)addr_buf) + 1;
else
- addr_buf = ((struct sockaddr_in6*)addr_buf) + 1;
+ addr_buf = ((struct sockaddr_in6 *)addr_buf) + 1;
}
nio_sctp_freepaddrs(paddr);
-
return isaa;
}
@@ -579,7 +572,6 @@
(JNIEnv *env, jclass klass, jint fd, jint assocId) {
struct sctp_setprim prim;
unsigned int prim_len = sizeof(prim);
- struct sockaddr* sap = (struct sockaddr*)&prim.ssp_addr;
prim.ssp_assoc_id = assocId;
@@ -589,7 +581,7 @@
return NULL;
}
- return SockAddrToInetSocketAddress(env, sap);
+ return SockAddrToInetSocketAddress(env, (SOCKETADDRESS *)&prim.ssp_addr);
}
/*
@@ -600,11 +592,10 @@
JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpNet_setPrimAddrOption0
(JNIEnv *env, jclass klass, jint fd, jint assocId, jobject iaObj, jint port) {
struct sctp_setprim prim;
- struct sockaddr* sap = (struct sockaddr*)&prim.ssp_addr;
- int sap_len = sizeof(sap);
- if (NET_InetAddressToSockaddr(env, iaObj, port, sap,
- &sap_len, JNI_TRUE) != 0) {
+ if (NET_InetAddressToSockaddr(env, iaObj, port,
+ (SOCKETADDRESS *)&prim.ssp_addr,
+ NULL, JNI_TRUE) != 0) {
return;
}
@@ -625,18 +616,17 @@
(JNIEnv *env, jclass klass, jint fd, jint assocId,
jobject iaObj, jint port, jboolean preferIPv6) {
struct sctp_setpeerprim prim;
- struct sockaddr* sap = (struct sockaddr*)&prim.sspp_addr;
- int sap_len = sizeof(sap);
- if (NET_InetAddressToSockaddr(env, iaObj, port, sap,
- &sap_len, preferIPv6) != 0) {
+ if (NET_InetAddressToSockaddr(env, iaObj, port,
+ (SOCKETADDRESS *)&prim.sspp_addr,
+ NULL, preferIPv6) != 0) {
return;
}
prim.sspp_assoc_id = assocId;
if (setsockopt(fd, IPPROTO_SCTP, SCTP_SET_PEER_PRIMARY_ADDR, &prim,
- sizeof(prim)) < 0) {
+ sizeof(prim)) < 0) {
JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
"sun.nio.ch.SctpNet.setPeerPrimAddrOption0");
}
--- a/jdk/test/ProblemList.txt Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/ProblemList.txt Tue Jan 17 11:35:28 2017 -0800
@@ -1,6 +1,6 @@
###########################################################################
#
-# Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 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
@@ -141,8 +141,6 @@
# jdk_io
-java/io/pathNames/GeneralWin32.java 8156595 windows-all
-
############################################################################
# jdk_management
@@ -203,8 +201,6 @@
sun/rmi/rmic/newrmic/equivalence/run.sh 8145980 generic-all
-java/rmi/registry/readTest/readTest.sh 7146543 generic-all
-
############################################################################
# jdk_security
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/io/File/WinDirRelative.java Tue Jan 17 11:35:28 2017 -0800
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8153250
+ * @summary Tests that files are correctly listed for a directory-relative path
+ * @requires (os.family == "windows")
+ */
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class WinDirRelative {
+ private static final char COLON = ':';
+ private static final String BASENAME = "TestFile_";
+ private static final String EXTENSION = ".txt";
+ private static final int NUM_FILES = 10;
+
+ private static boolean isLetter(char c) {
+ return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'));
+ }
+
+ public static void main(String[] args) throws Throwable {
+ // Get the working directory which is also the default
+ // directory for the current drive.
+ String userDir = System.getProperty("user.dir");
+
+ // Test only if a leading drive letter is found
+ if (isLetter(userDir.charAt(0)) && userDir.charAt(1) == COLON) {
+ // Create some empty files
+ List<String> filenames = new ArrayList<String>(NUM_FILES);
+ for (int i = 0; i < NUM_FILES; i++) {
+ String filename = BASENAME + i + EXTENSION;
+ filenames.add(filename);
+ File f = new File(filename);
+ f.createNewFile();
+ f.deleteOnExit();
+ System.out.printf("Created %s (%s)%n", filename,
+ f.getAbsolutePath());
+ }
+
+ // List files and verify that the ones with recognized names exist.
+ String prefix = userDir.substring(0, 2);
+ File p = new File(prefix);
+ int failures = 0;
+ int successes = 0;
+ for (File f : p.listFiles()) {
+ if (f.getName().toString().startsWith(BASENAME)) {
+ if (!f.exists()) {
+ System.err.printf("%s (%s) does not exist%n", f,
+ f.getAbsolutePath());
+ failures++;
+ } else {
+ successes++;
+ }
+ }
+ }
+
+ // Fail if there was an existence test failure or if not
+ // enough of the created files were found
+ boolean testFailed = false;
+ if (failures > 0) {
+ System.err.println("Existence check failed");
+ testFailed = true;
+ }
+ if (successes != NUM_FILES) {
+ System.err.println("Count check failed");
+ testFailed = true;
+ }
+ if (testFailed) {
+ throw new RuntimeException("Test failed");
+ }
+ }
+ }
+}
--- a/jdk/test/java/io/File/createTempFile/Patterns.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/java/io/File/createTempFile/Patterns.java Tue Jan 17 11:35:28 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 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
@@ -22,7 +22,7 @@
*/
/* @test
- @bug 4152178
+ @bug 4152178 8152272
@summary Check various temp-file prefix/suffix cases */
import java.io.File;
@@ -66,6 +66,7 @@
cky("xxx", "");
cky("xxx", "y");
cky("xxx", ".y");
+ cky("xyz", "Directory" + System.getProperty("file.separator"));
}
}
--- a/jdk/test/java/io/pathNames/General.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/java/io/pathNames/General.java Tue Jan 17 11:35:28 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, 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
@@ -40,6 +40,7 @@
private static int gensymCounter = 0;
protected static final String userDir = System.getProperty("user.dir");
+ protected static final String workSubDir = "tmp";
protected static String baseDir = null;
protected static String relative = null;
@@ -60,7 +61,10 @@
* direct or indirect calling) in a whole test.
*/
protected static void initTestData(int depth) throws IOException {
- File parent = new File(userDir);
+ File parent = new File(userDir + File.separator + workSubDir);
+ if (!parent.mkdir()) {
+ throw new IOException("Fail to create directory: " + parent);
+ }
for (int i = 0; i < depth; i++) {
File tmp = new File(parent, gensym());
tmp.createNewFile();
--- a/jdk/test/java/io/pathNames/GeneralWin32.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/java/io/pathNames/GeneralWin32.java Tue Jan 17 11:35:28 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, 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
@@ -53,7 +53,8 @@
private static void checkCaseLookup() throws IOException {
/* Use long names here to avoid 8.3 format, which Samba servers often
force to lowercase */
- File d = new File("XyZzY0123", "FOO_bar_BAZ");
+ File r = new File (workSubDir, "XyZzY0123");
+ File d = new File(r, "FOO_bar_BAZ");
File f = new File(d, "GLORPified");
if (!f.exists()) {
if (!d.exists()) {
@@ -74,9 +75,9 @@
case of filenames, rather than just using the input case */
File y = new File(userDir, f.getPath());
String ans = y.getPath();
- check(ans, "XyZzY0123\\FOO_bar_BAZ\\GLORPified");
- check(ans, "xyzzy0123\\foo_bar_baz\\glorpified");
- check(ans, "XYZZY0123\\FOO_BAR_BAZ\\GLORPIFIED");
+ check(ans, workSubDir + File.separator + "XyZzY0123\\FOO_bar_BAZ\\GLORPified");
+ check(ans, workSubDir + File.separator + "xyzzy0123\\foo_bar_baz\\glorpified");
+ check(ans, workSubDir + File.separator + "XYZZY0123\\FOO_BAR_BAZ\\GLORPIFIED");
}
private static void checkWild(File f) throws Exception {
@@ -125,20 +126,19 @@
throw new RuntimeException("Can't find an active drive");
}
- private static void checkDrive(int depth, char drive, boolean exists)
+ private static void checkDrive(int depth, String drive, boolean exists)
throws Exception
{
- String d = drive + ":";
- File df = new File(d);
- String ans = exists ? df.getAbsolutePath() : d;
+ File df = new File(drive);
+ String ans = exists ? df.getAbsolutePath() : drive;
if (!ans.endsWith("\\"))
ans = ans + "\\";
- checkNames(depth, false, ans, d);
+ checkNames(depth, false, ans, drive);
}
private static void checkDrivePaths(int depth) throws Exception {
- checkDrive(depth, findActiveDrive(), true);
- checkDrive(depth, findInactiveDrive(), false);
+ checkDrive(depth, findActiveDrive() + ":" + workSubDir + File.separator, true);
+ checkDrive(depth, findInactiveDrive() + ":", false);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/readTest/CodebaseTest.java Tue Jan 17 11:35:28 2017 -0800
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+/* @test
+ * @bug 7102369 7094468 7100592
+ * @modules java.rmi/sun.rmi.registry
+ * java.rmi/sun.rmi.server
+ * java.rmi/sun.rmi.transport
+ * java.rmi/sun.rmi.transport.tcp
+ * @library ../../testlibrary
+ * @build TestLibrary RMIRegistryRunner RegistryVM JavaVM testPkg.* RegistryLookup
+ * @summary remove java.rmi.server.codebase property parsing from registyimpl
+ * @run main/othervm CodebaseTest
+*/
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+
+public class CodebaseTest {
+
+ public static void main(String args[]) throws Exception {
+ RegistryVM rmiregistry = null;
+ JavaVM client = null;
+ try {
+ File src = new File(System.getProperty("test.classes", "."), "testPkg");
+ File dest = new File(System.getProperty("user.dir", "."), "testPkg");
+ Files.move(src.toPath(), dest.toPath(),
+ StandardCopyOption.REPLACE_EXISTING);
+
+ File rmiregistryDir =
+ new File(System.getProperty("user.dir", "."), "rmi_tmp");
+ rmiregistryDir.mkdirs();
+ rmiregistry = RegistryVM.createRegistryVMWithRunner(
+ "RMIRegistryRunner",
+ " -Djava.rmi.server.useCodebaseOnly=false"
+ + " -Duser.dir=" + rmiregistryDir.getAbsolutePath());
+ rmiregistry.start();
+ int port = rmiregistry.getPort();
+
+ File srcReadTest = new File(System.getProperty("test.classes", "."),
+ "RegistryLookup.class");
+ File destReadTest = new File(System.getProperty("user.dir", "."),
+ "RegistryLookup.class");
+ Files.move(srcReadTest.toPath(), destReadTest.toPath(),
+ StandardCopyOption.REPLACE_EXISTING);
+
+ File codebase = new File(System.getProperty("user.dir", "."));
+ client = new JavaVM("RegistryLookup",
+ " -Djava.rmi.server.codebase=" + codebase.toURI().toURL()
+ + " -cp ." + File.pathSeparator + System.getProperty("test.class.path"),
+ Integer.toString(port));
+ int exit = client.execute();
+ if (exit == RegistryLookup.EXIT_FAIL) {
+ throw new RuntimeException("Test Fails");
+ }
+ } finally {
+ if (rmiregistry != null) {
+ rmiregistry.cleanup();
+ }
+ if (client != null) {
+ client.cleanup();
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/readTest/RegistryLookup.java Tue Jan 17 11:35:28 2017 -0800
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+
+public class RegistryLookup {
+ public static final int EXIT_FAIL = 1;
+
+ public static void main(String args[]) throws Exception {
+ Registry registry = null;
+ int exit = 0;
+ try {
+ int port = Integer.valueOf(args[0]);
+
+ testPkg.Server obj = new testPkg.Server();
+ testPkg.Hello stub =
+ (testPkg.Hello) UnicastRemoteObject.exportObject(obj, 0);
+ // Bind the remote object's stub in the registry
+ registry = LocateRegistry.getRegistry(port);
+ registry.bind("Hello", stub);
+ System.err.println("Server ready");
+
+ testPkg.Client client = new testPkg.Client(port);
+ String testStubReturn = client.testStub();
+ if(!testStubReturn.equals(obj.hello)) {
+ throw new RuntimeException("Test Fails : "
+ + "unexpected string from stub call");
+ }
+ registry.unbind("Hello");
+ System.out.println("Test passed");
+ } catch (Exception ex) {
+ exit = EXIT_FAIL;
+ ex.printStackTrace();
+ }
+ // need to exit explicitly, and parent process uses exit value
+ // to tell if the test passed.
+ System.exit(exit);
+ }
+}
--- a/jdk/test/java/rmi/registry/readTest/readTest.java Tue Jan 17 18:24:28 2017 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.rmi.registry.Registry;
-import java.rmi.registry.LocateRegistry;
-import java.rmi.RemoteException;
-import java.rmi.server.UnicastRemoteObject;
-
-public class readTest {
-
- public static void main(String args[]) throws Exception {
- try {
- testPkg.Server obj = new testPkg.Server();
- testPkg.Hello stub = (testPkg.Hello) UnicastRemoteObject.exportObject(obj, 0);
- // Bind the remote object's stub in the registry
- Registry registry =
- LocateRegistry.getRegistry(TestLibrary.READTEST_REGISTRY_PORT);
- registry.bind("Hello", stub);
-
- System.err.println("Server ready");
-
- // now, let's test client
- testPkg.Client client =
- new testPkg.Client(TestLibrary.READTEST_REGISTRY_PORT);
- String testStubReturn = client.testStub();
- if(!testStubReturn.equals(obj.hello)) {
- throw new RuntimeException("Test Fails : unexpected string from stub call");
- } else {
- System.out.println("Test passed");
- }
- registry.unbind("Hello");
-
- } catch (Exception e) {
- System.err.println("Server exception: " + e.toString());
- e.printStackTrace();
- }
-
- }
-}
--- a/jdk/test/java/rmi/registry/readTest/readTest.sh Tue Jan 17 18:24:28 2017 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-#
-# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 7102369 7094468 7100592
-# @modules java.rmi/sun.rmi.registry
-# java.rmi/sun.rmi.server
-# java.rmi/sun.rmi.transport
-# java.rmi/sun.rmi.transport.tcp
-# @library ../../testlibrary
-# @build TestLibrary
-# @summary remove java.rmi.server.codebase property parsing from registyimpl
-# @run shell readTest.sh
-# @key intermittent
-
-OS=`uname -s`
-VER=`uname -r`
-ARGS=""
-REGARGS=""
-
-case "$OS" in
- SunOS | Linux | Darwin | AIX )
- PS=":"
- FS="/"
- CHMOD="${FS}bin${FS}chmod"
- FILEURL="file:"
- ;;
- Windows* )
- PS=";"
- FS="\\"
- CHMOD="chmod"
- FILEURL="file:/"
- if [ "$VER" -eq "5" ]; then
- ARGS="-Djdk.net.ephemeralPortRange.low=1024 -Djdk.net.ephemeralPortRange.high=65000"
- REGARGS="-J-Djdk.net.ephemeralPortRange.low=1024 -J-Djdk.net.ephemeralPortRange.high=65000"
- fi
- ;;
- CYGWIN* )
- PS=";"
- FS="/"
- CHMOD="chmod"
- FILEURL="file:/"
- if [ "$VER" -eq "5" ]; then
- ARGS="-Djdk.net.ephemeralPortRange.low=1024 -Djdk.net.ephemeralPortRange.high=65000"
- REGARGS="-J-Djdk.net.ephemeralPortRange.low=1024 -J-Djdk.net.ephemeralPortRange.high=65000"
- fi
- ;;
- * )
- echo "Unrecognized system!"
- exit 1;
- ;;
-esac
-
-TEST_CLASSPATH=.$PS${TESTCLASSPATH:-$TESTCLASSES}
-cp -r ${TESTSRC}${FS}* .
-${CHMOD} -R u+w *
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} testPkg${FS}*java
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -cp $TEST_CLASSPATH readTest.java
-
-mkdir rmi_tmp
-RMIREG_OUT=rmi.out
-#start rmiregistry without any local classes on classpath
-cd rmi_tmp
-# NOTE: This RMI Registry port must match TestLibrary.READTEST_REGISTRY_PORT
-${TESTJAVA}${FS}bin${FS}rmiregistry ${REGARGS} -J-Djava.rmi.server.useCodebaseOnly=false \
- ${TESTTOOLVMOPTS} 60005 > ..${FS}${RMIREG_OUT} 2>&1 &
-RMIREG_PID=$!
-# allow some time to start
-sleep 3
-cd ..
-
-case "$OS" in
- CYGWIN* )
- CODEBASE=`cygpath -w $PWD`
- ;;
- * )
- CODEBASE=`pwd`
- ;;
-esac
-# trailing / after code base is important for rmi codebase property.
-TESTVMOPTS="${TESTVMOPTS} \
- --add-exports java.rmi/sun.rmi.registry=ALL-UNNAMED \
- --add-exports java.rmi/sun.rmi.server=ALL-UNNAMED \
- --add-exports java.rmi/sun.rmi.transport=ALL-UNNAMED \
- --add-exports java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED"
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -cp $TEST_CLASSPATH ${ARGS} -Djava.rmi.server.codebase=${FILEURL}$CODEBASE/ readTest > OUT.TXT 2>&1 &
-TEST_PID=$!
-#bulk of testcase - let it run for a while
-sleep 5
-
-#we're done, kill processes first
-kill -9 ${RMIREG_PID} ${TEST_PID}
-sleep 3
-
-echo "Test output : "
-
-cat OUT.TXT
-echo "=============="
-echo "rmiregistry output : "
-cat ${RMIREG_OUT}
-echo "=============="
-
-grep "Server ready" OUT.TXT
-result1=$?
-grep "Test passed" OUT.TXT
-result2=$?
-
-if [ $result1 -eq 0 -a $result2 -eq 0 ]
-then
- echo "Passed"
- exitCode=0;
-else
- echo "Failed"
- exitCode=1
-fi
-rm -rf OUT.TXT ${RMIREG_OUT} rmi_tmp
-exit ${exitCode}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/readTest/registry.security.policy Tue Jan 17 11:35:28 2017 -0800
@@ -0,0 +1,12 @@
+grant {
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.registry";
+ permission java.util.PropertyPermission "env.class.path", "read";
+ permission java.io.FilePermission ".", "read";
+ permission java.util.PropertyPermission "user.dir", "read";
+ permission java.lang.RuntimePermission "createClassLoader";
+ permission java.lang.RuntimePermission "setContextClassLoader";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.server";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport.tcp";
+ permission java.net.SocketPermission "*:1024-", "listen,resolve,connect,accept";
+};
--- a/jdk/test/lib/security/SecurityTools.java Tue Jan 17 18:24:28 2017 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +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.
- */
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import jdk.testlibrary.JDKToolLauncher;
-import jdk.testlibrary.OutputAnalyzer;
-import jdk.testlibrary.ProcessTools;
-
-public class SecurityTools {
-
- public static final String NO_ALIAS = null;
-
- // keytool
-
- public static OutputAnalyzer keytool(List<String> options)
- throws Throwable {
-
- JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("keytool")
- .addVMArg("-Duser.language=en")
- .addVMArg("-Duser.country=US");
- for (String option : options) {
- if (option.startsWith("-J")) {
- launcher.addVMArg(option.substring(2));
- } else {
- launcher.addToolArg(option);
- }
- }
- return ProcessTools.executeCommand(launcher.getCommand());
- }
-
- public static OutputAnalyzer keytool(String options) throws Throwable {
- return keytool(options.split("\\s+"));
- }
-
- public static OutputAnalyzer keytool(String... options) throws Throwable {
- return keytool(List.of(options));
- }
-
- // jarsigner
-
- public static OutputAnalyzer jarsigner(String jar, String alias,
- List<String> options) throws Throwable {
- JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jarsigner")
- .addVMArg("-Duser.language=en")
- .addVMArg("-Duser.country=US");
- for (String option : options) {
- if (option.startsWith("-J")) {
- launcher.addVMArg(option.substring(2));
- } else {
- launcher.addToolArg(option);
- }
- }
- launcher.addToolArg(jar);
- if (alias != null) {
- launcher.addToolArg(alias);
- }
- return ProcessTools.executeCommand(launcher.getCommand());
- }
-
- public static OutputAnalyzer jarsigner(String jar, String alias,
- String options) throws Throwable {
-
- return jarsigner(jar, alias, options.split("\\s+"));
- }
-
- public static OutputAnalyzer jarsigner(String jar, String alias,
- String... options) throws Throwable {
-
- return jarsigner(jar, alias, List.of(options));
- }
-
- public static OutputAnalyzer sign(String jar, String alias, String... options)
- throws Throwable {
-
- return jarsigner(jar, alias,
- mergeOptions("-J-Djava.security.egd=file:/dev/./urandom", options));
- }
-
- public static OutputAnalyzer verify(String jar, String... options)
- throws Throwable {
-
- return jarsigner(jar, NO_ALIAS, mergeOptions("-verify", options));
- }
-
- // helper methods
-
- private static List<String> mergeOptions(
- String firstOption, String... secondPart) {
-
- return mergeOptions(List.of(firstOption), secondPart);
- }
-
- private static List<String> mergeOptions(
- List<String> firstPart, String... secondPart) {
-
- List<String> options = new ArrayList<>(firstPart);
- Collections.addAll(options, secondPart);
- return options;
- }
-}
--- a/jdk/test/sun/net/www/protocol/http/SetIfModifiedSince.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/sun/net/www/protocol/http/SetIfModifiedSince.java Tue Jan 17 11:35:28 2017 -0800
@@ -22,7 +22,7 @@
*/
/* @test
- @bug 4213164
+ @bug 4213164 8172253
@summary setIfModifiedSince mehtod in HttpURLConnection sometimes fails
*/
import java.util.*;
@@ -88,7 +88,7 @@
//url = new URL(args[0]);
url = new URL("http://localhost:" + String.valueOf(port) +
"/anything");
- con = (HttpURLConnection)url.openConnection();
+ con = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);
con.setIfModifiedSince(date.getTime());
con.connect();
--- a/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java Tue Jan 17 11:35:28 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2016, 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
@@ -28,7 +28,6 @@
import java.security.*;
import java.security.cert.*;
-import java.security.cert.Certificate;
import javax.net.ssl.*;
@@ -61,6 +60,8 @@
private static PeerFactory peerFactory;
+ static final CountDownLatch clientCondition = new CountDownLatch(1);
+
static abstract class Server implements Runnable {
final CipherTest cipherTest;
@@ -313,6 +314,10 @@
}
threads[i].start();
}
+
+ // The client threads are ready.
+ clientCondition.countDown();
+
try {
for (int i = 0; i < THREADS; i++) {
threads[i].join();
@@ -367,6 +372,10 @@
try {
runTest(params);
System.out.println("Passed " + params);
+ } catch (SocketTimeoutException ste) {
+ System.out.println("The client connects to the server timeout, "
+ + "so ignore the test.");
+ break;
} catch (Exception e) {
cipherTest.setFailed();
System.out.println("** Failed " + params + "**");
--- a/jdk/test/sun/security/pkcs11/sslecc/JSSEClient.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/sun/security/pkcs11/sslecc/JSSEClient.java Tue Jan 17 11:35:28 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2006, 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
@@ -23,10 +23,7 @@
import java.io.*;
import java.net.*;
-import java.util.*;
-import java.security.*;
-import java.security.cert.*;
import java.security.cert.Certificate;
import javax.net.ssl.*;
@@ -46,10 +43,30 @@
SSLSocket socket = null;
try {
keyManager.setAuthType(params.clientAuth);
- sslContext.init(new KeyManager[] {keyManager}, new TrustManager[] {cipherTest.trustManager}, cipherTest.secureRandom);
- SSLSocketFactory factory = (SSLSocketFactory)sslContext.getSocketFactory();
- socket = (SSLSocket)factory.createSocket("127.0.0.1", cipherTest.serverPort);
- socket.setSoTimeout(cipherTest.TIMEOUT);
+ sslContext.init(
+ new KeyManager[] { keyManager },
+ new TrustManager[] { CipherTest.trustManager },
+ CipherTest.secureRandom);
+ SSLSocketFactory factory
+ = (SSLSocketFactory) sslContext.getSocketFactory();
+
+ socket = (SSLSocket) factory.createSocket();
+ try {
+ socket.connect(new InetSocketAddress("127.0.0.1",
+ CipherTest.serverPort), 15000);
+ } catch (IOException ioe) {
+ // The server side may be impacted by naughty test cases or
+ // third party routines, and cannot accept connections.
+ //
+ // Just ignore the test if the connection cannot be
+ // established.
+ System.out.println(
+ "Cannot make a connection in 15 seconds. " +
+ "Ignore in client side.");
+ return;
+ }
+
+ socket.setSoTimeout(CipherTest.TIMEOUT);
socket.setEnabledCipherSuites(new String[] {params.cipherSuite});
socket.setEnabledProtocols(new String[] {params.protocol});
InputStream in = socket.getInputStream();
--- a/jdk/test/sun/security/pkcs11/sslecc/JSSEServer.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/sun/security/pkcs11/sslecc/JSSEServer.java Tue Jan 17 11:35:28 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2016, 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
@@ -24,8 +24,11 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.net.SocketTimeoutException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
@@ -40,24 +43,37 @@
JSSEServer(CipherTest cipherTest) throws Exception {
super(cipherTest);
SSLContext serverContext = SSLContext.getInstance("TLS");
- serverContext.init(new KeyManager[] {cipherTest.keyManager}, new TrustManager[] {cipherTest.trustManager}, cipherTest.secureRandom);
+ serverContext.init(
+ new KeyManager[] { CipherTest.keyManager },
+ new TrustManager[] { CipherTest.trustManager },
+ CipherTest.secureRandom);
SSLServerSocketFactory factory = (SSLServerSocketFactory)serverContext.getServerSocketFactory();
serverSocket = (SSLServerSocket)factory.createServerSocket(0);
- cipherTest.serverPort = serverSocket.getLocalPort();
+ serverSocket.setSoTimeout(CipherTest.TIMEOUT);
+ CipherTest.serverPort = serverSocket.getLocalPort();
serverSocket.setEnabledCipherSuites(factory.getSupportedCipherSuites());
serverSocket.setWantClientAuth(true);
}
@Override
public void run() {
- System.out.println("JSSE Server listening on port " + cipherTest.serverPort);
+ System.out.println("JSSE Server listening on port " + CipherTest.serverPort);
Executor exec = Executors.newFixedThreadPool
(CipherTest.THREADS, DaemonThreadFactory.INSTANCE);
+
try {
+ if (!CipherTest.clientCondition.await(CipherTest.TIMEOUT,
+ TimeUnit.MILLISECONDS)) {
+ System.out.println(
+ "The client is not the expected one or timeout. "
+ + "Ignore in server side.");
+ return;
+ }
+
while (true) {
final SSLSocket socket = (SSLSocket)serverSocket.accept();
- socket.setSoTimeout(cipherTest.TIMEOUT);
+ socket.setSoTimeout(CipherTest.TIMEOUT);
Runnable r = new Runnable() {
@Override
public void run() {
@@ -86,11 +102,12 @@
};
exec.execute(r);
}
- } catch (IOException e) {
+ } catch (SocketTimeoutException ste) {
+ System.out.println("The server got timeout for waiting for the connection, "
+ + "so ignore the test.");
+ } catch (Exception e) {
cipherTest.setFailed();
e.printStackTrace();
- //
}
}
-
}
--- a/jdk/test/sun/security/tools/keytool/PrintSSL.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/sun/security/tools/keytool/PrintSSL.java Tue Jan 17 11:35:28 2017 -0800
@@ -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
@@ -25,8 +25,7 @@
* @test
* @bug 6480981 8160624
* @summary keytool should be able to import certificates from remote SSL server
- * @library /lib/security
- * @library /lib/testlibrary
+ * @library /test/lib
* @run main/othervm PrintSSL
*/
@@ -36,7 +35,8 @@
import java.util.concurrent.CountDownLatch;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
-import jdk.testlibrary.OutputAnalyzer;
+import jdk.test.lib.SecurityTools;
+import jdk.test.lib.process.OutputAnalyzer;
public class PrintSSL {
--- a/jdk/test/sun/security/tools/keytool/ReadJar.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/sun/security/tools/keytool/ReadJar.java Tue Jan 17 11:35:28 2017 -0800
@@ -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
@@ -25,14 +25,15 @@
* @test
* @bug 6890872 8168882
* @summary keytool -printcert to recognize signed jar files
- * @library /lib/security
+ * @library /test/lib
* @library /lib/testlibrary
*/
import java.nio.file.Files;
import java.nio.file.Paths;
+import jdk.test.lib.SecurityTools;
+import jdk.test.lib.process.OutputAnalyzer;
import jdk.testlibrary.JarUtils;
-import jdk.testlibrary.OutputAnalyzer;
public class ReadJar {
--- a/jdk/test/tools/jar/InputFilesTest.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/tools/jar/InputFilesTest.java Tue Jan 17 11:35:28 2017 -0800
@@ -102,6 +102,7 @@
"META-INF/MANIFEST.MF" + nl +
"testfile1" + nl +
"testfile2" + nl +
+ "META-INF/versions/9/" + nl +
"META-INF/versions/9/testfile3" + nl +
"META-INF/versions/9/testfile4" + nl;
rm("test.jar test1 test2 test3 test4");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/Basic.java Tue Jan 17 11:35:28 2017 -0800
@@ -0,0 +1,466 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8146486 8172432
+ * @summary Fail to create a MR modular JAR with a versioned entry in
+ * base-versioned empty package
+ * @modules java.base/jdk.internal.module
+ * jdk.compiler
+ * jdk.jartool
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.FileUtils
+ * @run testng Basic
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Version;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.Set;
+import java.util.spi.ToolProvider;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.zip.ZipFile;
+
+import jdk.internal.module.ModuleInfoExtender;
+import jdk.testlibrary.FileUtils;
+
+public class Basic {
+ private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
+ .orElseThrow(() -> new RuntimeException("jar tool not found"));
+ private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac")
+ .orElseThrow(() -> new RuntimeException("javac tool not found"));
+ private final String linesep = System.lineSeparator();
+ private final Path testsrc;
+ private final Path userdir;
+ private final ByteArrayOutputStream outbytes = new ByteArrayOutputStream();
+ private final PrintStream out = new PrintStream(outbytes, true);
+ private final ByteArrayOutputStream errbytes = new ByteArrayOutputStream();
+ private final PrintStream err = new PrintStream(errbytes, true);
+
+ public Basic() throws IOException {
+ testsrc = Paths.get(System.getProperty("test.src"));
+ userdir = Paths.get(System.getProperty("user.dir", "."));
+
+ // compile the classes directory
+ Path source = testsrc.resolve("src").resolve("classes");
+ Path destination = Paths.get("classes");
+ javac(source, destination);
+
+ // compile the mr9 directory including module-info.java
+ source = testsrc.resolve("src").resolve("mr9");
+ destination = Paths.get("mr9");
+ javac(source, destination);
+
+ // move module-info.class for later use
+ Files.move(destination.resolve("module-info.class"),
+ Paths.get("module-info.class"));
+ }
+
+ private void javac(Path source, Path destination) throws IOException {
+ String[] args = Stream.concat(
+ Stream.of("-d", destination.toString()),
+ Files.walk(source)
+ .map(Path::toString)
+ .filter(s -> s.endsWith(".java"))
+ ).toArray(String[]::new);
+ JAVAC_TOOL.run(System.out, System.err, args);
+ }
+
+ private int jar(String cmd) {
+ outbytes.reset();
+ errbytes.reset();
+ return JAR_TOOL.run(out, err, cmd.split(" +"));
+ }
+
+ @AfterClass
+ public void cleanup() throws IOException {
+ Files.walk(userdir, 1)
+ .filter(p -> !p.equals(userdir))
+ .forEach(p -> {
+ try {
+ if (Files.isDirectory(p)) {
+ FileUtils.deleteFileTreeWithRetry(p);
+ } else {
+ FileUtils.deleteFileIfExistsWithRetry(p);
+ }
+ } catch (IOException x) {
+ throw new UncheckedIOException(x);
+ }
+ });
+ }
+
+ // updates a valid multi-release jar with a new public class in
+ // versioned section and fails
+ @Test
+ public void test1() {
+ // successful build of multi-release jar
+ int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
+ Assert.assertEquals(rc, 0);
+
+ jar("-tf mmr.jar");
+
+ Set<String> actual = lines(outbytes);
+ Set<String> expected = Set.of(
+ "META-INF/",
+ "META-INF/MANIFEST.MF",
+ "p/",
+ "p/Hi.class",
+ "META-INF/versions/9/p/Hi.class"
+ );
+ Assert.assertEquals(actual, expected);
+
+ // failed build because of new public class
+ rc = jar("-uf mmr.jar --release 9 -C mr9 p/internal/Bar.class");
+ Assert.assertEquals(rc, 1);
+
+ String s = new String(errbytes.toByteArray());
+ Assert.assertTrue(Message.NOT_FOUND_IN_BASE_ENTRY.match(s, "p/internal/Bar.class"));
+ }
+
+ // updates a valid multi-release jar with a module-info class and new
+ // concealed public class in versioned section and succeeds
+ @Test
+ public void test2() {
+ // successful build of multi-release jar
+ int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
+ Assert.assertEquals(rc, 0);
+
+ // successful build because of module-info and new public class
+ rc = jar("-uf mmr.jar module-info.class --release 9 -C mr9 p/internal/Bar.class");
+ Assert.assertEquals(rc, 0);
+
+ String s = new String(errbytes.toByteArray());
+ Assert.assertTrue(Message.NEW_CONCEALED_PACKAGE_WARNING.match(s, "p/internal/Bar.class"));
+
+ jar("-tf mmr.jar");
+
+ Set<String> actual = lines(outbytes);
+ Set<String> expected = Set.of(
+ "META-INF/",
+ "META-INF/MANIFEST.MF",
+ "p/",
+ "p/Hi.class",
+ "META-INF/versions/9/p/Hi.class",
+ "META-INF/versions/9/p/internal/Bar.class",
+ "module-info.class"
+ );
+ Assert.assertEquals(actual, expected);
+ }
+
+ // jar tool fails building mmr.jar because of new public class
+ @Test
+ public void test3() {
+ int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 .");
+ Assert.assertEquals(rc, 1);
+
+ String s = new String(errbytes.toByteArray());
+ Assert.assertTrue(Message.NOT_FOUND_IN_BASE_ENTRY.match(s, "p/internal/Bar.class"));
+ }
+
+ // jar tool succeeds building mmr.jar because of concealed package
+ @Test
+ public void test4() {
+ int rc = jar("-cf mmr.jar module-info.class -C classes . " +
+ "--release 9 module-info.class -C mr9 .");
+ Assert.assertEquals(rc, 0);
+
+ String s = new String(errbytes.toByteArray());
+ Assert.assertTrue(Message.NEW_CONCEALED_PACKAGE_WARNING.match(s, "p/internal/Bar.class"));
+
+ jar("-tf mmr.jar");
+
+ Set<String> actual = lines(outbytes);
+ Set<String> expected = Set.of(
+ "META-INF/",
+ "META-INF/MANIFEST.MF",
+ "module-info.class",
+ "META-INF/versions/9/module-info.class",
+ "p/",
+ "p/Hi.class",
+ "META-INF/versions/9/",
+ "META-INF/versions/9/p/",
+ "META-INF/versions/9/p/Hi.class",
+ "META-INF/versions/9/p/internal/",
+ "META-INF/versions/9/p/internal/Bar.class"
+ );
+ Assert.assertEquals(actual, expected);
+ }
+
+ // jar tool does two updates, no exported packages, all concealed
+ @Test
+ public void test5() throws IOException {
+ // compile the mr10 directory
+ Path source = testsrc.resolve("src").resolve("mr10");
+ Path destination = Paths.get("mr10");
+ javac(source, destination);
+
+ // create a directory for this tests special files
+ Files.createDirectory(Paths.get("test5"));
+
+ // create an empty module-info.java
+ String hi = "module hi {" + linesep + "}" + linesep;
+ Path modinfo = Paths.get("test5", "module-info.java");
+ Files.write(modinfo, hi.getBytes());
+
+ // and compile it
+ javac(modinfo, Paths.get("test5"));
+
+ int rc = jar("--create --file mr.jar -C classes .");
+ Assert.assertEquals(rc, 0);
+
+ rc = jar("--update --file mr.jar -C test5 module-info.class"
+ + " --release 9 -C mr9 .");
+ Assert.assertEquals(rc, 0);
+
+ jar("tf mr.jar");
+
+ Set<String> actual = lines(outbytes);
+ Set<String> expected = Set.of(
+ "META-INF/",
+ "META-INF/MANIFEST.MF",
+ "p/",
+ "p/Hi.class",
+ "META-INF/versions/9/",
+ "META-INF/versions/9/p/",
+ "META-INF/versions/9/p/Hi.class",
+ "META-INF/versions/9/p/internal/",
+ "META-INF/versions/9/p/internal/Bar.class",
+ "module-info.class"
+ );
+ Assert.assertEquals(actual, expected);
+
+ jar("-d --file mr.jar");
+
+ actual = lines(outbytes);
+ expected = Set.of(
+ "hi",
+ "requires mandated java.base",
+ "contains p",
+ "contains p.internal"
+ );
+ Assert.assertEquals(actual, expected);
+
+ rc = jar("--update --file mr.jar --release 10 -C mr10 .");
+ Assert.assertEquals(rc, 0);
+
+ jar("tf mr.jar");
+
+ actual = lines(outbytes);
+ expected = Set.of(
+ "META-INF/",
+ "META-INF/MANIFEST.MF",
+ "p/",
+ "p/Hi.class",
+ "META-INF/versions/9/",
+ "META-INF/versions/9/p/",
+ "META-INF/versions/9/p/Hi.class",
+ "META-INF/versions/9/p/internal/",
+ "META-INF/versions/9/p/internal/Bar.class",
+ "META-INF/versions/10/",
+ "META-INF/versions/10/p/",
+ "META-INF/versions/10/p/internal/",
+ "META-INF/versions/10/p/internal/bar/",
+ "META-INF/versions/10/p/internal/bar/Gee.class",
+ "module-info.class"
+ );
+ Assert.assertEquals(actual, expected);
+
+ jar("-d --file mr.jar");
+
+ actual = lines(outbytes);
+ expected = Set.of(
+ "hi",
+ "requires mandated java.base",
+ "contains p",
+ "contains p.internal",
+ "contains p.internal.bar"
+ );
+ Assert.assertEquals(actual, expected);
+ }
+
+ // root and versioned module-info entries have different main-class, version
+ // attributes
+ @Test
+ public void test6() throws IOException {
+ // create a directory for this tests special files
+ Files.createDirectory(Paths.get("test6"));
+ Files.createDirectory(Paths.get("test6-v9"));
+
+ // compile the classes directory
+ Path src = testsrc.resolve("src").resolve("classes");
+ Path dst = Paths.get("test6");
+ javac(src, dst);
+
+ byte[] mdBytes = Files.readAllBytes(Paths.get("module-info.class"));
+
+ ModuleInfoExtender mie = ModuleInfoExtender.newExtender(
+ new ByteArrayInputStream(mdBytes));
+
+ mie.mainClass("foo.main");
+ mie.version(Version.parse("1.0"));
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ mie.write(baos);
+ Files.write(Paths.get("test6", "module-info.class"), baos.toByteArray());
+ Files.write(Paths.get("test6-v9", "module-info.class"), baos.toByteArray());
+
+ int rc = jar("--create --file mmr.jar -C test6 . --release 9 -C test6-v9 .");
+ Assert.assertEquals(rc, 0);
+
+
+ // different main-class
+ mie = ModuleInfoExtender.newExtender(new ByteArrayInputStream(mdBytes));
+ mie.mainClass("foo.main2");
+ mie.version(Version.parse("1.0"));
+ baos.reset();
+ mie.write(baos);
+ Files.write(Paths.get("test6-v9", "module-info.class"), baos.toByteArray());
+
+ rc = jar("--create --file mmr.jar -C test6 . --release 9 -C test6-v9 .");
+ Assert.assertEquals(rc, 1);
+
+ Assert.assertTrue(Message.CONTAINS_DIFFERENT_MAINCLASS.match(
+ new String(errbytes.toByteArray()),
+ "META-INF/versions/9/module-info.class"));
+
+ // different version
+ mie = ModuleInfoExtender.newExtender(new ByteArrayInputStream(mdBytes));
+ mie.mainClass("foo.main");
+ mie.version(Version.parse("2.0"));
+ baos.reset();
+ mie.write(baos);
+ Files.write(Paths.get("test6-v9", "module-info.class"), baos.toByteArray());
+
+ rc = jar("--create --file mmr.jar -C test6 . --release 9 -C test6-v9 .");
+ Assert.assertEquals(rc, 1);
+
+ Assert.assertTrue(Message.CONTAINS_DIFFERENT_VERSION.match(
+ new String(errbytes.toByteArray()),
+ "META-INF/versions/9/module-info.class"));
+
+ }
+
+ // versioned mmr without root module-info.class
+ @Test
+ public void test7() throws IOException {
+ // create a directory for this tests special files
+ Files.createDirectory(Paths.get("test7"));
+ Files.createDirectory(Paths.get("test7-v9"));
+ Files.createDirectory(Paths.get("test7-v10"));
+
+ // compile the classes directory
+ Path src = testsrc.resolve("src").resolve("classes");
+ Path dst = Paths.get("test7");
+ javac(src, dst);
+
+ // move module-info.class to v9 later use
+ Files.copy(Paths.get("module-info.class"),
+ Paths.get("test7-v9", "module-info.class"));
+
+ Files.copy(Paths.get("test7-v9", "module-info.class"),
+ Paths.get("test7-v10", "module-info.class"));
+
+ int rc = jar("--create --file mmr.jar --main-class=foo.main -C test7 . --release 9 -C test7-v9 . --release 10 -C test7-v10 .");
+
+System.out.println("-----------------------");
+System.out.println( new String(errbytes.toByteArray()));
+
+
+ Assert.assertEquals(rc, 0);
+
+
+ jar("-tf mmr.jar");
+
+System.out.println("-----------------------");
+System.out.println( new String(outbytes.toByteArray()));
+
+ Optional<String> exp = Optional.of("foo.main");
+ try (ZipFile zf = new ZipFile("mmr.jar")) {
+ Assert.assertTrue(zf.getEntry("module-info.class") == null);
+
+ ModuleDescriptor md = ModuleDescriptor.read(
+ zf.getInputStream(zf.getEntry("META-INF/versions/9/module-info.class")));
+ Assert.assertEquals(md.mainClass(), exp);
+
+ md = ModuleDescriptor.read(
+ zf.getInputStream(zf.getEntry("META-INF/versions/10/module-info.class")));
+ Assert.assertEquals(md.mainClass(), exp);
+ }
+ }
+
+ private static Set<String> lines(ByteArrayOutputStream baos) {
+ String s = new String(baos.toByteArray());
+ return Arrays.stream(s.split("\\R"))
+ .map(l -> l.trim())
+ .filter(l -> l.length() > 0)
+ .collect(Collectors.toSet());
+ }
+
+ static enum Message {
+ CONTAINS_DIFFERENT_MAINCLASS(
+ ": module-info.class in a versioned directory contains different \"main-class\""
+ ),
+ CONTAINS_DIFFERENT_VERSION(
+ ": module-info.class in a versioned directory contains different \"version\""
+ ),
+ NOT_FOUND_IN_BASE_ENTRY(
+ ", contains a new public class not found in base entries"
+ ),
+ NEW_CONCEALED_PACKAGE_WARNING(
+ " is a public class" +
+ " in a concealed package, placing this jar on the class path will result" +
+ " in incompatible public interfaces"
+ );
+
+ final String msg;
+ Message(String msg) {
+ this.msg = msg;
+ }
+
+ /*
+ * Test if the given output contains this message ignoring the line break.
+ */
+ boolean match(String output, String entry) {
+ System.out.println("Expected: " + entry + msg);
+ System.out.println("Found: " + output);
+ return Arrays.stream(output.split("\\R"))
+ .collect(Collectors.joining(" "))
+ .contains(entry + msg);
+ }
+ }
+}
--- a/jdk/test/tools/jar/mmrjar/ConcealedPackage.java Tue Jan 17 18:24:28 2017 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,339 +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.
- */
-
-/*
- * @test
- * @bug 8146486
- * @summary Fail to create a MR modular JAR with a versioned entry in
- * base-versioned empty package
- * @modules jdk.compiler
- * jdk.jartool
- * @library /lib/testlibrary
- * @build jdk.testlibrary.FileUtils
- * @run testng ConcealedPackage
- */
-
-import org.testng.Assert;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.Test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Arrays;
-import java.util.Set;
-import java.util.spi.ToolProvider;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import jdk.testlibrary.FileUtils;
-
-public class ConcealedPackage {
- private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
- .orElseThrow(() -> new RuntimeException("jar tool not found"));
- private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac")
- .orElseThrow(() -> new RuntimeException("javac tool not found"));
- private final String linesep = System.lineSeparator();
- private final Path testsrc;
- private final Path userdir;
- private final ByteArrayOutputStream outbytes = new ByteArrayOutputStream();
- private final PrintStream out = new PrintStream(outbytes, true);
- private final ByteArrayOutputStream errbytes = new ByteArrayOutputStream();
- private final PrintStream err = new PrintStream(errbytes, true);
-
- public ConcealedPackage() throws IOException {
- testsrc = Paths.get(System.getProperty("test.src"));
- userdir = Paths.get(System.getProperty("user.dir", "."));
-
- // compile the classes directory
- Path source = testsrc.resolve("src").resolve("classes");
- Path destination = Paths.get("classes");
- javac(source, destination);
-
- // compile the mr9 directory including module-info.java
- source = testsrc.resolve("src").resolve("mr9");
- destination = Paths.get("mr9");
- javac(source, destination);
-
- // move module-info.class for later use
- Files.move(destination.resolve("module-info.class"),
- Paths.get("module-info.class"));
- }
-
- private void javac(Path source, Path destination) throws IOException {
- String[] args = Stream.concat(
- Stream.of("-d", destination.toString()),
- Files.walk(source)
- .map(Path::toString)
- .filter(s -> s.endsWith(".java"))
- ).toArray(String[]::new);
- JAVAC_TOOL.run(System.out, System.err, args);
- }
-
- private int jar(String cmd) {
- outbytes.reset();
- errbytes.reset();
- return JAR_TOOL.run(out, err, cmd.split(" +"));
- }
-
- @AfterClass
- public void cleanup() throws IOException {
- Files.walk(userdir, 1)
- .filter(p -> !p.equals(userdir))
- .forEach(p -> {
- try {
- if (Files.isDirectory(p)) {
- FileUtils.deleteFileTreeWithRetry(p);
- } else {
- FileUtils.deleteFileIfExistsWithRetry(p);
- }
- } catch (IOException x) {
- throw new UncheckedIOException(x);
- }
- });
- }
-
- // updates a valid multi-release jar with a new public class in
- // versioned section and fails
- @Test
- public void test1() {
- // successful build of multi-release jar
- int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
- Assert.assertEquals(rc, 0);
-
- jar("-tf mmr.jar");
-
- Set<String> actual = lines(outbytes);
- Set<String> expected = Set.of(
- "META-INF/",
- "META-INF/MANIFEST.MF",
- "p/",
- "p/Hi.class",
- "META-INF/versions/9/p/Hi.class"
- );
- Assert.assertEquals(actual, expected);
-
- // failed build because of new public class
- rc = jar("-uf mmr.jar --release 9 -C mr9 p/internal/Bar.class");
- Assert.assertEquals(rc, 1);
-
- String s = new String(errbytes.toByteArray());
- Assert.assertTrue(Message.NOT_FOUND_IN_BASE_ENTRY.match(s, "p/internal/Bar.class"));
- }
-
- // updates a valid multi-release jar with a module-info class and new
- // concealed public class in versioned section and succeeds
- @Test
- public void test2() {
- // successful build of multi-release jar
- int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
- Assert.assertEquals(rc, 0);
-
- // successful build because of module-info and new public class
- rc = jar("-uf mmr.jar module-info.class --release 9 -C mr9 p/internal/Bar.class");
- Assert.assertEquals(rc, 0);
-
- String s = new String(errbytes.toByteArray());
- Assert.assertTrue(Message.NEW_CONCEALED_PACKAGE_WARNING.match(s, "p/internal/Bar.class"));
-
- jar("-tf mmr.jar");
-
- Set<String> actual = lines(outbytes);
- Set<String> expected = Set.of(
- "META-INF/",
- "META-INF/MANIFEST.MF",
- "p/",
- "p/Hi.class",
- "META-INF/versions/9/p/Hi.class",
- "META-INF/versions/9/p/internal/Bar.class",
- "module-info.class"
- );
- Assert.assertEquals(actual, expected);
- }
-
- // jar tool fails building mmr.jar because of new public class
- @Test
- public void test3() {
- int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 .");
- Assert.assertEquals(rc, 1);
-
- String s = new String(errbytes.toByteArray());
- Assert.assertTrue(Message.NOT_FOUND_IN_BASE_ENTRY.match(s, "p/internal/Bar.class"));
- }
-
- // jar tool succeeds building mmr.jar because of concealed package
- @Test
- public void test4() {
- int rc = jar("-cf mmr.jar module-info.class -C classes . " +
- "--release 9 module-info.class -C mr9 .");
- Assert.assertEquals(rc, 0);
-
- String s = new String(errbytes.toByteArray());
- Assert.assertTrue(Message.NEW_CONCEALED_PACKAGE_WARNING.match(s, "p/internal/Bar.class"));
-
- jar("-tf mmr.jar");
-
- Set<String> actual = lines(outbytes);
- Set<String> expected = Set.of(
- "META-INF/",
- "META-INF/MANIFEST.MF",
- "module-info.class",
- "META-INF/versions/9/module-info.class",
- "p/",
- "p/Hi.class",
- "META-INF/versions/9/p/",
- "META-INF/versions/9/p/Hi.class",
- "META-INF/versions/9/p/internal/",
- "META-INF/versions/9/p/internal/Bar.class"
- );
- Assert.assertEquals(actual, expected);
- }
-
- // jar tool does two updates, no exported packages, all concealed
- @Test
- public void test5() throws IOException {
- // compile the mr10 directory
- Path source = testsrc.resolve("src").resolve("mr10");
- Path destination = Paths.get("mr10");
- javac(source, destination);
-
- // create a directory for this tests special files
- Files.createDirectory(Paths.get("test5"));
-
- // create an empty module-info.java
- String hi = "module hi {" + linesep + "}" + linesep;
- Path modinfo = Paths.get("test5", "module-info.java");
- Files.write(modinfo, hi.getBytes());
-
- // and compile it
- javac(modinfo, Paths.get("test5"));
-
- int rc = jar("--create --file mr.jar -C classes .");
- Assert.assertEquals(rc, 0);
-
- rc = jar("--update --file mr.jar -C test5 module-info.class"
- + " --release 9 -C mr9 .");
- Assert.assertEquals(rc, 0);
-
- jar("tf mr.jar");
-
- Set<String> actual = lines(outbytes);
- Set<String> expected = Set.of(
- "META-INF/",
- "META-INF/MANIFEST.MF",
- "p/",
- "p/Hi.class",
- "META-INF/versions/9/p/",
- "META-INF/versions/9/p/Hi.class",
- "META-INF/versions/9/p/internal/",
- "META-INF/versions/9/p/internal/Bar.class",
- "module-info.class"
- );
- Assert.assertEquals(actual, expected);
-
- jar("-d --file mr.jar");
-
- actual = lines(outbytes);
- expected = Set.of(
- "hi",
- "requires mandated java.base",
- "contains p",
- "contains p.internal"
- );
- Assert.assertEquals(actual, expected);
-
- rc = jar("--update --file mr.jar --release 10 -C mr10 .");
- Assert.assertEquals(rc, 0);
-
- jar("tf mr.jar");
-
- actual = lines(outbytes);
- expected = Set.of(
- "META-INF/",
- "META-INF/MANIFEST.MF",
- "p/",
- "p/Hi.class",
- "META-INF/versions/9/p/",
- "META-INF/versions/9/p/Hi.class",
- "META-INF/versions/9/p/internal/",
- "META-INF/versions/9/p/internal/Bar.class",
- "META-INF/versions/10/p/",
- "META-INF/versions/10/p/internal/",
- "META-INF/versions/10/p/internal/bar/",
- "META-INF/versions/10/p/internal/bar/Gee.class",
- "module-info.class"
- );
- Assert.assertEquals(actual, expected);
-
- jar("-d --file mr.jar");
-
- actual = lines(outbytes);
- expected = Set.of(
- "hi",
- "requires mandated java.base",
- "contains p",
- "contains p.internal",
- "contains p.internal.bar"
- );
- Assert.assertEquals(actual, expected);
- }
-
- private static Set<String> lines(ByteArrayOutputStream baos) {
- String s = new String(baos.toByteArray());
- return Arrays.stream(s.split("\\R"))
- .map(l -> l.trim())
- .filter(l -> l.length() > 0)
- .collect(Collectors.toSet());
- }
-
- static enum Message {
- NOT_FOUND_IN_BASE_ENTRY(
- ", contains a new public class not found in base entries"
- ),
- NEW_CONCEALED_PACKAGE_WARNING(
- " is a public class" +
- " in a concealed package, placing this jar on the class path will result" +
- " in incompatible public interfaces"
- );
-
- final String msg;
- Message(String msg) {
- this.msg = msg;
- }
-
- /*
- * Test if the given output contains this message ignoring the line break.
- */
- boolean match(String output, String entry) {
- System.out.println("Expected: " + entry + msg);
- System.out.println("Found: " + output);
- return Arrays.stream(output.split("\\R"))
- .collect(Collectors.joining(" "))
- .contains(entry + msg);
- }
- }
-}
--- a/jdk/test/tools/jar/modularJar/Basic.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/tools/jar/modularJar/Basic.java Tue Jan 17 11:35:28 2017 -0800
@@ -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
@@ -46,7 +46,7 @@
/*
* @test
- * @bug 8167328
+ * @bug 8167328 8171830
* @library /lib/testlibrary
* @modules jdk.compiler
* jdk.jartool
@@ -241,6 +241,11 @@
java(mp, FOO.moduleName + "/" + FOO.mainClass)
.assertSuccess()
+.resultChecker(r -> {
+ System.out.println("===================================");
+ System.out.println(r.output);
+ System.out.println("===================================");
+})
.resultChecker(r -> assertModuleData(r, FOO));
try (InputStream fis = Files.newInputStream(modularJar);
JarInputStream jis = new JarInputStream(fis)) {
@@ -417,6 +422,7 @@
jar("--update",
"--file=" + modularJar.toString(),
"--main-class=" + FOO.mainClass,
+ "--module-version=" + FOO.version,
"-m", mrjarDir.resolve("META-INF/MANIFEST.MF").toRealPath().toString(),
"-C", mrjarDir.toString(), "META-INF/versions/9/module-info.class")
.assertSuccess();
@@ -734,6 +740,25 @@
}
@Test
+ public void exportCreateWithMissingPkg() throws IOException {
+
+ Path foobar = TEST_SRC.resolve("src").resolve("foobar");
+ Path dst = Files.createDirectories(MODULE_CLASSES.resolve("foobar"));
+ javac(dst, null, sourceList(foobar));
+
+ Path mp = Paths.get("exportWithMissingPkg");
+ createTestDir(mp);
+ Path modClasses = dst;
+ Path modularJar = mp.resolve("foofoo.jar");
+
+ jar("--create",
+ "--file=" + modularJar.toString(),
+ "-C", modClasses.toString(), "module-info.class",
+ "-C", modClasses.toString(), "jdk/test/foo/Foo.class")
+ .assertFailure();
+ }
+
+ @Test
public void printModuleDescriptorFoo() throws IOException {
Path mp = Paths.get("printModuleDescriptorFoo");
createTestDir(mp);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/modularJar/src/foobar/Bar.java Tue Jan 17 11:35:28 2017 -0800
@@ -0,0 +1,28 @@
+/*
+ * 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 jdk.test.bar;
+
+public class Bar {
+ public static void main(String[] args) {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/modularJar/src/foobar/Foo.java Tue Jan 17 11:35:28 2017 -0800
@@ -0,0 +1,28 @@
+/*
+ * 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 jdk.test.foo;
+
+public class Foo {
+ public static void main(String[] args) {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/modularJar/src/foobar/module-info.java Tue Jan 17 11:35:28 2017 -0800
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+module foo {
+ exports jdk.test.foo;
+ exports jdk.test.bar;
+ opens jdk.test.foo;
+ opens jdk.test.bar;
+}
--- a/jdk/test/tools/jar/multiRelease/Basic1.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/tools/jar/multiRelease/Basic1.java Tue Jan 17 11:35:28 2017 -0800
@@ -62,15 +62,20 @@
Path source = Paths.get(src, "data", test, "base", "version");
javac(classes, source.resolve("Main.java"), source.resolve("Version.java"));
- Path v9 = Paths.get("v9").resolve("META-INF").resolve("versions").resolve("9");
+ Path v9 = Paths.get("v9");
Files.createDirectories(v9);
source = Paths.get(src, "data", test, "v9", "version");
javac(v9, source.resolve("Version.java"));
- Path v10 = Paths.get("v10").resolve("META-INF").resolve("versions").resolve("10");
+ Path v10 = Paths.get("v10");
Files.createDirectories(v10);
source = Paths.get(src, "data", test, "v10", "version");
javac(v10, source.resolve("Version.java"));
+
+ Path v10_1 = Paths.get("v10_1").resolve("META-INF").resolve("versions").resolve("v10");
+ Files.createDirectories(v10_1);
+ source = Paths.get(src, "data", test, "v10", "version");
+ javac(v10_1, source.resolve("Version.java"));
}
@Test
@@ -95,28 +100,30 @@
new String[] {"classes", "base", "version", "Version.class"},
"META-INF/versions/9/version/Version.class",
- new String[] {"v9", "META-INF", "versions", "9", "version", "Version.class"},
+ new String[] {"v9", "version", "Version.class"},
"META-INF/versions/10/version/Version.class",
- new String[] {"v10", "META-INF", "versions", "10", "version", "Version.class"}
+ new String[] {"v10", "version", "Version.class"}
);
compare(jarfile, names);
}
+
@Test
public void testFail() throws IOException {
String jarfile = "test.jar";
Path classes = Paths.get("classes");
- Path v9 = Paths.get("v9");
- Path v10 = Paths.get("v10");
+ Path v10 = Paths.get("v10_1");
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
- "--release", "9", "-C", v10.toString(), ".")
+ "--release", "10", "-C", v10.toString(), ".")
.assertFailure()
.outputContains("unexpected versioned entry META-INF/versions/");
}
+
+
private void checkMultiRelease(String jarFile, boolean expected) throws IOException {
try (JarFile jf = new JarFile(new File(jarFile), true, ZipFile.OPEN_READ,
JarFile.runtimeVersion())) {
--- a/jdk/test/tools/jmod/JmodTest.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/tools/jmod/JmodTest.java Tue Jan 17 11:35:28 2017 -0800
@@ -580,36 +580,24 @@
}
@Test
- public void testTmpFileAlreadyExists() throws IOException {
- // Implementation detail: jmod tool creates <jmod-file>.tmp
- // Ensure that there are no problems if existing
-
- Path jmod = MODS_DIR.resolve("testTmpFileAlreadyExists.jmod");
- Path tmp = MODS_DIR.resolve("testTmpFileAlreadyExists.jmod.tmp");
- FileUtils.deleteFileIfExistsWithRetry(jmod);
- FileUtils.deleteFileIfExistsWithRetry(tmp);
- Files.createFile(tmp);
- String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
-
- jmod("create",
- "--class-path", cp,
- jmod.toString())
- .assertSuccess()
- .resultChecker(r ->
- assertTrue(Files.notExists(tmp), "Unexpected tmp file:" + tmp)
- );
- }
-
- @Test
public void testTmpFileRemoved() throws IOException {
// Implementation detail: jmod tool creates <jmod-file>.tmp
// Ensure that it is removed in the event of a failure.
// The failure in this case is a class in the unnamed package.
- Path jmod = MODS_DIR.resolve("testTmpFileRemoved.jmod");
- Path tmp = MODS_DIR.resolve("testTmpFileRemoved.jmod.tmp");
+ String filename = "testTmpFileRemoved.jmod";
+ Path jmod = MODS_DIR.resolve(filename);
+
+ // clean up files
FileUtils.deleteFileIfExistsWithRetry(jmod);
- FileUtils.deleteFileIfExistsWithRetry(tmp);
+ findTmpFiles(filename).forEach(tmp -> {
+ try {
+ FileUtils.deleteFileIfExistsWithRetry(tmp);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ });
+
String cp = EXPLODED_DIR.resolve("foo").resolve("classes") + File.pathSeparator +
EXPLODED_DIR.resolve("foo").resolve("classes")
.resolve("jdk").resolve("test").resolve("foo").toString();
@@ -620,10 +608,22 @@
.assertFailure()
.resultChecker(r -> {
assertContains(r.output, "unnamed package");
- assertTrue(Files.notExists(tmp), "Unexpected tmp file:" + tmp);
+ Set<Path> tmpfiles = findTmpFiles(filename).collect(toSet());
+ assertTrue(tmpfiles.isEmpty(), "Unexpected tmp file:" + tmpfiles);
});
}
+ private Stream<Path> findTmpFiles(String prefix) {
+ try {
+ Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir"));
+ return Files.find(tmpdir, 1, (p, attrs) ->
+ p.getFileName().toString().startsWith(prefix)
+ && p.getFileName().toString().endsWith(".tmp"));
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
// ---
static boolean compileModule(String name, Path dest) throws IOException {
--- a/jdk/test/tools/jmod/hashes/HashesTest.java Tue Jan 17 18:24:28 2017 +0300
+++ b/jdk/test/tools/jmod/hashes/HashesTest.java Tue Jan 17 11:35:28 2017 -0800
@@ -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
@@ -23,19 +23,22 @@
/*
* @test
+ * @bug 8160286
* @summary Test the recording and checking of module hashes
- * @author Andrei Eremeev
* @library /lib/testlibrary
* @modules java.base/jdk.internal.misc
* java.base/jdk.internal.module
+ * jdk.compiler
+ * jdk.jartool
* jdk.jlink
- * jdk.compiler
- * @build CompilerUtils
+ * @build CompilerUtils ModuleInfoMaker
* @run testng HashesTest
*/
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.io.UncheckedIOException;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReader;
@@ -53,109 +56,311 @@
import java.util.Set;
import java.util.spi.ToolProvider;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import jdk.internal.module.ModuleInfo;
import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModulePath;
-import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
+import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
public class HashesTest {
static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod")
.orElseThrow(() ->
new RuntimeException("jmod tool not found")
);
+ static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
+ .orElseThrow(() ->
+ new RuntimeException("jar tool not found")
+ );
- private final Path testSrc = Paths.get(System.getProperty("test.src"));
- private final Path modSrc = testSrc.resolve("src");
- private final Path mods = Paths.get("mods");
- private final Path jmods = Paths.get("jmods");
- private final String[] modules = new String[] { "m1", "m2", "m3"};
+ private final Path mods;
+ private final Path srcDir;
+ private final Path lib;
+ private final ModuleInfoMaker builder;
+ HashesTest(Path dest) throws IOException {
+ if (Files.exists(dest)) {
+ deleteDirectory(dest);
+ }
+ this.mods = dest.resolve("mods");
+ this.srcDir = dest.resolve("src");
+ this.lib = dest.resolve("lib");
+ this.builder = new ModuleInfoMaker(srcDir);
+
+ Files.createDirectories(lib);
+ Files.createDirectories(mods);
+ }
+
+ @Test
+ public static void test() throws IOException {
+ Path dest = Paths.get("test");
+ HashesTest ht = new HashesTest(dest);
- @BeforeTest
- private void setup() throws Exception {
- if (Files.exists(jmods)) {
- deleteDirectory(jmods);
- }
- Files.createDirectories(jmods);
+ // create modules for test cases
+ ht.makeModule("m2");
+ ht.makeModule("m3");
+ ht.makeModule("m1", "m2", "m3");
+
+ ht.makeModule("org.bar", TRANSITIVE, "m1");
+ ht.makeModule("org.foo", TRANSITIVE, "org.bar");
+
+ // create JMOD for m1, m2, m3
+ ht.makeJmod("m2");
+ ht.makeJmod("m3");
+
+ // no hash is recorded since m1 has outgoing edges
+ ht.jmodHashModules("m1", ".*");
+
+ // no hash is recorded in m1, m2, m3
+ assertTrue(ht.hashes("m1") == null);
+ assertTrue(ht.hashes("m2") == null);
+ assertTrue(ht.hashes("m3") == null);
+
+ // hash m1 in m2
+ ht.jmodHashModules("m2", "m1");
+ ht.checkHashes("m2", "m1");
+
+ // hash m1 in m2
+ ht.jmodHashModules("m2", ".*");
+ ht.checkHashes("m2", "m1");
- // build m2, m3 required by m1
- compileModule("m2", modSrc);
- jmod("m2");
+ // create m2.jmod with no hash
+ ht.makeJmod("m2");
+ // run jmod hash command to hash m1 in m2 and m3
+ runJmod(List.of("hash", "--module-path", ht.lib.toString(),
+ "--hash-modules", ".*"));
+ ht.checkHashes("m2", "m1");
+ ht.checkHashes("m3", "m1");
+
+ // check transitive requires
+ ht.makeJmod("org.bar");
+ ht.makeJmod("org.foo");
- compileModule("m3", modSrc);
- jmod("m3");
+ ht.jmodHashModules("org.bar", "org.*");
+ ht.checkHashes("org.bar", "org.foo");
+
+ ht.jmodHashModules( "m3", ".*");
+ ht.checkHashes("m3", "org.foo", "org.bar", "m1");
+ }
+
+ @Test
+ public static void multiBaseModules() throws IOException {
+ Path dest = Paths.get("test2");
+ HashesTest ht = new HashesTest(dest);
- // build m1
- compileModule("m1", modSrc);
- // no hash is recorded since m1 has outgoing edges
- jmod("m1", "--module-path", jmods.toString(), "--hash-modules", ".*");
+ /*
+ * y2 -----------> y1
+ * |______
+ * | |
+ * V V
+ * z3 -> z2
+ * | |
+ * | V
+ * |---> z1
+ */
+
+ ht.makeModule("z1");
+ ht.makeModule("z2", "z1");
+ ht.makeModule("z3", "z1", "z2");
+
+ ht.makeModule("y1");
+ ht.makeModule("y2", "y1", "z2", "z3");
- // compile org.bar and org.foo
- compileModule("org.bar", modSrc);
- compileModule("org.foo", modSrc);
+ Set<String> ys = Set.of("y1", "y2");
+ Set<String> zs = Set.of("z1", "z2", "z3");
+
+ // create JMOD files
+ Stream.concat(ys.stream(), zs.stream()).forEach(ht::makeJmod);
+
+ // run jmod hash command
+ runJmod(List.of("hash", "--module-path", ht.lib.toString(),
+ "--hash-modules", ".*"));
+
+ /*
+ * z1 and y1 are the modules with hashes recorded.
+ */
+ ht.checkHashes("y1", "y2");
+ ht.checkHashes("z1", "z2", "z3", "y2");
+ Stream.concat(ys.stream(), zs.stream())
+ .filter(mn -> !mn.equals("y1") && !mn.equals("z1"))
+ .forEach(mn -> assertTrue(ht.hashes(mn) == null));
}
@Test
- public void test() throws Exception {
- for (String mn : modules) {
- assertTrue(hashes(mn) == null);
+ public static void mixJmodAndJarFile() throws IOException {
+ Path dest = Paths.get("test3");
+ HashesTest ht = new HashesTest(dest);
+
+ /*
+ * j3 -----------> j2
+ * |______
+ * | |
+ * V V
+ * m3 -> m2
+ * | |
+ * | V
+ * |---> m1 -> j1 -> jdk.jlink
+ */
+
+ ht.makeModule("j1");
+ ht.makeModule("j2");
+ ht.makeModule("m1", "j1");
+ ht.makeModule("m2", "m1");
+ ht.makeModule("m3", "m1", "m2");
+
+ ht.makeModule("j3", "j2", "m2", "m3");
+
+ Set<String> jars = Set.of("j1", "j2", "j3");
+ Set<String> jmods = Set.of("m1", "m2", "m3");
+
+ // create JMOD and JAR files
+ jars.forEach(ht::makeJar);
+ jmods.forEach(ht::makeJmod);
+
+ // run jmod hash command
+ runJmod(List.of("hash", "--module-path", ht.lib.toString(),
+ "--hash-modules", "^j.*|^m.*"));
+
+ /*
+ * j1 and j2 are the modules with hashes recorded.
+ */
+ ht.checkHashes("j2", "j3");
+ ht.checkHashes("j1", "m1", "m2", "m3", "j3");
+ Stream.concat(jars.stream(), jmods.stream())
+ .filter(mn -> !mn.equals("j1") && !mn.equals("j2"))
+ .forEach(mn -> assertTrue(ht.hashes(mn) == null));
+ }
+
+ @Test
+ public static void upgradeableModule() throws IOException {
+ Path mpath = Paths.get(System.getProperty("java.home"), "jmods");
+ if (!Files.exists(mpath)) {
+ return;
}
- // hash m1 in m2
- jmod("m2", "--module-path", jmods.toString(), "--hash-modules", "m1");
- checkHashes(hashes("m2"), "m1");
-
- // hash m1 in m2
- jmod("m2", "--module-path", jmods.toString(), "--hash-modules", ".*");
- checkHashes(hashes("m2"), "m1");
+ Path dest = Paths.get("test4");
+ HashesTest ht = new HashesTest(dest);
+ ht.makeModule("m1");
+ ht.makeModule("java.xml.bind", "m1");
+ ht.makeModule("java.xml.ws", "java.xml.bind");
+ ht.makeModule("m2", "java.xml.ws");
- // create m2.jmod with no hash
- jmod("m2");
- // run jmod hash command to hash m1 in m2 and m3
- runJmod(Arrays.asList("hash", "--module-path", jmods.toString(),
- "--hash-modules", ".*"));
- checkHashes(hashes("m2"), "m1");
- checkHashes(hashes("m3"), "m1");
+ ht.makeJmod("m1");
+ ht.makeJmod("m2");
+ ht.makeJmod("java.xml.ws");
+ ht.makeJmod("java.xml.bind",
+ "--module-path",
+ ht.lib.toString() + File.pathSeparator + mpath,
+ "--hash-modules", "^java.xml.*|^m.*");
- jmod("org.bar");
- jmod("org.foo");
-
- jmod("org.bar", "--module-path", jmods.toString(), "--hash-modules", "org.*");
- checkHashes(hashes("org.bar"), "org.foo");
-
- jmod("m3", "--module-path", jmods.toString(), "--hash-modules", ".*");
- checkHashes(hashes("m3"), "org.foo", "org.bar", "m1");
+ ht.checkHashes("java.xml.bind", "java.xml.ws", "m2");
}
- private void checkHashes(ModuleHashes hashes, String... hashModules) {
+ @Test
+ public static void testImageJmods() throws IOException {
+ Path mpath = Paths.get(System.getProperty("java.home"), "jmods");
+ if (!Files.exists(mpath)) {
+ return;
+ }
+
+ Path dest = Paths.get("test5");
+ HashesTest ht = new HashesTest(dest);
+ ht.makeModule("m1", "jdk.compiler", "jdk.attach");
+ ht.makeModule("m2", "m1");
+ ht.makeModule("m3", "java.compiler");
+
+ ht.makeJmod("m1");
+ ht.makeJmod("m2");
+
+ runJmod(List.of("hash",
+ "--module-path",
+ mpath.toString() + File.pathSeparator + ht.lib.toString(),
+ "--hash-modules", ".*"));
+
+ validateImageJmodsTest(ht, mpath);
+ }
+
+ @Test
+ public static void testImageJmods1() throws IOException {
+ Path mpath = Paths.get(System.getProperty("java.home"), "jmods");
+ if (!Files.exists(mpath)) {
+ return;
+ }
+
+ Path dest = Paths.get("test6");
+ HashesTest ht = new HashesTest(dest);
+ ht.makeModule("m1", "jdk.compiler", "jdk.attach");
+ ht.makeModule("m2", "m1");
+ ht.makeModule("m3", "java.compiler");
+
+ ht.makeJar("m2");
+ ht.makeJar("m1",
+ "--module-path",
+ mpath.toString() + File.pathSeparator + ht.lib.toString(),
+ "--hash-modules", ".*");
+ validateImageJmodsTest(ht, mpath);
+ }
+
+ private static void validateImageJmodsTest(HashesTest ht, Path mpath)
+ throws IOException
+ {
+ // hash is recorded in m1 and not any other packaged modules on module path
+ ht.checkHashes("m1", "m2");
+ assertTrue(ht.hashes("m2") == null);
+
+ // should not override any JDK packaged modules
+ ModuleFinder finder = new ModulePath(Runtime.version(),
+ true,
+ mpath);
+ assertTrue(ht.hashes(finder,"jdk.compiler") == null);
+ assertTrue(ht.hashes(finder,"jdk.attach") == null);
+ }
+
+ private void checkHashes(String mn, String... hashModules) throws IOException {
+ ModuleHashes hashes = hashes(mn);
assertTrue(hashes.names().equals(Set.of(hashModules)));
}
- private ModuleHashes hashes(String name) throws Exception {
+ private ModuleHashes hashes(String name) {
ModuleFinder finder = new ModulePath(Runtime.version(),
true,
- jmods.resolve(name + ".jmod"));
+ lib);
+ return hashes(finder, name);
+ }
+
+ private ModuleHashes hashes(ModuleFinder finder, String name) {
ModuleReference mref = finder.find(name).orElseThrow(RuntimeException::new);
- ModuleReader reader = mref.open();
- try (InputStream in = reader.open("module-info.class").get()) {
- ModuleHashes hashes = ModuleInfo.read(in, null).recordedHashes();
- System.out.format("hashes in module %s %s%n", name,
+ try {
+ ModuleReader reader = mref.open();
+ try (InputStream in = reader.open("module-info.class").get()) {
+ ModuleHashes hashes = ModuleInfo.read(in, null).recordedHashes();
+ System.out.format("hashes in module %s %s%n", name,
(hashes != null) ? "present" : "absent");
- if (hashes != null) {
- hashes.names().stream()
- .sorted()
- .forEach(n -> System.out.format(" %s %s%n", n, hashes.hashFor(n)));
+ if (hashes != null) {
+ hashes.names().stream().sorted().forEach(n ->
+ System.out.format(" %s %s%n", n, toHex(hashes.hashFor(n)))
+ );
+ }
+ return hashes;
+ } finally {
+ reader.close();
}
- return hashes;
- } finally {
- reader.close();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
}
}
+ private String toHex(byte[] ba) {
+ StringBuilder sb = new StringBuilder(ba.length);
+ for (byte b: ba) {
+ sb.append(String.format("%02x", b & 0xff));
+ }
+ return sb.toString();
+ }
+
private void deleteDirectory(Path dir) throws IOException {
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
@Override
@@ -176,31 +381,94 @@
});
}
+
+ private void makeModule(String mn, String... deps) throws IOException {
+ makeModule(mn, null, deps);
+ }
+
+ private void makeModule(String mn, ModuleDescriptor.Requires.Modifier mod, String... deps)
+ throws IOException
+ {
+ if (mod != null && mod != TRANSITIVE && mod != STATIC) {
+ throw new IllegalArgumentException(mod.toString());
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("module " + mn + " {").append("\n");
+ Arrays.stream(deps).forEach(req -> {
+ sb.append(" requires ");
+ if (mod != null) {
+ sb.append(mod.toString().toLowerCase()).append(" ");
+ }
+ sb.append(req + ";\n");
+ });
+ sb.append("}\n");
+ builder.writeJavaFiles(mn, sb.toString());
+
+ compileModule(mn, srcDir);
+ }
+
private void compileModule(String moduleName, Path src) throws IOException {
Path msrc = src.resolve(moduleName);
assertTrue(CompilerUtils.compile(msrc, mods, "--module-source-path", src.toString()));
}
- private void jmod(String moduleName, String... options) throws IOException {
+ private void jmodHashModules(String moduleName, String hashModulesPattern) {
+ makeJmod(moduleName, "--module-path", lib.toString(),
+ "--hash-modules", hashModulesPattern);
+ }
+
+ private void makeJmod(String moduleName, String... options) {
Path mclasses = mods.resolve(moduleName);
- Path outfile = jmods.resolve(moduleName + ".jmod");
+ Path outfile = lib.resolve(moduleName + ".jmod");
List<String> args = new ArrayList<>();
args.add("create");
Collections.addAll(args, options);
Collections.addAll(args, "--class-path", mclasses.toString(),
outfile.toString());
- if (Files.exists(outfile))
- Files.delete(outfile);
-
+ if (Files.exists(outfile)) {
+ try {
+ Files.delete(outfile);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
runJmod(args);
}
- private void runJmod(List<String> args) {
+ private static void runJmod(List<String> args) {
int rc = JMOD_TOOL.run(System.out, System.out, args.toArray(new String[args.size()]));
- System.out.println("jmod options: " + args.stream().collect(Collectors.joining(" ")));
+ System.out.println("jmod " + args.stream().collect(Collectors.joining(" ")));
if (rc != 0) {
- throw new AssertionError("Jmod failed: rc = " + rc);
+ throw new AssertionError("jmod failed: rc = " + rc);
+ }
+ }
+
+ private void makeJar(String moduleName, String... options) {
+ Path mclasses = mods.resolve(moduleName);
+ Path outfile = lib.resolve(moduleName + ".jar");
+ List<String> args = new ArrayList<>();
+ Stream.concat(Stream.of("--create",
+ "--file=" + outfile.toString()),
+ Arrays.stream(options))
+ .forEach(args::add);
+ args.add("-C");
+ args.add(mclasses.toString());
+ args.add(".");
+
+ if (Files.exists(outfile)) {
+ try {
+ Files.delete(outfile);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ int rc = JAR_TOOL.run(System.out, System.out, args.toArray(new String[args.size()]));
+ System.out.println("jar " + args.stream().collect(Collectors.joining(" ")));
+ if (rc != 0) {
+ throw new AssertionError("jar failed: rc = " + rc);
}
}
}
--- a/jdk/test/tools/jmod/hashes/src/m1/module-info.java Tue Jan 17 18:24:28 2017 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-module m1 {
- requires m2;
- requires m3;
-}
--- a/jdk/test/tools/jmod/hashes/src/m1/org/m1/Main.java Tue Jan 17 18:24:28 2017 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.m1;
-
-import org.m2.Util;
-import org.m3.Name;
-
-public class Main {
- public static void main(String[] args) {
- System.out.println(Util.timeOfDay());
- System.out.println(Name.name());
- }
-}
--- a/jdk/test/tools/jmod/hashes/src/m2/module-info.java Tue Jan 17 18:24:28 2017 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-module m2 {
- exports org.m2;
-}
--- a/jdk/test/tools/jmod/hashes/src/m2/org/m2/Util.java Tue Jan 17 18:24:28 2017 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.m2;
-
-public class Util {
- private Util() { }
-
- public static String timeOfDay() {
- return "Time for lunch";
- }
-}
--- a/jdk/test/tools/jmod/hashes/src/m3/module-info.java Tue Jan 17 18:24:28 2017 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-module m3 {
- exports org.m3;
-}
--- a/jdk/test/tools/jmod/hashes/src/m3/org/m3/Name.java Tue Jan 17 18:24:28 2017 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.m3;
-
-public class Name {
- private Name() { }
-
- public static String name() {
- return "m3";
- }
-}
--- a/jdk/test/tools/jmod/hashes/src/org.bar/module-info.java Tue Jan 17 18:24:28 2017 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +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.
- */
-
-module org.bar {
- requires transitive m1;
-}
--- a/jdk/test/tools/jmod/hashes/src/org.foo/module-info.java Tue Jan 17 18:24:28 2017 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +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.
- */
-
-module org.foo {
- requires transitive org.bar;
-}