Skip to content

Commit c9a2620

Browse files
authored
🐛fix: close stream, avoid leak (#43)
🐛fix: close stream, avoid leak
1 parent 15dc743 commit c9a2620

File tree

4 files changed

+115
-40
lines changed

4 files changed

+115
-40
lines changed

pom.xml

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<java.version>1.8</java.version>
1414
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
1515
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
16-
<version.guava>31.1-jre</version.guava>
16+
<version.guava>32.0.1-jre</version.guava>
1717
<version.okhttp>3.14.9</version.okhttp>
1818
<version.logback>1.2.11</version.logback>
1919
<version.jackson>2.14.0</version.jackson>
@@ -116,19 +116,6 @@
116116
<version>2.2</version>
117117
<scope>test</scope>
118118
</dependency>
119-
<!-- Dependencies used by examples in this project (not required for using Spock) -->
120-
<dependency>
121-
<groupId>com.h2database</groupId>
122-
<artifactId>h2</artifactId>
123-
<version>2.1.210</version>
124-
<scope>test</scope>
125-
</dependency>
126-
<dependency>
127-
<groupId>org.codehaus.groovy</groupId>
128-
<artifactId>groovy-sql</artifactId>
129-
<version>${groovy.version}</version>
130-
<scope>test</scope>
131-
</dependency>
132119
</dependencies>
133120

134121
<build>

src/main/java/com/featureprobe/sdk/server/FPContext.java

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import okhttp3.Headers;
2121
import org.slf4j.Logger;
2222

23+
import java.io.IOException;
2324
import java.io.InputStream;
2425
import java.net.MalformedURLException;
2526
import java.net.URI;
@@ -29,7 +30,7 @@
2930
import java.util.Objects;
3031
import java.util.Properties;
3132

32-
final class FPContext {
33+
class FPContext {
3334

3435
private static final Logger logger = Loggers.MAIN;
3536

@@ -81,19 +82,17 @@ final class FPContext {
8182
this.realtimeUri = config.realtimeUri;
8283
}
8384
} catch (MalformedURLException e) {
84-
logger.error("construction context error", e);
85+
logger.error("construction context error MalformedURLException");
8586
} catch (URISyntaxException e) {
86-
logger.error("construction context error", e);
87+
logger.error("construction context error URISyntaxException");
8788
}
8889
this.serverSdkKey = serverSdkKey;
8990
this.refreshInterval = config.refreshInterval;
9091
this.location = config.location;
9192
this.httpConfiguration = config.httpConfiguration;
9293
String sdkVersion = getVersion();
93-
this.headers = config.httpConfiguration.headers.newBuilder()
94-
.add(GET_SDK_KEY_HEADER, serverSdkKey)
95-
.add(USER_AGENT_HEADER, SDK_FLAG_PREFIX + sdkVersion)
96-
.build();
94+
this.headers = config.httpConfiguration.headers.newBuilder().add(GET_SDK_KEY_HEADER, serverSdkKey)
95+
.add(USER_AGENT_HEADER, SDK_FLAG_PREFIX + sdkVersion).build();
9796
}
9897

9998
public URL getSynchronizerUrl() {
@@ -124,32 +123,41 @@ public Headers getHeaders() {
124123
return headers;
125124
}
126125

127-
private synchronized String getVersion() {
128-
String version = null;
129-
try {
130-
Properties p = new Properties();
131-
InputStream is = getClass()
132-
.getResourceAsStream("/META-INF/maven/com.featureprobe/server-sdk-java/pom.properties");
126+
public synchronized String getVersion() {
127+
try (
128+
InputStream is =
129+
getResourceAsStream("/META-INF/maven/com.featureprobe/server-sdk-java/pom.properties")) {
133130
if (is != null) {
131+
Properties p = new Properties();
134132
p.load(is);
135-
version = p.getProperty("version", DEFAULT_SDK_VERSION);
133+
return p.getProperty("version", DEFAULT_SDK_VERSION);
136134
}
137-
} catch (Exception e) {
135+
} catch (IOException e) {
136+
logger.error("get version error", e);
137+
}
138138

139+
Package aPackage = getPackage();
140+
if (aPackage == null) {
141+
return DEFAULT_SDK_VERSION;
139142
}
140-
if (version == null) {
141-
Package aPackage = getClass().getPackage();
142-
if (aPackage != null) {
143-
version = aPackage.getImplementationVersion();
144-
if (version == null) {
145-
version = aPackage.getSpecificationVersion();
146-
}
147-
}
143+
144+
String version = aPackage.getImplementationVersion();
145+
if (version != null) {
146+
return version;
148147
}
149-
if (version == null) {
150-
version = DEFAULT_SDK_VERSION;
148+
version = aPackage.getSpecificationVersion();
149+
if (version != null) {
150+
return version;
151151
}
152-
return version;
152+
return DEFAULT_SDK_VERSION;
153+
}
154+
155+
protected Package getPackage() {
156+
return getClass().getPackage();
157+
}
158+
159+
protected InputStream getResourceAsStream(String resource) {
160+
return getClass().getResourceAsStream(resource);
153161
}
154162

155163
public URI getRealtimeUri() {

src/main/java/com/featureprobe/sdk/server/model/Rule.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ public final class Rule {
3131
private List<Condition> conditions;
3232

3333
public HitResult hit(FPUser user, Map<String, Segment> segments, String toggleKey) {
34+
if (user == null || toggleKey == null || toggleKey.isEmpty()) {
35+
return new HitResult(false);
36+
}
3437
for (Condition condition : conditions) {
3538
if (condition.getType() != ConditionType.SEGMENT
3639
&& condition.getType() != ConditionType.DATETIME
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package com.featureprobe.sdk.server
2+
3+
import spock.lang.Specification
4+
5+
class FPContextSpec extends Specification {
6+
7+
def fpContextInstance = new FPContext("", new FPConfig(new FPConfig.Builder()))
8+
9+
def 'test getVersion when properties file exists'() {
10+
given:
11+
Properties properties = new Properties()
12+
String expectedVersion = '1.0.0'
13+
properties.setProperty('version', expectedVersion)
14+
InputStream inputStream = new ByteArrayInputStream(propertiesToString(properties).bytes)
15+
FPContext spyFPContextInstance = Spy(fpContextInstance)
16+
spyFPContextInstance.getResourceAsStream(_) >> inputStream
17+
18+
when:
19+
String actualVersion = spyFPContextInstance.getVersion()
20+
21+
then:
22+
actualVersion == expectedVersion
23+
}
24+
25+
def 'test getVersion when properties file not exists but package version exists'() {
26+
given:
27+
Package mockedPackage = Mock(Package)
28+
mockedPackage.getImplementationVersion() >> '1.0.1'
29+
mockedPackage.getSpecificationVersion() >> '1.0.2'
30+
FPContext spyFPContextInstance = Spy(fpContextInstance)
31+
spyFPContextInstance.getResourceAsStream(_) >> null
32+
spyFPContextInstance.getPackage() >> mockedPackage
33+
34+
when:
35+
String actualVersion = spyFPContextInstance.getVersion()
36+
37+
then:
38+
actualVersion == '1.0.1'
39+
}
40+
41+
def 'test getVersion when properties file not exists and only specification version exists'() {
42+
given:
43+
Package mockedPackage = Mock(Package)
44+
mockedPackage.getImplementationVersion() >> null
45+
mockedPackage.getSpecificationVersion() >> '1.0.2'
46+
FPContext spyFPContextInstance = Spy(fpContextInstance)
47+
spyFPContextInstance.getResourceAsStream(_) >> null
48+
spyFPContextInstance.getPackage() >> mockedPackage
49+
50+
when:
51+
String actualVersion = spyFPContextInstance.getVersion()
52+
53+
then:
54+
actualVersion == '1.0.2'
55+
}
56+
57+
def 'test getVersion when properties file not exists and package version not exists'() {
58+
given:
59+
FPContext spyFPContextInstance = Spy(fpContextInstance)
60+
spyFPContextInstance.getResourceAsStream(_) >> null
61+
spyFPContextInstance.getPackage() >> null
62+
63+
when:
64+
String actualVersion = spyFPContextInstance.getVersion()
65+
66+
then:
67+
actualVersion == "unknown"
68+
}
69+
70+
private String propertiesToString(Properties properties) {
71+
StringBuilder sb = new StringBuilder()
72+
properties.each { key, value ->
73+
sb.append("${key}=${value}\n")
74+
}
75+
return sb.toString()
76+
}
77+
}

0 commit comments

Comments
 (0)