1717package com .sun .mail .util .logging ;
1818
1919import java .io .*;
20- import java .lang .invoke .MethodHandle ;
21- import java .lang .invoke .MethodHandles ;
22- import java .lang .invoke .MethodHandles .Lookup ;
23- import java .lang .invoke .MethodType ;
2420import java .lang .reflect .InvocationTargetException ;
2521import java .lang .reflect .Method ;
2622import java .lang .reflect .Modifier ;
@@ -60,71 +56,74 @@ final class LogManagerProperties extends Properties {
6056 */
6157 private static final long serialVersionUID = -2239983349056806252L ;
6258
63- /**
64- * Public lookup for method handles.
65- */
66- private static final Lookup LOOKUP = MethodHandles .publicLookup ();
67-
6859 /**
6960 * Holds the method used to get the LogRecord instant if running on JDK 9 or
7061 * later.
7162 */
72- private static final MethodHandle LR_GET_INSTANT ;
63+ private static final Method LR_GET_INSTANT ;
7364
7465 /**
7566 * Holds the method used to get the long thread id if running on JDK 16 or
7667 * later.
7768 */
78- private static final MethodHandle LR_GET_LONG_TID ;
69+ private static final Method LR_GET_LONG_TID ;
7970
8071 /**
8172 * Holds the method used to get the default time zone if running on JDK 9 or
8273 * later.
8374 */
84- private static final MethodHandle ZI_SYSTEM_DEFAULT ;
75+ private static final Method ZI_SYSTEM_DEFAULT ;
8576
8677 /**
8778 * Holds the method used to convert and instant to a zoned date time if
8879 * running on JDK 9 later.
8980 */
90- private static final MethodHandle ZDT_OF_INSTANT ;
91-
81+ private static final Method ZDT_OF_INSTANT ;
9282
83+ /**
84+ * MethodHandle is available starting at JDK7 and Andriod API 26.
85+ */
9386 static { //Added in JDK16 see JDK-8245302
94- MethodHandle lrgltid = null ;
87+ Method lrtid = null ;
9588 try {
96- lrgltid = LOOKUP .findVirtual (LogRecord .class ,
97- "getLongThreadID" , MethodType .methodType (long .class ));
89+ lrtid = LogRecord .class .getMethod ("getLongThreadID" );
9890 } catch (final RuntimeException ignore ) {
9991 } catch (final Exception ignore ) { //No need for specific catch.
10092 } catch (final LinkageError ignore ) {
10193 }
102- LR_GET_LONG_TID = lrgltid ;
94+ LR_GET_LONG_TID = lrtid ;
10395 }
10496
105- static { //Added in JDK 9 see JDK-8072645
106- MethodHandle lrgi = null ;
107- MethodHandle zisd = null ;
108- MethodHandle zdtoi = null ;
97+ static {
98+ Method lrgi = null ;
99+ Method zisd = null ;
100+ Method zdtoi = null ;
109101 try {
110- lrgi = LOOKUP .findVirtual (LogRecord .class , "getInstant" ,
111- MethodType .methodType (findClass ("java.time.Instant" )));
112-
113- zisd = LOOKUP .findStatic (findClass ("java.time.ZoneId" ),
114- "systemDefault" ,
115- MethodType .methodType (findClass ("java.time.ZoneId" )));
116-
117- zdtoi = LOOKUP .findStatic (findClass ("java.time.ZonedDateTime" ),
118- "ofInstant" ,
119- MethodType .methodType (findClass ("java.time.ZonedDateTime" ),
120- findClass ("java.time.Instant" ),
121- findClass ("java.time.ZoneId" )));
102+ lrgi = LogRecord .class .getMethod ("getInstant" );
103+ assert Comparable .class
104+ .isAssignableFrom (lrgi .getReturnType ()) : lrgi ;
105+ zisd = findClass ("java.time.ZoneId" )
106+ .getMethod ("systemDefault" );
107+ if (!Modifier .isStatic (zisd .getModifiers ())) {
108+ zisd = null ;
109+ throw new NoSuchMethodException (zisd .toString ());
110+ }
111+
112+ zdtoi = findClass ("java.time.ZonedDateTime" )
113+ .getMethod ("ofInstant" , findClass ("java.time.Instant" ),
114+ findClass ("java.time.ZoneId" ));
115+ if (!Modifier .isStatic (zdtoi .getModifiers ())
116+ || !Comparable .class .isAssignableFrom (
117+ zdtoi .getReturnType ())) {
118+ zdtoi = null ;
119+ throw new NoSuchMethodException (zdtoi .toString ());
120+ }
122121 } catch (final RuntimeException ignore ) {
123122 } catch (final Exception ignore ) { //No need for specific catch.
124123 } catch (final LinkageError ignore ) {
125124 } finally {
126125 if (lrgi == null || zisd == null || zdtoi == null ) {
127- lrgi = null ;
126+ lrgi = null ; //If any are null then clear all.
128127 zisd = null ;
129128 zdtoi = null ;
130129 }
@@ -322,22 +321,31 @@ static boolean hasLogManager() {
322321 * @throws NullPointerException if record is null.
323322 * @since JavaMail 1.5.6
324323 */
325- static Comparable <?> getZonedDateTime (final LogRecord record ) {
324+ @ SuppressWarnings ("UseSpecificCatch" )
325+ static Comparable <?> getZonedDateTime (LogRecord record ) {
326326 if (record == null ) {
327327 throw new NullPointerException ();
328328 }
329-
330- MethodHandle m = ZDT_OF_INSTANT ;
329+ final Method m = ZDT_OF_INSTANT ;
331330 if (m != null ) {
332331 try {
333- return (Comparable <?>) m .invoke (
332+ return (Comparable <?>) m .invoke (( Object ) null ,
334333 LR_GET_INSTANT .invoke (record ),
335- ZI_SYSTEM_DEFAULT .invoke ());
336- } catch (final RuntimeException | Error e ) {
337- throw e ; //Avoid catch all
338- } catch (final Throwable ute ) {
339- throw new UndeclaredThrowableException (ute );
340- }
334+ ZI_SYSTEM_DEFAULT .invoke ((Object ) null ));
335+ } catch (final RuntimeException ignore ) {
336+ assert LR_GET_INSTANT != null
337+ && ZI_SYSTEM_DEFAULT != null : ignore ;
338+ } catch (final InvocationTargetException ite ) {
339+ final Throwable cause = ite .getCause ();
340+ if (cause instanceof Error ) {
341+ throw (Error ) cause ;
342+ } else if (cause instanceof RuntimeException ) {
343+ throw (RuntimeException ) cause ;
344+ } else { //Should never happen.
345+ throw new UndeclaredThrowableException (ite );
346+ }
347+ } catch (final Exception ignore ) {
348+ }
341349 }
342350 return null ;
343351 }
@@ -355,14 +363,21 @@ static Long getLongThreadID(final LogRecord record) {
355363 throw new NullPointerException ();
356364 }
357365
358- final MethodHandle m = LR_GET_LONG_TID ;
366+ final Method m = LR_GET_LONG_TID ;
359367 if (m != null ) {
360368 try {
361- return (long ) m .invoke (record );
362- } catch (final RuntimeException | Error e ) {
363- throw e ;
364- } catch (final Throwable ute ) {
365- throw new UndeclaredThrowableException (ute );
369+ return (Long ) m .invoke (record );
370+ } catch (final InvocationTargetException ite ) {
371+ final Throwable cause = ite .getCause ();
372+ if (cause instanceof Error ) {
373+ throw (Error ) cause ;
374+ } else if (cause instanceof RuntimeException ) {
375+ throw (RuntimeException ) cause ;
376+ } else { //Should never happen.
377+ throw new UndeclaredThrowableException (ite );
378+ }
379+ } catch (final RuntimeException ignore ) {
380+ } catch (final Exception ignore ) {
366381 }
367382 }
368383 return null ;
@@ -405,9 +420,10 @@ static String getLocalHost(final Object s) throws Exception {
405420 *
406421 * @param value an ISO-8601 duration character sequence.
407422 * @return the number of milliseconds parsed from the duration.
423+ * @throws ArithmeticException if the duration is too large or too small.
408424 * @throws ClassNotFoundException if the java.time classes are not present.
409425 * @throws IllegalAccessException if the method is inaccessible.
410- * @throws RuntimeException if the method throws an exception.
426+ * @throws InvocationTargetException if the method throws an exception.
411427 * @throws LinkageError if the linkage fails.
412428 * @throws NullPointerException if the given duration is null.
413429 * @throws ExceptionInInitializerError if the static initializer fails.
@@ -421,20 +437,29 @@ static long parseDurationToMillis(final CharSequence value) throws Exception {
421437 if (value == null ) {
422438 throw new NullPointerException ();
423439 }
424-
425440 try {
426- Class <?> k = findClass ("java.time.Duration" );
427- MethodHandle dp = LOOKUP .findStatic (k , "parse" ,
428- MethodType .methodType (k , CharSequence .class ));
429-
430- MethodHandle dtm = LOOKUP .findVirtual (k , "toMillis" ,
431- MethodType .methodType (Long .TYPE ));
432- return (long ) dtm .invoke (dp .invoke (value ));
433- } catch (final RuntimeException | LinkageError
434- | ReflectiveOperationException fail ) {
435- throw fail ; //avoid catch all
436- } catch (Throwable cause ) {
437- throw new InvocationTargetException (cause );
441+ final Class <?> k = findClass ("java.time.Duration" );
442+ final Method parse = k .getMethod ("parse" , CharSequence .class );
443+ if (!k .isAssignableFrom (parse .getReturnType ())
444+ || !Modifier .isStatic (parse .getModifiers ())) {
445+ throw new NoSuchMethodException (parse .toString ());
446+ }
447+
448+ final Method toMillis = k .getMethod ("toMillis" );
449+ if (!Long .TYPE .isAssignableFrom (toMillis .getReturnType ())
450+ || Modifier .isStatic (toMillis .getModifiers ())) {
451+ throw new NoSuchMethodException (toMillis .toString ());
452+ }
453+ return (Long ) toMillis .invoke (parse .invoke (null , value ));
454+ } catch (final ExceptionInInitializerError EIIE ) {
455+ throw wrapOrThrow (EIIE );
456+ } catch (final InvocationTargetException ite ) {
457+ final Throwable cause = ite .getCause ();
458+ if (cause instanceof ArithmeticException ) {
459+ throw (ArithmeticException ) cause ;
460+ } else {
461+ throw paramOrError (ite );
462+ }
438463 }
439464 }
440465
0 commit comments