|
3 | 3 | import com.google.gson.JsonArray; |
4 | 4 | import org.apache.log4j.Logger; |
5 | 5 | import org.jetbrains.annotations.NotNull; |
| 6 | +import org.jetbrains.annotations.Nullable; |
6 | 7 | import xyz.gianlu.librespot.mercury.MercuryClient; |
7 | 8 | import xyz.gianlu.librespot.mercury.MercuryRequests; |
8 | 9 |
|
9 | 10 | import java.io.IOException; |
| 11 | +import java.util.ArrayList; |
10 | 12 | import java.util.Arrays; |
11 | | -import java.util.HashMap; |
12 | | -import java.util.Map; |
| 13 | +import java.util.List; |
| 14 | +import java.util.Objects; |
13 | 15 |
|
14 | 16 | /** |
15 | 17 | * @author Gianlu |
16 | 18 | */ |
17 | | -public class TokenProvider { |
| 19 | +public final class TokenProvider { |
18 | 20 | private final static Logger LOGGER = Logger.getLogger(TokenProvider.class); |
19 | 21 | private final static int TOKEN_EXPIRE_THRESHOLD = 10; |
20 | 22 | private final Session session; |
21 | | - private final Map<String, StoredToken> tokens = new HashMap<>(); |
| 23 | + private final List<StoredToken> tokens = new ArrayList<>(); |
22 | 24 |
|
23 | 25 | TokenProvider(@NotNull Session session) { |
24 | 26 | this.session = session; |
25 | 27 | } |
26 | 28 |
|
| 29 | + @Nullable |
| 30 | + private StoredToken findTokenWithAllScopes(String[] scopes) { |
| 31 | + for (StoredToken token : tokens) |
| 32 | + if (token.hasScopes(scopes)) |
| 33 | + return token; |
| 34 | + |
| 35 | + return null; |
| 36 | + } |
| 37 | + |
27 | 38 | @NotNull |
28 | | - public StoredToken getToken(@NotNull String scope) throws IOException, MercuryClient.MercuryException { |
29 | | - if (scope.contains(",")) throw new UnsupportedOperationException("Only single scope tokens are supported."); |
| 39 | + public StoredToken getToken(@NotNull String... scopes) throws IOException, MercuryClient.MercuryException { |
| 40 | + if (scopes.length == 0) throw new IllegalArgumentException(); |
30 | 41 |
|
31 | | - StoredToken token = tokens.get(scope); |
| 42 | + StoredToken token = findTokenWithAllScopes(scopes); |
32 | 43 | if (token != null) { |
33 | | - if (token.expired()) tokens.remove(scope); |
| 44 | + if (token.expired()) tokens.remove(token); |
34 | 45 | else return token; |
35 | 46 | } |
36 | 47 |
|
37 | | - LOGGER.debug(String.format("Token expired or not suitable, requesting again. {scope: %s, oldToken: %s}", scope, token)); |
38 | | - MercuryRequests.KeymasterToken resp = session.mercury().sendSync(MercuryRequests.requestToken(session.deviceId(), scope)); |
| 48 | + LOGGER.debug(String.format("Token expired or not suitable, requesting again. {scopes: %s, oldToken: %s}", Arrays.asList(scopes), token)); |
| 49 | + MercuryRequests.KeymasterToken resp = session.mercury().sendSync(MercuryRequests.requestToken(session.deviceId(), String.join(",", scopes))); |
39 | 50 | token = new StoredToken(resp); |
40 | 51 |
|
41 | | - LOGGER.debug(String.format("Updated token successfully! {scope: %s, newToken: %s}", scope, token)); |
| 52 | + LOGGER.debug(String.format("Updated token successfully! {scopes: %s, newToken: %s}", Arrays.asList(scopes), token)); |
| 53 | + tokens.add(token); |
42 | 54 |
|
43 | | - tokens.put(scope, token); |
44 | 55 | return token; |
45 | 56 | } |
46 | 57 |
|
@@ -79,5 +90,21 @@ public String toString() { |
79 | 90 | ", timestamp=" + timestamp + |
80 | 91 | '}'; |
81 | 92 | } |
| 93 | + |
| 94 | + public boolean hasScope(@NotNull String scope) { |
| 95 | + for (String s : scopes) |
| 96 | + if (Objects.equals(s, scope)) |
| 97 | + return true; |
| 98 | + |
| 99 | + return false; |
| 100 | + } |
| 101 | + |
| 102 | + public boolean hasScopes(String[] sc) { |
| 103 | + for (String s : sc) |
| 104 | + if (!hasScope(s)) |
| 105 | + return false; |
| 106 | + |
| 107 | + return true; |
| 108 | + } |
82 | 109 | } |
83 | 110 | } |
0 commit comments