diff options
author | Stefan Bodewig <bodewig@apache.org> | 2021-10-28 16:08:05 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-28 16:08:05 +0200 |
commit | 44582f1c7952464373c099b5ea56b1dcc46bb27a (patch) | |
tree | d26e06616a17299d687c4d68d7c9ef295ab432ae | |
parent | 832157cbf1a97a21aae3293e665ae682b2a0a69e (diff) | |
parent | cd1bb841b12184ea08da2c56b855ecc583aeafb3 (diff) | |
download | ant-44582f1c7952464373c099b5ea56b1dcc46bb27a.tar.gz |
Merge pull request #161 from twogee/jakarta-mail
Use Jakarta EE
-rw-r--r-- | build.xml | 13 | ||||
-rw-r--r-- | fetch.xml | 6 | ||||
-rw-r--r-- | lib/libraries.properties | 4 | ||||
-rw-r--r-- | src/etc/poms/ant-jakartamail/pom.xml | 98 | ||||
-rw-r--r-- | src/etc/poms/ant-javamail/pom.xml | 4 | ||||
-rw-r--r-- | src/etc/poms/ant/pom.xml | 2 | ||||
-rw-r--r-- | src/etc/poms/pom.xml | 1 | ||||
-rw-r--r-- | src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java | 37 | ||||
-rw-r--r-- | src/main/org/apache/tools/ant/taskdefs/email/JakartaMimeMailer.java | 340 | ||||
-rw-r--r-- | src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java | 2 | ||||
-rw-r--r-- | src/main/org/apache/tools/ant/util/ClasspathUtils.java | 4 |
11 files changed, 498 insertions, 13 deletions
@@ -277,6 +277,12 @@ </or> </selector> + <selector id="needs.jakartamail"> + <or> + <filename name="${ant.package}/taskdefs/email/JakartaMimeMailer*"/> + </or> + </selector> + <selector id="needs.netrexx"> <filename name="${optional.package}/NetRexxC*"/> </selector> @@ -360,6 +366,7 @@ <selector refid="needs.imageio"/> <selector refid="needs.jai"/> <selector refid="needs.javamail"/> + <selector refid="needs.jakartamail"/> <selector refid="needs.jdepend"/> <selector refid="needs.jmf"/> <selector refid="needs.jsch"/> @@ -507,6 +514,9 @@ <available property="javamail.present" classname="javax.mail.Transport" classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/> + <available property="jakartamail.present" + classname="jakarta.mail.Transport" + classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/> <available property="graaljs.present" classname="com.oracle.truffle.js.scriptengine.GraalJSScriptEngine" classpathref="classpath" ignoresystemclasses="${ignoresystemclasses}"/> @@ -704,6 +714,7 @@ <selector refid="needs.commons-logging" unless="commons.logging.present"/> <selector refid="needs.apache-bsf" unless="bsf.present"/> <selector refid="needs.javamail" unless="javamail.present"/> + <selector refid="needs.jakartamail" unless="jakartamail.present"/> <selector refid="needs.netrexx" unless="netrexx.present"/> <selector refid="needs.commons-net" unless="commons.net.present"/> <selector refid="needs.antlr" unless="antlr.present"/> @@ -867,6 +878,7 @@ <optional-jar dep="commons-logging"/> <optional-jar dep="apache-bsf"/> <optional-jar dep="javamail"/> + <optional-jar dep="jakartamail"/> <optional-jar dep="netrexx"/> <optional-jar dep="commons-net"/> <optional-jar dep="antlr"/> @@ -962,6 +974,7 @@ <optional-src-jar dep="commons-logging"/> <optional-src-jar dep="apache-bsf"/> <optional-src-jar dep="javamail"/> + <optional-src-jar dep="jakartamail"/> <optional-src-jar dep="netrexx"/> <optional-src-jar dep="commons-net"/> <optional-src-jar dep="antlr"/> @@ -335,6 +335,12 @@ Set -Ddest=LOCATION on the command line <f2 project="which"/> </target> + <target name="javamail" + description="load Java Mail" + depends="init"> + <f2 project="com.sun.mail" archive="javax.mail"/> + </target> + <target name="jakartamail" description="load Jakarta Mail" depends="init"> diff --git a/lib/libraries.properties b/lib/libraries.properties index ec536522e..349e199fb 100644 --- a/lib/libraries.properties +++ b/lib/libraries.properties @@ -51,7 +51,9 @@ hamcrest-core.version=1.3 hamcrest-library.version=${hamcrest-core.version} jai-core.version=1.1.3 jai-codec.version=1.1.3 -jakarta.mail.version=1.6.4 +# Later 1.6 versions call themselves "jakarta.mail" but do not use the namespace yet +javax.mail.version=1.6.2 +jakarta.mail.version=2.0.1 jakarta-regexp.version=1.4 # Later versions of Tomcat provide a jspc task jasper-compiler.version=4.1.36 diff --git a/src/etc/poms/ant-jakartamail/pom.xml b/src/etc/poms/ant-jakartamail/pom.xml new file mode 100644 index 000000000..4d17f87ac --- /dev/null +++ b/src/etc/poms/ant-jakartamail/pom.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<!-- + This POM has been created manually by the Ant Development Team. + Please contact us if you are not satisfied with the data contained in this POM. + URL : https://ant.apache.org +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <groupId>org.apache.ant</groupId> + <artifactId>ant-parent</artifactId> + <relativePath>../pom.xml</relativePath> + <version>1.10.12-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <url>https://ant.apache.org/</url> + <groupId>org.apache.ant</groupId> + <artifactId>ant-jakartamail</artifactId> + <version>1.10.12-SNAPSHOT</version> + <name>Apache Ant + JakartaMail</name> + <description>implementation of the mail task based on Jakarta EE mail. + Required to send emails to SMTP servers using user/password combinations + or to send mail over SSL</description> + <dependencies> + <dependency> + <groupId>org.apache.ant</groupId> + <artifactId>ant</artifactId> + <version>1.10.12-SNAPSHOT</version> + <scope>compile</scope> + </dependency> + <dependency> + <!-- This brings in the necessary dependencies. + See https://eclipse-ee4j.github.io/mail/ --> + <groupId>com.sun.mail</groupId> + <artifactId>jakarta.mail</artifactId> + <version>2.0.1</version> + <scope>compile</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <includes> + <include>org/apache/tools/ant/taskdefs/email/JakartaMimeMailer*</include> + </includes> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <index>true</index> + <manifest> + <addExtensions>true</addExtensions> + <addDefaultImplementationEntries>true</addDefaultImplementationEntries> + <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> + </manifest> + </archive> + </configuration> + </plugin> + </plugins> + <resources> + <resource> + <directory>../../../..</directory> + <targetPath>META-INF</targetPath> + <includes> + <include>LICENSE</include> + <include>NOTICE</include> + </includes> + </resource> + </resources> + <sourceDirectory>../../../../src/main</sourceDirectory> + <testSourceDirectory>../../../../src/testcases</testSourceDirectory> + <outputDirectory>../../../../target/${project.artifactId}/classes</outputDirectory> + <testOutputDirectory>../../../../target/${project.artifactId}/testcases</testOutputDirectory> + <directory>../../../../target/${project.artifactId}</directory> + </build> +</project> diff --git a/src/etc/poms/ant-javamail/pom.xml b/src/etc/poms/ant-javamail/pom.xml index 26a6b787b..05b2dec8d 100644 --- a/src/etc/poms/ant-javamail/pom.xml +++ b/src/etc/poms/ant-javamail/pom.xml @@ -48,8 +48,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/m <!-- This brings in the necessary dependencies. See https://eclipse-ee4j.github.io/mail/ --> <groupId>com.sun.mail</groupId> - <artifactId>jakarta.mail</artifactId> - <version>1.6.4</version> + <artifactId>javax.mail</artifactId> + <version>1.6.2</version> <scope>compile</scope> </dependency> </dependencies> diff --git a/src/etc/poms/ant/pom.xml b/src/etc/poms/ant/pom.xml index d52bc2683..8ce508b84 100644 --- a/src/etc/poms/ant/pom.xml +++ b/src/etc/poms/ant/pom.xml @@ -160,7 +160,7 @@ <exclude>org/apache/tools/ant/launch/</exclude> <exclude>org/apache/tools/ant/listener/CommonsLoggingListener*</exclude> <exclude>org/apache/tools/ant/listener/Log4jListener*</exclude> - <exclude>org/apache/tools/ant/taskdefs/email/MimeMailer*</exclude> + <exclude>org/apache/tools/ant/taskdefs/email/*MimeMailer*</exclude> <exclude>${modules.exclude}</exclude> <exclude>org/apache/tools/ant/taskdefs/optional/NetRexxC*</exclude> <exclude>org/apache/tools/ant/taskdefs/optional/Xalan2TraceSupport*</exclude> diff --git a/src/etc/poms/pom.xml b/src/etc/poms/pom.xml index 3ab41dbd5..893ceee66 100644 --- a/src/etc/poms/pom.xml +++ b/src/etc/poms/pom.xml @@ -95,6 +95,7 @@ <module>ant-imageio</module> <module>ant-jai</module> <module>ant-javamail</module> + <module>ant-jakartamail</module> <module>ant-jdepend</module> <module>ant-jmf</module> <module>ant-jsch</module> diff --git a/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java b/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java index 54f811743..5336d06fd 100644 --- a/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java +++ b/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java @@ -449,16 +449,9 @@ public class EmailTask extends Task { // prepare for the auto select mechanism boolean autoFound = false; // try MIME format - if (MIME.equals(encoding) - || (AUTO.equals(encoding) && !autoFound)) { + if (MIME.equals(encoding) || AUTO.equals(encoding)) { try { - //check to make sure that activation.jar - //and mail.jar are available - see bug 31969 - Class.forName("javax.activation.DataHandler"); - Class.forName("javax.mail.internet.MimeMessage"); - - mailer = ClasspathUtils.newInstance( - "org.apache.tools.ant.taskdefs.email.MimeMailer", + mailer = ClasspathUtils.newInstance(getMailerImplementation(), EmailTask.class.getClassLoader(), Mailer.class); autoFound = true; @@ -600,6 +593,32 @@ public class EmailTask extends Task { } } + private String getMailerImplementation() { + //check to make sure that activation.jar + //and mail.jar are available - see bug 31969 + try { + Class.forName("jakarta.activation.DataHandler"); + Class.forName("jakarta.mail.internet.MimeMessage"); + + return "org.apache.tools.ant.taskdefs.email.JakartaMimeMailer"; + } catch (ClassNotFoundException cnfe) { + logBuildException("Could not find Jakarta MIME mail: ", + new BuildException(cnfe)); + } + + try { + Class.forName("javax.activation.DataHandler"); + Class.forName("javax.mail.internet.MimeMessage"); + + return "org.apache.tools.ant.taskdefs.email.MimeMailer"; + } catch (ClassNotFoundException cnfe) { + logBuildException("Could not find MIME mail: ", + new BuildException(cnfe)); + } + + return "org.apache.tools.ant.taskdefs.email.Mailer"; + } + private void logBuildException(String reason, BuildException e) { Throwable t = e.getCause() == null ? e : e.getCause(); log(reason + t.getMessage(), Project.MSG_WARN); diff --git a/src/main/org/apache/tools/ant/taskdefs/email/JakartaMimeMailer.java b/src/main/org/apache/tools/ant/taskdefs/email/JakartaMimeMailer.java new file mode 100644 index 000000000..80d3fda37 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/email/JakartaMimeMailer.java @@ -0,0 +1,340 @@ +/* + * 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.tools.ant.taskdefs.email; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.security.Provider; +import java.security.Security; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Properties; +import java.util.StringTokenizer; +import java.util.Vector; + +import jakarta.activation.DataHandler; +import jakarta.activation.DataSource; +import jakarta.activation.FileDataSource; +import jakarta.mail.Address; +import jakarta.mail.Authenticator; +import jakarta.mail.Message; +import jakarta.mail.MessagingException; +import jakarta.mail.PasswordAuthentication; +import jakarta.mail.SendFailedException; +import jakarta.mail.Session; +import jakarta.mail.Transport; +import jakarta.mail.internet.AddressException; +import jakarta.mail.internet.InternetAddress; +import jakarta.mail.internet.MimeBodyPart; +import jakarta.mail.internet.MimeMessage; +import jakarta.mail.internet.MimeMultipart; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; + + +/** + * Uses the JakartaMail classes to send Mime format email. + * + * @since Ant 1.10.12 + */ +public class JakartaMimeMailer extends Mailer { + private static final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; + + private static final String GENERIC_ERROR = + "Problem while sending mime mail:"; + + /** Default character set */ + private static final String DEFAULT_CHARSET + = System.getProperty("file.encoding"); + + // To work properly with national charsets we have to use + // implementation of interface jakarta.activation.DataSource + /** + * String data source implementation. + */ + class StringDataSource implements DataSource { + private String data = null; + private String type = null; + private String charset = null; + private ByteArrayOutputStream out; + + @Override + public InputStream getInputStream() throws IOException { + if (data == null && out == null) { + throw new IOException("No data"); + } + if (out != null) { + final String encodedOut = out.toString(charset); + data = (data != null) ? data.concat(encodedOut) : encodedOut; + out = null; + } + return new ByteArrayInputStream(data.getBytes(charset)); + } + + @Override + public OutputStream getOutputStream() throws IOException { + out = (out == null) ? new ByteArrayOutputStream() : out; + return out; + } + + public void setContentType(final String type) { + this.type = type.toLowerCase(Locale.ENGLISH); + } + + @Override + public String getContentType() { + if (type != null && type.indexOf("charset") > 0 + && type.startsWith("text/")) { + return type; + } + // Must be like "text/plain; charset=windows-1251" + return (type != null ? type : "text/plain") + + "; charset=" + charset; + } + + @Override + public String getName() { + return "StringDataSource"; + } + + public void setCharset(final String charset) { + this.charset = charset; + } + + public String getCharset() { + return charset; + } + } + + /** + * Send the email. + * + * @throws BuildException if the email can't be sent. + */ + @Override + public void send() { + try { + final Properties props = new Properties(); + + props.put("mail.smtp.host", host); + props.put("mail.smtp.port", String.valueOf(port)); + + // Aside, the JDK is clearly unaware of the Scottish + // 'session', which involves excessive quantities of + // alcohol :-) + Session sesh; + Authenticator auth = null; + if (SSL) { + try { + final Provider p = + Class.forName("com.sun.net.ssl.internal.ssl.Provider") + .asSubclass(Provider.class).getDeclaredConstructor().newInstance(); + Security.addProvider(p); + } catch (final Exception e) { + throw new BuildException( + "could not instantiate ssl security provider, check that you have JSSE in your classpath"); + } + // SMTP provider + props.put("mail.smtp.socketFactory.class", SSL_FACTORY); + props.put("mail.smtp.socketFactory.fallback", "false"); + props.put("mail.smtps.host", host); + if (isPortExplicitlySpecified()) { + props.put("mail.smtps.port", String.valueOf(port)); + props.put("mail.smtp.socketFactory.port", + String.valueOf(port)); + } + } + if (user != null || password != null) { + props.put("mail.smtp.auth", "true"); + auth = new SimpleAuthenticator(user, password); + } + if (isStartTLSEnabled()) { + props.put("mail.smtp.starttls.enable", "true"); + } + sesh = Session.getInstance(props, auth); + + //create the message + final MimeMessage msg = new MimeMessage(sesh); + final MimeMultipart attachments = new MimeMultipart(); + + //set the sender + if (from.getName() == null) { + msg.setFrom(new InternetAddress(from.getAddress())); + } else { + msg.setFrom(new InternetAddress(from.getAddress(), + from.getName())); + } + // set the reply to addresses + msg.setReplyTo(internetAddresses(replyToList)); + msg.setRecipients(Message.RecipientType.TO, + internetAddresses(toList)); + msg.setRecipients(Message.RecipientType.CC, + internetAddresses(ccList)); + msg.setRecipients(Message.RecipientType.BCC, + internetAddresses(bccList)); + + // Choosing character set of the mail message + // First: looking it from MimeType + String charset = parseCharSetFromMimeType(message.getMimeType()); + if (charset != null) { + // Assign/reassign message charset from MimeType + message.setCharset(charset); + } else { + // Next: looking if charset having explicit definition + charset = message.getCharset(); + if (charset == null) { + // Using default + charset = DEFAULT_CHARSET; + message.setCharset(charset); + } + } + // Using jakarta.activation.DataSource paradigm + final StringDataSource sds = new StringDataSource(); + sds.setContentType(message.getMimeType()); + sds.setCharset(charset); + + if (subject != null) { + msg.setSubject(subject, charset); + } + msg.addHeader("Date", getDate()); + + if (headers != null) { + for (Header h : headers) { + msg.addHeader(h.getName(), h.getValue()); + } + } + final PrintStream out = new PrintStream(sds.getOutputStream()); + message.print(out); + out.close(); + + final MimeBodyPart textbody = new MimeBodyPart(); + textbody.setDataHandler(new DataHandler(sds)); + attachments.addBodyPart(textbody); + + for (File file : files) { + MimeBodyPart body = new MimeBodyPart(); + if (!file.exists() || !file.canRead()) { + throw new BuildException( + "File \"%s\" does not exist or is not readable.", + file.getAbsolutePath()); + } + final FileDataSource fileData = new FileDataSource(file); + final DataHandler fileDataHandler = new DataHandler(fileData); + + body.setDataHandler(fileDataHandler); + body.setFileName(file.getName()); + attachments.addBodyPart(body); + } + msg.setContent(attachments); + try { + // Send the message using SMTP, or SMTPS if the host uses SSL + final Transport transport = sesh.getTransport(SSL ? "smtps" : "smtp"); + transport.connect(host, user, password); + transport.sendMessage(msg, msg.getAllRecipients()); + } catch (final SendFailedException sfe) { + if (!shouldIgnoreInvalidRecipients()) { + throw new BuildException(GENERIC_ERROR, sfe); + } + if (sfe.getValidSentAddresses() == null + || sfe.getValidSentAddresses().length == 0) { + throw new BuildException("Couldn't reach any recipient", + sfe); + } + Address[] invalid = sfe.getInvalidAddresses(); + if (invalid == null) { + invalid = new Address[0]; + } + for (Address address : invalid) { + didntReach(address, "invalid", sfe); + } + Address[] validUnsent = sfe.getValidUnsentAddresses(); + if (validUnsent == null) { + validUnsent = new Address[0]; + } + for (Address address : validUnsent) { + didntReach(address, "valid", sfe); + } + } + } catch (MessagingException | IOException e) { + throw new BuildException(GENERIC_ERROR, e); + } + } + + private static InternetAddress[] internetAddresses(final Vector<EmailAddress> list) + throws AddressException, UnsupportedEncodingException { + + final List<InternetAddress> addrs = new ArrayList<>(); + + for (final EmailAddress addr : list) { + final String name = addr.getName(); + addrs.add((name == null) + ? new InternetAddress(addr.getAddress()) + : new InternetAddress(addr.getAddress(), name)); + } + return addrs.toArray(new InternetAddress[addrs.size()]); + } + + private String parseCharSetFromMimeType(final String type) { + if (type == null) { + return null; + } + final int pos = type.indexOf("charset"); + if (pos < 0) { + return null; + } + // Assuming mime type in form "text/XXXX; charset=XXXXXX" + final StringTokenizer token = new StringTokenizer(type.substring(pos), "=; "); + token.nextToken(); // Skip 'charset=' + return token.nextToken(); + } + + private void didntReach(final Address addr, final String category, + final MessagingException ex) { + final String msg = "Failed to send mail to " + category + " address " + + addr + " because of " + ex.getMessage(); + if (task != null) { + task.log(msg, Project.MSG_WARN); + } else { + System.err.println(msg); + } + } + + static class SimpleAuthenticator extends Authenticator { + private String user = null; + private String password = null; + + public SimpleAuthenticator(final String user, final String password) { + this.user = user; + this.password = password; + } + + @Override + public PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(user, password); + } + } +} + diff --git a/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java b/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java index 319c1dc7c..387078b8a 100644 --- a/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java +++ b/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java @@ -58,7 +58,9 @@ import org.apache.tools.ant.Project; * Uses the JavaMail classes to send Mime format email. * * @since Ant 1.5 + * @deprecated see org.apache.tools.ant.taskdefs.email.JakartaMimeMailer */ +@Deprecated public class MimeMailer extends Mailer { private static final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; diff --git a/src/main/org/apache/tools/ant/util/ClasspathUtils.java b/src/main/org/apache/tools/ant/util/ClasspathUtils.java index 9e9b2ddc5..e14ed3ef8 100644 --- a/src/main/org/apache/tools/ant/util/ClasspathUtils.java +++ b/src/main/org/apache/tools/ant/util/ClasspathUtils.java @@ -26,6 +26,7 @@ import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.Reference; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; // CheckStyle:HideUtilityClassConstructorCheck OFF - bc @@ -251,6 +252,9 @@ public class ClasspathUtils { try { @SuppressWarnings("unchecked") Class<T> clazz = (Class<T>) Class.forName(className, true, userDefinedLoader); + if (Modifier.isAbstract(clazz.getModifiers())) { + throw new BuildException("Abstract class " + className); + } T o = clazz.getDeclaredConstructor().newInstance(); if (!expectedType.isInstance(o)) { throw new BuildException( |