Skip to content

Commit 7e3def0

Browse files
author
adriancole
committed
to facilitate higher reuse, remove guava dep
1 parent 316f4b9 commit 7e3def0

35 files changed

Lines changed: 771 additions & 560 deletions

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ static class GsonModule {
4747
final Decoder gsonDecoder = new Decoder() {
4848
Gson gson = new Gson();
4949

50-
@Override public Object decode(String methodKey, Reader reader, TypeToken<?> type) {
51-
return gson.fromJson(reader, type.getType());
50+
@Override public Object decode(String methodKey, Reader reader, Type type) {
51+
return gson.fromJson(reader, type);
5252
}
5353
};
5454
}

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ project(':feign-core') {
3535
}
3636

3737
dependencies {
38-
compile 'com.google.guava:guava:14.0.1'
3938
compile 'com.squareup.dagger:dagger:1.0.1'
4039
compile 'javax.ws.rs:jsr311-api:1.1.1'
4140
provided 'com.squareup.dagger:dagger-compiler:1.0.1'
41+
testCompile 'com.google.guava:guava:14.0.1'
4242
testCompile 'com.google.code.gson:gson:2.2.4'
4343
testCompile 'com.fasterxml.jackson.core:jackson-databind:2.2.2'
4444
testCompile 'org.testng:testng:6.8.1'

feign-core/src/main/java/feign/Client.java

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@
1515
*/
1616
package feign;
1717

18-
import com.google.common.collect.ImmutableListMultimap;
19-
import com.google.common.io.ByteSink;
20-
2118
import java.io.IOException;
2219
import java.io.InputStream;
2320
import java.io.InputStreamReader;
2421
import java.io.OutputStream;
22+
import java.io.OutputStreamWriter;
2523
import java.io.Reader;
24+
import java.io.Writer;
2625
import java.net.HttpURLConnection;
2726
import java.net.URL;
27+
import java.util.Collection;
28+
import java.util.LinkedHashMap;
2829
import java.util.List;
2930
import java.util.Map;
30-
import java.util.Map.Entry;
3131

3232
import javax.inject.Inject;
3333
import javax.net.ssl.HttpsURLConnection;
@@ -36,8 +36,8 @@
3636
import dagger.Lazy;
3737
import feign.Request.Options;
3838

39-
import static com.google.common.base.Charsets.UTF_8;
40-
import static com.google.common.net.HttpHeaders.CONTENT_LENGTH;
39+
import static feign.Util.CONTENT_LENGTH;
40+
import static feign.Util.UTF_8;
4141

4242
/**
4343
* Submits HTTP {@link Request requests}. Implementations are expected to be
@@ -80,37 +80,46 @@ HttpURLConnection convertAndSend(Request request, Options options) throws IOExce
8080
connection.setRequestMethod(request.method());
8181

8282
Integer contentLength = null;
83-
for (Entry<String, String> header : request.headers().entries()) {
84-
if (header.getKey().equals(CONTENT_LENGTH))
85-
contentLength = Integer.valueOf(header.getValue());
86-
connection.addRequestProperty(header.getKey(), header.getValue());
83+
for (String field : request.headers().keySet()) {
84+
for (String value : request.headers().get(field)) {
85+
if (field.equals(CONTENT_LENGTH)) {
86+
contentLength = Integer.valueOf(value);
87+
}
88+
connection.addRequestProperty(field, value);
89+
}
8790
}
8891

89-
if (request.body().isPresent()) {
92+
if (request.body() != null) {
9093
if (contentLength != null) {
9194
connection.setFixedLengthStreamingMode(contentLength);
9295
} else {
9396
connection.setChunkedStreamingMode(8196);
9497
}
9598
connection.setDoOutput(true);
96-
new ByteSink() {
97-
public OutputStream openStream() throws IOException {
98-
return connection.getOutputStream();
99+
OutputStream out = connection.getOutputStream();
100+
try {
101+
out.write(request.body().getBytes(UTF_8));
102+
} finally {
103+
try {
104+
out.close();
105+
} catch (IOException suppressed) { // NOPMD
99106
}
100-
}.asCharSink(UTF_8).write(request.body().get());
107+
}
101108
}
102109
return connection;
103110
}
104111

112+
private static final int BUF_SIZE = 0x800; // 2K chars (4K bytes)
113+
105114
Response convertResponse(HttpURLConnection connection) throws IOException {
106115
int status = connection.getResponseCode();
107116
String reason = connection.getResponseMessage();
108117

109-
ImmutableListMultimap.Builder<String, String> headers = ImmutableListMultimap.builder();
118+
Map<String, Collection<String>> headers = new LinkedHashMap<String, Collection<String>>();
110119
for (Map.Entry<String, List<String>> field : connection.getHeaderFields().entrySet()) {
111120
// response message
112121
if (field.getKey() != null)
113-
headers.putAll(field.getKey(), field.getValue());
122+
headers.put(field.getKey(), field.getValue());
114123
}
115124

116125
Integer length = connection.getContentLength();
@@ -123,7 +132,7 @@ Response convertResponse(HttpURLConnection connection) throws IOException {
123132
stream = connection.getInputStream();
124133
}
125134
Reader body = stream != null ? new InputStreamReader(stream) : null;
126-
return Response.create(status, reason, headers.build(), body, length);
135+
return Response.create(status, reason, headers, body, length);
127136
}
128137
}
129138
}

feign-core/src/main/java/feign/Contract.java

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@
1515
*/
1616
package feign;
1717

18-
import com.google.common.base.Joiner;
19-
import com.google.common.collect.ImmutableList;
20-
import com.google.common.collect.ImmutableSet;
21-
import com.google.common.reflect.TypeToken;
22-
2318
import java.lang.annotation.Annotation;
2419
import java.lang.reflect.Method;
2520
import java.net.URI;
21+
import java.util.ArrayList;
22+
import java.util.Collection;
23+
import java.util.LinkedHashSet;
24+
import java.util.Set;
2625

2726
import javax.ws.rs.Consumes;
2827
import javax.ws.rs.FormParam;
@@ -33,28 +32,29 @@
3332
import javax.ws.rs.Produces;
3433
import javax.ws.rs.QueryParam;
3534

36-
import static com.google.common.base.Preconditions.checkState;
37-
import static com.google.common.net.HttpHeaders.ACCEPT;
38-
import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
35+
import static feign.Util.ACCEPT;
36+
import static feign.Util.CONTENT_TYPE;
37+
import static feign.Util.checkState;
38+
import static feign.Util.join;
3939

4040
/**
4141
* Defines what annotations and values are valid on interfaces.
4242
*/
4343
public final class Contract {
4444

45-
public static ImmutableSet<MethodMetadata> parseAndValidatateMetadata(Class<?> declaring) {
46-
ImmutableSet.Builder<MethodMetadata> builder = ImmutableSet.builder();
45+
public static Set<MethodMetadata> parseAndValidatateMetadata(Class<?> declaring) {
46+
Set<MethodMetadata> metadata = new LinkedHashSet<MethodMetadata>();
4747
for (Method method : declaring.getDeclaredMethods()) {
4848
if (method.getDeclaringClass() == Object.class)
4949
continue;
50-
builder.add(parseAndValidatateMetadata(method));
50+
metadata.add(parseAndValidatateMetadata(method));
5151
}
52-
return builder.build();
52+
return metadata;
5353
}
5454

5555
public static MethodMetadata parseAndValidatateMetadata(Method method) {
5656
MethodMetadata data = new MethodMetadata();
57-
data.returnType(TypeToken.of(method.getGenericReturnType()));
57+
data.returnType(method.getGenericReturnType());
5858
data.configKey(Feign.configKey(method));
5959

6060
for (Annotation methodAnnotation : method.getAnnotations()) {
@@ -75,9 +75,9 @@ public static MethodMetadata parseAndValidatateMetadata(Method method) {
7575
} else if (annotationType == Path.class) {
7676
data.template().append(Path.class.cast(methodAnnotation).value());
7777
} else if (annotationType == Produces.class) {
78-
data.template().header(CONTENT_TYPE, Joiner.on(',').join(((Produces) methodAnnotation).value()));
78+
data.template().header(CONTENT_TYPE, join(',', ((Produces) methodAnnotation).value()));
7979
} else if (annotationType == Consumes.class) {
80-
data.template().header(ACCEPT, Joiner.on(',').join(((Consumes) methodAnnotation).value()));
80+
data.template().header(ACCEPT, join(',', ((Consumes) methodAnnotation).value()));
8181
}
8282
}
8383
checkState(data.template().method() != null, "Method %s not annotated with HTTP method type (ex. GET, POST)",
@@ -95,28 +95,24 @@ public static MethodMetadata parseAndValidatateMetadata(Method method) {
9595
for (Annotation parameterAnnotation : parameterAnnotations) {
9696
Class<? extends Annotation> annotationType = parameterAnnotation.annotationType();
9797
if (annotationType == PathParam.class) {
98-
data.indexToName().put(i, PathParam.class.cast(parameterAnnotation).value());
98+
indexName(data, i, PathParam.class.cast(parameterAnnotation).value());
9999
hasHttpAnnotation = true;
100100
} else if (annotationType == QueryParam.class) {
101101
String name = QueryParam.class.cast(parameterAnnotation).value();
102-
data.template().query(
103-
name,
104-
ImmutableList.<String>builder().addAll(data.template().queries().get(name))
105-
.add(String.format("{%s}", name)).build());
106-
data.indexToName().put(i, name);
102+
Collection<String> query = addTemplatedParam(data.template().queries().get(name), name);
103+
data.template().query(name, query);
104+
indexName(data, i, name);
107105
hasHttpAnnotation = true;
108106
} else if (annotationType == HeaderParam.class) {
109107
String name = HeaderParam.class.cast(parameterAnnotation).value();
110-
data.template().header(
111-
name,
112-
ImmutableList.<String>builder().addAll(data.template().headers().get(name))
113-
.add(String.format("{%s}", name)).build());
114-
data.indexToName().put(i, name);
108+
Collection<String> header = addTemplatedParam(data.template().headers().get(name), name);
109+
data.template().header(name, header);
110+
indexName(data, i, name);
115111
hasHttpAnnotation = true;
116112
} else if (annotationType == FormParam.class) {
117113
String form = FormParam.class.cast(parameterAnnotation).value();
118114
data.formParams().add(form);
119-
data.indexToName().put(i, form);
115+
indexName(data, i, form);
120116
hasHttpAnnotation = true;
121117
}
122118
}
@@ -132,4 +128,17 @@ public static MethodMetadata parseAndValidatateMetadata(Method method) {
132128
}
133129
return data;
134130
}
131+
132+
private static Collection<String> addTemplatedParam(Collection<String> possiblyNull, String name) {
133+
if (possiblyNull == null)
134+
possiblyNull = new ArrayList<String>();
135+
possiblyNull.add(String.format("{%s}", name));
136+
return possiblyNull;
137+
}
138+
139+
private static void indexName(MethodMetadata data, int i, String name) {
140+
Collection<String> names = data.indexToName().containsKey(i) ? data.indexToName().get(i) : new ArrayList<String>();
141+
names.add(name);
142+
data.indexToName().put(i, names);
143+
}
135144
}

feign-core/src/main/java/feign/Feign.java

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,10 @@
1515
*/
1616
package feign;
1717

18-
import com.google.common.base.Optional;
19-
import com.google.common.collect.ImmutableList;
20-
import com.google.common.collect.ImmutableMap;
21-
2218
import java.lang.reflect.Method;
19+
import java.util.ArrayList;
20+
import java.util.Collections;
21+
import java.util.List;
2322
import java.util.Map;
2423

2524
import javax.net.ssl.SSLSocketFactory;
@@ -67,23 +66,16 @@ public static <T> T create(Target<T> target, Object... modules) {
6766
* {@link Target targeted} http apis.
6867
*/
6968
public static Feign create(Object... modules) {
70-
Object[] modulesForGraph = ImmutableList.builder() //
71-
.add(new Defaults()) //
72-
.add(new ReflectiveFeign.Module()) //
73-
.add(Optional.fromNullable(modules).or(new Object[]{})).build().toArray();
74-
return ObjectGraph.create(modulesForGraph).get(Feign.class);
69+
return ObjectGraph.create(modulesForGraph(modules).toArray()).get(Feign.class);
7570
}
7671

72+
7773
/**
7874
* Returns an {@link ObjectGraph Dagger ObjectGraph} that can inject a
7975
* {@link ReflectiveFeign reflective} Feign.
8076
*/
8177
public static ObjectGraph createObjectGraph(Object... modules) {
82-
Object[] modulesForGraph = ImmutableList.builder() //
83-
.add(new Defaults()) //
84-
.add(new ReflectiveFeign.Module()) //
85-
.add(Optional.fromNullable(modules).or(new Object[]{})).build().toArray();
86-
return ObjectGraph.create(modulesForGraph);
78+
return ObjectGraph.create(modulesForGraph(modules).toArray());
8779
}
8880

8981
@dagger.Module(complete = false, injects = Feign.class, library = true)
@@ -106,23 +98,23 @@ public static class Defaults {
10698
}
10799

108100
@Provides Map<String, Options> noOptions() {
109-
return ImmutableMap.of();
101+
return Collections.emptyMap();
110102
}
111103

112104
@Provides Map<String, BodyEncoder> noBodyEncoders() {
113-
return ImmutableMap.of();
105+
return Collections.emptyMap();
114106
}
115107

116108
@Provides Map<String, FormEncoder> noFormEncoders() {
117-
return ImmutableMap.of();
109+
return Collections.emptyMap();
118110
}
119111

120112
@Provides Map<String, Decoder> noDecoders() {
121-
return ImmutableMap.of();
113+
return Collections.emptyMap();
122114
}
123115

124116
@Provides Map<String, ErrorDecoder> noErrorDecoders() {
125-
return ImmutableMap.of();
117+
return Collections.emptyMap();
126118
}
127119
}
128120

@@ -157,6 +149,16 @@ public static String configKey(Method method) {
157149
return builder.append(')').toString();
158150
}
159151

152+
private static List<Object> modulesForGraph(Object... modules) {
153+
List<Object> modulesForGraph = new ArrayList<Object>(3);
154+
modulesForGraph.add(new Defaults());
155+
modulesForGraph.add(new ReflectiveFeign.Module());
156+
if (modules != null)
157+
for (Object module : modules)
158+
modulesForGraph.add(module);
159+
return modulesForGraph;
160+
}
161+
160162
Feign() {
161163

162164
}

feign-core/src/main/java/feign/FeignException.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,26 @@
1515
*/
1616
package feign;
1717

18-
import com.google.common.reflect.TypeToken;
19-
2018
import java.io.IOException;
2119

22-
import feign.codec.Decoder;
2320
import feign.codec.ToStringDecoder;
2421

2522
import static java.lang.String.format;
2623

2724
/**
28-
* Origin exception type for all HttpApis.
25+
* Origin exception type for all Http Apis.
2926
*/
3027
public class FeignException extends RuntimeException {
3128
static FeignException errorReading(Request request, Response response, IOException cause) {
3229
return new FeignException(format("%s %s %s", cause.getMessage(), request.method(), request.url(), 0), cause);
3330
}
3431

35-
private static final Decoder toString = new ToStringDecoder();
36-
private static final TypeToken<String> stringToken = TypeToken.of(String.class);
32+
private static final ToStringDecoder toString = new ToStringDecoder();
3733

3834
public static FeignException errorStatus(String methodKey, Response response) {
3935
String message = format("status %s reading %s", response.status(), methodKey);
4036
try {
41-
Object body = toString.decode(methodKey, response, stringToken);
37+
Object body = toString.decode(methodKey, response, String.class);
4238
if (body != null) {
4339
response = Response.create(response.status(), response.reason(), response.headers(), body.toString());
4440
message += "; content:\n" + body;

0 commit comments

Comments
 (0)