8206181: ExceptionInInitializerError: improve handling of exceptions in user-provided taglets

Reviewed-by: jjg
This commit is contained in:
Pavel Rappo 2022-01-11 14:28:03 +00:00
parent 86d0abb66b
commit 5aecb37211
8 changed files with 431 additions and 12 deletions

View File

@ -250,23 +250,22 @@ public class TagletManager {
* @param fileManager the file manager to load classes and resources
*/
public void addCustomTag(String classname, JavaFileManager fileManager) {
ClassLoader tagClassLoader = fileManager.getClassLoader(TAGLET_PATH);
if (configuration.workArounds.accessInternalAPI()) {
Module thisModule = getClass().getModule();
Module tagletLoaderUnnamedModule = tagClassLoader.getUnnamedModule();
List<String> pkgs = List.of(
"jdk.javadoc.doclet",
"jdk.javadoc.internal.doclets.toolkit",
"jdk.javadoc.internal.doclets.formats.html");
pkgs.forEach(p -> thisModule.addOpens(p, tagletLoaderUnnamedModule));
}
try {
ClassLoader tagClassLoader;
tagClassLoader = fileManager.getClassLoader(TAGLET_PATH);
if (configuration.workArounds.accessInternalAPI()) {
Module thisModule = getClass().getModule();
Module tagletLoaderUnnamedModule = tagClassLoader.getUnnamedModule();
List<String> pkgs = List.of(
"jdk.javadoc.doclet",
"jdk.javadoc.internal.doclets.toolkit",
"jdk.javadoc.internal.doclets.formats.html");
pkgs.forEach(p -> thisModule.addOpens(p, tagletLoaderUnnamedModule));
}
Class<? extends jdk.javadoc.doclet.Taglet> customTagClass =
tagClassLoader.loadClass(classname).asSubclass(jdk.javadoc.doclet.Taglet.class);
jdk.javadoc.doclet.Taglet instance = customTagClass.getConstructor().newInstance();
registerTaglet(instance);
} catch (ReflectiveOperationException exc) {
} catch (ReflectiveOperationException | ExceptionInInitializerError | ClassCastException exc) {
messages.error("doclet.Error_taglet_not_registered", exc.getClass().getName(),
classname);
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.Element;
import com.sun.source.doctree.DocTree;
import jdk.javadoc.doclet.Taglet;
public class ClassCastExceptionTaglet /* does NOT implement jdk.javadoc.doclet.Taglet */ {
public Set<Taglet.Location> getAllowedLocations() {
return EnumSet.allOf(Taglet.Location.class);
}
public boolean isInlineTag() {
return false;
}
public String getName() {
return "ClassCastExceptionTaglet";
}
public String toString(List<? extends DocTree> tags, Element element) {
return "";
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.Element;
import com.sun.source.doctree.DocTree;
import jdk.javadoc.doclet.Taglet;
public class ExceptionInInitializerErrorTaglet implements Taglet {
static {
if (true) {
throw new RuntimeException();
}
}
@Override
public Set<Taglet.Location> getAllowedLocations() {
return EnumSet.allOf(Taglet.Location.class);
}
@Override
public boolean isInlineTag() {
return false;
}
@Override
public String getName() {
return "ExceptionInInitializerErrorTaglet";
}
@Override
public String toString(List<? extends DocTree> tags, Element element) {
return "";
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.Element;
import com.sun.source.doctree.DocTree;
import jdk.javadoc.doclet.Taglet;
public abstract class InstantiationExceptionTaglet implements Taglet {
@Override
public Set<Taglet.Location> getAllowedLocations() {
return EnumSet.allOf(Taglet.Location.class);
}
@Override
public boolean isInlineTag() {
return false;
}
@Override
public String getName() {
return "InstantiationExceptionTaglet";
}
@Override
public String toString(List<? extends DocTree> tags, Element element) {
return "";
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.Element;
import com.sun.source.doctree.DocTree;
import jdk.javadoc.doclet.Taglet;
public class InvocationTargetExceptionTaglet implements Taglet {
public InvocationTargetExceptionTaglet() {
throw new RuntimeException();
}
@Override
public Set<Location> getAllowedLocations() {
return EnumSet.allOf(Location.class);
}
@Override
public boolean isInlineTag() {
return false;
}
@Override
public String getName() {
return "InvocationTargetExceptionTaglet";
}
@Override
public String toString(List<? extends DocTree> tags, Element element) {
return "";
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.Element;
import com.sun.source.doctree.DocTree;
import jdk.javadoc.doclet.Taglet;
public class NoSuchMethodExceptionNoNullaryCtorTaglet implements Taglet {
public NoSuchMethodExceptionNoNullaryCtorTaglet(Object obj) {}
@Override
public Set<Location> getAllowedLocations() {
return EnumSet.allOf(Taglet.Location.class);
}
@Override
public boolean isInlineTag() {
return false;
}
@Override
public String getName() {
return "NoSuchMethodExceptionNoNullaryCtorTaglet";
}
@Override
public String toString(List<? extends DocTree> tags, Element element) {
return "";
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.Element;
import com.sun.source.doctree.DocTree;
import jdk.javadoc.doclet.Taglet;
public class NoSuchMethodExceptionPrivateCtorTaglet implements Taglet {
private NoSuchMethodExceptionPrivateCtorTaglet() {}
@Override
public Set<Taglet.Location> getAllowedLocations() {
return EnumSet.allOf(Taglet.Location.class);
}
@Override
public boolean isInlineTag() {
return false;
}
@Override
public String getName() {
return "NoSuchMethodExceptionPrivateCtorTaglet";
}
@Override
public String toString(List<? extends DocTree> tags, Element element) {
return "";
}
}

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2021, 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 8206181
* @library ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
* @build javadoc.tester.* *
* @run main TestRegistrationErrors
*/
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import javadoc.tester.JavadocTester;
public class TestRegistrationErrors extends JavadocTester {
public static void main(String... args) throws Exception {
TestRegistrationErrors tester = new TestRegistrationErrors();
tester.runTests();
}
@Test
public void test() throws Exception {
try (Stream<Path> tagletClasses = findTagletClasses()) {
tagletClasses.forEach(p -> {
String tagletName = getTagletName(p);
javadoc("-d", "out-" + tagletName, // a directory per taglet
"-tagletpath", System.getProperty("test.classes"),
"-taglet", tagletName,
testSrc("TestRegistrationErrors.java")); // specify this file
checkExit(Exit.ERROR);
new OutputChecker(Output.OUT).checkUnique(Pattern.compile("thrown while trying to register Taglet"));
checkNoCrashes();
});
}
}
private static Stream<Path> findTagletClasses() throws IOException {
var path = Path.of(System.getProperty("test.classes"));
return Files.find(path, Integer.MAX_VALUE,
(p, a) -> a.isRegularFile() && p.toString().endsWith("Taglet.class"));
}
private static String getTagletName(Path tagletClass) {
Path fileName = tagletClass.getFileName();
return fileName.toString().substring(0, fileName.toString().lastIndexOf('.'));
}
protected void checkNoCrashes() {
checking("check crashes");
Matcher matcher = Pattern.compile("\\s*at.*\\(.*\\.java:\\d+\\)")
.matcher(getOutput(Output.STDERR));
if (!matcher.find()) {
passed("");
} else {
failed("Looks like a stacktrace: " + matcher.group());
}
}
}