mirror of
https://github.com/M66B/FairEmail.git
synced 2024-12-31 20:25:38 +00:00
Updated to JakartaMail 1.6.7
This commit is contained in:
parent
a9034efbfe
commit
1227cd0b4a
9 changed files with 300 additions and 105 deletions
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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><formatter-name>.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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue