提交 63cc742a 编写于 作者: B bchristi

8176329: jdeps to detect MR jar file and output a warning

Reviewed-by: mchung
上级 066fbafb
/* /*
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -34,8 +34,10 @@ import java.nio.file.Path; ...@@ -34,8 +34,10 @@ import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor; import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.util.*; import java.util.*;
import java.util.jar.Attributes;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.jar.Manifest;
/** /**
* ClassFileReader reads ClassFile(s) of a given path that can be * ClassFileReader reads ClassFile(s) of a given path that can be
...@@ -154,6 +156,8 @@ public class ClassFileReader { ...@@ -154,6 +156,8 @@ public class ClassFileReader {
} }
} }
public boolean isMultiReleaseJar() throws IOException { return false; }
public String toString() { public String toString() {
return path.toString(); return path.toString();
} }
...@@ -290,6 +294,16 @@ public class ClassFileReader { ...@@ -290,6 +294,16 @@ public class ClassFileReader {
} }
}; };
} }
@Override
public boolean isMultiReleaseJar() throws IOException {
Manifest mf = this.jarfile.getManifest();
if (mf != null) {
Attributes atts = mf.getMainAttributes();
return "true".equalsIgnoreCase(atts.getValue("Multi-Release"));
}
return false;
}
} }
class JarFileIterator implements Iterator<ClassFile> { class JarFileIterator implements Iterator<ClassFile> {
......
/* /*
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -515,6 +515,13 @@ class JdepsTask { ...@@ -515,6 +515,13 @@ class JdepsTask {
// add all classpath archives to the source locations for reporting // add all classpath archives to the source locations for reporting
sourceLocations.addAll(classpaths); sourceLocations.addAll(classpaths);
// warn about Multi-Release jars
for (Archive a : sourceLocations) {
if (a.reader().isMultiReleaseJar()) {
warning("warn.mrjar.usejdk9", a.getPathName());
}
}
// Work queue of names of classfiles to be searched. // Work queue of names of classfiles to be searched.
// Entries will be unique, and for classes that do not yet have // Entries will be unique, and for classes that do not yet have
// dependencies in the results map. // dependencies in the results map.
......
...@@ -99,6 +99,10 @@ subject to be removed or changed incompatibly and could break your application.\ ...@@ -99,6 +99,10 @@ subject to be removed or changed incompatibly and could break your application.\
Please modify your code to eliminate dependency on any JDK internal APIs.\n\ Please modify your code to eliminate dependency on any JDK internal APIs.\n\
For the most recent update on JDK internal API replacements, please check:\n\ For the most recent update on JDK internal API replacements, please check:\n\
{0} {0}
warn.mrjar.usejdk9=\
{0} is a multi-release jar file.\n\
All versioned entries are analyzed. To analyze the entries for a specific\n\
version, use a newer version of jdeps (JDK 9 or later) \"--multi-release\" option.
artifact.not.found=not found artifact.not.found=not found
jdeps.wiki.url=https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool jdeps.wiki.url=https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool
// No translation needed // No translation needed
com.sun.crypto.provider.SunJCE=Use java.security.Security.getProvider(provider-name) @since 1.3 com.sun.crypto.provider.SunJCE=Use java.security.Security.getProvider(provider-name) @since 1.3
com.sun.image.codec=Use javax.imageio @since 1.4
com.sun.org.apache.xml.internal.security=Use java.xml.crypto @since 1.6 com.sun.org.apache.xml.internal.security=Use java.xml.crypto @since 1.6
com.sun.org.apache.xml.internal.security.utils.Base64=Use java.util.Base64 @since 1.8 com.sun.org.apache.xml.internal.security.utils.Base64=Use java.util.Base64 @since 1.8
com.sun.org.apache.xml.internal.resolver=Use javax.xml.catalog @since 9
com.sun.net.ssl=Use javax.net.ssl @since 1.4 com.sun.net.ssl=Use javax.net.ssl @since 1.4
com.sun.net.ssl.internal.ssl.Provider=Use java.security.Security.getProvider(provider-name) @since 1.3 com.sun.net.ssl.internal.ssl.Provider=Use java.security.Security.getProvider(provider-name) @since 1.3
com.sun.rowset=Use javax.sql.rowset.RowSetProvider @since 1.7 com.sun.rowset=Use javax.sql.rowset.RowSetProvider @since 1.7
com.sun.tools.doclets.standard=Use jdk.javadoc.doclets.StandardDoclet @since 9.
com.sun.tools.javac.tree=Use com.sun.source @since 1.6 com.sun.tools.javac.tree=Use com.sun.source @since 1.6
com.sun.tools.javac=Use javax.tools and javax.lang.model @since 1.6 com.sun.tools.javac=Use javax.tools and javax.lang.model @since 1.6
sun.awt.image.codec=Use javax.imageio @since 1.4 java.awt.peer=Should not use. See https://bugs.openjdk.java.net/browse/JDK-8037739
sun.misc.BASE64Encoder=Use java.util.Base64 @since 1.8 java.awt.dnd.peer=Should not use. See https://bugs.openjdk.java.net/browse/JDK-8037739
sun.misc.BASE64Decoder=Use java.util.Base64 @since 1.8 jdk.internal.ref.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 or java.lang.ref.Cleaner @since 9
sun.misc.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 sun.awt.CausedFocusEvent=Use java.awt.event.FocusEvent::getCause @since 9
sun.misc.Service=Use java.util.ServiceLoader @since 1.6 sun.font.FontUtilities=See java.awt.Font.textRequiresLayout @since 9
sun.reflect.Reflection=See http://openjdk.java.net/jeps/260
sun.reflect.ReflectionFactory=See http://openjdk.java.net/jeps/260
sun.misc.Unsafe=See http://openjdk.java.net/jeps/260
sun.misc.Signal=See http://openjdk.java.net/jeps/260
sun.misc.SignalHandler=See http://openjdk.java.net/jeps/260
sun.security.action=Use java.security.PrivilegedAction @since 1.1 sun.security.action=Use java.security.PrivilegedAction @since 1.1
sun.security.krb5=Use com.sun.security.jgss sun.security.krb5=Use com.sun.security.jgss
sun.security.provider.PolicyFile=Use java.security.Policy.getInstance("JavaPolicy", new URIParameter(uri)) @since 1.6 sun.security.provider.PolicyFile=Use java.security.Policy.getInstance("JavaPolicy", new URIParameter(uri)) @since 1.6
sun.security.provider.Sun=Use java.security.Security.getProvider(provider-name) @since 1.3 sun.security.provider.Sun=Use java.security.Security.getProvider(provider-name) @since 1.3
sun.security.util.HostnameChecker=Use javax.net.ssl.SSLParameters.setEndpointIdentificationAlgorithm("HTTPS") @since 1.7\n\
or javax.net.ssl.HttpsURLConnection.setHostnameVerifier() @since 1.4
sun.security.util.SecurityConstants=Use appropriate java.security.Permission subclass @since 1.1 sun.security.util.SecurityConstants=Use appropriate java.security.Permission subclass @since 1.1
sun.security.x509.X500Name=Use javax.security.auth.x500.X500Principal @since 1.4 sun.security.x509.X500Name=Use javax.security.auth.x500.X500Principal @since 1.4
sun.tools.jar=Use java.util.jar or jar tool @since 1.2 sun.tools.jar=Use java.util.jar @since 1.2
sun.tools.jar.Main=Use java.util.spi.ToolProvider @since 9
# Internal APIs removed in JDK 9
com.apple.eawt=Use java.awt.Desktop @since 9. See http://openjdk.java.net/jeps/272
com.apple.concurrent=Removed in JDK 9. See https://bugs.openjdk.java.net/browse/JDK-8148187
com.sun.image.codec.jpeg=Use javax.imageio @since 1.4
sun.awt.image.codec=Use javax.imageio @since 1.4
sun.misc.BASE64Encoder=Use java.util.Base64 @since 1.8
sun.misc.BASE64Decoder=Use java.util.Base64 @since 1.8
sun.misc.ClassLoaderUtil=Use java.net.URLClassLoader.close() @since 1.7
sun.misc.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 or java.lang.ref.Cleaner @since 9.\n\
See http://openjdk.java.net/jeps/260.
sun.misc.Service=Use java.util.ServiceLoader @since 1.6
sun.misc=Removed in JDK 9. See http://openjdk.java.net/jeps/260
sun.reflect=Removed in JDK 9. See http://openjdk.java.net/jeps/260
/*
* 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 8176329
* @summary Test for jdeps warning when it encounters a multi-release jar
* @run testng MRJarWarning
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import org.testng.Assert;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class MRJarWarning {
private static final String WARNING = " is a multi-release jar file";
private static final String MRJAR_ATTR = "Multi-Release";
Path mrjar1;
Path mrjar2;
Path nonMRjar;
Path mrjarAllCaps;
private Attributes defaultAttributes;
@BeforeSuite
public void setup() throws IOException {
defaultAttributes = new Attributes();
defaultAttributes.putValue("Manifest-Version", "1.0");
defaultAttributes.putValue("Created-By", "1.8.0-internal");
mrjar1 = Paths.get("mrjar1.jar");
mrjar2 = Paths.get("mrjar2.jar");
nonMRjar = Paths.get("nonMRjar.jar");
mrjarAllCaps = Paths.get("mrjarAllCaps.jar");
Attributes mrJarAttrs = new Attributes(defaultAttributes);
mrJarAttrs.putValue(MRJAR_ATTR, "true");
build(mrjar1, mrJarAttrs);
build(mrjar2, mrJarAttrs);
build(nonMRjar, defaultAttributes);
// JEP 238 - "Multi-Release JAR Files" states that the attribute name
// and value are case insensitive. Try with all caps to ensure that
// jdeps still recognizes a multi-release jar.
Attributes allCapsAttrs = new Attributes(defaultAttributes);
allCapsAttrs.putValue(MRJAR_ATTR.toUpperCase(), "TRUE");
build(mrjarAllCaps, allCapsAttrs);
}
@DataProvider(name="provider")
private Object[][] args() {
// jdeps warning messages may be localized.
// This test only checks for the English version. Return an empty
// array (skip testing) if the default language is not English.
String language = Locale.getDefault().getLanguage();
System.out.println("Language: " + language);
if ("en".equals(language)) {
return new Object[][] {
// one mrjar arg
{ Arrays.asList(mrjar1.toString()),
Arrays.asList(mrjar1)},
// two mrjar args
{ Arrays.asList(mrjar1.toString(), mrjar2.toString()),
Arrays.asList(mrjar1, mrjar2)},
// one mrjar arg, with mrjar on classpath
{ Arrays.asList("-cp", mrjar2.toString(), mrjar1.toString()),
Arrays.asList(mrjar1, mrjar2)},
// non-mrjar arg, with mrjar on classpath
{ Arrays.asList("-cp", mrjar1.toString(), nonMRjar.toString()),
Arrays.asList(mrjar1)},
// mrjar arg with jar attribute name/value in ALL CAPS
{ Arrays.asList(mrjarAllCaps.toString()),
Arrays.asList(mrjarAllCaps)},
// non-mrjar arg
{ Arrays.asList(nonMRjar.toString()),
Collections.emptyList()}
};
} else {
System.out.println("Non-English language \""+ language +
"\"; test passes superficially");
return new Object[][]{};
}
}
/* Run jdeps with the arguments given in 'args', and confirm that a warning
* is issued for each Multi-Release jar in 'expectedMRpaths'.
*/
@Test(dataProvider="provider")
public void checkWarning(List<String> args, List<Path> expectedMRpaths) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
int rc = com.sun.tools.jdeps.Main.run(args.toArray(new String[args.size()]), pw);
pw.close();
expectedMRJars(sw.toString(), expectedMRpaths);
Assert.assertEquals(rc, 0, "non-zero exit code from jdeps");
}
/* Confirm that warnings for the specified paths are in the output (or that
* warnings are absent if 'paths' is empty).
* Doesn't check for extra, unexpected warnings.
*/
private static void expectedMRJars(String output, List<Path> paths) {
if (paths.isEmpty()) {
Assert.assertFalse(output.contains(WARNING),
"Expected no mrjars, but found:\n" + output);
} else {
for (Path path : paths) {
String expect = "Warning: " + path.toString() + WARNING;
Assert.assertTrue(output.contains(expect),
"Did not find:\n" + expect + "\nin:\n" + output + "\n");
}
}
}
/* Build a jar at the expected path, containing the given attributes */
private static void build(Path path, Attributes attributes) throws IOException {
try (OutputStream os = Files.newOutputStream(path);
JarOutputStream jos = new JarOutputStream(os)) {
JarEntry me = new JarEntry("META-INF/MANIFEST.MF");
jos.putNextEntry(me);
Manifest manifest = new Manifest();
manifest.getMainAttributes().putAll(attributes);
manifest.write(jos);
jos.closeEntry();
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册