001// Generated by delombok at Mon Jan 02 16:27:27 UTC 2023
002package io.cui.tools.lang;
003
004import static io.cui.tools.string.MoreStrings.isEmpty;
005import java.lang.reflect.AccessibleObject;
006import java.lang.reflect.Constructor;
007import java.security.AccessController;
008import java.security.PrivilegedAction;
009import java.security.PrivilegedActionException;
010import java.security.PrivilegedExceptionAction;
011import java.util.Arrays;
012import java.util.Collections;
013import java.util.Map;
014import java.util.Optional;
015import java.util.Properties;
016import io.cui.tools.logging.CuiLogger;
017// owolff: The casts are necessary for the return type
018/**
019 * Helper class providing some convenience method for interacting with {@link SecurityManager}
020 * related stuff. In essence, it uses {@link AccessController#doPrivileged(PrivilegedAction)} for
021 * its
022 * method in case a {@link SecurityManager} is set.
023 *
024 * @author Oliver Wolff
025 */
026@SuppressWarnings("java:S1905")
027public final class SecuritySupport {
028    private static final String SECURITY_MANAGER_CONFIGURED = "A SecurityManager is configured, using PrivilegedAction";
029    private static final CuiLogger LOGGER = new CuiLogger(SecuritySupport.class);
030
031    /**
032     * @return the context-classloader if obtainable, {@link Optional#empty()} otherwise
033     */
034    public static Optional<ClassLoader> getContextClassLoader() {
035        if (null == System.getSecurityManager()) {
036            LOGGER.trace("No SecurityManager configured, accessing context-class-loader");
037            return Optional.ofNullable(Thread.currentThread().getContextClassLoader());
038        } else {
039            LOGGER.trace(SECURITY_MANAGER_CONFIGURED);
040            return AccessController.doPrivileged((PrivilegedAction<Optional<ClassLoader>>) () -> {
041                try {
042                    return Optional.ofNullable(Thread.currentThread().getContextClassLoader());
043                } catch (SecurityException e) {
044                    LOGGER.warn("Unable to access context-class-loader due to SecurityException", e);
045                    return Optional.empty();
046                }
047            });
048        }
049    }
050
051    /**
052     * @param object to be set accessible
053     * @param accessible value
054     */
055    public static void setAccessible(AccessibleObject object, boolean accessible) {
056        if (null == System.getSecurityManager()) {
057            LOGGER.trace("No SecurityManager configured, setting accessible directly");
058            object.setAccessible(accessible);
059        } else {
060            LOGGER.trace(SECURITY_MANAGER_CONFIGURED);
061            AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
062                try {
063                    object.setAccessible(accessible);
064                } catch (SecurityException e) {
065                    LOGGER.warn("Unable to call \'setAccessible\' due to SecurityException", e);
066                }
067                return null;
068            });
069        }
070    }
071
072    /**
073     * @param propertyName If is null or empty the method will return {@link Optional#empty()}
074     * @return an {@link Optional} on the requested property
075     */
076    public static Optional<String> accessSystemProperty(String propertyName) {
077        if (isEmpty(propertyName)) {
078            return Optional.empty();
079        }
080        if (null == System.getSecurityManager()) {
081            LOGGER.trace("No SecurityManager configured, accessing System-Property directly");
082            return Optional.ofNullable(System.getProperty(propertyName));
083        } else {
084            LOGGER.trace(SECURITY_MANAGER_CONFIGURED);
085            return AccessController.doPrivileged((PrivilegedAction<Optional<String>>) () -> {
086                try {
087                    return Optional.ofNullable(System.getProperty(propertyName));
088                } catch (SecurityException e) {
089                    LOGGER.warn("Unable to call \'System.getProperty\' due to SecurityException", e);
090                }
091                return Optional.empty();
092            });
093        }
094    }
095
096    /**
097     * @return the {@link Properties} derived by {@link System#getProperties()}. If this can not be
098     *         achieved it returns an empty {@link Properties} object.
099     */
100    public static Properties accessSystemProperties() {
101        if (null == System.getSecurityManager()) {
102            LOGGER.trace("No SecurityManager configured, accessing System.getProperties directly");
103            return System.getProperties();
104        } else {
105            LOGGER.trace(SECURITY_MANAGER_CONFIGURED);
106            return AccessController.doPrivileged((PrivilegedAction<Properties>) () -> {
107                try {
108                    return System.getProperties();
109                } catch (SecurityException e) {
110                    LOGGER.warn("Unable to call \'System.getProperties\' due to SecurityException", e);
111                }
112                return new Properties();
113            });
114        }
115    }
116
117    /**
118     * @return the map derived by {@link System#getenv()}. If this can not be achieved it returns an
119     *         empty map.
120     */
121    public static Map<String, String> accessSystemEnv() {
122        if (null == System.getSecurityManager()) {
123            LOGGER.trace("No SecurityManager configured, accessing System.getenv directly");
124            return System.getenv();
125        } else {
126            LOGGER.trace(SECURITY_MANAGER_CONFIGURED);
127            return AccessController.doPrivileged((PrivilegedAction<Map<String, String>>) () -> {
128                try {
129                    return System.getenv();
130                } catch (SecurityException e) {
131                    LOGGER.warn("Unable to call \'System.getenv\' due to SecurityException", e);
132                }
133                return Collections.emptyMap();
134            });
135        }
136    }
137
138    // owolff: using wildcards here is the only sensible thing to
139    // do
140    /**
141     * @param <T>
142     * @param clazz The type of the object
143     * @param paramTypes to be used for identifying the constructor
144     * @return the found constructor.
145     * @throws NoSuchMethodException to be thrown, if there is no corresponding constructor
146     * @throws IllegalStateException for cases where the {@link PrivilegedAction} fails but is not a
147     *             {@link NoSuchMethodException}
148     */
149    @SuppressWarnings("squid:S1452")
150    public static <T> Constructor<? extends T> getDeclaredConstructor(Class<T> clazz, Class<?>... paramTypes) throws NoSuchMethodException {
151        if (null == System.getSecurityManager()) {
152            LOGGER.trace("No SecurityManager configured, accessing declared constructors directly");
153            return clazz.getDeclaredConstructor(paramTypes);
154        } else {
155            try {
156                LOGGER.trace(SECURITY_MANAGER_CONFIGURED);
157                return AccessController.doPrivileged((PrivilegedExceptionAction<Constructor<? extends T>>) () -> {
158                    Constructor<? extends T> constructor = null;
159                    try {
160                        constructor = clazz.getDeclaredConstructor(paramTypes);
161                    } catch (SecurityException e) {
162                        LOGGER.warn(e, "Unable to call \'getDeclaredConstructor\' due to SecurityException, class=\'{}\', paramTypes=\'{}\'", clazz.toString(), Arrays.toString(paramTypes));
163                    }
164                    return constructor;
165                });
166            } catch (PrivilegedActionException e) {
167                Exception e2 = e.getException();
168                if (e2 instanceof NoSuchMethodException) {
169                    throw (NoSuchMethodException) e2;
170                } else {
171                    throw new IllegalStateException(e2);
172                }
173            }
174        }
175    }
176
177    @java.lang.SuppressWarnings("all")
178    @lombok.Generated
179    private SecuritySupport() {
180        throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated");
181    }
182}