001/*
002 * acme4j - Java ACME client
003 *
004 * Copyright (C) 2019 Richard "Shred" K├Ârber
005 *   http://acme4j.shredzone.org
006 *
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
013 */
014package org.shredzone.acme4j.connector;
015
016import java.net.Authenticator;
017import java.net.ProxySelector;
018import java.net.http.HttpClient;
019import java.time.Duration;
020import java.util.Optional;
021
022import edu.umd.cs.findbugs.annotations.Nullable;
023import org.slf4j.LoggerFactory;
024
025/**
026 * Contains network settings to be used for network connections.
027 *
028 * @since 2.8
029 */
030public class NetworkSettings {
031
032    /**
033     * Name of the system property to control GZIP compression. Expects a boolean value.
034     */
035    public static final String GZIP_PROPERTY_NAME = "org.shredzone.acme4j.gzip_compression";
036
037    private ProxySelector proxySelector = HttpClient.Builder.NO_PROXY;
038    private Duration timeout = Duration.ofSeconds(10);
039    private @Nullable Authenticator authenticator = null;
040    private boolean compression = true;
041
042    public NetworkSettings() {
043        try {
044            Optional.ofNullable(System.getProperty(GZIP_PROPERTY_NAME))
045                    .map(Boolean::parseBoolean)
046                    .ifPresent(val -> compression = val);
047        } catch (Exception ex) {
048            // Ignore a broken property name or a SecurityException
049            LoggerFactory.getLogger(NetworkSettings.class)
050                    .warn("Could not read system property: {}", GZIP_PROPERTY_NAME, ex);
051        }
052    }
053
054    /**
055     * Gets the {@link ProxySelector} to be used for connections.
056     *
057     * @since 3.0.0
058     */
059    public ProxySelector getProxySelector() {
060        return proxySelector;
061    }
062
063    /**
064     * Sets a {@link ProxySelector} that is to be used for all connections. If
065     * {@code null}, {@link HttpClient.Builder#NO_PROXY} is used, which is also the
066     * default.
067     *
068     * @since 3.0.0
069     */
070    public void setProxySelector(@Nullable ProxySelector proxySelector) {
071        this.proxySelector = proxySelector != null ? proxySelector : HttpClient.Builder.NO_PROXY;
072    }
073
074    /**
075     * Gets the {@link Authenticator} to be used, or {@code null} if none is to be set.
076     *
077     * @since 3.0.0
078     */
079    public @Nullable Authenticator getAuthenticator() {
080        return authenticator;
081    }
082
083    /**
084     * Sets an {@link Authenticator} to be used if HTTP authentication is needed (e.g.
085     * by a proxy). {@code null} means that no authenticator shall be set.
086     *
087     * @since 3.0.0
088     */
089    public void setAuthenticator(@Nullable Authenticator authenticator) {
090        this.authenticator = authenticator;
091    }
092
093    /**
094     * Gets the current network timeout.
095     */
096    public Duration getTimeout() {
097        return timeout;
098    }
099
100    /**
101     * Sets the network timeout to be used for connections. Defaults to 10 seconds.
102     *
103     * @param timeout
104     *         Network timeout {@link Duration}
105     */
106    public void setTimeout(Duration timeout) {
107        if (timeout == null || timeout.isNegative() || timeout.isZero()) {
108            throw new IllegalArgumentException("Timeout must be positive");
109        }
110
111        this.timeout = timeout;
112    }
113
114    /**
115     * Checks if HTTP compression is enabled.
116     *
117     * @since 3.0.0
118     */
119    public boolean isCompressionEnabled() {
120        return compression;
121    }
122
123    /**
124     * Sets if HTTP compression is enabled. It is enabled by default, but can be
125     * disabled e.g. for debugging purposes.
126     * <p>
127     * acme4j gzip compression can also be controlled via the {@value #GZIP_PROPERTY_NAME}
128     * system property.
129     *
130     * @since 3.0.0
131     */
132    public void setCompressionEnabled(boolean compression) {
133        this.compression = compression;
134    }
135
136}