• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SingingBush / dubclient / #55

20 Aug 2025 09:03PM UTC coverage: 37.073% (+0.4%) from 36.639%
#55

push

SingingBush
fix imports in test for httpclient5

39 of 242 branches covered (16.12%)

Branch coverage included in aggregate %.

232 of 489 relevant lines covered (47.44%)

1.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.51
/src/main/java/com/singingbush/dubclient/DubClientImpl.java
1
package com.singingbush.dubclient;
2

3
import com.google.gson.Gson;
4
import com.google.gson.GsonBuilder;
5
import com.google.gson.JsonSyntaxException;
6
import com.singingbush.dubclient.data.*;
7
import org.apache.hc.client5.http.classic.methods.HttpGet;
8
import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
9
import org.apache.hc.client5.http.config.ConnectionConfig;
10
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
11
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
12
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
13
import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager;
14
import org.apache.hc.core5.http.HttpEntity;
15
import org.apache.hc.core5.http.ParseException;
16
import org.apache.hc.core5.http.io.entity.EntityUtils;
17
import org.jetbrains.annotations.NotNull;
18
import org.slf4j.Logger;
19
import org.slf4j.LoggerFactory;
20

21
import java.io.File;
22
import java.io.FileNotFoundException;
23
import java.io.IOException;
24
import java.io.Reader;
25
import java.nio.charset.StandardCharsets;
26
import java.util.concurrent.TimeUnit;
27
import java.util.stream.Stream;
28

29
/**
30
 * @author Samael Bate (singingbush)
31
 * created on 16/06/18
32
 */
33
class DubClientImpl implements DubClient {
34

35
    private static final Logger log = LoggerFactory.getLogger(DubClientImpl.class);
3✔
36

37
    private final String repositoryUrl;
38
    private final CloseableHttpClient httpClient;
39
    private final Gson gson;
40

41
    DubClientImpl(@NotNull String repositoryUrl,
42
                         long timeout,
43
                         @NotNull String userAgent) {
3✔
44
        this.repositoryUrl = repositoryUrl;
3✔
45

46
        final BasicHttpClientConnectionManager cm = new BasicHttpClientConnectionManager();
3✔
47
        cm.setConnectionConfig(ConnectionConfig.custom()
3✔
48
            .setConnectTimeout(timeout, TimeUnit.MILLISECONDS)
3✔
49
            .setSocketTimeout((int) timeout, TimeUnit.MILLISECONDS)
3✔
50
            .build());
3✔
51

52
        httpClient = HttpClientBuilder.create()
3✔
53
            .setConnectionManager(cm)
3✔
54
            .setUserAgent(userAgent)
3✔
55
            .build();
3✔
56

57
        gson = new GsonBuilder().create();
3✔
58
    }
3✔
59

60
    @Override
61
    public DubProject parseProjectFile(@NotNull File dubFile) {
62
        if (!dubFile.exists()) throw new IllegalArgumentException("dub file does not exist");
2!
63
        if (!dubFile.isFile()) throw new IllegalArgumentException("dub file does not a valid file");
2!
64
        if (!dubFile.canRead()) throw new IllegalArgumentException("dub file cannot be read");
2!
65

66
        final DubFileParser parser = dubFile.getName().endsWith(".json") ? new JsonDubFileParser() : new SdlDubFileParser();
2✔
67

68
        try {
69
            return parser.parse(dubFile);
2✔
70
        } catch (final FileNotFoundException e) {
×
71
            log.error(String.format("The file '%s' was not found", dubFile.getName()), e);
×
72
        }
73
        return null; // todo: don't return null, throw a custom exception
×
74
    }
75

76
    @Override
77
    public DubProject parseDubJsonFile(@NotNull Reader reader) {
78
        final DubFileParser parser = new JsonDubFileParser();
2✔
79
        return parser.parse(reader);
2✔
80
    }
81

82
    @Override
83
    public DubProject parseDubSdlFile(@NotNull Reader reader) {
84
        final DubFileParser parser = new SdlDubFileParser();
2✔
85
        return parser.parse(reader);
2✔
86
    }
87

88
    @Override
89
    public Stream<SearchResult> search(@NotNull final String text) throws DubRepositoryException {
90
        if (text.isEmpty()) throw new IllegalArgumentException("Search text cannot be blank");
3!
91

92
        final HttpUriRequest request = new HttpGet(String.format("%s/api/packages/search?q=%s", repositoryUrl, text));
3✔
93

94
        return Stream.of(callApi(request, SearchResult[].class));
3✔
95
    }
96

97
    @Override
98
    public PackageInfo packageInfo(@NotNull final String packageName) throws DubRepositoryException {
99
        if (packageName.isEmpty()) throw new IllegalArgumentException("Package Name cannot be blank");
2!
100

101
        final HttpUriRequest request = new HttpGet(String.format("%s/api/packages/%s/info", repositoryUrl, packageName));
2✔
102

103
        return callApi(request, PackageInfo.class);
2✔
104
    }
105

106
    @Override
107
    public VersionInfo packageInfo(@NotNull final String packageName, @NotNull final String version) throws DubRepositoryException {
108
        if (packageName.isEmpty() || version.isEmpty()) throw new IllegalArgumentException("args cannot be blank");
2!
109

110
        final HttpUriRequest request = new HttpGet(String.format("%s/api/packages/%s/%s/info", repositoryUrl, packageName, version));
2✔
111

112
        return callApi(request, VersionInfo.class);
2✔
113
    }
114

115
    @Override
116
    public PackageStats packageStats(@NotNull final String packageName) throws DubRepositoryException {
117
        if (packageName.isEmpty()) throw new IllegalArgumentException("Package Name cannot be blank");
2!
118

119
        final HttpUriRequest request = new HttpGet(String.format("%s/api/packages/%s/stats", repositoryUrl, packageName));
2✔
120

121
        return callApi(request, PackageStats.class);
2✔
122
    }
123

124
    @Override
125
    public DownloadStats packageStats(@NotNull final String packageName, @NotNull final String version) throws DubRepositoryException {
126
        if (packageName.isEmpty() || version.isEmpty()) throw new IllegalArgumentException("args cannot be blank");
2!
127

128
        final HttpUriRequest request = new HttpGet(String.format("%s/api/packages/%s/%s/stats", repositoryUrl, packageName, version));
2✔
129

130
        return callApi(request, PackageStats.class).getDownloads();
2✔
131
    }
132

133
    @Override
134
    public String latestVersion(@NotNull final String packageName) throws DubRepositoryException {
135
        if (packageName.isEmpty()) throw new IllegalArgumentException("Package Name cannot be blank");
2!
136

137
        final HttpUriRequest request = new HttpGet(String.format("%s/api/packages/%s/latest", repositoryUrl, packageName));
2✔
138

139
        return callApi(request, String.class);
2✔
140
    }
141

142
    private <T> T callApi(@NotNull final HttpUriRequest request, @NotNull final Class<T> clazz) throws DubRepositoryException {
143
        log.info("making HTTP request to {}", request.getRequestUri());
3✔
144

145
        try (final CloseableHttpResponse response = httpClient.execute(request)) {
3✔
146
            if(response != null) {
3!
147
                final int status = response.getCode();
3✔
148
                final HttpEntity httpEntity = response.getEntity();
3✔
149
                if(httpEntity != null) {
3✔
150
                    if(status == 200) {
3!
151
                        return parseResponse(httpEntity, clazz);
3✔
152
                    } else {
153
                        log.warn(String.format("DUB repository returned %s", status));
×
154
                        log.debug("Server status message: {}", parseResponse(httpEntity, ErrorMessage.class).getStatusMessage());
×
155
                    }
156
                }
157
            } else {
2✔
158
                log.warn("no response from DUB repository");
×
159
            }
160
        } catch (final IOException e) {
3!
161
            log.error(e.getMessage());
2✔
162
        }
2✔
163

164
        throw new DubRepositoryException("");
2✔
165
    }
166

167
    private <T> T parseResponse(@NotNull final HttpEntity entity, @NotNull final Class<T> clazz) throws IOException, DubRepositoryException {
168
        try {
169
            return gson.fromJson(EntityUtils.toString(entity, StandardCharsets.UTF_8), clazz);
3✔
170
        } catch (final JsonSyntaxException | ParseException e) {
2✔
171
            log.error("unable to parse the json response from the dub repository", e);
2✔
172
            throw new DubRepositoryException("the json response was not as expected", e);
2✔
173
        }
174
    }
175

176
    @Override
177
    public String toString() {
178
        final StringBuilder sb = new StringBuilder("DubClientImpl{");
×
179
        sb.append("repositoryUrl='").append(repositoryUrl).append('\'');
×
180
        sb.append(", httpClient=").append(httpClient);
×
181
        sb.append(", gson=").append(gson);
×
182
        sb.append('}');
×
183
        return sb.toString();
×
184
    }
185
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc