blob: f4a17aadda3a0e4b8ca08429e7a35e634fa0ad17 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.bcel.classfile;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Stream;
import org.apache.bcel.Const;
import org.apache.commons.lang3.stream.Streams;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
/**
* Tests {@code module-info.class} files.
*/
public final class ConstantPoolModuleAccessTest {
static Stream<URL> testJREModules() throws IOException {
return Streams.of(ConstantPoolModuleAccessTest.class.getClassLoader().getResources("module-info.class"));
}
@ParameterizedTest
@MethodSource
void testJREModules(final URL url) throws Exception {
try (InputStream inputStream = url.openStream()) {
final ClassParser classParser = new ClassParser(inputStream, "module-info.class");
final JavaClass javaClass = classParser.parse();
final ConstantPool constantPool = javaClass.getConstantPool();
final EmptyVisitor visitor = new EmptyVisitor() {
@Override
public void visitModule(final Module obj) {
final String urlPath = url.getPath();
if (urlPath.contains("/commons-")) {
assertEquals(4096, obj.getModuleFlags(), url.toString());
} else {
assertEquals(0, obj.getModuleFlags(), url.toString());
}
final String[] usedClassNames = obj.getUsedClassNames(constantPool, true);
if (urlPath.contains("junit-jupiter-engine")) {
assertEquals(1, usedClassNames.length);
assertEquals("org.junit.jupiter.api.extension.Extension", usedClassNames[0]);
} else if (urlPath.contains("junit-platform-launcher")) {
final List<String> expected = new ArrayList<>();
expected.add("org.junit.platform.engine.TestEngine");
expected.add("org.junit.platform.launcher.LauncherDiscoveryListener");
expected.add("org.junit.platform.launcher.LauncherInterceptor");
expected.add("org.junit.platform.launcher.LauncherSessionListener");
expected.add("org.junit.platform.launcher.PostDiscoveryFilter");
expected.add("org.junit.platform.launcher.TestExecutionListener");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("junit-platform-common")) {
final List<String> expected = new ArrayList<>();
expected.add("org.junit.platform.commons.support.scanning.ClasspathScanner");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("junit-platform-engine")) {
final List<String> expected = new ArrayList<>();
expected.add("org.junit.platform.engine.discovery.DiscoverySelectorIdentifierParser");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/java.rmi/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("java.rmi.server.RMIClassLoaderSpi");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/java.xml/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("javax.xml.datatype.DatatypeFactory");
expected.add("javax.xml.parsers.DocumentBuilderFactory");
expected.add("javax.xml.parsers.SAXParserFactory");
expected.add("javax.xml.stream.XMLEventFactory");
expected.add("javax.xml.stream.XMLInputFactory");
expected.add("javax.xml.stream.XMLOutputFactory");
expected.add("javax.xml.transform.TransformerFactory");
expected.add("javax.xml.validation.SchemaFactory");
expected.add("javax.xml.xpath.XPathFactory");
expected.add("org.xml.sax.XMLReader");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/java.datatransfer/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("sun.datatransfer.DesktopDatatransferService");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/java.desktop/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("java.awt.im.spi.InputMethodDescriptor");
expected.add("javax.accessibility.AccessibilityProvider");
expected.add("javax.imageio.spi.ImageInputStreamSpi");
expected.add("javax.imageio.spi.ImageOutputStreamSpi");
expected.add("javax.imageio.spi.ImageReaderSpi");
expected.add("javax.imageio.spi.ImageTranscoderSpi");
expected.add("javax.imageio.spi.ImageWriterSpi");
expected.add("javax.print.PrintServiceLookup");
expected.add("javax.print.StreamPrintServiceFactory");
expected.add("javax.sound.midi.spi.MidiDeviceProvider");
expected.add("javax.sound.midi.spi.MidiFileReader");
expected.add("javax.sound.midi.spi.MidiFileWriter");
expected.add("javax.sound.midi.spi.SoundbankReader");
expected.add("javax.sound.sampled.spi.AudioFileReader");
expected.add("javax.sound.sampled.spi.AudioFileWriter");
expected.add("javax.sound.sampled.spi.FormatConversionProvider");
expected.add("javax.sound.sampled.spi.MixerProvider");
expected.add("sun.swing.InteropProvider");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/java.naming/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("javax.naming.ldap.StartTlsResponse");
expected.add("javax.naming.spi.InitialContextFactory");
if (javaClass.getMajor() > Const.MAJOR_11) {
expected.add("javax.naming.ldap.spi.LdapDnsProvider");
}
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/java.prefs/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("java.util.prefs.PreferencesFactory");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/java.base/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("java.lang.System$LoggerFinder");
expected.add("java.net.ContentHandlerFactory");
if (javaClass.getMajor() > Const.MAJOR_17) {
expected.add("java.net.spi.InetAddressResolverProvider");
}
expected.add("java.net.spi.URLStreamHandlerProvider");
expected.add("java.nio.channels.spi.AsynchronousChannelProvider");
expected.add("java.nio.channels.spi.SelectorProvider");
expected.add("java.nio.charset.spi.CharsetProvider");
expected.add("java.nio.file.spi.FileSystemProvider");
expected.add("java.nio.file.spi.FileTypeDetector");
expected.add("java.security.Provider");
expected.add("java.text.spi.BreakIteratorProvider");
expected.add("java.text.spi.CollatorProvider");
expected.add("java.text.spi.DateFormatProvider");
expected.add("java.text.spi.DateFormatSymbolsProvider");
expected.add("java.text.spi.DecimalFormatSymbolsProvider");
expected.add("java.text.spi.NumberFormatProvider");
expected.add("java.time.chrono.AbstractChronology");
expected.add("java.time.chrono.Chronology");
expected.add("java.time.zone.ZoneRulesProvider");
if (javaClass.getMajor() > Const.MAJOR_11 && javaClass.getMajor() < Const.MAJOR_24) {
expected.add("java.util.random.RandomGenerator");
}
expected.add("java.util.spi.CalendarDataProvider");
expected.add("java.util.spi.CalendarNameProvider");
expected.add("java.util.spi.CurrencyNameProvider");
expected.add("java.util.spi.LocaleNameProvider");
expected.add("java.util.spi.ResourceBundleControlProvider");
expected.add("java.util.spi.ResourceBundleProvider");
expected.add("java.util.spi.TimeZoneNameProvider");
expected.add("java.util.spi.ToolProvider");
expected.add("javax.security.auth.spi.LoginModule");
if (javaClass.getMajor() > Const.MAJOR_17) {
expected.add("jdk.internal.io.JdkConsoleProvider");
}
expected.add("jdk.internal.logger.DefaultLoggerFinder");
expected.add("sun.text.spi.JavaTimeDateTimePatternProvider");
expected.add("sun.util.locale.provider.LocaleDataMetaInfo");
if (javaClass.getMajor() <= Const.MAJOR_25) {
expected.add("sun.util.resources.LocaleData$CommonResourceBundleProvider");
expected.add("sun.util.resources.LocaleData$SupplementaryResourceBundleProvider");
} else {
expected.add("sun.util.resources.LocaleData$LocaleDataResourceBundleProvider");
}
expected.add("sun.util.spi.CalendarProvider");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.management.agent/module-info.class") && javaClass.getMajor() < Const.MAJOR_21) {
final List<String> expected = new ArrayList<>();
expected.add("jdk.internal.agent.spi.AgentProvider");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/java.management/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("javax.management.remote.JMXConnectorProvider");
expected.add("javax.management.remote.JMXConnectorServerProvider");
expected.add("sun.management.spi.PlatformMBeanProvider");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/java.sql/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("java.sql.Driver");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.httpserver/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("com.sun.net.httpserver.spi.HttpServerProvider");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/java.sql.rowset/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("javax.sql.rowset.RowSetFactory");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/java.compiler/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("javax.tools.DocumentationTool");
expected.add("javax.tools.JavaCompiler");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/java.scripting/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("javax.script.ScriptEngineFactory");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.dynalink/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("jdk.dynalink.linker.GuardingDynamicLinkerExporter");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.jdi/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("com.sun.jdi.connect.Connector");
expected.add("com.sun.jdi.connect.spi.TransportService");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.compiler/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("javax.annotation.processing.Processor");
expected.add("com.sun.source.util.Plugin");
if (javaClass.getMajor() > Const.MAJOR_11) {
expected.add("com.sun.tools.doclint.DocLint");
}
expected.add("com.sun.tools.javac.platform.PlatformProvider");
if (javaClass.getMajor() > Const.MAJOR_23) {
expected.add("com.sun.tools.javac.api.JavacTrees$DocCommentTreeTransformer");
}
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.jconsole/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("com.sun.tools.jconsole.JConsolePlugin");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.attach/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("com.sun.tools.attach.spi.AttachProvider");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.jshell/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("jdk.jshell.spi.ExecutionControlProvider");
expected.add("jdk.internal.editor.spi.BuildInEditorProvider");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.internal.le/module-info.class")) {
final List<String> expected = new ArrayList<>();
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.jlink/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("jdk.tools.jlink.plugin.Plugin");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.internal.jvmstat/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("sun.jvmstat.monitor.MonitoredHostService");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.jpackage/module-info.class")) {
final List<String> expected = new ArrayList<>();
if (javaClass.getMajor() <= Const.MAJOR_25) {
expected.add("jdk.jpackage.internal.Bundler");
expected.add("jdk.jpackage.internal.Bundlers");
} else {
expected.add("jdk.jpackage.internal.cli.CliBundlingEnvironment");
}
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.naming.ldap/module-info.class")) {
final List<String> expected = new ArrayList<>();
expected.add("com.sun.jndi.ldap.spi.LdapDnsProvider");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.jsobject/module-info.class") && javaClass.getMajor() == Const.MAJOR_11) {
final List<String> expected = new ArrayList<>();
expected.add("jdk.internal.netscape.javascript.spi.JSObjectProvider");
assertEquals(expected, Arrays.asList(usedClassNames));
} else if (urlPath.contains("/jdk.jdeps/module-info.class") && javaClass.getMajor() > Const.MAJOR_24) {
final List<String> expected = new ArrayList<>();
expected.add("com.sun.tools.javac.platform.PlatformProvider");
assertEquals(expected, Arrays.asList(usedClassNames));
} else {
assertEquals(0, usedClassNames.length, () -> "Found " + Arrays.toString(usedClassNames) + " in " + urlPath);
}
super.visitModule(obj);
}
@Override
public void visitModuleExports(final ModuleExports obj) {
assertEquals(0, obj.getExportsFlags(), url.toString());
final String packageName = obj.getPackageName(constantPool);
final String[] toModuleNames = obj.getToModuleNames(constantPool);
if (url.getPath().contains("junit-platform-commons")) {
final Set<String> expected = new TreeSet<>();
expected.add("org.junit.jupiter.api");
expected.add("org.junit.jupiter.engine");
expected.add("org.junit.jupiter.migrationsupport");
expected.add("org.junit.jupiter.params");
expected.add("org.junit.platform.console");
expected.add("org.junit.platform.engine");
expected.add("org.junit.platform.launcher");
expected.add("org.junit.platform.reporting");
expected.add("org.junit.platform.runner");
expected.add("org.junit.platform.suite.api");
switch (packageName) {
case "org.junit.platform.commons.util":
expected.add("org.junit.platform.suite.commons");
expected.add("org.junit.platform.suite.engine");
expected.add("org.junit.platform.testkit");
expected.add("org.junit.vintage.engine");
expected.add("org.junit.platform.jfr");
assertEquals(expected, new TreeSet<>(Arrays.asList(toModuleNames)));
break;
case "org.junit.platform.commons.logging":
expected.add("org.junit.platform.suite.engine");
expected.add("org.junit.platform.testkit");
expected.add("org.junit.vintage.engine");
assertEquals(expected, new TreeSet<>(Arrays.asList(toModuleNames)));
break;
default:
assertEquals(0, toModuleNames.length);
break;
}
}
super.visitModuleExports(obj);
}
@Override
public void visitModuleOpens(final ModuleOpens obj) {
assertEquals(0, obj.getOpensFlags(), url.toString());
final String packageName = obj.getPackageName(constantPool);
final String[] toModuleNames = obj.getToModuleNames(constantPool);
final String urlPath = url.getPath();
if (urlPath.contains("junit-jupiter-engine")) {
assertEquals("org.junit.jupiter.engine.extension", packageName);
assertEquals(1, toModuleNames.length);
assertEquals("org.junit.platform.commons", toModuleNames[0]);
} else if (urlPath.contains("junit-jupiter-api")) {
assertEquals("org.junit.jupiter.api.condition", packageName);
assertEquals(1, toModuleNames.length);
assertEquals("org.junit.platform.commons", toModuleNames[0]);
}
super.visitModuleOpens(obj);
}
@Override
public void visitModuleProvides(final ModuleProvides obj) {
final String interfaceName = obj.getInterfaceName(constantPool);
final String[] implementationClassNames = obj.getImplementationClassNames(constantPool, true);
final String urlPath = url.getPath();
if (urlPath.contains("junit-jupiter-engine")) {
assertEquals("org.junit.platform.engine.TestEngine", interfaceName);
assertEquals(1, implementationClassNames.length);
assertEquals("org.junit.jupiter.engine.JupiterTestEngine", implementationClassNames[0]);
} else if (urlPath.contains("junit-platform-launcher")) {
assertEquals("org.junit.platform.launcher.TestExecutionListener", interfaceName);
assertEquals(1, implementationClassNames.length);
assertEquals("org.junit.platform.launcher.listeners.UniqueIdTrackingListener", implementationClassNames[0]);
}
super.visitModuleProvides(obj);
}
@Override
public void visitModuleRequires(final ModuleRequires obj) {
if (url.getPath().contains("junit-jupiter-engine")) {
final String moduleName = obj.getModuleName(constantPool);
final Map<String, Integer> expected = new HashMap<>();
expected.put("java.base", 32768);
expected.put("org.apiguardian.api", 64);
expected.put("org.junit.jupiter.api", 0);
expected.put("org.junit.platform.commons", 0);
expected.put("org.junit.platform.engine", 0);
expected.put("org.opentest4j", 0);
assertTrue(expected.containsKey(moduleName));
assertEquals(expected.get(moduleName), obj.getRequiresFlags(), moduleName);
}
super.visitModuleRequires(obj);
}
};
javaClass.accept(new DescendingVisitor(javaClass, visitor));
}
}
}