--- a/jdk/make/ModuleTools.gmk Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/make/ModuleTools.gmk Thu Jan 19 07:02:33 2017 -0800
@@ -39,7 +39,6 @@
build.tools.jigsaw.GenGraphs
TOOL_MODULESUMMARY := $(BUILD_JAVA) -esa -ea -cp $(TOOLS_CLASSES_DIR) \
- --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED \
build.tools.jigsaw.ModuleSummary
TOOL_ADD_PACKAGES_ATTRIBUTE := $(BUILD_JAVA) $(JAVA_FLAGS_SMALL) \
--- a/jdk/src/java.base/share/classes/java/lang/Class.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java Thu Jan 19 07:02:33 2017 -0800
@@ -508,8 +508,9 @@
public T newInstance()
throws InstantiationException, IllegalAccessException
{
- if (System.getSecurityManager() != null) {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), false);
}
// NOTE: the following code may not be strictly correct under
@@ -1223,38 +1224,27 @@
// Perform access check
final Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
- enclosingCandidate.checkMemberAccess(Member.DECLARED,
- Reflection.getCallerClass(), true);
- // Client is ok to access declared methods but j.l.Class might not be.
- Method[] candidates = AccessController.doPrivileged(
- new PrivilegedAction<>() {
- @Override
- public Method[] run() {
- return enclosingCandidate.getDeclaredMethods();
- }
- });
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ enclosingCandidate.checkMemberAccess(sm, Member.DECLARED,
+ Reflection.getCallerClass(), true);
+ }
+ Method[] candidates = enclosingCandidate.privateGetDeclaredMethods(false);
+
/*
* Loop over all declared methods; match method name,
* number of and type of parameters, *and* return
* type. Matching return type is also necessary
* because of covariant returns, etc.
*/
- for(Method m: candidates) {
- if (m.getName().equals(enclosingInfo.getName()) ) {
- Class<?>[] candidateParamClasses = m.getParameterTypes();
- if (candidateParamClasses.length == parameterClasses.length) {
- boolean matches = true;
- for(int i = 0; i < candidateParamClasses.length; i++) {
- if (!candidateParamClasses[i].equals(parameterClasses[i])) {
- matches = false;
- break;
- }
- }
-
- if (matches) { // finally, check return type
- if (m.getReturnType().equals(returnType) )
- return m;
- }
+ ReflectionFactory fact = getReflectionFactory();
+ for (Method m : candidates) {
+ if (m.getName().equals(enclosingInfo.getName()) &&
+ arrayContentsEq(parameterClasses,
+ fact.getExecutableSharedParameterTypes(m))) {
+ // finally, check return type
+ if (m.getReturnType().equals(returnType)) {
+ return fact.copyMethod(m);
}
}
}
@@ -1390,33 +1380,23 @@
// Perform access check
final Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
- enclosingCandidate.checkMemberAccess(Member.DECLARED,
- Reflection.getCallerClass(), true);
- // Client is ok to access declared methods but j.l.Class might not be.
- Constructor<?>[] candidates = AccessController.doPrivileged(
- new PrivilegedAction<>() {
- @Override
- public Constructor<?>[] run() {
- return enclosingCandidate.getDeclaredConstructors();
- }
- });
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ enclosingCandidate.checkMemberAccess(sm, Member.DECLARED,
+ Reflection.getCallerClass(), true);
+ }
+
+ Constructor<?>[] candidates = enclosingCandidate
+ .privateGetDeclaredConstructors(false);
/*
* Loop over all declared constructors; match number
* of and type of parameters.
*/
- for(Constructor<?> c: candidates) {
- Class<?>[] candidateParamClasses = c.getParameterTypes();
- if (candidateParamClasses.length == parameterClasses.length) {
- boolean matches = true;
- for(int i = 0; i < candidateParamClasses.length; i++) {
- if (!candidateParamClasses[i].equals(parameterClasses[i])) {
- matches = false;
- break;
- }
- }
-
- if (matches)
- return c;
+ ReflectionFactory fact = getReflectionFactory();
+ for (Constructor<?> c : candidates) {
+ if (arrayContentsEq(parameterClasses,
+ fact.getExecutableSharedParameterTypes(c))) {
+ return fact.copyConstructor(c);
}
}
@@ -1446,9 +1426,13 @@
public Class<?> getDeclaringClass() throws SecurityException {
final Class<?> candidate = getDeclaringClass0();
- if (candidate != null)
- candidate.checkPackageAccess(
+ if (candidate != null) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ candidate.checkPackageAccess(sm,
ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
+ }
+ }
return candidate;
}
@@ -1496,9 +1480,13 @@
enclosingCandidate = enclosingClass;
}
- if (enclosingCandidate != null)
- enclosingCandidate.checkPackageAccess(
+ if (enclosingCandidate != null) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ enclosingCandidate.checkPackageAccess(sm,
ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
+ }
+ }
return enclosingCandidate;
}
@@ -1688,7 +1676,10 @@
*/
@CallerSensitive
public Class<?>[] getClasses() {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), false);
+ }
// Privileged so this implementation can look at DECLARED classes,
// something the caller might not have privilege to do. The code here
@@ -1754,7 +1745,10 @@
*/
@CallerSensitive
public Field[] getFields() throws SecurityException {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
return copyFields(privateGetPublicFields(null));
}
@@ -1841,7 +1835,10 @@
*/
@CallerSensitive
public Method[] getMethods() throws SecurityException {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
return copyMethods(privateGetPublicMethods());
}
@@ -1877,7 +1874,10 @@
*/
@CallerSensitive
public Constructor<?>[] getConstructors() throws SecurityException {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
return copyConstructors(privateGetDeclaredConstructors(true));
}
@@ -1928,7 +1928,10 @@
public Field getField(String name)
throws NoSuchFieldException, SecurityException {
Objects.requireNonNull(name);
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
Field field = getField0(name);
if (field == null) {
throw new NoSuchFieldException(name);
@@ -2034,10 +2037,13 @@
public Method getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
Objects.requireNonNull(name);
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
Method method = getMethod0(name, parameterTypes);
if (method == null) {
- throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
+ throw new NoSuchMethodException(methodToString(name, parameterTypes));
}
return getReflectionFactory().copyMethod(method);
}
@@ -2092,8 +2098,12 @@
*/
@CallerSensitive
public Constructor<T> getConstructor(Class<?>... parameterTypes)
- throws NoSuchMethodException, SecurityException {
- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
+ throws NoSuchMethodException, SecurityException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
+ }
return getReflectionFactory().copyConstructor(
getConstructor0(parameterTypes, Member.PUBLIC));
}
@@ -2136,7 +2146,10 @@
*/
@CallerSensitive
public Class<?>[] getDeclaredClasses() throws SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), false);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), false);
+ }
return getDeclaredClasses0();
}
@@ -2185,7 +2198,10 @@
*/
@CallerSensitive
public Field[] getDeclaredFields() throws SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
return copyFields(privateGetDeclaredFields(false));
}
@@ -2244,7 +2260,10 @@
*/
@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
return copyMethods(privateGetDeclaredMethods(false));
}
@@ -2289,7 +2308,10 @@
*/
@CallerSensitive
public Constructor<?>[] getDeclaredConstructors() throws SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
return copyConstructors(privateGetDeclaredConstructors(false));
}
@@ -2338,7 +2360,10 @@
public Field getDeclaredField(String name)
throws NoSuchFieldException, SecurityException {
Objects.requireNonNull(name);
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
Field field = searchFields(privateGetDeclaredFields(false), name);
if (field == null) {
throw new NoSuchFieldException(name);
@@ -2399,10 +2424,13 @@
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
Objects.requireNonNull(name);
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) {
- throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
+ throw new NoSuchMethodException(methodToString(name, parameterTypes));
}
return getReflectionFactory().copyMethod(method);
}
@@ -2448,8 +2476,13 @@
*/
@CallerSensitive
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
- throws NoSuchMethodException, SecurityException {
- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
+ throws NoSuchMethodException, SecurityException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
+ }
+
return getReflectionFactory().copyConstructor(
getConstructor0(parameterTypes, Member.DECLARED));
}
@@ -2697,51 +2730,49 @@
*
* <p> Default policy: allow all clients access with normal Java access
* control.
+ *
+ * <p> NOTE: should only be called if a SecurityManager is installed
*/
- private void checkMemberAccess(int which, Class<?> caller, boolean checkProxyInterfaces) {
- final SecurityManager s = System.getSecurityManager();
- if (s != null) {
- /* Default policy allows access to all {@link Member#PUBLIC} members,
- * as well as access to classes that have the same class loader as the caller.
- * In all other cases, it requires RuntimePermission("accessDeclaredMembers")
- * permission.
- */
- final ClassLoader ccl = ClassLoader.getClassLoader(caller);
+ private void checkMemberAccess(SecurityManager sm, int which,
+ Class<?> caller, boolean checkProxyInterfaces) {
+ /* Default policy allows access to all {@link Member#PUBLIC} members,
+ * as well as access to classes that have the same class loader as the caller.
+ * In all other cases, it requires RuntimePermission("accessDeclaredMembers")
+ * permission.
+ */
+ final ClassLoader ccl = caller.getClassLoader0();
+ if (which != Member.PUBLIC) {
final ClassLoader cl = getClassLoader0();
- if (which != Member.PUBLIC) {
- if (ccl != cl) {
- s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
- }
+ if (ccl != cl) {
+ sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
}
- this.checkPackageAccess(ccl, checkProxyInterfaces);
}
+ this.checkPackageAccess(sm, ccl, checkProxyInterfaces);
}
/*
* Checks if a client loaded in ClassLoader ccl is allowed to access this
* class under the current package access policy. If access is denied,
* throw a SecurityException.
+ *
+ * NOTE: this method should only be called if a SecurityManager is active
*/
- private void checkPackageAccess(final ClassLoader ccl, boolean checkProxyInterfaces) {
- final SecurityManager s = System.getSecurityManager();
- if (s != null) {
- final ClassLoader cl = getClassLoader0();
-
- if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
- String name = this.getName();
- int i = name.lastIndexOf('.');
- if (i != -1) {
- // skip the package access check on a proxy class in default proxy package
- String pkg = name.substring(0, i);
- if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) {
- s.checkPackageAccess(pkg);
- }
+ private void checkPackageAccess(SecurityManager sm, final ClassLoader ccl,
+ boolean checkProxyInterfaces) {
+ final ClassLoader cl = getClassLoader0();
+
+ if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
+ String pkg = this.getPackageName();
+ if (pkg != null && !pkg.isEmpty()) {
+ // skip the package access check on a proxy class in default proxy package
+ if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) {
+ sm.checkPackageAccess(pkg);
}
}
- // check package access on the proxy interfaces
- if (checkProxyInterfaces && Proxy.isProxyClass(this)) {
- ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces());
- }
+ }
+ // check package access on the proxy interfaces
+ if (checkProxyInterfaces && Proxy.isProxyClass(this)) {
+ ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces());
}
}
@@ -2755,11 +2786,9 @@
while (c.isArray()) {
c = c.getComponentType();
}
- String baseName = c.getName();
- int index = baseName.lastIndexOf('.');
- if (index != -1) {
- name = baseName.substring(0, index).replace('.', '/')
- +"/"+name;
+ String baseName = c.getPackageName();
+ if (baseName != null && !baseName.isEmpty()) {
+ name = baseName.replace('.', '/') + "/" + name;
}
} else {
name = name.substring(1);
@@ -3233,7 +3262,7 @@
return constructor;
}
}
- throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
+ throw new NoSuchMethodException(methodToString("<init>", parameterTypes));
}
//
@@ -3294,8 +3323,11 @@
private native Constructor<T>[] getDeclaredConstructors0(boolean publicOnly);
private native Class<?>[] getDeclaredClasses0();
- private static String argumentTypesToString(Class<?>[] argTypes) {
- StringJoiner sj = new StringJoiner(", ", "(", ")");
+ /**
+ * Helper method to get the method name from arguments.
+ */
+ private String methodToString(String name, Class<?>[] argTypes) {
+ StringJoiner sj = new StringJoiner(", ", getName() + "." + name + "(", ")");
if (argTypes != null) {
for (int i = 0; i < argTypes.length; i++) {
Class<?> c = argTypes[i];
--- a/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java Thu Jan 19 07:02:33 2017 -0800
@@ -28,6 +28,8 @@
import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+import jdk.internal.vm.annotation.Stable;
+
/**
* A {@code CallSite} is a holder for a variable {@link MethodHandle},
* which is called its {@code target}.
@@ -215,19 +217,36 @@
public abstract MethodHandle dynamicInvoker();
/*non-public*/ MethodHandle makeDynamicInvoker() {
- MethodHandle getTarget = GET_TARGET.bindArgumentL(0, this);
+ MethodHandle getTarget = getTargetHandle().bindArgumentL(0, this);
MethodHandle invoker = MethodHandles.exactInvoker(this.type());
return MethodHandles.foldArguments(invoker, getTarget);
}
- private static final MethodHandle GET_TARGET;
- private static final MethodHandle THROW_UCS;
- static {
+ private static @Stable MethodHandle GET_TARGET;
+ private static MethodHandle getTargetHandle() {
+ MethodHandle handle = GET_TARGET;
+ if (handle != null) {
+ return handle;
+ }
try {
- GET_TARGET = IMPL_LOOKUP.
- findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
- THROW_UCS = IMPL_LOOKUP.
- findStatic(CallSite.class, "uninitializedCallSite", MethodType.methodType(Object.class, Object[].class));
+ return GET_TARGET = IMPL_LOOKUP.
+ findVirtual(CallSite.class, "getTarget",
+ MethodType.methodType(MethodHandle.class));
+ } catch (ReflectiveOperationException e) {
+ throw newInternalError(e);
+ }
+ }
+
+ private static @Stable MethodHandle THROW_UCS;
+ private static MethodHandle uninitializedCallSiteHandle() {
+ MethodHandle handle = THROW_UCS;
+ if (handle != null) {
+ return handle;
+ }
+ try {
+ return THROW_UCS = IMPL_LOOKUP.
+ findStatic(CallSite.class, "uninitializedCallSite",
+ MethodType.methodType(Object.class, Object[].class));
} catch (ReflectiveOperationException e) {
throw newInternalError(e);
}
@@ -242,7 +261,7 @@
MethodType basicType = targetType.basicType();
MethodHandle invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_UNINIT_CS);
if (invoker == null) {
- invoker = THROW_UCS.asType(basicType);
+ invoker = uninitializedCallSiteHandle().asType(basicType);
invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_UNINIT_CS, invoker);
}
// unchecked view is OK since no values will be received or returned
@@ -250,12 +269,16 @@
}
// unsafe stuff:
- private static final long TARGET_OFFSET;
- private static final long CONTEXT_OFFSET;
- static {
+ private static @Stable long TARGET_OFFSET;
+ private static long getTargetOffset() {
+ long offset = TARGET_OFFSET;
+ if (offset > 0) {
+ return offset;
+ }
try {
- TARGET_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("target"));
- CONTEXT_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("context"));
+ offset = TARGET_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("target"));
+ assert(offset > 0);
+ return offset;
} catch (Exception ex) { throw newInternalError(ex); }
}
@@ -265,7 +288,7 @@
}
/*package-private*/
MethodHandle getTargetVolatile() {
- return (MethodHandle) UNSAFE.getObjectVolatile(this, TARGET_OFFSET);
+ return (MethodHandle) UNSAFE.getObjectVolatile(this, getTargetOffset());
}
/*package-private*/
void setTargetVolatile(MethodHandle newTarget) {
@@ -324,7 +347,7 @@
final int NON_SPREAD_ARG_COUNT = 3; // (caller, name, type)
if (NON_SPREAD_ARG_COUNT + argv.length > MethodType.MAX_MH_ARITY)
throw new BootstrapMethodError("too many bootstrap method arguments");
- MethodType bsmType = bootstrapMethod.type();
+
MethodType invocationType = MethodType.genericMethodType(NON_SPREAD_ARG_COUNT + argv.length);
MethodHandle typedBSM = bootstrapMethod.asType(invocationType);
MethodHandle spreader = invocationType.invokers().spreadInvoker(NON_SPREAD_ARG_COUNT);
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java Thu Jan 19 07:02:33 2017 -0800
@@ -1128,7 +1128,7 @@
public String toMethodDescriptorString() {
String desc = methodDescriptor;
if (desc == null) {
- desc = BytecodeDescriptor.unparse(this);
+ desc = BytecodeDescriptor.unparseMethod(this.rtype, this.ptypes);
methodDescriptor = desc;
}
return desc;
@@ -1256,7 +1256,7 @@
private final ReferenceQueue<T> stale;
public ConcurrentWeakInternSet() {
- this.map = new ConcurrentHashMap<>();
+ this.map = new ConcurrentHashMap<>(512);
this.stale = new ReferenceQueue<>();
}
--- a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/src/java.base/share/classes/java/util/ResourceBundle.java Thu Jan 19 07:02:33 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
@@ -2134,7 +2134,7 @@
/**
* Removes all resource bundles from the cache that have been loaded
- * by the caller's module using the caller's class loader.
+ * by the caller's module.
*
* @since 1.6
* @see ResourceBundle.Control#getTimeToLive(String,Locale)
@@ -2142,50 +2142,26 @@
@CallerSensitive
public static final void clearCache() {
Class<?> caller = Reflection.getCallerClass();
- clearCacheImpl(caller.getModule(), caller.getClassLoader());
+ cacheList.keySet().removeIf(
+ key -> key.getCallerModule() == caller.getModule()
+ );
}
/**
* Removes all resource bundles from the cache that have been loaded
- * by the caller's module using the given class loader.
+ * by the given class loader.
*
* @param loader the class loader
* @exception NullPointerException if <code>loader</code> is null
* @since 1.6
* @see ResourceBundle.Control#getTimeToLive(String,Locale)
*/
- @CallerSensitive
public static final void clearCache(ClassLoader loader) {
Objects.requireNonNull(loader);
- Class<?> caller = Reflection.getCallerClass();
- clearCacheImpl(caller.getModule(), loader);
- }
-
- /**
- * Removes all resource bundles from the cache that have been loaded by the
- * given {@code module}.
- *
- * @param module the module
- * @throws NullPointerException
- * if {@code module} is {@code null}
- * @throws SecurityException
- * if the caller doesn't have the permission to
- * {@linkplain Module#getClassLoader() get the class loader}
- * of the given {@code module}
- * @since 9
- * @see ResourceBundle.Control#getTimeToLive(String,Locale)
- */
- public static final void clearCache(Module module) {
- Objects.requireNonNull(module);
- clearCacheImpl(module, module.getClassLoader());
- }
-
- private static void clearCacheImpl(Module callerModule, ClassLoader loader) {
cacheList.keySet().removeIf(
key -> {
Module m;
- return key.getCallerModule() == callerModule &&
- (m = key.getModule()) != null &&
+ return (m = key.getModule()) != null &&
getLoader(m) == loader;
}
);
--- a/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java Thu Jan 19 07:02:33 2017 -0800
@@ -96,7 +96,7 @@
final Class<?> declaringClass = m.getDeclaringClass();
- checkPackageAccess(declaringClass);
+ privateCheckPackageAccess(sm, declaringClass);
if (Modifier.isPublic(m.getModifiers()) &&
Modifier.isPublic(declaringClass.getModifiers()))
@@ -114,9 +114,27 @@
* also check the package access on the proxy interfaces.
*/
public static void checkPackageAccess(Class<?> clazz) {
- checkPackageAccess(clazz.getName());
+ SecurityManager s = System.getSecurityManager();
+ if (s != null) {
+ privateCheckPackageAccess(s, clazz);
+ }
+ }
+
+ /**
+ * NOTE: should only be called if a SecurityManager is installed
+ */
+ private static void privateCheckPackageAccess(SecurityManager s, Class<?> clazz) {
+ while (clazz.isArray()) {
+ clazz = clazz.getComponentType();
+ }
+
+ String pkg = clazz.getPackageName();
+ if (pkg != null && !pkg.isEmpty()) {
+ s.checkPackageAccess(pkg);
+ }
+
if (isNonPublicProxyClass(clazz)) {
- checkProxyPackageAccess(clazz);
+ privateCheckProxyPackageAccess(s, clazz);
}
}
@@ -195,15 +213,21 @@
public static void checkProxyPackageAccess(Class<?> clazz) {
SecurityManager s = System.getSecurityManager();
if (s != null) {
- // check proxy interfaces if the given class is a proxy class
- if (Proxy.isProxyClass(clazz)) {
- for (Class<?> intf : clazz.getInterfaces()) {
- checkPackageAccess(intf);
- }
+ privateCheckProxyPackageAccess(s, clazz);
+ }
+ }
+
+ /**
+ * NOTE: should only be called if a SecurityManager is installed
+ */
+ private static void privateCheckProxyPackageAccess(SecurityManager s, Class<?> clazz) {
+ // check proxy interfaces if the given class is a proxy class
+ if (Proxy.isProxyClass(clazz)) {
+ for (Class<?> intf : clazz.getInterfaces()) {
+ privateCheckPackageAccess(s, intf);
}
}
}
-
/**
* Access check on the interfaces that a proxy class implements and throw
* {@code SecurityException} if it accesses a restricted package from
@@ -220,7 +244,7 @@
for (Class<?> intf : interfaces) {
ClassLoader cl = intf.getClassLoader();
if (needsPackageAccessCheck(ccl, cl)) {
- checkPackageAccess(intf);
+ privateCheckPackageAccess(sm, intf);
}
}
}
@@ -236,10 +260,11 @@
* package that bypasses checkPackageAccess.
*/
public static boolean isNonPublicProxyClass(Class<?> cls) {
- String name = cls.getName();
- int i = name.lastIndexOf('.');
- String pkg = (i != -1) ? name.substring(0, i) : "";
- return Proxy.isProxyClass(cls) && !pkg.startsWith(PROXY_PACKAGE);
+ if (!Proxy.isProxyClass(cls)) {
+ return false;
+ }
+ String pkg = cls.getPackageName();
+ return pkg == null || !pkg.startsWith(PROXY_PACKAGE);
}
/**
@@ -255,7 +280,7 @@
// check if it is a valid proxy instance
if (proxy == null || !Proxy.isProxyClass(proxy.getClass())) {
throw new IllegalArgumentException("Not a Proxy instance");
-}
+ }
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalArgumentException("Can't handle static method");
}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java Thu Jan 19 07:02:33 2017 -0800
@@ -165,18 +165,9 @@
throw new PluginException("TargetPlatform attribute is missing for java.base module");
}
- Path bin = root.resolve(BIN_DIRNAME);
+ checkResourcePool(files);
- // check any duplicated resource files
- Map<Path, Set<String>> duplicates = new HashMap<>();
- files.entries()
- .filter(f -> f.type() != ResourcePoolEntry.Type.CLASS_OR_RESOURCE)
- .collect(groupingBy(this::entryToImagePath,
- mapping(ResourcePoolEntry::moduleName, toSet())))
- .entrySet()
- .stream()
- .filter(e -> e.getValue().size() > 1)
- .forEach(e -> duplicates.put(e.getKey(), e.getValue()));
+ Path bin = root.resolve(BIN_DIRNAME);
// write non-classes resource files to the image
files.entries()
@@ -185,13 +176,8 @@
try {
accept(f);
} catch (FileAlreadyExistsException e) {
- // error for duplicated entries
- Path path = entryToImagePath(f);
- UncheckedIOException x =
- new UncheckedIOException(path + " duplicated in " +
- duplicates.get(path), e);
- x.addSuppressed(e);
- throw x;
+ // Should not happen! Duplicates checking already done!
+ throw new AssertionError("Duplicate entry!", e);
} catch (IOException ioExp) {
throw new UncheckedIOException(ioExp);
}
@@ -242,6 +228,27 @@
}
}
+ private void checkResourcePool(ResourcePool pool) {
+ // For now, only duplicate resources check. Add more checks here (if any)
+ checkDuplicateResources(pool);
+ }
+
+ private void checkDuplicateResources(ResourcePool pool) {
+ // check any duplicated resources
+ Map<Path, Set<String>> duplicates = new HashMap<>();
+ pool.entries()
+ .filter(f -> f.type() != ResourcePoolEntry.Type.CLASS_OR_RESOURCE)
+ .collect(groupingBy(this::entryToImagePath,
+ mapping(ResourcePoolEntry::moduleName, toSet())))
+ .entrySet()
+ .stream()
+ .filter(e -> e.getValue().size() > 1)
+ .forEach(e -> duplicates.put(e.getKey(), e.getValue()));
+ if (!duplicates.isEmpty()) {
+ throw new PluginException("Duplicate resources: " + duplicates);
+ }
+ }
+
/**
* Generates launcher scripts.
*
--- a/jdk/src/jdk.jlink/share/classes/module-info.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/src/jdk.jlink/share/classes/module-info.java Thu Jan 19 07:02:33 2017 -0800
@@ -24,8 +24,6 @@
*/
module jdk.jlink {
- exports jdk.tools.jlink.plugin;
-
requires jdk.internal.opt;
requires jdk.jdeps;
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java Thu Jan 19 07:02:33 2017 -0800
@@ -135,7 +135,7 @@
TreeMap<Integer,IndexNode> map = new TreeMap<>();
IndexNode child = metaInfVersions.child;
while (child != null) {
- Integer key = getVersion(child.name, metaInfVersions.name.length);
+ Integer key = getVersion(child.name, metaInfVersions.name.length + 1);
if (key != null && key <= version) {
map.put(key, child);
}
@@ -149,7 +149,7 @@
*/
private Integer getVersion(byte[] name, int offset) {
try {
- return Integer.parseInt(getString(Arrays.copyOfRange(name, offset, name.length-1)));
+ return Integer.parseInt(getString(Arrays.copyOfRange(name, offset, name.length)));
} catch (NumberFormatException x) {
// ignore this even though it might indicate issues with the JAR structure
return null;
@@ -176,7 +176,7 @@
* returns foo/bar.class
*/
private byte[] getRootName(IndexNode prefix, IndexNode inode) {
- int offset = prefix.name.length - 1;
+ int offset = prefix.name.length;
byte[] fullName = inode.name;
return Arrays.copyOfRange(fullName, offset, fullName.length);
}
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipCoder.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipCoder.java Thu Jan 19 07:02:33 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2014, 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
@@ -34,97 +34,95 @@
import java.nio.charset.CodingErrorAction;
import java.util.Arrays;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.nio.charset.StandardCharsets.ISO_8859_1;
+
/**
* Utility class for zipfile name and comment decoding and encoding
*
* @author Xueming Shen
*/
-final class ZipCoder {
+class ZipCoder {
+
+ static class UTF8 extends ZipCoder {
+ UTF8() {
+ super(UTF_8);
+ }
+
+ @Override
+ byte[] getBytes(String s) { // fast pass for ascii
+ for (int i = 0; i < s.length(); i++) {
+ if (s.charAt(i) > 0x7f) return super.getBytes(s);
+ }
+ return s.getBytes(ISO_8859_1);
+ }
- String toString(byte[] ba, int length) {
+ @Override
+ String toString(byte[] ba) {
+ for (byte b : ba) {
+ if (b < 0) return super.toString(ba);
+ }
+ return new String(ba, ISO_8859_1);
+ }
+ }
+
+ private static ZipCoder utf8 = new UTF8();
+
+ public static ZipCoder get(String csn) {
+ Charset cs = Charset.forName(csn);
+ if (cs.name().equals("UTF-8")) {
+ return utf8;
+ }
+ return new ZipCoder(cs);
+ }
+
+ String toString(byte[] ba) {
CharsetDecoder cd = decoder().reset();
- int len = (int)(length * cd.maxCharsPerByte());
- char[] ca = new char[len];
- if (len == 0)
- return new String(ca);
- ByteBuffer bb = ByteBuffer.wrap(ba, 0, length);
+ int clen = (int)(ba.length * cd.maxCharsPerByte());
+ char[] ca = new char[clen];
+ if (clen == 0)
+ return new String(ca);
+ ByteBuffer bb = ByteBuffer.wrap(ba, 0, ba.length);
CharBuffer cb = CharBuffer.wrap(ca);
CoderResult cr = cd.decode(bb, cb, true);
if (!cr.isUnderflow())
- throw new IllegalArgumentException(cr.toString());
+ throw new IllegalArgumentException(cr.toString());
cr = cd.flush(cb);
if (!cr.isUnderflow())
- throw new IllegalArgumentException(cr.toString());
+ throw new IllegalArgumentException(cr.toString());
return new String(ca, 0, cb.position());
}
- String toString(byte[] ba) {
- return toString(ba, ba.length);
- }
-
byte[] getBytes(String s) {
CharsetEncoder ce = encoder().reset();
char[] ca = s.toCharArray();
int len = (int)(ca.length * ce.maxBytesPerChar());
byte[] ba = new byte[len];
if (len == 0)
- return ba;
+ return ba;
ByteBuffer bb = ByteBuffer.wrap(ba);
CharBuffer cb = CharBuffer.wrap(ca);
CoderResult cr = ce.encode(cb, bb, true);
if (!cr.isUnderflow())
- throw new IllegalArgumentException(cr.toString());
+ throw new IllegalArgumentException(cr.toString());
cr = ce.flush(bb);
if (!cr.isUnderflow())
- throw new IllegalArgumentException(cr.toString());
+ throw new IllegalArgumentException(cr.toString());
if (bb.position() == ba.length) // defensive copy?
- return ba;
+ return ba;
else
- return Arrays.copyOf(ba, bb.position());
- }
-
- // assume invoked only if "this" is not utf8
- byte[] getBytesUTF8(String s) {
- if (isutf8)
- return getBytes(s);
- if (utf8 == null)
- utf8 = new ZipCoder(Charset.forName("UTF-8"));
- return utf8.getBytes(s);
- }
-
- String toStringUTF8(byte[] ba, int len) {
- if (isutf8)
- return toString(ba, len);
- if (utf8 == null)
- utf8 = new ZipCoder(Charset.forName("UTF-8"));
- return utf8.toString(ba, len);
+ return Arrays.copyOf(ba, bb.position());
}
boolean isUTF8() {
- return isutf8;
+ return cs == UTF_8;
}
private Charset cs;
- private boolean isutf8;
- private ZipCoder utf8;
private ZipCoder(Charset cs) {
this.cs = cs;
- this.isutf8 = cs.name().equals("UTF-8");
- }
-
- static ZipCoder get(Charset charset) {
- return new ZipCoder(charset);
- }
-
- static ZipCoder get(String csn) {
- try {
- return new ZipCoder(Charset.forName(csn));
- } catch (Throwable t) {
- t.printStackTrace();
- }
- return new ZipCoder(Charset.defaultCharset());
}
private final ThreadLocal<CharsetDecoder> decTL = new ThreadLocal<>();
@@ -133,10 +131,10 @@
private CharsetDecoder decoder() {
CharsetDecoder dec = decTL.get();
if (dec == null) {
- dec = cs.newDecoder()
- .onMalformedInput(CodingErrorAction.REPORT)
- .onUnmappableCharacter(CodingErrorAction.REPORT);
- decTL.set(dec);
+ dec = cs.newDecoder()
+ .onMalformedInput(CodingErrorAction.REPORT)
+ .onUnmappableCharacter(CodingErrorAction.REPORT);
+ decTL.set(dec);
}
return dec;
}
@@ -144,10 +142,10 @@
private CharsetEncoder encoder() {
CharsetEncoder enc = encTL.get();
if (enc == null) {
- enc = cs.newEncoder()
- .onMalformedInput(CodingErrorAction.REPORT)
- .onUnmappableCharacter(CodingErrorAction.REPORT);
- encTL.set(enc);
+ enc = cs.newEncoder()
+ .onMalformedInput(CodingErrorAction.REPORT)
+ .onUnmappableCharacter(CodingErrorAction.REPORT);
+ encTL.set(enc);
}
return enc;
}
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Thu Jan 19 07:02:33 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2015, 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
@@ -314,8 +314,8 @@
IndexNode inode = getInode(path);
if (inode == null)
return null;
- e = new Entry(inode.name); // pseudo directory
- e.method = METHOD_STORED; // STORED for dir
+ e = new Entry(inode.name, inode.isdir); // pseudo directory
+ e.method = METHOD_STORED; // STORED for dir
e.mtime = e.atime = e.ctime = zfsDefaultTimeStamp;
}
} finally {
@@ -400,7 +400,8 @@
List<Path> list = new ArrayList<>();
IndexNode child = inode.child;
while (child != null) {
- ZipPath zp = new ZipPath(this, child.name);
+ // assume all path from zip file itself is "normalized"
+ ZipPath zp = new ZipPath(this, child.name, true);
if (filter == null || filter.accept(zp))
list.add(zp);
child = child.sibling;
@@ -415,14 +416,14 @@
throws IOException
{
checkWritable();
- dir = toDirectoryPath(dir);
+ // dir = toDirectoryPath(dir);
beginWrite();
try {
ensureOpen();
if (dir.length == 0 || exists(dir)) // root dir, or exiting dir
throw new FileAlreadyExistsException(getString(dir));
checkParents(dir);
- Entry e = new Entry(dir, Entry.NEW);
+ Entry e = new Entry(dir, Entry.NEW, true);
e.method = METHOD_STORED; // STORED for dir
update(e);
} finally {
@@ -463,7 +464,7 @@
} else {
checkParents(dst);
}
- Entry u = new Entry(eSrc, Entry.COPY); // copy eSrc entry
+ Entry u = new Entry(eSrc, Entry.COPY); // copy eSrc entry
u.name(dst); // change name
if (eSrc.type == Entry.NEW || eSrc.type == Entry.FILECH)
{
@@ -533,7 +534,7 @@
if (!hasCreate && !hasCreateNew)
throw new NoSuchFileException(getString(path));
checkParents(path);
- return getOutputStream(new Entry(path, Entry.NEW));
+ return getOutputStream(new Entry(path, Entry.NEW, false));
}
} finally {
endRead();
@@ -887,7 +888,7 @@
int off = getParentOff(path);
if (off <= 1)
return ROOTPATH;
- return Arrays.copyOf(path, off + 1);
+ return Arrays.copyOf(path, off);
}
private static int getParentOff(byte[] path) {
@@ -1075,11 +1076,9 @@
if (pos + CENHDR + nlen > limit) {
zerror("invalid CEN header (bad header size)");
}
- byte[] name = new byte[nlen + 1];
- System.arraycopy(cen, pos + CENHDR, name, 1, nlen);
- name[0] = '/';
- IndexNode inode = new IndexNode(name, pos);
+ IndexNode inode = new IndexNode(cen, pos + CENHDR, nlen, pos);
inodes.put(inode, inode);
+
// skip ext and comment
pos += (CENHDR + nlen + elen + clen);
}
@@ -1112,7 +1111,7 @@
private boolean hasUpdate = false;
// shared key. consumer guarantees the "writeLock" before use it.
- private final IndexNode LOOKUPKEY = IndexNode.keyOf(null);
+ private final IndexNode LOOKUPKEY = new IndexNode(null, -1);
private void updateDelete(IndexNode inode) {
beginWrite();
@@ -1312,16 +1311,7 @@
IndexNode getInode(byte[] path) {
if (path == null)
throw new NullPointerException("path");
- IndexNode key = IndexNode.keyOf(path);
- IndexNode inode = inodes.get(key);
- if (inode == null &&
- (path.length == 0 || path[path.length -1] != '/')) {
- // if does not ends with a slash
- path = Arrays.copyOf(path, path.length + 1);
- path[path.length - 1] = '/';
- inode = inodes.get(key.as(path));
- }
- return inode;
+ return inodes.get(IndexNode.keyOf(path));
}
Entry getEntry(byte[] path) throws IOException {
@@ -1782,8 +1772,11 @@
int hashcode; // node is hashable/hashed by its name
int pos = -1; // position in cen table, -1 menas the
// entry does not exists in zip file
- IndexNode(byte[] name) {
+ boolean isdir;
+
+ IndexNode(byte[] name, boolean isdir) {
name(name);
+ this.isdir = isdir;
this.pos = -1;
}
@@ -1792,8 +1785,28 @@
this.pos = pos;
}
+ // constructor for cenInit()
+ IndexNode(byte[] cen, int noff, int nlen, int pos) {
+ if (cen[noff + nlen - 1] == '/') {
+ isdir = true;
+ nlen--;
+ }
+ name = new byte[nlen + 1];
+ System.arraycopy(cen, pos + CENHDR, name, 1, nlen);
+ name[0] = '/';
+ name(name);
+ this.pos = pos;
+ }
+
+ private static final ThreadLocal<IndexNode> cachedKey = new ThreadLocal<>();
+
final static IndexNode keyOf(byte[] name) { // get a lookup key;
- return new IndexNode(name, -1);
+ IndexNode key = cachedKey.get();
+ if (key == null) {
+ key = new IndexNode(name, -1);
+ cachedKey.set(key);
+ }
+ return key.as(name);
}
final void name(byte[] name) {
@@ -1807,8 +1820,7 @@
}
boolean isDir() {
- return name != null &&
- (name.length == 0 || name[name.length - 1] == '/');
+ return isdir;
}
public boolean equals(Object other) {
@@ -1865,8 +1877,9 @@
Entry() {}
- Entry(byte[] name) {
+ Entry(byte[] name, boolean isdir) {
name(name);
+ this.isdir = isdir;
this.mtime = this.ctime = this.atime = System.currentTimeMillis();
this.crc = 0;
this.size = 0;
@@ -1874,13 +1887,14 @@
this.method = METHOD_DEFLATED;
}
- Entry(byte[] name, int type) {
- this(name);
+ Entry(byte[] name, int type, boolean isdir) {
+ this(name, isdir);
this.type = type;
}
Entry (Entry e, int type) {
name(e.name);
+ this.isdir = e.isdir;
this.version = e.version;
this.ctime = e.ctime;
this.atime = e.atime;
@@ -1902,7 +1916,7 @@
}
Entry (byte[] name, Path file, int type) {
- this(name, type);
+ this(name, type, false);
this.file = file;
this.method = METHOD_STORED;
}
@@ -1948,6 +1962,7 @@
locoff = CENOFF(cen, pos);
pos += CENHDR;
this.name = inode.name;
+ this.isdir = inode.isdir;
this.hashcode = inode.hashcode;
pos += nlen;
@@ -1974,9 +1989,10 @@
int elenEXTT = 0; // extra for Extended Timestamp
boolean foundExtraTime = false; // if time stamp NTFS, EXTT present
- // confirm size/length
+ byte[] zname = isdir ? toDirectoryPath(name) : name;
- int nlen = (name != null) ? name.length - 1 : 0; // name has [0] as "slash"
+ // confirm size/length
+ int nlen = (zname != null) ? zname.length - 1 : 0; // name has [0] as "slash"
int elen = (extra != null) ? extra.length : 0;
int eoff = 0;
int clen = (comment != null) ? comment.length : 0;
@@ -2037,7 +2053,7 @@
writeShort(os, 0); // internal file attributes (unused)
writeInt(os, 0); // external file attributes (unused)
writeInt(os, locoff0); // relative offset of local header
- writeBytes(os, name, 1, nlen);
+ writeBytes(os, zname, 1, nlen);
if (elen64 != 0) {
writeShort(os, EXTID_ZIP64);// Zip64 extra
writeShort(os, elen64 - 4); // size of "this" extra block
@@ -2075,87 +2091,13 @@
}
///////////////////// LOC //////////////////////
- static Entry readLOC(ZipFileSystem zipfs, long pos)
- throws IOException
- {
- return readLOC(zipfs, pos, new byte[1024]);
- }
-
- static Entry readLOC(ZipFileSystem zipfs, long pos, byte[] buf)
- throws IOException
- {
- return new Entry().loc(zipfs, pos, buf);
- }
-
- Entry loc(ZipFileSystem zipfs, long pos, byte[] buf)
- throws IOException
- {
- assert (buf.length >= LOCHDR);
- if (zipfs.readFullyAt(buf, 0, LOCHDR , pos) != LOCHDR)
- throw new ZipException("loc: reading failed");
- if (!locSigAt(buf, 0))
- throw new ZipException("loc: wrong sig ->"
- + Long.toString(getSig(buf, 0), 16));
- //startPos = pos;
- version = LOCVER(buf);
- flag = LOCFLG(buf);
- method = LOCHOW(buf);
- mtime = dosToJavaTime(LOCTIM(buf));
- crc = LOCCRC(buf);
- csize = LOCSIZ(buf);
- size = LOCLEN(buf);
- int nlen = LOCNAM(buf);
- int elen = LOCEXT(buf);
-
- name = new byte[nlen + 1];
- name[0] = '/';
- if (zipfs.readFullyAt(name, 1, nlen, pos + LOCHDR) != nlen) {
- throw new ZipException("loc: name reading failed");
- }
- if (elen > 0) {
- extra = new byte[elen];
- if (zipfs.readFullyAt(extra, 0, elen, pos + LOCHDR + nlen)
- != elen) {
- throw new ZipException("loc: ext reading failed");
- }
- }
- pos += (LOCHDR + nlen + elen);
- if ((flag & FLAG_DATADESCR) != 0) {
- // Data Descriptor
- Entry e = zipfs.getEntry(name); // get the size/csize from cen
- if (e == null)
- throw new ZipException("loc: name not found in cen");
- size = e.size;
- csize = e.csize;
- pos += (method == METHOD_STORED ? size : csize);
- if (size >= ZIP64_MINVAL || csize >= ZIP64_MINVAL)
- pos += 24;
- else
- pos += 16;
- } else {
- if (extra != null &&
- (size == ZIP64_MINVAL || csize == ZIP64_MINVAL)) {
- // zip64 ext: must include both size and csize
- int off = 0;
- while (off + 20 < elen) { // HeaderID+DataSize+Data
- int sz = SH(extra, off + 2);
- if (SH(extra, off) == EXTID_ZIP64 && sz == 16) {
- size = LL(extra, off + 4);
- csize = LL(extra, off + 12);
- break;
- }
- off += (sz + 4);
- }
- }
- pos += (method == METHOD_STORED ? size : csize);
- }
- return this;
- }
int writeLOC(OutputStream os) throws IOException {
writeInt(os, LOCSIG); // LOC header signature
int version = version();
- int nlen = (name != null) ? name.length - 1 : 0; // [0] is slash
+
+ byte[] zname = isdir ? toDirectoryPath(name) : name;
+ int nlen = (zname != null) ? zname.length - 1 : 0; // [0] is slash
int elen = (extra != null) ? extra.length : 0;
boolean foundExtraTime = false; // if extra timestamp present
int eoff = 0;
@@ -2214,7 +2156,7 @@
}
writeShort(os, nlen);
writeShort(os, elen + elen64 + elenNTFS + elenEXTT);
- writeBytes(os, name, 1, nlen);
+ writeBytes(os, zname, 1, nlen);
if (elen64 != 0) {
writeShort(os, EXTID_ZIP64);
writeShort(os, 16);
@@ -2551,7 +2493,7 @@
private void buildNodeTree() throws IOException {
beginWrite();
try {
- IndexNode root = new IndexNode(ROOTPATH);
+ IndexNode root = new IndexNode(ROOTPATH, true);
IndexNode[] nodes = inodes.keySet().toArray(new IndexNode[0]);
inodes.put(root, root);
ParentLookup lookup = new ParentLookup();
@@ -2564,7 +2506,7 @@
root.child = node;
break;
}
- lookup = lookup.as(node.name, off + 1);
+ lookup = lookup.as(node.name, off);
if (inodes.containsKey(lookup)) {
parent = inodes.get(lookup);
node.sibling = parent.child;
@@ -2572,7 +2514,7 @@
break;
}
// add new pseudo directory entry
- parent = new IndexNode(Arrays.copyOf(node.name, off + 1));
+ parent = new IndexNode(Arrays.copyOf(node.name, off), true);
inodes.put(parent, parent);
node.sibling = parent.child;
parent.child = node;
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java Thu Jan 19 07:02:33 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2014, 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
@@ -59,8 +59,7 @@
} else {
if (zfs.zc.isUTF8()) {
this.path = normalize(path);
- } else {
- // see normalize(String);
+ } else { // see normalize(String);
this.path = normalize(zfs.getString(path));
}
}
@@ -68,12 +67,7 @@
ZipPath(ZipFileSystem zfs, String path) {
this.zfs = zfs;
- if (zfs.zc.isUTF8()) {
- this.path = normalize(zfs.getBytes(path));
- } else {
- // see normalize(String);
- this.path = normalize(path);
- }
+ this.path = normalize(path);
}
@Override
@@ -84,33 +78,31 @@
return null;
}
- @Override
+ @Override
public Path getFileName() {
- initOffsets();
- int count = offsets.length;
- if (count == 0)
- return null; // no elements so no name
- if (count == 1 && path[0] != '/')
+ int off = path.length;
+ if (off == 0 || off == 1 && path[0] == '/')
+ return null;
+ while (--off >= 0 && path[off] != '/') {}
+ if (off < 0)
return this;
- int lastOffset = offsets[count-1];
- int len = path.length - lastOffset;
- byte[] result = new byte[len];
- System.arraycopy(path, lastOffset, result, 0, len);
- return new ZipPath(zfs, result);
+ off++;
+ byte[] result = new byte[path.length - off];
+ System.arraycopy(path, off, result, 0, result.length);
+ return new ZipPath(getFileSystem(), result, true);
}
@Override
public ZipPath getParent() {
- initOffsets();
- int count = offsets.length;
- if (count == 0) // no elements so no parent
+ int off = path.length;
+ if (off == 0 || off == 1 && path[0] == '/')
return null;
- int len = offsets[count-1] - 1;
- if (len <= 0) // parent is root only (may be null)
+ while (--off >= 0 && path[off] != '/') {}
+ if (off <= 0)
return getRoot();
- byte[] result = new byte[len];
- System.arraycopy(path, 0, result, 0, len);
- return new ZipPath(zfs, result);
+ byte[] result = new byte[off];
+ System.arraycopy(path, 0, result, 0, off);
+ return new ZipPath(getFileSystem(), result, true);
}
@Override
@@ -277,30 +269,36 @@
@Override
public boolean isAbsolute() {
- return (this.path.length > 0 && path[0] == '/');
+ return path.length > 0 && path[0] == '/';
}
@Override
public ZipPath resolve(Path other) {
- final ZipPath o = checkPath(other);
- int tlen = this.path.length;
- if (tlen == 0 || o.isAbsolute())
+ ZipPath o = checkPath(other);
+ if (o.path.length == 0)
+ return this;
+ if (o.isAbsolute() || this.path.length == 0)
return o;
- int olen = o.path.length;
- if (olen == 0)
- return this;
+ return resolve(o.path);
+ }
+
+ // opath is normalized, just concat
+ private ZipPath resolve(byte[] opath) {
byte[] resolved = null;
- if (this.path[tlen - 1] == '/') {
+ byte[] tpath = this.path;
+ int tlen = tpath.length;
+ int olen = opath.length;
+ if (path[tlen - 1] == '/') {
resolved = new byte[tlen + olen];
- System.arraycopy(path, 0, resolved, 0, tlen);
- System.arraycopy(o.path, 0, resolved, tlen, olen);
+ System.arraycopy(tpath, 0, resolved, 0, tlen);
+ System.arraycopy(opath, 0, resolved, tlen, olen);
} else {
resolved = new byte[tlen + 1 + olen];
- System.arraycopy(path, 0, resolved, 0, tlen);
+ System.arraycopy(tpath, 0, resolved, 0, tlen);
resolved[tlen] = '/';
- System.arraycopy(o.path, 0, resolved, tlen + 1, olen);
+ System.arraycopy(opath, 0, resolved, tlen + 1, olen);
}
- return new ZipPath(zfs, resolved);
+ return new ZipPath(zfs, resolved, true);
}
@Override
@@ -351,7 +349,12 @@
@Override
public ZipPath resolve(String other) {
- return resolve(zfs.getPath(other));
+ byte[] opath = normalize(other);
+ if (opath.length == 0)
+ return this;
+ if (opath[0] == '/' || this.path.length == 0)
+ return new ZipPath(zfs, opath, true);
+ return resolve(opath);
}
@Override
@@ -455,8 +458,9 @@
return normalize(path, i - 1);
prevC = c;
}
- if (len > 1 && prevC == '/')
+ if (len > 1 && prevC == '/') {
return Arrays.copyOf(path, len - 1);
+ }
return path;
}
@@ -490,6 +494,8 @@
// to avoid incorrectly normalizing byte '0x5c' (as '\')
// to '/'.
private byte[] normalize(String path) {
+ if (zfs.zc.isUTF8())
+ return normalize(zfs.getBytes(path));
int len = path.length();
if (len == 0)
return new byte[0];
@@ -533,7 +539,8 @@
// Remove DotSlash(./) and resolve DotDot (..) components
private byte[] getResolved() {
for (int i = 0; i < path.length; i++) {
- if (path[i] == (byte)'.') {
+ if (path[i] == (byte)'.' &&
+ (i + 1 == path.length || path[i + 1] == '/')) {
return resolve0();
}
}
@@ -976,5 +983,4 @@
}
return sb.toString();
}
-
}
--- a/jdk/test/ProblemList.txt Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/ProblemList.txt Thu Jan 19 07:02:33 2017 -0800
@@ -258,6 +258,8 @@
tools/jlink/multireleasejar/JLinkMultiReleaseJarTest.java 8169971 windows-x64
+tools/jlink/CustomPluginTest.java 8172864 generic-all
+
############################################################################
# jdk_jdi
--- a/jdk/test/TEST.ROOT Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/TEST.ROOT Thu Jan 19 07:02:33 2017 -0800
@@ -26,8 +26,8 @@
# Allow querying of various System properties in @requires clauses
requires.properties=sun.arch.data.model java.runtime.name
-# Tests using jtreg 4.2 b04 features
-requiredVersion=4.2 b04
+# Tests using jtreg 4.2 b05 features
+requiredVersion=4.2 b05
# Path to libraries in the topmost test directory. This is needed so @library
# does not need ../../ notation to reach them
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/LogManagerInModuleTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+import java.nio.file.Paths;
+import java.util.logging.Handler;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+
+/**
+ * @test
+ * @bug 8172886
+ * @summary Verifies that a custom LogManager or custom Handler can be
+ * instantiated by the logging system if they are in a package
+ * that is exported to java.logging by a module.
+ * @build test.logmanager/test.logmanager.TestLogManager
+ * test.handlers/test.handlers.TestHandler
+ * test.config/test.config.LogConfig
+ * LogManagerInModuleTest
+ * @run main/othervm --add-modules test.logmanager,test.handlers
+ * -Djava.util.logging.manager=test.logmanager.TestLogManager
+ * LogManagerInModuleTest
+ * @run main/othervm --add-modules test.logmanager,test.handlers,test.config
+ * -Djava.util.logging.manager=test.logmanager.TestLogManager
+ * -Djava.util.logging.config.class=test.config.LogConfig
+ * LogManagerInModuleTest
+ *
+ * @author danielfuchs
+ */
+public class LogManagerInModuleTest {
+
+ public static void main(String[] args) throws Exception {
+ if (System.getProperty("java.util.logging.config.class", null) == null) {
+ System.setProperty("java.util.logging.config.file",
+ Paths.get(System.getProperty("test.src", "src"),
+ "logging.properties").toString());
+ }
+ // sanity check
+ if (LogManagerInModuleTest.class.getModule().isNamed()) {
+ throw new RuntimeException("Unexpected named module for "
+ + LogManagerInModuleTest.class + ": "
+ + LogManagerInModuleTest.class.getModule().getName());
+ }
+
+ // now check that the LogManager was correctly instantiated.
+ LogManager manager = LogManager.getLogManager();
+ System.out.println("LogManager: " + manager);
+ Class<?> logManagerClass = manager.getClass();
+ if (!"test.logmanager".equals(logManagerClass.getModule().getName())) {
+ throw new RuntimeException("Bad module for log manager: "
+ + logManagerClass.getModule() + "; class is: "
+ + logManagerClass.getName());
+ }
+
+ Logger logger = Logger.getLogger("com.xyz.foo");
+ Handler[] handlers = logger.getHandlers();
+ if (handlers.length != 1) {
+ throw new RuntimeException("Expected 1 handler, found " + handlers.length);
+ }
+ Class<?> handlerClass = handlers[0].getClass();
+ if (!"test.handlers".equals(handlerClass.getModule().getName())) {
+ throw new RuntimeException("Bad module for handler: "
+ + handlerClass.getModule() + "; class is: "
+ + handlerClass.getName());
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/logging.properties Thu Jan 19 07:02:33 2017 -0800
@@ -0,0 +1,56 @@
+############################################################
+# Global properties
+############################################################
+
+# "handlers" specifies a comma separated list of log Handler
+# classes. These handlers will be installed during VM startup.
+# Note that these classes must be on the system classpath.
+# By default we only configure a ConsoleHandler, which will only
+# show messages at the INFO and above levels.
+handlers= java.util.logging.ConsoleHandler
+
+# To also add the FileHandler, use the following line instead.
+#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
+
+# Default global logging level.
+# This specifies which kinds of events are logged across
+# all loggers. For any given facility this global level
+# can be overriden by a facility specific level
+# Note that the ConsoleHandler also has a separate level
+# setting to limit messages printed to the console.
+.level= INFO
+
+############################################################
+# Handler specific properties.
+# Describes specific configuration info for Handlers.
+############################################################
+
+# default file output is in user's home directory.
+java.util.logging.FileHandler.pattern = %h/java%u.log
+java.util.logging.FileHandler.limit = 50000
+java.util.logging.FileHandler.count = 1
+# Default number of locks FileHandler can obtain synchronously.
+# This specifies maximum number of attempts to obtain lock file by FileHandler
+# implemented by incrementing the unique field %u as per FileHandler API documentation.
+java.util.logging.FileHandler.maxLocks = 100
+java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
+
+# Limit the message that are printed on the console to INFO and above.
+java.util.logging.ConsoleHandler.level = INFO
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+# Example to customize the SimpleFormatter output format
+# to print one-line log message like this:
+# <level>: <log message> [<date/time>]
+#
+# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n
+
+############################################################
+# Facility specific properties.
+# Provides extra control for each logger.
+############################################################
+
+# For example, set the com.xyz.foo logger to only log SEVERE
+# messages:
+com.xyz.foo.level = SEVERE
+com.xyz.foo.handlers = test.handlers.TestHandler
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/test.config/module-info.java Thu Jan 19 07:02:33 2017 -0800
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+module test.config {
+ requires java.logging;
+ requires test.handlers;
+ // makes it possible for java.logging to instantiate test.config.LogConfig;
+ // this doesn't need to be a qualified export, but making it so will prevent
+ // any other module from being able to instantiate the provided classes.
+ exports test.config to java.logging;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/test.config/test/config/LogConfig.java Thu Jan 19 07:02:33 2017 -0800
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.config;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+import test.handlers.TestHandler;
+
+/**
+ * A dummy class that configures the logging system.
+ * @author danielfuchs
+ */
+public class LogConfig {
+ private static final List<Logger> LOGGERS = new ArrayList<>();
+ public LogConfig() {
+ LogManager manager = LogManager.getLogManager();
+ Logger logger = Logger.getLogger("com.xyz.foo");
+ if (logger.getHandlers().length > 0) {
+ System.err.println(this.getClass().getName() + ": "
+ + "Unexpected handlers: "
+ + List.of(logger.getHandlers()));
+ throw new RuntimeException("Unexpected handlers: "
+ + List.of(logger.getHandlers()));
+ }
+ logger.addHandler(new TestHandler());
+ LOGGERS.add(logger);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/test.handlers/module-info.java Thu Jan 19 07:02:33 2017 -0800
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+module test.handlers {
+ requires transitive java.logging;
+ // makes it possible for java.logging and test.config to instantiate
+ // test.handlers.TestHandler;
+ // this doesn't need to be a qualified export, but making it so will prevent
+ // any other module from being able to instantiate the provided classes.
+ exports test.handlers to java.logging, test.config;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/test.handlers/test/handlers/TestHandler.java Thu Jan 19 07:02:33 2017 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.handlers;
+
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+
+/**
+ * A dummy Handler that does nothing.
+ * @author danielfuchs
+ */
+public class TestHandler extends Handler {
+
+ @Override
+ public void publish(LogRecord record) {
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void close() throws SecurityException {
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/test.logmanager/module-info.java Thu Jan 19 07:02:33 2017 -0800
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+module test.logmanager {
+ requires java.logging;
+ // makes it possible for java.logging to instantiate
+ // test.logmanager.TestLogManager;
+ // this doesn't need to be a qualified export, but making it so will prevent
+ // any other module from being able to instantiate the provided classes.
+ exports test.logmanager to java.logging;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/modules/LogManagerInModule/test.logmanager/test/logmanager/TestLogManager.java Thu Jan 19 07:02:33 2017 -0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.logmanager;
+
+import java.util.logging.LogManager;
+
+/**
+ * A dummy LogManager that simply extends the standard class.
+ * @author danielfuchs
+ */
+public class TestLogManager extends LogManager {
+
+}
--- a/jdk/test/jdk/nio/zipfs/PathOps.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/jdk/nio/zipfs/PathOps.java Thu Jan 19 07:02:33 2017 -0800
@@ -31,7 +31,7 @@
/**
*
* @test
- * @bug 8038500 8040059 8139956 8146754
+ * @bug 8038500 8040059 8139956 8146754 8172921
* @summary Tests path operations for zip provider.
*
* @run main PathOps
@@ -180,6 +180,13 @@
return this;
}
+ PathOps resolvePath(String other, String expected) {
+ out.format("test resolve %s\n", other);
+ checkPath();
+ check(path.resolve(fs.getPath(other)), expected);
+ return this;
+ }
+
PathOps resolveSibling(String other, String expected) {
out.format("test resolveSibling %s\n", other);
checkPath();
@@ -384,6 +391,30 @@
.resolve("", "")
.resolve("foo", "foo")
.resolve("/foo", "/foo");
+ test("/")
+ .resolve("", "/")
+ .resolve("foo", "/foo")
+ .resolve("/foo", "/foo")
+ .resolve("/foo/", "/foo");
+
+ // resolve(Path)
+ test("/tmp")
+ .resolvePath("foo", "/tmp/foo")
+ .resolvePath("/foo", "/foo")
+ .resolvePath("", "/tmp");
+ test("tmp")
+ .resolvePath("foo", "tmp/foo")
+ .resolvePath("/foo", "/foo")
+ .resolvePath("", "tmp");
+ test("")
+ .resolvePath("", "")
+ .resolvePath("foo", "foo")
+ .resolvePath("/foo", "/foo");
+ test("/")
+ .resolvePath("", "/")
+ .resolvePath("foo", "/foo")
+ .resolvePath("/foo", "/foo")
+ .resolvePath("/foo/", "/foo");
// resolveSibling
test("foo")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/ApiValidatorTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -0,0 +1,193 @@
+/*
+ * 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
+ * @summary Tests for API validator.
+ * @library /test/lib /lib/testlibrary
+ * @modules java.base/jdk.internal.misc
+ * jdk.compiler
+ * jdk.jartool
+ * @build jdk.test.lib.JDKToolFinder jdk.test.lib.Utils jdk.test.lib.process.*
+ * @build jdk.testlibrary.FileUtils
+ * @build MRTestBase
+ * @run testng ApiValidatorTest
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.FileUtils;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class ApiValidatorTest extends MRTestBase {
+
+ @Test(dataProvider = "signatureChange")
+ public void changeMethodSignature(String sigBase, String sigV10,
+ boolean isAcceptable,
+ Method method) throws Throwable {
+ Path root = Paths.get(method.getName());
+ Path classes = root.resolve("classes");
+
+ String METHOD_SIG = "#SIG";
+ String classTemplate =
+ "public class C { \n" +
+ " " + METHOD_SIG + "{ throw new RuntimeException(); };\n" +
+ "}\n";
+ String base = classTemplate.replace(METHOD_SIG, sigBase);
+ String v10 = classTemplate.replace(METHOD_SIG, sigV10);
+
+ compileTemplate(classes.resolve("base"), base);
+ compileTemplate(classes.resolve("v10"), v10);
+
+ String jarfile = root.resolve("test.jar").toString();
+ OutputAnalyzer result = jar("cf", jarfile,
+ "-C", classes.resolve("base").toString(), ".",
+ "--release", "10", "-C", classes.resolve("v10").toString(),
+ ".");
+ if (isAcceptable) {
+ result.shouldHaveExitValue(SUCCESS)
+ .shouldBeEmpty();
+ } else {
+ result.shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("contains a class with different api from earlier version");
+ }
+
+ FileUtils.deleteFileTreeWithRetry(root);
+ }
+
+ @DataProvider
+ Object[][] signatureChange() {
+ return new Object[][]{
+ {"public int m()", "protected int m()", false},
+ {"protected int m()", "public int m()", false},
+ {"public int m()", "int m()", false},
+ {"protected int m()", "private int m()", false},
+ {"private int m()", "int m()", true},
+ {"int m()", "private int m()", true},
+ {"int m()", "private int m(boolean b)", true},
+ {"public int m()", "public int m(int i)", false},
+ {"public int m()", "public int k()", false},
+ {"public int m()", "private int k()", false},
+// @ignore JDK-8172147 {"public int m()", "public boolean m()", false},
+// @ignore JDK-8172147 {"public boolean", "public Boolean", false},
+// @ignore JDK-8172147 {"public <T> T", "public <T extends String> T", false},
+ };
+ }
+
+ @Test(dataProvider = "publicAPI")
+ public void introducingPublicMembers(String publicAPI,
+ Method method) throws Throwable {
+ Path root = Paths.get(method.getName());
+ Path classes = root.resolve("classes");
+
+ String API = "#API";
+ String classTemplate =
+ "public class C { \n" +
+ " " + API + "\n" +
+ " public void method(){ };\n" +
+ "}\n";
+ String base = classTemplate.replace(API, "");
+ String v10 = classTemplate.replace(API, publicAPI);
+
+ compileTemplate(classes.resolve("base"), base);
+ compileTemplate(classes.resolve("v10"), v10);
+
+ String jarfile = root.resolve("test.jar").toString();
+ jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+ "--release", "10", "-C", classes.resolve("v10").toString(), ".")
+ .shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("contains a class with different api from earlier version");
+
+ FileUtils.deleteFileTreeWithRetry(root);
+ }
+
+ @DataProvider
+ Object[][] publicAPI() {
+ return new Object[][]{
+// @ignore JDK-8172148 {"protected class Inner { public void m(){ } } "}, // protected inner class
+// @ignore JDK-8172148 {"public class Inner { public void m(){ } }"}, // public inner class
+// @ignore JDK-8172148 {"public enum E { A; }"}, // public enum
+ {"public void m(){ }"}, // public method
+ {"protected void m(){ }"}, // protected method
+ };
+ }
+
+ @Test(dataProvider = "privateAPI")
+ public void introducingPrivateMembers(String privateAPI,
+ Method method) throws Throwable {
+ Path root = Paths.get(method.getName());
+ Path classes = root.resolve("classes");
+
+ String API = "#API";
+ String classTemplate =
+ "public class C { \n" +
+ " " + API + "\n" +
+ " public void method(){ };\n" +
+ "}\n";
+ String base = classTemplate.replace(API, "");
+ String v10 = classTemplate.replace(API, privateAPI);
+
+ compileTemplate(classes.resolve("base"), base);
+ compileTemplate(classes.resolve("v10"), v10);
+
+ String jarfile = root.resolve("test.jar").toString();
+ jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+ "--release", "10", "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
+ // add release
+ jar("uf", jarfile,
+ "--release", "11", "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
+ // replace release
+ jar("uf", jarfile,
+ "--release", "11", "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
+
+ FileUtils.deleteFileTreeWithRetry(root);
+ }
+
+ @DataProvider
+ Object[][] privateAPI() {
+ return new Object[][]{
+ {"private class Inner { public void m(){ } } "}, // private inner class
+ {"class Inner { public void m(){ } }"}, // package private inner class
+ {"enum E { A; }"}, // package private enum
+ // Local class and private method
+ {"private void m(){ class Inner { public void m(){} } Inner i = null; }"},
+ {"void m(){ }"}, // package private method
+ };
+ }
+
+ private void compileTemplate(Path classes, String template) throws Throwable {
+ Path classSourceFile = Files.createDirectories(
+ classes.getParent().resolve("src").resolve(classes.getFileName()))
+ .resolve("C.java");
+ Files.write(classSourceFile, template.getBytes());
+ javac(classes, classSourceFile);
+ }
+}
\ No newline at end of file
--- a/jdk/test/tools/jar/multiRelease/Basic.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jar/multiRelease/Basic.java Thu Jan 19 07:02:33 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
@@ -23,69 +23,59 @@
/*
* @test
- * @library /test/lib
+ * @library /test/lib /lib/testlibrary
* @modules java.base/jdk.internal.misc
* jdk.compiler
* jdk.jartool
- * @build jdk.test.lib.JDKToolFinder jdk.test.lib.Utils
+ * @build jdk.test.lib.JDKToolFinder jdk.test.lib.Utils jdk.test.lib.process.*
+ * @build jdk.testlibrary.FileUtils
+ * @build MRTestBase
* @run testng Basic
*/
import static org.testng.Assert.*;
+import jdk.testlibrary.FileUtils;
import org.testng.annotations.*;
-import java.io.*;
+import java.io.File;
import java.nio.file.*;
-import java.nio.file.attribute.*;
import java.util.*;
-import java.util.function.Consumer;
-import java.util.jar.*;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.zip.*;
+import java.util.jar.JarFile;
+import java.util.zip.ZipFile;
-import jdk.test.lib.JDKToolFinder;
-import jdk.test.lib.Utils;
-
-
-import static java.lang.String.format;
-import static java.lang.System.out;
-
-public class Basic {
- private final String src = System.getProperty("test.src", ".");
- private final String usr = System.getProperty("user.dir", ".");
+public class Basic extends MRTestBase {
@Test
// create a regular, non-multi-release jar
- public void test00() throws IOException {
+ public void test00() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
Path classes = Paths.get("classes");
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".")
- .assertSuccess();
+ .shouldHaveExitValue(SUCCESS);
checkMultiRelease(jarfile, false);
- Map<String,String[]> names = Map.of(
+ Map<String, String[]> names = Map.of(
"version/Main.class",
- new String[] {"base", "version", "Main.class"},
+ new String[]{"base", "version", "Main.class"},
"version/Version.class",
- new String[] {"base", "version", "Version.class"}
+ new String[]{"base", "version", "Version.class"}
);
compare(jarfile, names);
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// create a multi-release jar
- public void test01() throws IOException {
+ public void test01() throws Throwable {
String jarfile = "test.jar";
compile("test01");
@@ -94,68 +84,96 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".",
"--release", "10", "-C", classes.resolve("v10").toString(), ".")
- .assertSuccess();
+ .shouldHaveExitValue(SUCCESS);
checkMultiRelease(jarfile, true);
- Map<String,String[]> names = Map.of(
+ Map<String, String[]> names = Map.of(
"version/Main.class",
- new String[] {"base", "version", "Main.class"},
+ new String[]{"base", "version", "Main.class"},
"version/Version.class",
- new String[] {"base", "version", "Version.class"},
+ new String[]{"base", "version", "Version.class"},
"META-INF/versions/9/version/Version.class",
- new String[] {"v9", "version", "Version.class"},
+ new String[]{"v9", "version", "Version.class"},
"META-INF/versions/10/version/Version.class",
- new String[] {"v10", "version", "Version.class"}
+ new String[]{"v10", "version", "Version.class"}
);
compare(jarfile, names);
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
+ }
+
+ @Test
+ public void versionFormat() throws Throwable {
+ String jarfile = "test.jar";
+
+ compile("test01");
+
+ Path classes = Paths.get("classes");
+
+ // valid
+ for (String release : List.of("10000", "09", "00010", "10")) {
+ jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+ "--release", release, "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS)
+ .shouldBeEmpty();
+ }
+ // invalid
+ for (String release : List.of("9.0", "8", "v9",
+ "9v", "0", "-10")) {
+ jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+ "--release", release, "-C", classes.resolve("v10").toString(), ".")
+ .shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("release " + release + " not valid");
+ }
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// update a regular jar to a multi-release jar
- public void test02() throws IOException {
+ public void test02() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
Path classes = Paths.get("classes");
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".")
- .assertSuccess();
+ .shouldHaveExitValue(SUCCESS);
checkMultiRelease(jarfile, false);
- jar("uf", jarfile, "--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertSuccess();
+ jar("uf", jarfile,
+ "--release", "9", "-C", classes.resolve("v9").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
checkMultiRelease(jarfile, true);
- Map<String,String[]> names = Map.of(
+ Map<String, String[]> names = Map.of(
"version/Main.class",
- new String[] {"base", "version", "Main.class"},
+ new String[]{"base", "version", "Main.class"},
"version/Version.class",
- new String[] {"base", "version", "Version.class"},
+ new String[]{"base", "version", "Version.class"},
"META-INF/versions/9/version/Version.class",
- new String[] {"v9", "version", "Version.class"}
+ new String[]{"v9", "version", "Version.class"}
);
compare(jarfile, names);
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// replace a base entry and a versioned entry
- public void test03() throws IOException {
+ public void test03() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -163,19 +181,19 @@
Path classes = Paths.get("classes");
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertSuccess();
+ .shouldHaveExitValue(SUCCESS);
checkMultiRelease(jarfile, true);
- Map<String,String[]> names = Map.of(
+ Map<String, String[]> names = Map.of(
"version/Main.class",
- new String[] {"base", "version", "Main.class"},
+ new String[]{"base", "version", "Main.class"},
"version/Version.class",
- new String[] {"base", "version", "Version.class"},
+ new String[]{"base", "version", "Version.class"},
"META-INF/versions/9/version/Version.class",
- new String[] {"v9", "version", "Version.class"}
+ new String[]{"v9", "version", "Version.class"}
);
compare(jarfile, names);
@@ -184,25 +202,25 @@
// version/Version.class entry in versions/9 section
jar("uf", jarfile, "-C", classes.resolve("v9").toString(), "version",
"--release", "9", "-C", classes.resolve("v10").toString(), ".")
- .assertSuccess();
+ .shouldHaveExitValue(SUCCESS);
checkMultiRelease(jarfile, true);
names = Map.of(
"version/Main.class",
- new String[] {"base", "version", "Main.class"},
+ new String[]{"base", "version", "Main.class"},
"version/Version.class",
- new String[] {"v9", "version", "Version.class"},
+ new String[]{"v9", "version", "Version.class"},
"META-INF/versions/9/version/Version.class",
- new String[] {"v10", "version", "Version.class"}
+ new String[]{"v10", "version", "Version.class"}
);
compare(jarfile, names);
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
/*
@@ -211,7 +229,7 @@
@Test
// META-INF/versions/9 class has different api than base class
- public void test04() throws IOException {
+ public void test04() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -224,18 +242,16 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertFailure()
- .resultChecker(r ->
- assertTrue(r.output.contains("different api from earlier"), r.output)
- );
+ .shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("different api from earlier");
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// META-INF/versions/9 contains an extra public class
- public void test05() throws IOException {
+ public void test05() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -248,18 +264,16 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertFailure()
- .resultChecker(r ->
- assertTrue(r.output.contains("contains a new public class"), r.output)
- );
+ .shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("contains a new public class");
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// META-INF/versions/9 contains an extra package private class -- this is okay
- public void test06() throws IOException {
+ public void test06() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -272,16 +286,16 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertSuccess();
+ .shouldHaveExitValue(SUCCESS);
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// META-INF/versions/9 contains an identical class to base entry class
// this is okay but produces warning
- public void test07() throws IOException {
+ public void test07() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -294,19 +308,42 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertSuccess()
- .resultChecker(r ->
- assertTrue(r.outputContains("contains a class that is identical"), r.output)
- );
+ .shouldHaveExitValue(SUCCESS)
+ .shouldContain("contains a class that")
+ .shouldContain("is identical");
+
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
+ }
+
+ @Test
+ // META-INF/versions/9 contains an identical class to previous version entry class
+ // this is okay but produces warning
+ public void identicalClassToPreviousVersion() throws Throwable {
+ String jarfile = "test.jar";
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ compile("test01"); //use same data as test01
+
+ Path classes = Paths.get("classes");
+
+ jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+ "--release", "9", "-C", classes.resolve("v9").toString(), ".")
+ .shouldHaveExitValue(SUCCESS)
+ .shouldBeEmpty();
+ jar("uf", jarfile,
+ "--release", "10", "-C", classes.resolve("v9").toString(), ".")
+ .shouldHaveExitValue(SUCCESS)
+ .shouldContain("contains a class that")
+ .shouldContain("is identical");
+
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// resources with same name in different versions
// this is okay but produces warning
- public void test08() throws IOException {
+ public void test08() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -320,10 +357,8 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertSuccess()
- .resultChecker(r ->
- assertTrue(r.output.isEmpty(), r.output)
- );
+ .shouldHaveExitValue(SUCCESS)
+ .shouldBeEmpty();
// now add a different resource with same name to META-INF/version/9
Files.copy(source.resolve("Main.java"), classes.resolve("v9")
@@ -331,18 +366,16 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertSuccess()
- .resultChecker(r ->
- assertTrue(r.output.contains("multiple resources with same name"), r.output)
- );
+ .shouldHaveExitValue(SUCCESS)
+ .shouldContain("multiple resources with same name");
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// a class with an internal name different from the external name
- public void test09() throws IOException {
+ public void test09() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -355,18 +388,16 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertFailure()
- .resultChecker(r ->
- assertTrue(r.output.contains("names do not match"), r.output)
- );
+ .shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("names do not match");
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// assure that basic nested classes are acceptable
- public void test10() throws IOException {
+ public void test10() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -383,15 +414,15 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertSuccess();
+ .shouldHaveExitValue(SUCCESS);
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// a base entry contains a nested class that doesn't have a matching top level class
- public void test11() throws IOException {
+ public void test11() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -409,30 +440,29 @@
source = Paths.get(src, "data", "test10", "v9", "version");
javac(classes.resolve("v9"), source.resolve("Nested.java"));
- jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+ List<String> output = jar("cf", jarfile,
+ "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertFailure()
- .resultChecker(r -> {
- String[] msg = r.output.split("\\R");
- // There should be 3 error messages, cascading from the first. Once we
- // remove the base top level class, the base nested class becomes isolated,
- // also the versioned top level class becomes a new public class, thus ignored
- // for subsequent checks, leading to the associated versioned nested class
- // becoming an isolated nested class
- assertTrue(msg.length == 4);
- assertTrue(msg[0].contains("an isolated nested class"), msg[0]);
- assertTrue(msg[1].contains("contains a new public class"), msg[1]);
- assertTrue(msg[2].contains("an isolated nested class"), msg[2]);
- assertTrue(msg[3].contains("invalid multi-release jar file"), msg[3]);
- });
+ .shouldNotHaveExitValue(SUCCESS)
+ .asLines();
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
+ assertTrue(output.size() == 4);
+ assertTrue(output.get(0).contains("an isolated nested class"),
+ output.get(0));
+ assertTrue(output.get(1).contains("contains a new public class"),
+ output.get(1));
+ assertTrue(output.get(2).contains("an isolated nested class"),
+ output.get(2));
+ assertTrue(output.get(3).contains("invalid multi-release jar file"),
+ output.get(3));
+
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
@Test
// a versioned entry contains a nested class that doesn't have a matching top level class
- public void test12() throws IOException {
+ public void test12() throws Throwable {
String jarfile = "test.jar";
compile("test01"); //use same data as test01
@@ -452,178 +482,59 @@
jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
"--release", "9", "-C", classes.resolve("v9").toString(), ".")
- .assertFailure()
- .resultChecker(r ->
- assertTrue(r.outputContains("an isolated nested class"), r.output)
- );
-
- delete(jarfile);
- deleteDir(Paths.get(usr, "classes"));
- }
-
- /*
- * Test Infrastructure
- */
- private void compile(String test) throws IOException {
- Path classes = Paths.get(usr, "classes", "base");
- Files.createDirectories(classes);
- Path source = Paths.get(src, "data", test, "base", "version");
- javac(classes, source.resolve("Main.java"), source.resolve("Version.java"));
-
- classes = Paths.get(usr, "classes", "v9");
- Files.createDirectories(classes);
- source = Paths.get(src, "data", test, "v9", "version");
- javac(classes, source.resolve("Version.java"));
-
- classes = Paths.get(usr, "classes", "v10");
- Files.createDirectories(classes);
- source = Paths.get(src, "data", test, "v10", "version");
- javac(classes, source.resolve("Version.java"));
- }
-
- private void checkMultiRelease(String jarFile, boolean expected) throws IOException {
- try (JarFile jf = new JarFile(new File(jarFile), true, ZipFile.OPEN_READ,
- JarFile.runtimeVersion())) {
- assertEquals(jf.isMultiRelease(), expected);
- }
- }
+ .shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("an isolated nested class");
- // compares the bytes found in the jar entries with the bytes found in the
- // corresponding data files used to create the entries
- private void compare(String jarfile, Map<String,String[]> names) throws IOException {
- try (JarFile jf = new JarFile(jarfile)) {
- for (String name : names.keySet()) {
- Path path = Paths.get("classes", names.get(name));
- byte[] b1 = Files.readAllBytes(path);
- byte[] b2;
- JarEntry je = jf.getJarEntry(name);
- try (InputStream is = jf.getInputStream(je)) {
- b2 = is.readAllBytes();
- }
- assertEquals(b1,b2);
- }
- }
- }
-
- private void delete(String name) throws IOException {
- Files.deleteIfExists(Paths.get(usr, name));
- }
-
- private void deleteDir(Path dir) throws IOException {
- Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
- Files.delete(file);
- return FileVisitResult.CONTINUE;
- }
-
- @Override
- public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
- Files.delete(dir);
- return FileVisitResult.CONTINUE;
- }
- });
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
- /*
- * The following methods were taken from modular jar and other jar tests
- */
+ @Test
+ public void testCustomManifest() throws Throwable {
+ String jarfile = "test.jar";
- void javac(Path dest, Path... sourceFiles) throws IOException {
- String javac = JDKToolFinder.getJDKTool("javac");
+ compile("test01");
- List<String> commands = new ArrayList<>();
- commands.add(javac);
- String opts = System.getProperty("test.compiler.opts");
- if (!opts.isEmpty()) {
- commands.addAll(Arrays.asList(opts.split(" +")));
- }
- commands.add("-d");
- commands.add(dest.toString());
- Stream.of(sourceFiles).map(Object::toString).forEach(x -> commands.add(x));
+ Path classes = Paths.get("classes");
+ Path manifest = Paths.get("Manifest.txt");
- quickFail(run(new ProcessBuilder(commands)));
- }
+ // create
+ Files.write(manifest, "Class-Path: MyUtils.jar\n".getBytes());
- Result jarWithStdin(File stdinSource, String... args) {
- String jar = JDKToolFinder.getJDKTool("jar");
- List<String> commands = new ArrayList<>();
- commands.add(jar);
- commands.addAll(Utils.getForwardVmOptions());
- Stream.of(args).forEach(x -> commands.add(x));
- ProcessBuilder p = new ProcessBuilder(commands);
- if (stdinSource != null)
- p.redirectInput(stdinSource);
- return run(p);
- }
+ jar("cfm", jarfile, manifest.toString(),
+ "-C", classes.resolve("base").toString(), ".",
+ "--release", "10", "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS)
+ .shouldBeEmpty();
- Result jar(String... args) {
- return jarWithStdin(null, args);
- }
-
- void quickFail(Result r) {
- if (r.ec != 0)
- throw new RuntimeException(r.output);
- }
-
- Result run(ProcessBuilder pb) {
- Process p;
- out.printf("Running: %s%n", pb.command());
- try {
- p = pb.start();
- } catch (IOException e) {
- throw new RuntimeException(
- format("Couldn't start process '%s'", pb.command()), e);
+ try (JarFile jf = new JarFile(new File(jarfile), true,
+ ZipFile.OPEN_READ, JarFile.runtimeVersion())) {
+ assertTrue(jf.isMultiRelease(), "Not multi-release jar");
+ assertEquals(jf.getManifest()
+ .getMainAttributes()
+ .getValue("Class-Path"),
+ "MyUtils.jar");
}
- String output;
- try {
- output = toString(p.getInputStream(), p.getErrorStream());
- } catch (IOException e) {
- throw new RuntimeException(
- format("Couldn't read process output '%s'", pb.command()), e);
+ // update
+ Files.write(manifest, "Multi-release: false\n".getBytes());
+
+ jar("ufm", jarfile, manifest.toString(),
+ "-C", classes.resolve("base").toString(), ".",
+ "--release", "9", "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS)
+ .shouldContain("WARNING: Duplicate name in Manifest: Multi-release.");
+
+ try (JarFile jf = new JarFile(new File(jarfile), true,
+ ZipFile.OPEN_READ, JarFile.runtimeVersion())) {
+ assertTrue(jf.isMultiRelease(), "Not multi-release jar");
+ assertEquals(jf.getManifest()
+ .getMainAttributes()
+ .getValue("Class-Path"),
+ "MyUtils.jar");
}
- try {
- p.waitFor();
- } catch (InterruptedException e) {
- throw new RuntimeException(
- format("Process hasn't finished '%s'", pb.command()), e);
- }
- return new Result(p.exitValue(), output);
- }
-
- String toString(InputStream in1, InputStream in2) throws IOException {
- try (ByteArrayOutputStream dst = new ByteArrayOutputStream();
- InputStream concatenated = new SequenceInputStream(in1, in2)) {
- concatenated.transferTo(dst);
- return new String(dst.toByteArray(), "UTF-8");
- }
- }
-
- static class Result {
- final int ec;
- final String output;
-
- private Result(int ec, String output) {
- this.ec = ec;
- this.output = output;
- }
-
- boolean outputContains(String msg) {
- return Arrays.stream(output.split("\\R"))
- .collect(Collectors.joining(" "))
- .contains(msg);
- }
-
- Result assertSuccess() {
- assertTrue(ec == 0, format("ec: %d, output: %s", ec, output));
- return this;
- }
- Result assertFailure() {
- assertTrue(ec != 0, format("ec: %d, output: %s", ec, output));
- return this;
- }
- Result resultChecker(Consumer<Result> r) { r.accept(this); return this; }
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(jarfile));
+ FileUtils.deleteFileTreeWithRetry(Paths.get(usr, "classes"));
}
}
--- a/jdk/test/tools/jar/multiRelease/Basic1.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jar/multiRelease/Basic1.java Thu Jan 19 07:02:33 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
@@ -28,76 +28,65 @@
* jdk.compiler
* jdk.jartool
* @build jdk.test.lib.JDKToolFinder jdk.test.lib.Utils
+ * @build MRTestBase
* @run testng Basic1
*/
-import static org.testng.Assert.*;
-
import org.testng.annotations.*;
-import java.io.*;
import java.nio.file.*;
import java.util.*;
-import java.util.function.Consumer;
-import java.util.jar.*;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.zip.*;
-import jdk.test.lib.JDKToolFinder;
-import jdk.test.lib.Utils;
-
-
-import static java.lang.String.format;
-import static java.lang.System.out;
-
-public class Basic1 {
- private final String src = System.getProperty("test.src", ".");
+public class Basic1 extends MRTestBase {
@BeforeTest
- public void setup() throws IOException {
+ public void setup() throws Throwable {
String test = "test01";
- Path classes = Paths.get("classes", "base");
- Files.createDirectories(classes);
+ Path classes = Paths.get("classes");
+
+ Path base = classes.resolve("base");
+ Files.createDirectories(base);
Path source = Paths.get(src, "data", test, "base", "version");
- javac(classes, source.resolve("Main.java"), source.resolve("Version.java"));
+ javac(base, source.resolve("Main.java"), source.resolve("Version.java"));
- Path v9 = Paths.get("v9");
+ Path v9 = classes.resolve("v9");
Files.createDirectories(v9);
source = Paths.get(src, "data", test, "v9", "version");
javac(v9, source.resolve("Version.java"));
- Path v10 = Paths.get("v10");
+ Path v10 = classes.resolve("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");
+ Path v10_1 = classes.resolve("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
- public void test() throws IOException {
+ public void test() throws Throwable {
String jarfile = "test.jar";
Path classes = Paths.get("classes");
- Path v9 = Paths.get("v9");
- Path v10 = Paths.get("v10");
+
+ Path base = classes.resolve("base");
+ Path v9 = classes.resolve("v9");
+ Path v10 = classes.resolve("v10");
- jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
- "--release", "9", "-C", v9.toString(), ".",
- "--release", "10", "-C", v10.toString(), ".")
- .assertSuccess();
+ jar("cf", jarfile, "-C", base.toString(), ".",
+ "--release", "9", "-C", v9.toString(), ".",
+ "--release", "10", "-C", v10.toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
checkMultiRelease(jarfile, true);
- Map<String,String[]> names = Map.of(
- "version/Main.class",
- new String[] {"classes", "base", "version", "Main.class"},
+ Map<String, String[]> names = Map.of(
+ "version/Main.class",
+ new String[]{"base", "version", "Main.class"},
- "version/Version.class",
- new String[] {"classes", "base", "version", "Version.class"},
+ "version/Version.class",
+ new String[]{"base", "version", "Version.class"},
"META-INF/versions/9/version/Version.class",
new String[] {"v9", "version", "Version.class"},
@@ -109,144 +98,16 @@
compare(jarfile, names);
}
-
@Test
- public void testFail() throws IOException {
+ public void testFail() throws Throwable {
String jarfile = "test.jar";
Path classes = Paths.get("classes");
- Path v10 = Paths.get("v10_1");
-
- jar("cf", jarfile, "-C", classes.resolve("base").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())) {
- assertEquals(jf.isMultiRelease(), expected);
- }
- }
-
- // compares the bytes found in the jar entries with the bytes found in the
- // corresponding data files used to create the entries
- private void compare(String jarfile, Map<String,String[]> names) throws IOException {
- try (JarFile jf = new JarFile(jarfile)) {
- for (String name : names.keySet()) {
- Path path = Paths.get("", names.get(name));
- byte[] b1 = Files.readAllBytes(path);
- byte[] b2;
- JarEntry je = jf.getJarEntry(name);
- try (InputStream is = jf.getInputStream(je)) {
- b2 = is.readAllBytes();
- }
- assertEquals(b1,b2);
- }
- }
- }
-
- /*
- * The following methods were taken from modular jar and other jar tests
- */
-
- void javac(Path dest, Path... sourceFiles) throws IOException {
- String javac = JDKToolFinder.getJDKTool("javac");
-
- List<String> commands = new ArrayList<>();
- commands.add(javac);
- String opts = System.getProperty("test.compiler.opts");
- if (!opts.isEmpty()) {
- commands.addAll(Arrays.asList(opts.split(" +")));
- }
- commands.add("-d");
- commands.add(dest.toString());
- Stream.of(sourceFiles).map(Object::toString).forEach(x -> commands.add(x));
-
- quickFail(run(new ProcessBuilder(commands)));
- }
-
- Result jarWithStdin(File stdinSource, String... args) {
- String jar = JDKToolFinder.getJDKTool("jar");
- List<String> commands = new ArrayList<>();
- commands.add(jar);
- commands.addAll(Utils.getForwardVmOptions());
- Stream.of(args).forEach(x -> commands.add(x));
- ProcessBuilder p = new ProcessBuilder(commands);
- if (stdinSource != null)
- p.redirectInput(stdinSource);
- return run(p);
- }
+ Path base = classes.resolve("base");
+ Path v10 = classes.resolve("v10_1");
- Result jar(String... args) {
- return jarWithStdin(null, args);
- }
-
- void quickFail(Result r) {
- if (r.ec != 0)
- throw new RuntimeException(r.output);
- }
-
- Result run(ProcessBuilder pb) {
- Process p;
- out.printf("Running: %s%n", pb.command());
- try {
- p = pb.start();
- } catch (IOException e) {
- throw new RuntimeException(
- format("Couldn't start process '%s'", pb.command()), e);
- }
-
- String output;
- try {
- output = toString(p.getInputStream(), p.getErrorStream());
- } catch (IOException e) {
- throw new RuntimeException(
- format("Couldn't read process output '%s'", pb.command()), e);
- }
-
- try {
- p.waitFor();
- } catch (InterruptedException e) {
- throw new RuntimeException(
- format("Process hasn't finished '%s'", pb.command()), e);
- }
- return new Result(p.exitValue(), output);
- }
-
- String toString(InputStream in1, InputStream in2) throws IOException {
- try (ByteArrayOutputStream dst = new ByteArrayOutputStream();
- InputStream concatenated = new SequenceInputStream(in1, in2)) {
- concatenated.transferTo(dst);
- return new String(dst.toByteArray(), "UTF-8");
- }
- }
-
- static class Result {
- final int ec;
- final String output;
-
- private Result(int ec, String output) {
- this.ec = ec;
- this.output = output;
- }
-
- boolean outputContains(String msg) {
- return Arrays.stream(output.split("\\R"))
- .collect(Collectors.joining(" "))
- .contains(msg);
- }
-
- Result assertSuccess() {
- assertTrue(ec == 0, format("ec: %d, output: %s", ec, output));
- return this;
- }
- Result assertFailure() {
- assertTrue(ec != 0, format("ec: %d, output: %s", ec, output));
- return this;
- }
- Result resultChecker(Consumer<Result> r) { r.accept(this); return this; }
+ jar("cf", jarfile, "-C", base.toString(), ".",
+ "--release", "10", "-C", v10.toString(), ".")
+ .shouldNotHaveExitValue(SUCCESS)
+ .shouldContain("unexpected versioned entry META-INF/versions/");
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/MRTestBase.java Thu Jan 19 07:02:33 2017 -0800
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+import java.io.*;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Stream;
+import java.util.zip.ZipFile;
+
+import static org.testng.Assert.assertEquals;
+
+public class MRTestBase {
+
+ public static final int SUCCESS = 0;
+
+ protected final String src = System.getProperty("test.src", ".");
+ protected final String usr = System.getProperty("user.dir", ".");
+
+ protected void compile(String test) throws Throwable {
+ Path classes = Paths.get(usr, "classes", "base");
+ Files.createDirectories(classes);
+ Path source = Paths.get(src, "data", test, "base", "version");
+ javac(classes, source.resolve("Main.java"), source.resolve("Version.java"));
+
+ classes = Paths.get(usr, "classes", "v9");
+ Files.createDirectories(classes);
+ source = Paths.get(src, "data", test, "v9", "version");
+ javac(classes, source.resolve("Version.java"));
+
+ classes = Paths.get(usr, "classes", "v10");
+ Files.createDirectories(classes);
+ source = Paths.get(src, "data", test, "v10", "version");
+ javac(classes, source.resolve("Version.java"));
+ }
+
+ protected void checkMultiRelease(String jarFile,
+ boolean expected) throws IOException {
+ try (JarFile jf = new JarFile(new File(jarFile), true,
+ ZipFile.OPEN_READ, JarFile.runtimeVersion())) {
+ assertEquals(jf.isMultiRelease(), expected);
+ }
+ }
+
+ // compares the bytes found in the jar entries with the bytes found in the
+ // corresponding data files used to create the entries
+ protected void compare(String jarfile,
+ Map<String, String[]> names) throws IOException {
+ try (JarFile jf = new JarFile(jarfile)) {
+ for (String name : names.keySet()) {
+ Path path = Paths.get("classes", names.get(name));
+ byte[] b1 = Files.readAllBytes(path);
+ byte[] b2;
+ JarEntry je = jf.getJarEntry(name);
+ try (InputStream is = jf.getInputStream(je)) {
+ b2 = is.readAllBytes();
+ }
+ assertEquals(b1, b2);
+ }
+ }
+ }
+
+ void javac(Path dest, Path... sourceFiles) throws Throwable {
+ String javac = JDKToolFinder.getJDKTool("javac");
+
+ List<String> commands = new ArrayList<>();
+ commands.add(javac);
+ String opts = System.getProperty("test.compiler.opts");
+ if (!opts.isEmpty()) {
+ commands.addAll(Arrays.asList(opts.split(" +")));
+ }
+ commands.addAll(Utils.getForwardVmOptions());
+ commands.add("-d");
+ commands.add(dest.toString());
+ Stream.of(sourceFiles)
+ .map(Object::toString)
+ .forEach(x -> commands.add(x));
+
+ ProcessTools.executeCommand(new ProcessBuilder(commands))
+ .shouldHaveExitValue(SUCCESS);
+ }
+
+ OutputAnalyzer jarWithStdin(File stdinSource,
+ String... args) throws Throwable {
+
+ String jar = JDKToolFinder.getJDKTool("jar");
+ List<String> commands = new ArrayList<>();
+ commands.add(jar);
+ commands.addAll(Utils.getForwardVmOptions());
+ Stream.of(args).forEach(x -> commands.add(x));
+ ProcessBuilder p = new ProcessBuilder(commands);
+ if (stdinSource != null)
+ p.redirectInput(stdinSource);
+ return ProcessTools.executeCommand(p);
+ }
+
+ OutputAnalyzer jar(String... args) throws Throwable {
+ return jarWithStdin(null, args);
+ }
+}
\ No newline at end of file
--- a/jdk/test/tools/jar/multiRelease/data/test04/v9/version/Version.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jar/multiRelease/data/test04/v9/version/Version.java Thu Jan 19 07:02:33 2017 -0800
@@ -8,7 +8,7 @@
protected void doNothing() {
}
- // extra publc method
+ // extra public method
public void anyName() {
}
}
--- a/jdk/test/tools/jlink/DefaultProviderTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/DefaultProviderTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -44,6 +44,7 @@
* @modules java.base/jdk.internal.jimage
* jdk.jdeps/com.sun.tools.classfile
* jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
--- a/jdk/test/tools/jlink/ImageFileCreatorTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/ImageFileCreatorTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -48,6 +48,7 @@
* @author Jean-Francois Denise
* @modules jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.builder
+ * jdk.jlink/jdk.tools.jlink.plugin
* java.base/jdk.internal.jimage
* @run main/othervm -verbose:gc -Xmx1g ImageFileCreatorTest
*/
--- a/jdk/test/tools/jlink/ImageFilePoolTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/ImageFilePoolTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -26,6 +26,7 @@
* @summary Test a pool containing external files.
* @author Andrei Eremeev
* @modules jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run build ImageFilePoolTest
* @run main ImageFilePoolTest
*/
--- a/jdk/test/tools/jlink/IntegrationTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/IntegrationTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -62,6 +62,7 @@
* jdk.jlink/jdk.tools.jlink.builder
* jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
--- a/jdk/test/tools/jlink/JLink2Test.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/JLink2Test.java Thu Jan 19 07:02:33 2017 -0800
@@ -29,6 +29,7 @@
* @modules java.base/jdk.internal.jimage
* jdk.jdeps/com.sun.tools.classfile
* jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
--- a/jdk/test/tools/jlink/JLinkOptionsTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/JLinkOptionsTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -39,6 +39,7 @@
* @modules java.base/jdk.internal.jimage
* jdk.jdeps/com.sun.tools.classfile
* jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
--- a/jdk/test/tools/jlink/JLinkPostProcessingTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/JLinkPostProcessingTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -46,6 +46,7 @@
* @modules java.base/jdk.internal.jimage
* jdk.jdeps/com.sun.tools.classfile
* jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
--- a/jdk/test/tools/jlink/JLinkTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/JLinkTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -48,6 +48,7 @@
* @modules java.base/jdk.internal.jimage
* jdk.jdeps/com.sun.tools.classfile
* jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
* @build tests.*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/ResourceDuplicateCheckTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -0,0 +1,85 @@
+/*
+ * 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 8168254
+ * @summary Detect duplicated resources in packaged modules
+ * @modules jdk.jlink/jdk.tools.jlink.builder
+ * jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
+ * @run build ResourceDuplicateCheckTest
+ * @run main ResourceDuplicateCheckTest
+ */
+
+import java.net.URI;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import jdk.tools.jlink.builder.DefaultImageBuilder;
+import jdk.tools.jlink.internal.ResourcePoolEntryFactory;
+import jdk.tools.jlink.internal.ResourcePoolManager;
+import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
+
+public class ResourceDuplicateCheckTest {
+ public static void main(String[] args) throws Exception {
+ new ResourceDuplicateCheckTest().test();
+ }
+
+ public void test() throws Exception {
+ ResourcePoolManager input = new ResourcePoolManager();
+ // need java.base module info because OS name is retrieved from it from storeFiles
+ input.add(ResourcePoolEntryFactory.create("/java.base/module-info.class",
+ ResourcePoolEntry.Type.CLASS_OR_RESOURCE, getJavaBaseModuleInfo()));
+
+ // same NATIVE_CMD from two different modules
+ input.add(newInMemoryImageFile("/com.acme/bin/myexec",
+ ResourcePoolEntry.Type.NATIVE_CMD, "mylib"));
+ input.add(newInMemoryImageFile("/com.foo/bin/myexec",
+ ResourcePoolEntry.Type.NATIVE_CMD, "mylib"));
+ Path root = Paths.get(System.getProperty("test.classes"));
+ DefaultImageBuilder writer = new DefaultImageBuilder(root, Collections.emptyMap());
+ try {
+ writer.storeFiles(input.resourcePool());
+ } catch (PluginException pe) {
+ if (! pe.getMessage().contains("Duplicate resources:")) {
+ throw new AssertionError("expected duplicate resources message");
+ }
+ }
+ }
+
+ private byte[] getJavaBaseModuleInfo() throws Exception {
+ Path path = FileSystems.
+ getFileSystem(URI.create("jrt:/")).
+ getPath("/modules/java.base/module-info.class");
+ return Files.readAllBytes(path);
+ }
+
+ private static ResourcePoolEntry newInMemoryImageFile(String path,
+ ResourcePoolEntry.Type type, String content) {
+ return ResourcePoolEntryFactory.create(path, type, content.getBytes());
+ }
+}
--- a/jdk/test/tools/jlink/ResourcePoolTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/ResourcePoolTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -26,6 +26,7 @@
* @summary Test a pool containing jimage resources and classes.
* @author Jean-Francois Denise
* @modules jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run build ResourcePoolTest
* @run main ResourcePoolTest
*/
--- a/jdk/test/tools/jlink/plugins/CompressorPluginTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/plugins/CompressorPluginTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -28,6 +28,7 @@
* @modules java.base/jdk.internal.jimage.decompressor
* jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run main CompressorPluginTest
*/
import java.net.URI;
--- a/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -27,6 +27,7 @@
* @author Jean-Francois Denise
* @modules jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run main ExcludeFilesPluginTest
*/
--- a/jdk/test/tools/jlink/plugins/ExcludePluginTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/plugins/ExcludePluginTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -27,6 +27,7 @@
* @author Jean-Francois Denise
* @modules jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run main ExcludePluginTest
*/
--- a/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -27,6 +27,7 @@
* @author Jean-Francois Denise
* @modules jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run main ExcludeVMPluginTest
*/
import java.io.ByteArrayInputStream;
--- a/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -48,6 +48,7 @@
* jdk.jdeps/com.sun.tools.classfile
* jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage
* jdk.compiler
--- a/jdk/test/tools/jlink/plugins/LastSorterTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/plugins/LastSorterTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -25,8 +25,9 @@
* @test
* @summary Test last sorter property
* @author Jean-Francois Denise
- * @modules jdk.jlink/jdk.tools.jlink.internal
- * jdk.jlink/jdk.tools.jlink
+ * @modules jdk.jlink/jdk.tools.jlink
+ * jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run main/othervm LastSorterTest
*/
--- a/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/plugins/PluginsNegativeTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -25,8 +25,9 @@
* @test
* @summary Negative test for ImagePluginStack.
* @author Andrei Eremeev
- * @modules jdk.jlink/jdk.tools.jlink.internal
- * jdk.jlink/jdk.tools.jlink
+ * @modules jdk.jlink/jdk.tools.jlink
+ * jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run main/othervm PluginsNegativeTest
*/
import java.lang.reflect.Layer;
--- a/jdk/test/tools/jlink/plugins/PrevisitorTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/plugins/PrevisitorTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -25,8 +25,9 @@
* @test
* @summary Test previsitor
* @author Andrei Eremeev
- * @modules jdk.jlink/jdk.tools.jlink.internal
- * jdk.jlink/jdk.tools.jlink
+ * @modules jdk.jlink/jdk.tools.jlink
+ * jdk.jlink/jdk.tools.jlink.internal
+ * jdk.jlink/jdk.tools.jlink.plugin
* @run main/othervm PrevisitorTest
*/
import java.nio.ByteOrder;
--- a/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -30,6 +30,7 @@
* java.base/jdk.internal.jimage.decompressor
* jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jmod
* jdk.jlink/jdk.tools.jimage
* jdk.jdeps/com.sun.tools.classfile
--- a/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jlink/plugins/StripDebugPluginTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -30,6 +30,7 @@
* @modules java.base/jdk.internal.jimage
* jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
+ * jdk.jlink/jdk.tools.jlink.plugin
* jdk.jlink/jdk.tools.jimage
* jdk.jlink/jdk.tools.jmod
* jdk.jdeps/com.sun.tools.classfile
--- a/jdk/test/tools/jmod/JmodTest.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/jmod/JmodTest.java Thu Jan 19 07:02:33 2017 -0800
@@ -29,7 +29,7 @@
* @modules jdk.compiler
* jdk.jlink
* @build jdk.testlibrary.FileUtils CompilerUtils
- * @run testng JmodTest
+ * @run testng/othervm -Djava.io.tmpdir=. JmodTest
*/
import java.io.*;
@@ -40,8 +40,10 @@
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.spi.ToolProvider;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import jdk.testlibrary.FileUtils;
+import jdk.testlibrary.JDKToolFinder;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
@@ -593,9 +595,7 @@
findTmpFiles(filename).forEach(tmp -> {
try {
FileUtils.deleteFileIfExistsWithRetry(tmp);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
+ } catch (IOException e) {}
});
String cp = EXPLODED_DIR.resolve("foo").resolve("classes") + File.pathSeparator +
@@ -608,17 +608,25 @@
.assertFailure()
.resultChecker(r -> {
assertContains(r.output, "unnamed package");
- Set<Path> tmpfiles = findTmpFiles(filename).collect(toSet());
+ List<Path> tmpfiles = findTmpFiles(filename);
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"));
+ /*
+ * Returns the list of writeable tmp files with the given prefix.
+ *
+ * Ignore the non-writeable tmp files because this test is possibly
+ * running by another user.
+ */
+ private List<Path> findTmpFiles(String prefix) {
+ Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir"));
+ try (Stream<Path> stream = Files.list(tmpdir)) {
+ return stream.filter(p -> {
+ String fn = p.getFileName().toString();
+ return Files.isWritable(p)
+ && fn.startsWith(prefix) && fn.endsWith(".tmp");
+ }).collect(Collectors.toList());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
--- a/jdk/test/tools/pack200/Utils.java Thu Nov 17 09:51:10 2016 -0800
+++ b/jdk/test/tools/pack200/Utils.java Thu Jan 19 07:02:33 2017 -0800
@@ -111,6 +111,7 @@
compiler("-d",
XCLASSES.getName(),
+ "--add-modules=jdk.jdeps",
"--add-exports=jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED",
"@" + tmpFile.getAbsolutePath());