// 
// Decompiled by Procyon v0.6.0
// 

package com.nimbusds.jose.jwk.source;

import java.util.Collections;
import com.nimbusds.jose.KeySourceException;
import com.nimbusds.jose.jwk.JWK;
import java.util.List;
import com.nimbusds.jose.jwk.JWKSelector;
import java.util.Iterator;
import java.util.Set;
import com.nimbusds.jose.jwk.JWKMatcher;
import com.nimbusds.jose.util.Resource;
import java.text.ParseException;
import java.io.IOException;
import com.nimbusds.jose.RemoteKeySourceException;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.util.DefaultResourceRetriever;
import java.util.Objects;
import com.nimbusds.jose.util.ResourceRetriever;
import java.net.URL;
import com.nimbusds.jose.shaded.jcip.ThreadSafe;
import com.nimbusds.jose.proc.SecurityContext;

@ThreadSafe
@Deprecated
public class RemoteJWKSet<C extends SecurityContext> implements JWKSource<C>
{
    public static final int DEFAULT_HTTP_CONNECT_TIMEOUT = 500;
    public static final int DEFAULT_HTTP_READ_TIMEOUT = 500;
    public static final int DEFAULT_HTTP_SIZE_LIMIT = 51200;
    private final URL jwkSetURL;
    private final JWKSource<C> failoverJWKSource;
    private final JWKSetCache jwkSetCache;
    private final ResourceRetriever jwkSetRetriever;
    
    public static int resolveDefaultHTTPConnectTimeout() {
        return resolveDefault(RemoteJWKSet.class.getName() + ".defaultHttpConnectTimeout", 500);
    }
    
    public static int resolveDefaultHTTPReadTimeout() {
        return resolveDefault(RemoteJWKSet.class.getName() + ".defaultHttpReadTimeout", 500);
    }
    
    public static int resolveDefaultHTTPSizeLimit() {
        return resolveDefault(RemoteJWKSet.class.getName() + ".defaultHttpSizeLimit", 51200);
    }
    
    private static int resolveDefault(final String sysPropertyName, final int defaultValue) {
        final String value = System.getProperty(sysPropertyName);
        if (value == null) {
            return defaultValue;
        }
        try {
            return Integer.parseInt(value);
        }
        catch (final NumberFormatException e) {
            return defaultValue;
        }
    }
    
    public RemoteJWKSet(final URL jwkSetURL) {
        this(jwkSetURL, (JWKSource)null);
    }
    
    public RemoteJWKSet(final URL jwkSetURL, final JWKSource<C> failoverJWKSource) {
        this(jwkSetURL, failoverJWKSource, null, null);
    }
    
    public RemoteJWKSet(final URL jwkSetURL, final ResourceRetriever resourceRetriever) {
        this(jwkSetURL, resourceRetriever, null);
    }
    
    public RemoteJWKSet(final URL jwkSetURL, final ResourceRetriever resourceRetriever, final JWKSetCache jwkSetCache) {
        this(jwkSetURL, null, resourceRetriever, jwkSetCache);
    }
    
    public RemoteJWKSet(final URL jwkSetURL, final JWKSource<C> failoverJWKSource, final ResourceRetriever resourceRetriever, final JWKSetCache jwkSetCache) {
        this.jwkSetURL = Objects.requireNonNull(jwkSetURL);
        this.failoverJWKSource = failoverJWKSource;
        if (resourceRetriever != null) {
            this.jwkSetRetriever = resourceRetriever;
        }
        else {
            this.jwkSetRetriever = new DefaultResourceRetriever(resolveDefaultHTTPConnectTimeout(), resolveDefaultHTTPReadTimeout(), resolveDefaultHTTPSizeLimit());
        }
        if (jwkSetCache != null) {
            this.jwkSetCache = jwkSetCache;
        }
        else {
            this.jwkSetCache = new DefaultJWKSetCache();
        }
    }
    
    private JWKSet updateJWKSetFromURL() throws RemoteKeySourceException {
        Resource res;
        try {
            res = this.jwkSetRetriever.retrieveResource(this.jwkSetURL);
        }
        catch (final IOException e) {
            throw new RemoteKeySourceException("Couldn't retrieve remote JWK set: " + e.getMessage(), e);
        }
        JWKSet jwkSet;
        try {
            jwkSet = JWKSet.parse(res.getContent());
        }
        catch (final ParseException e2) {
            throw new RemoteKeySourceException("Couldn't parse remote JWK set: " + e2.getMessage(), e2);
        }
        this.jwkSetCache.put(jwkSet);
        return jwkSet;
    }
    
    public URL getJWKSetURL() {
        return this.jwkSetURL;
    }
    
    public JWKSource<C> getFailoverJWKSource() {
        return this.failoverJWKSource;
    }
    
    public ResourceRetriever getResourceRetriever() {
        return this.jwkSetRetriever;
    }
    
    public JWKSetCache getJWKSetCache() {
        return this.jwkSetCache;
    }
    
    public JWKSet getCachedJWKSet() {
        return this.jwkSetCache.get();
    }
    
    protected static String getFirstSpecifiedKeyID(final JWKMatcher jwkMatcher) {
        final Set<String> keyIDs = jwkMatcher.getKeyIDs();
        if (keyIDs == null || keyIDs.isEmpty()) {
            return null;
        }
        for (final String id : keyIDs) {
            if (id != null) {
                return id;
            }
        }
        return null;
    }
    
    private List<JWK> failover(final Exception exception, final JWKSelector jwkSelector, final C context) throws RemoteKeySourceException {
        if (this.getFailoverJWKSource() == null) {
            return null;
        }
        try {
            return this.getFailoverJWKSource().get(jwkSelector, context);
        }
        catch (final KeySourceException kse) {
            throw new RemoteKeySourceException(exception.getMessage() + "; Failover JWK source retrieval failed with: " + kse.getMessage(), kse);
        }
    }
    
    @Override
    public List<JWK> get(final JWKSelector jwkSelector, final C context) throws RemoteKeySourceException {
        JWKSet jwkSet = this.jwkSetCache.get();
        Label_0106: {
            if (!this.jwkSetCache.requiresRefresh()) {
                if (jwkSet != null) {
                    break Label_0106;
                }
            }
            try {
                synchronized (this) {
                    jwkSet = this.jwkSetCache.get();
                    if (this.jwkSetCache.requiresRefresh() || jwkSet == null) {
                        jwkSet = this.updateJWKSetFromURL();
                    }
                }
            }
            catch (final Exception e) {
                final List<JWK> failoverMatches = this.failover(e, jwkSelector, context);
                if (failoverMatches != null) {
                    return failoverMatches;
                }
                if (jwkSet == null) {
                    throw e;
                }
            }
        }
        final List<JWK> matches = jwkSelector.select(jwkSet);
        if (!matches.isEmpty()) {
            return matches;
        }
        final String soughtKeyID = getFirstSpecifiedKeyID(jwkSelector.getMatcher());
        if (soughtKeyID == null) {
            return Collections.emptyList();
        }
        if (jwkSet.getKeyByKeyId(soughtKeyID) != null) {
            return Collections.emptyList();
        }
        try {
            synchronized (this) {
                if (jwkSet == this.jwkSetCache.get()) {
                    jwkSet = this.updateJWKSetFromURL();
                }
                else {
                    jwkSet = this.jwkSetCache.get();
                }
            }
        }
        catch (final KeySourceException e2) {
            final List<JWK> failoverMatches2 = this.failover(e2, jwkSelector, context);
            if (failoverMatches2 != null) {
                return failoverMatches2;
            }
            throw e2;
        }
        if (jwkSet == null) {
            return Collections.emptyList();
        }
        return jwkSelector.select(jwkSet);
    }
}
