Updated to JakartaMail 1.6.7

This commit is contained in:
M66B 2021-04-25 20:28:24 +02:00
parent a9034efbfe
commit 1227cd0b4a
9 changed files with 300 additions and 105 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@ -30,7 +30,6 @@ import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import com.sun.mail.util.PropUtil;
@ -545,23 +544,63 @@ public class Protocol {
public SocketChannel getChannel() {
SocketChannel ret = socket.getChannel();
if (ret != null)
return ret;
return ret;
// XXX - Android is broken and SSL wrapped sockets don't delegate
// the getChannel method to the wrapped Socket
if (socket instanceof SSLSocket) {
try {
Field f = socket.getClass().getDeclaredField("socket");
f.setAccessible(true);
Socket s = (Socket)f.get(socket);
ret = s.getChannel();
} catch (Exception ex) {
// ignore anything that might go wrong
}
ret = Protocol.findSocketChannel(socket);
}
return ret;
}
/**
* Android is broken and SSL wrapped sockets don't delegate
* the getChannel method to the wrapped Socket.
*
* @param socket a non null socket
* @return the SocketChannel or null if not found
*/
private static SocketChannel findSocketChannel(Socket socket) {
//Search class hierarchy for field name socket regardless of modifier.
for (Class<?> k = socket.getClass(); k != Object.class; k = k.getSuperclass()) {
try {
Field f = k.getDeclaredField("socket");
f.setAccessible(true);
Socket s = (Socket) f.get(socket);
SocketChannel ret = s.getChannel();
if (ret != null) {
return ret;
}
} catch (Exception ignore) {
//ignore anything that might go wrong
}
}
//Search class hierarchy for fields that can hold a Socket
//or subclass regardless of modifier. Fields declared as super types of Socket
//will be ignored.
for (Class<?> k = socket.getClass(); k != Object.class; k = k.getSuperclass()) {
try {
for (Field f : k.getDeclaredFields()) {
if (Socket.class.isAssignableFrom(f.getType())) {
try {
f.setAccessible(true);
Socket s = (Socket) f.get(socket);
SocketChannel ret = s.getChannel();
if (ret != null) {
return ret;
}
} catch (Exception ignore) {
//ignore anything that might go wrong
}
}
}
} catch (Exception ignore) {
//ignore anything that might go wrong
}
}
return null;
}
/**
* Return the local SocketAddress (host and port) for this
* end of the connection.

View File

@ -630,6 +630,7 @@ public class IMAPProtocol extends Protocol {
authenticated = true;
}
/**
* The AUTHENTICATE command with AUTH=PLAIN authentication scheme.
* This is based heavly on the {@link #authlogin} method.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@ -23,7 +23,6 @@ import java.security.*;
import java.util.logging.Level;
import java.nio.charset.StandardCharsets;
import javax.net.ssl.SSLSocket;
import com.sun.mail.auth.Ntlm;
import com.sun.mail.util.ASCIIUtility;
import com.sun.mail.util.BASE64DecoderStream;
@ -44,7 +43,7 @@ class Response {
}
/**
* This class provides a POP3 connection and implements
* This class provides a POP3 connection and implements
* the POP3 protocol requests.
*
* APOP support courtesy of "chamness".
@ -76,7 +75,7 @@ class Protocol {
// sometimes the returned size isn't quite big enough
private static final int SLOP = 128;
/**
/**
* Open a connection to the POP3 server.
*/
Protocol(String host, int port, MailLogger logger,
@ -393,7 +392,7 @@ class Protocol {
}
/**
* Gets the APOP message digest.
* Gets the APOP message digest.
* From RFC 1939:
*
* The 'digest' parameter is calculated by applying the MD5
@ -446,6 +445,25 @@ class Protocol {
return enabled;
}
/**
* Run authentication query based on command and initial response
*
* @param command - command passed to server
* @param ir - initial response, part of the query
* @throws IOException
*/
protected void runAuthenticationCommand(String command, String ir) throws IOException {
if (logger.isLoggable(Level.FINE)) {
logger.fine(command + " using one line authentication format");
}
if (ir != null) {
resp = simpleCommand(command + " " + (ir.length() == 0 ? "=" : ir));
} else {
resp = simpleCommand(command);
}
}
/**
* Start the authentication handshake by issuing the AUTH command.
* Delegate to the doAuth method to do the mechanism-specific
@ -461,11 +479,8 @@ class Protocol {
logger.fine("AUTH " + mech + " command trace suppressed");
suspendTracing();
}
if (ir != null)
resp = simpleCommand("AUTH " + mech + " " +
(ir.length() == 0 ? "=" : ir));
else
resp = simpleCommand("AUTH " + mech);
runAuthenticationCommand("AUTH " + mech, ir);
if (resp.cont)
doAuth(host, authzid, user, passwd);
@ -681,6 +696,26 @@ class Protocol {
return ASCIIUtility.toString(b);
}
@Override
protected void runAuthenticationCommand(String command, String ir) throws IOException {
Boolean isTwoLineAuthenticationFormat = getBoolProp(
props,
prefix + ".auth.xoauth2.two.line.authentication.format");
if (isTwoLineAuthenticationFormat) {
if (logger.isLoggable(Level.FINE)) {
logger.fine(command + " using two line authentication format");
}
resp = twoLinesCommand(
command,
(ir.length() == 0 ? "=" : ir)
);
} else {
super.runAuthenticationCommand(command, ir);
}
}
@Override
void doAuth(String host, String authzid, String user, String passwd)
throws IOException {
@ -1120,6 +1155,29 @@ class Protocol {
return r;
}
/**
* Issue a two line POP3 command and return the response
* Refer to {@link #simpleCommand(String)} for a single line command
*
* @param firstCommand first command we want to pass to server e.g AUTH XOAUTH2
* @param secondCommand second command e.g Base64 encoded authorization string
* @return Response
* @throws IOException
*/
private Response twoLinesCommand(String firstCommand, String secondCommand) throws IOException {
String cmd = firstCommand + " " + secondCommand;
batchCommandStart(cmd);
simpleCommand(firstCommand);
batchCommandContinue(cmd);
Response r = simpleCommand(secondCommand);
batchCommandEnd();
return r;
}
/**
* Send the specified command.
*/

View File

@ -4,7 +4,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--
Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@ -390,6 +390,13 @@ setting this property to "false" or by setting the "mail.pop3.auth.mechanisms"
property to "XOAUTH2".</TD>
</TR>
<TR>
<TD><A ID="mail.pop3.auth.xoauth2.two.line.authentication.format">mail.pop3.auth.xoauth2.two.line.authentication.format</A></TD>
<TD>boolean</TD>
<TD>If true, splits authentication command on two lines.
Default is false.</TD>
</TR>
<TR>
<TD><A ID="mail.pop3.socketFactory">mail.pop3.socketFactory</A></TD>
<TD>SocketFactory</TD>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at

View File

@ -322,12 +322,12 @@ public class WriteTimeoutSocket extends Socket {
* @return the FileDescriptor object
*/
public FileDescriptor getFileDescriptor$() {
//The loop handles issues with non-public classes between
//java.net.Socket and the actual socket type held in this object.
//Must inspect java.net.Socket to ensure compatiblity with old behavior.
for (Class<?> k = socket.getClass(); k != Object.class; k = k.getSuperclass()) {
//The loop handles issues with non-public classes between
//java.net.Socket and the actual socket type held in this object.
//Must inspect java.net.Socket to ensure compatiblity with old behavior.
for (Class<?> k = socket.getClass(); k != Object.class; k = k.getSuperclass()) {
try {
Method m = k.getDeclaredMethod("getFileDescriptor$");
Method m = k.getDeclaredMethod("getFileDescriptor$");
if (FileDescriptor.class.isAssignableFrom(m.getReturnType())) {
//Skip setAccessible so non-public methods fail to invoke.
return (FileDescriptor) m.invoke(socket);

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2019 Jason Mehrens. All rights reserved.
* Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2021 Jason Mehrens. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@ -21,8 +21,9 @@ import java.util.logging.LogRecord;
/**
* A plain text formatter that can produce fixed width output. By default this
* formatter will produce output no greater than 160 characters wide plus the
* separator and newline characters. Only specified fields support an
* formatter will produce output no greater than 160 characters
* (Unicode code points) wide plus the separator and newline characters. Only
* specified fields support an
* {@linkplain #toAlternate(java.lang.String) alternate} fixed width format.
* <p>
* By default each <code>CompactFormatter</code> is initialized using the
@ -33,8 +34,10 @@ import java.util.logging.LogRecord;
* used.
* <ul>
* <li>&lt;formatter-name&gt;.format - the {@linkplain java.util.Formatter
* format} string used to transform the output. The format string can be
* used to fix the output size. (defaults to <code>%7$#.160s%n</code>)</li>
* format} string used to transform the output. The arguments are explained
* in detail in the {@linkplain #format(java.util.logging.LogRecord) format}
* documentation. The format string can be used to fix the output size.
* (defaults to <code>%7$#.160s%n</code>)</li>
* </ul>
*
* @author Jason Mehrens
@ -112,10 +115,12 @@ public class CompactFormatter extends java.util.logging.Formatter {
* and a relevant stack trace element if available; otherwise, an empty
* string is used.</li>
* <li>{@code message|thrown} The message and the thrown properties joined
* as one parameter. This parameter supports
* as one parameter. Width and precision are by Unicode code points. This
* parameter supports
* {@linkplain #toAlternate(java.lang.String) alternate} form.</li>
* <li>{@code thrown|message} The thrown and message properties joined as
* one parameter. This parameter supports
* one parameter. Width and precision are by Unicode code points. This
* parameter supports
* {@linkplain #toAlternate(java.lang.String) alternate} form.</li>
* <li>{@code sequence} the
* {@linkplain LogRecord#getSequenceNumber() sequence number} if the given
@ -128,10 +133,12 @@ public class CompactFormatter extends java.util.logging.Formatter {
* {@linkplain #formatError(LogRecord) error message} without any stack
* trace.</li>
* <li>{@code message|error} The message and error properties joined as one
* parameter. This parameter supports
* parameter. Width and precision are by Unicode code points. This parameter
* supports
* {@linkplain #toAlternate(java.lang.String) alternate} form.</li>
* <li>{@code error|message} The error and message properties joined as one
* parameter. This parameter supports
* parameter. Width and precision are by Unicode code points. This parameter
* supports
* {@linkplain #toAlternate(java.lang.String) alternate} form.</li>
* <li>{@code backtrace} only the
* {@linkplain #formatBackTrace(LogRecord) stack trace} of the given
@ -148,17 +155,19 @@ public class CompactFormatter extends java.util.logging.Formatter {
* <ul>
* <li>{@code com.sun.mail.util.logging.CompactFormatter.format=%7$#.160s%n}
* <p>
* This prints only 160 characters of the message|thrown ({@code 7$}) using
* the {@linkplain #toAlternate(java.lang.String) alternate} form. The
* separator is not included as part of the total width.
* This prints only 160 characters (Unicode code points) of the
* message|thrown ({@code 7$}) using the
* {@linkplain #toAlternate(java.lang.String) alternate} form. The separator
* is not included as part of the total width.
* <pre>
* Encoding failed.|NullPointerException: null String.getBytes(:913)
* </pre>
*
* <li>{@code com.sun.mail.util.logging.CompactFormatter.format=%7$#.20s%n}
* <p>
* This prints only 20 characters of the message|thrown ({@code 7$}) using
* the {@linkplain #toAlternate(java.lang.String) alternate} form. This will
* This prints only 20 characters (Unicode code points) of the
* message|thrown ({@code 7$}) using the
* {@linkplain #toAlternate(java.lang.String) alternate} form. This will
* perform a weighted truncation of both the message and thrown properties
* of the log record. The separator is not included as part of the total
* width.
@ -179,8 +188,9 @@ public class CompactFormatter extends java.util.logging.Formatter {
*
* <li>{@code com.sun.mail.util.logging.CompactFormatter.format=%4$s: %12$#.160s%n}
* <p>
* This prints the log level ({@code 4$}) and only 160 characters of the
* message|error ({@code 12$}) using the alternate form.
* This prints the log level ({@code 4$}) and only 160 characters
* (Unicode code points) of the message|error ({@code 12$}) using the
* alternate form.
* <pre>
* SEVERE: Unable to send notification.|SocketException: Permission denied: connect
* </pre>
@ -335,21 +345,22 @@ public class CompactFormatter extends java.util.logging.Formatter {
}
/**
* Formats the thread id property of the given log record. By default this
* is formatted as a {@code long} by an unsigned conversion.
* Formats the thread id property of the given log record. Long thread ids
* are preferred if supported. Otherwise, the integer thread id is
* formatted as a {@code long} by an unsigned conversion.
*
* @param record the record.
* @return the formatted thread id as a number.
* @throws NullPointerException if the given record is null.
* @since JavaMail 1.5.4
*/
@SuppressWarnings("deprecation") //See JDK-8245302
public Number formatThreadID(final LogRecord record) {
/**
* Thread.getID is defined as long and LogRecord.getThreadID is defined
* as int. Convert to unsigned as a means to better map the two types of
* thread identifiers.
*/
return (((long) record.getThreadID()) & 0xffffffffL);
Long id = LogManagerProperties.getLongThreadID(record);
if (id == null) {
id = (((long) record.getThreadID()) & 0xffffffffL);
}
return id;
}
/**
@ -474,12 +485,7 @@ public class CompactFormatter extends java.util.logging.Formatter {
*/
private String formatStackTraceElement(final StackTraceElement s) {
String v = simpleClassName(s.getClassName());
String result;
if (v != null) {
result = s.toString().replace(s.getClassName(), v);
} else {
result = s.toString();
}
String result = s.toString().replace(s.getClassName(), v);
//If the class name contains the simple file name then remove file name.
v = simpleFileName(s.getFileName());
@ -753,7 +759,7 @@ public class CompactFormatter extends java.util.logging.Formatter {
* @return true if null or spaces.
*/
private static boolean isNullOrSpaces(final String s) {
return s == null || s.trim().length() == 0;
return s == null || s.trim().isEmpty();
}
/**
@ -799,41 +805,58 @@ public class CompactFormatter extends java.util.logging.Formatter {
r = toAlternate(r);
}
if (precision <= 0) {
precision = Integer.MAX_VALUE;
}
int lc = 0;
int rc = 0;
if (precision >= 0) {
lc = minCodePointCount(l, precision);
rc = minCodePointCount(r, precision);
int fence = Math.min(l.length(), precision);
if (fence > (precision >> 1)) {
fence = Math.max(fence - r.length(), fence >> 1);
}
if (fence > 0) {
if (fence > l.length()
&& Character.isHighSurrogate(l.charAt(fence - 1))) {
--fence;
if (lc > (precision >> 1)) {
lc = Math.max(lc - rc, lc >> 1);
}
l = l.substring(0, fence);
rc = Math.min(precision - lc, rc);
l = l.substring(0, l.offsetByCodePoints(0, lc));
r = r.substring(0, r.offsetByCodePoints(0, rc));
}
r = r.substring(0, Math.min(precision - fence, r.length()));
if (width > 0) {
if (precision < 0) {
lc = minCodePointCount(l, width);
rc = minCodePointCount(r, width);
}
final int half = width >> 1;
if (l.length() < half) {
l = pad(flags, l, half);
if (lc < half) {
l = pad(flags, l, half - lc);
}
if (r.length() < half) {
r = pad(flags, r, half);
if (rc < half) {
r = pad(flags, r, half - rc);
}
}
Object[] empty = Collections.emptySet().toArray();
formatter.format(l, empty);
if (l.length() != 0 && r.length() != 0) {
formatter.format("|", empty);
formatter.format(l);
if (!l.isEmpty() && !r.isEmpty()) {
formatter.format("|");
}
formatter.format(r, empty);
formatter.format(r);
}
/**
* Counts the number code points with an upper bound.
*
* @param s the string to count, never null.
* @param limit the max number of code points needed.
* @return the number of code points, never greater than the limit.
*/
private int minCodePointCount(String s, final int limit) {
//assert limit >= 0 : limit;
final int len = s.length();
if ((len - limit) >= limit) {
return limit;
}
return Math.min(s.codePointCount(0, len), limit);
}
/**
@ -841,12 +864,13 @@ public class CompactFormatter extends java.util.logging.Formatter {
*
* @param flags the formatter flags.
* @param s the string to pad.
* @param length the final string length.
* @param padding the number of spaces to add.
* @return the padded string.
*/
private String pad(int flags, String s, int length) {
final int padding = length - s.length();
final StringBuilder b = new StringBuilder(length);
private String pad(int flags, String s, int padding) {
//assert padding >= 0 : padding;
final StringBuilder b = new StringBuilder(
Math.max(s.length() + padding, padding));
if ((flags & java.util.FormattableFlags.LEFT_JUSTIFY)
== java.util.FormattableFlags.LEFT_JUSTIFY) {
for (int i = 0; i < padding; ++i) {

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2009, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2019 Jason Mehrens. All rights reserved.
* Copyright (c) 2009, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2021 Jason Mehrens. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@ -55,12 +55,19 @@ final class LogManagerProperties extends Properties {
* Generated serial id.
*/
private static final long serialVersionUID = -2239983349056806252L;
/**
* Holds the method used to get the LogRecord instant if running on JDK 9 or
* later.
*/
private static final Method LR_GET_INSTANT;
/**
* Holds the method used to get the long thread id if running on JDK 16 or
* later.
*/
private static final Method LR_GET_LONG_TID;
/**
* Holds the method used to get the default time zone if running on JDK 9 or
* later.
@ -73,6 +80,20 @@ final class LogManagerProperties extends Properties {
*/
private static final Method ZDT_OF_INSTANT;
/**
* MethodHandle is available starting at JDK7 and Andriod API 26.
*/
static { //Added in JDK16 see JDK-8245302
Method lrtid = null;
try {
lrtid = LogRecord.class.getMethod("getLongThreadID");
} catch (final RuntimeException ignore) {
} catch (final Exception ignore) { //No need for specific catch.
} catch (final LinkageError ignore) {
}
LR_GET_LONG_TID = lrtid;
}
static {
Method lrgi = null;
Method zisd = null;
@ -84,17 +105,17 @@ final class LogManagerProperties extends Properties {
zisd = findClass("java.time.ZoneId")
.getMethod("systemDefault");
if (!Modifier.isStatic(zisd.getModifiers())) {
zisd = null;
throw new NoSuchMethodException(zisd.toString());
}
zdtoi = findClass("java.time.ZonedDateTime")
.getMethod("ofInstant", findClass("java.time.Instant"),
findClass("java.time.ZoneId"));
if (!Modifier.isStatic(zdtoi.getModifiers())) {
throw new NoSuchMethodException(zdtoi.toString());
}
if (!Comparable.class.isAssignableFrom(zdtoi.getReturnType())) {
if (!Modifier.isStatic(zdtoi.getModifiers())
|| !Comparable.class.isAssignableFrom(
zdtoi.getReturnType())) {
zdtoi = null;
throw new NoSuchMethodException(zdtoi.toString());
}
} catch (final RuntimeException ignore) {
@ -112,6 +133,7 @@ final class LogManagerProperties extends Properties {
ZI_SYSTEM_DEFAULT = zisd;
ZDT_OF_INSTANT = zdtoi;
}
/**
* Caches the read only reflection class names string array. Declared
* volatile for safe publishing only. The VO_VOLATILE_REFERENCE_TO_ARRAY
@ -328,6 +350,39 @@ final class LogManagerProperties extends Properties {
return null;
}
/**
* Gets the long thread id from the given log record.
*
* @param record used to get the long thread id.
* @return null if LogRecord doesn't support long thread ids.
* @throws NullPointerException if record is null.
* @since JavaMail 1.6.7
*/
static Long getLongThreadID(final LogRecord record) {
if (record == null) {
throw new NullPointerException();
}
final Method m = LR_GET_LONG_TID;
if (m != null) {
try {
return (Long) m.invoke(record);
} catch (final InvocationTargetException ite) {
final Throwable cause = ite.getCause();
if (cause instanceof Error) {
throw (Error) cause;
} else if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else { //Should never happen.
throw new UndeclaredThrowableException(ite);
}
} catch (final RuntimeException ignore) {
} catch (final Exception ignore) {
}
}
return null;
}
/**
* Gets the local host name from the given service.
*
@ -365,6 +420,7 @@ final class LogManagerProperties extends Properties {
*
* @param value an ISO-8601 duration character sequence.
* @return the number of milliseconds parsed from the duration.
* @throws ArithmeticException if the duration is too large or too small.
* @throws ClassNotFoundException if the java.time classes are not present.
* @throws IllegalAccessException if the method is inaccessible.
* @throws InvocationTargetException if the method throws an exception.
@ -378,6 +434,9 @@ final class LogManagerProperties extends Properties {
* @since JavaMail 1.5.5
*/
static long parseDurationToMillis(final CharSequence value) throws Exception {
if (value == null) {
throw new NullPointerException();
}
try {
final Class<?> k = findClass("java.time.Duration");
final Method parse = k.getMethod("parse", CharSequence.class);
@ -395,7 +454,12 @@ final class LogManagerProperties extends Properties {
} catch (final ExceptionInInitializerError EIIE) {
throw wrapOrThrow(EIIE);
} catch (final InvocationTargetException ite) {
throw paramOrError(ite);
final Throwable cause = ite.getCause();
if (cause instanceof ArithmeticException) {
throw (ArithmeticException) cause;
} else {
throw paramOrError(ite);
}
}
}
@ -517,9 +581,9 @@ final class LogManagerProperties extends Properties {
}
Comparator<T> reverse = null;
//Comparator in Java 1.8 has 'reversed' as a default method.
//Comparator in JDK8 has 'reversed' as a default method.
//This code calls that method first to allow custom
//code to define what reverse order means.
//code to define what reverse order means in versions older than JDK8.
try {
//assert Modifier.isPublic(c.getClass().getModifiers()) :
// Modifier.toString(c.getClass().getModifiers());
@ -532,11 +596,9 @@ final class LogManagerProperties extends Properties {
throw wrapOrThrow(eiie);
}
}
} catch (final NoSuchMethodException ignore) {
} catch (final IllegalAccessException ignore) {
} catch (final RuntimeException ignore) {
} catch (final InvocationTargetException ite) {
paramOrError(ite); //Ignore invocation bugs (returned values).
} catch (final ReflectiveOperationException | RuntimeException ignore) {
}
if (reverse == null) {
@ -642,6 +704,8 @@ final class LogManagerProperties extends Properties {
final Class<?> thisClass = LogManagerProperties.class;
assert Modifier.isFinal(thisClass.getModifiers()) : thisClass;
try {
//This code must use reflection to capture extra frames.
//The invoke API doesn't produce the frames needed.
final HashSet<String> traces = new HashSet<>();
Throwable t = Throwable.class.getConstructor().newInstance();
for (StackTraceElement ste : t.getStackTrace()) {
@ -652,6 +716,8 @@ final class LogManagerProperties extends Properties {
}
}
//This code must use reflection to capture extra frames.
//The invoke API doesn't produce the frames needed.
Throwable.class.getMethod("fillInStackTrace").invoke(t);
for (StackTraceElement ste : t.getStackTrace()) {
if (!thisClass.getName().equals(ste.getClassName())) {
@ -756,10 +822,10 @@ final class LogManagerProperties extends Properties {
}
/**
* This code is modified from the LogManager, which explictly states
* This code is modified from the LogManager, which explicitly states
* searching the system class loader first, then the context class loader.
* There is resistance (compatibility) to change this behavior to simply
* searching the context class loader.
* searching the context class loader. See JDK-6878454.
*
* @param name full class name
* @return the class.