001package io.prometheus.jmx; 002 003import java.lang.reflect.InvocationTargetException; 004import java.lang.reflect.Method; 005import java.util.logging.Level; 006import java.util.logging.Logger; 007 008public class OptionalValueExtractor { 009 010 private static final Logger LOGGER = Logger.getLogger(OptionalValueExtractor.class.getName()); 011 012 private static final String OPTIONAL_CLASS_NAME = "java.util.Optional"; 013 private static final Class<?> OPTIONAL_CLASS = findOptionalClass(); 014 private static final Method OR_ELSE_METHOD = findOrElseMethod(); 015 016 private static Class<?> findOptionalClass() { 017 Class<?> optionalClass = null; 018 try { 019 optionalClass = Class.forName(OPTIONAL_CLASS_NAME); 020 } catch (ClassNotFoundException e) { 021 LOGGER.log(Level.FINE, "{0}: class not found (not running on Java 8+)", OPTIONAL_CLASS_NAME); // that's okay 022 } 023 if (optionalClass != null) { 024 LOGGER.log(Level.FINE, "{0} will be supported", OPTIONAL_CLASS_NAME); 025 } 026 return optionalClass; 027 } 028 029 private static Method findOrElseMethod() { 030 if (OPTIONAL_CLASS != null) { 031 try { 032 return OPTIONAL_CLASS.getMethod("orElse", Object.class); 033 } catch (NoSuchMethodException e) { 034 LOGGER.log(Level.WARNING, "{0}.orElse(Object): method not found!", OPTIONAL_CLASS_NAME); // that would be weird! 035 } 036 } 037 return null; 038 } 039 040 public boolean isOptional(Object o) { 041 return (o != null) 042 && OPTIONAL_CLASS == o.getClass() // Optional is final, no need for isAssignableFrom() 043 && OR_ELSE_METHOD != null; // would we be able to extract value from this Optional? 044 } 045 046 public Object getOptionalValueOrNull(Object o) { 047 try { 048 return OR_ELSE_METHOD.invoke(o, (Object) null); 049 } catch (IllegalAccessException e) { 050 LOGGER.log(Level.FINE, "IllegalAccessException calling orElse(null) on {0}", o); 051 } catch (IllegalArgumentException e) { 052 LOGGER.log(Level.FINE, "IllegalArgumentException calling orElse(null) on {0}", o); 053 } catch (InvocationTargetException e) { 054 LOGGER.log(Level.FINE, "InvocationTargetException calling orElse(null) on {0}", o); 055 } 056 return null; 057 } 058}