Compare commits

...

28 Commits
master ... 6.x

Author SHA1 Message Date
Rob Spieldenner a4f9c71fe5 Merge pull request #129 from rspieldenner/6xbuildupdate 10 years ago
Rob Spieldenner 3c5f63ad4c Fix references for IDEs to take lists 10 years ago
Rob Spieldenner 4872d34eec Build upgrades 10 years ago
Rob Spieldenner dd7be2e5ce Upgrade gradle to 2.2.1 10 years ago
Adrian Cole 07ed946121 version=6.2.0-SNAPSHOT 10 years ago
Bob T Builder 6f13cd3ba9 [Gradle Release Plugin] - new version commit: '6.1.4'. 10 years ago
Allen Wang ca94c83ea2 Merge pull request #119 from allenxwang/6.x-ribbon 10 years ago
Allen Wang 4064d5120c change dependency to feign projects instead of artifacts. 10 years ago
Allen Wang 4999d695cd remove the feign-slf4j sub project from the previous cherry pick 10 years ago
Allen Wang 544971194a cherry picking from master for ribbon 2 changes 10 years ago
Amit Joshi 37917020ff cherry pick from master for ribbon 2 compatibility issue 10 years ago
Bob T Builder c55602eeaa [Gradle Release Plugin] - new version commit: '6.1.3'. 11 years ago
allenxwang 40800f1baa Merge pull request #104 from allenxwang/6.x 11 years ago
Allen Wang b2405a1c0a Pump up versions of feign libraries used by examples. 11 years ago
Adrian Cole 314229871f Merge pull request #103 from wnagele/6.x 11 years ago
Wolfgang Nagele 0032df538a Fix for bug #85 11 years ago
Bob T Builder 66c3ad9735 [Gradle Release Plugin] - new version commit: '6.1.2'. 11 years ago
Adrian Cole 2e00aadef3 Merge pull request #102 from allenxwang/6.x 11 years ago
Allen Wang 7a992424cc Bump version to 6.1.1 and change example dependency to 6.x releases. 11 years ago
Rodrigo Saito 7cb9807be0 When User and/or Password are too long, then the Authorization Header is broken because of sun Base64Encoder impl. 11 years ago
Bob T Builder 24ac724685 [Gradle Release Plugin] - new version commit: '6.0.2-SNAPSHOT'. 11 years ago
Bob T Builder 6dd00b2620 [Gradle Release Plugin] - pre tag commit: '6.0.1'. 11 years ago
Adrian Cole 022d3a24ba Merge pull request #88 from michael-oliver-pearson/feature/disable-exceptions 11 years ago
Adrian Cole 2ef9e006c9 Merge pull request #90 from allenxwang/6.x 11 years ago
Allen Wang 6528295eff Update to Ribbon 0.3.1 11 years ago
michael cc07679afe Return basic response object in all cases 11 years ago
Bob T Builder 58b65e7c50 [Gradle Release Plugin] - new version commit: '6.0.1-SNAPSHOT'. 11 years ago
Bob T Builder 6bf9abf8a9 [Gradle Release Plugin] - pre tag commit: '6.0.0'. 11 years ago
  1. 6
      CHANGELOG.md
  2. 124
      build.gradle
  3. 13
      codequality/HEADER
  4. 15
      core/build.gradle
  5. 21
      core/src/main/java/feign/Contract.java
  6. 17
      core/src/main/java/feign/MethodHandler.java
  7. 160
      core/src/main/java/feign/auth/Base64.java
  8. 4
      core/src/main/java/feign/auth/BasicAuthRequestInterceptor.java
  9. 12
      core/src/test/java/feign/FeignTest.java
  10. 14
      core/src/test/java/feign/auth/BasicAuthRequestInterceptorTest.java
  11. 4
      dagger.gradle
  12. 10
      example-github/build.gradle
  13. 10
      example-wikipedia/build.gradle
  14. 1
      gradle.properties
  15. 11
      gradle/buildscript.gradle
  16. 26
      gradle/check.gradle
  17. 101
      gradle/convention.gradle
  18. 10
      gradle/license.gradle
  19. 70
      gradle/maven.gradle
  20. 1
      gradle/netflix-oss.gradle
  21. 61
      gradle/release.gradle
  22. BIN
      gradle/wrapper/gradle-wrapper.jar
  23. 4
      gradle/wrapper/gradle-wrapper.properties
  24. 13
      gson/build.gradle
  25. 14
      jackson/build.gradle
  26. 15
      jaxrs/build.gradle
  27. 14
      ribbon/build.gradle
  28. 76
      ribbon/src/main/java/feign/ribbon/LBClient.java
  29. 13
      sax/build.gradle

6
CHANGES.md → CHANGELOG.md

@ -1,3 +1,9 @@ @@ -1,3 +1,9 @@
### Version 6.1.2
* Named query parameters on GET request result in POST request (bug #85)
### Version 6.0.2
* Fix for BasicAuthRequestInterceptor when username and/or password are long.
### Version 6.0
* Support binary request and response bodies.

124
build.gradle

@ -1,120 +1,20 @@ @@ -1,120 +1,20 @@
// Establish version and status
ext.githubProjectName = rootProject.name // Change if github project name is not the same as the root project's name
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
apply from: file('gradle/buildscript.gradle'), to: buildscript
plugins {
id 'nebula.netflixoss' version '2.2.2'
}
allprojects {
repositories {
mavenLocal()
mavenCentral()
maven { url 'https://oss.sonatype.org/content/repositories/releases/' }
}
ext {
githubProjectName = rootProject.name // Change if github project name is not the same as the root project's name
}
apply from: file('gradle/convention.gradle')
apply from: file('gradle/maven.gradle')
apply from: file('gradle/check.gradle')
apply from: file('gradle/license.gradle')
apply from: file('gradle/release.gradle')
apply plugin: 'idea'
subprojects {
apply from: rootProject.file('dagger.gradle')
group = "com.netflix.${githubProjectName}" // TEMPLATE: Set to organization of project
}
project(':feign-core') {
apply plugin: 'java'
test {
useTestNG()
}
dependencies {
testCompile 'com.google.guava:guava:14.0.1'
testCompile 'com.google.code.gson:gson:2.2.4'
testCompile 'com.fasterxml.jackson.core:jackson-databind:2.2.2'
testCompile 'org.testng:testng:6.8.5'
testCompile 'com.google.mockwebserver:mockwebserver:20130706'
}
}
project(':feign-sax') {
apply plugin: 'java'
test {
useTestNG()
}
dependencies {
compile project(':feign-core')
testCompile 'com.google.guava:guava:14.0.1'
testCompile 'org.testng:testng:6.8.5'
}
}
project(':feign-gson') {
apply plugin: 'java'
test {
useTestNG()
}
dependencies {
compile project(':feign-core')
compile 'com.google.code.gson:gson:2.2.4'
testCompile 'org.testng:testng:6.8.5'
}
}
project(':feign-jackson') {
apply plugin: 'java'
test {
useTestNG()
}
dependencies {
compile project(':feign-core')
compile 'com.fasterxml.jackson.core:jackson-databind:2.2.2'
testCompile 'org.testng:testng:6.8.5'
testCompile 'com.google.guava:guava:14.0.1'
}
}
project(':feign-jaxrs') {
apply plugin: 'java'
apply plugin: 'nebula.netflixoss'
test {
useTestNG()
}
dependencies {
compile project(':feign-core')
compile 'javax.ws.rs:jsr311-api:1.1.1'
testCompile project(':feign-gson')
testCompile 'com.google.guava:guava:14.0.1'
testCompile 'org.testng:testng:6.8.5'
}
}
project(':feign-ribbon') {
apply plugin: 'java'
test {
useTestNG()
}
dependencies {
compile project(':feign-core')
compile 'com.netflix.ribbon:ribbon-core:0.2.3'
testCompile 'org.testng:testng:6.8.5'
testCompile 'com.google.mockwebserver:mockwebserver:20130706'
repositories {
jcenter()
//mavenLocal()
//mavenCentral()
//maven { url 'https://oss.sonatype.org/content/repositories/releases/' }
}
apply from: rootProject.file('dagger.gradle')
group = "com.netflix.${githubProjectName}" // TEMPLATE: Set to organization of project
}

13
codequality/HEADER

@ -1,13 +0,0 @@ @@ -1,13 +0,0 @@
Copyright ${year} Netflix, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

15
core/build.gradle

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
apply plugin: 'java'
sourceCompatibility = 1.6
test {
useTestNG()
}
dependencies {
testCompile 'com.google.guava:guava:14.0.1'
testCompile 'com.google.code.gson:gson:2.2.4'
testCompile 'com.fasterxml.jackson.core:jackson-databind:2.2.2'
testCompile 'org.testng:testng:6.8.5'
testCompile 'com.google.mockwebserver:mockwebserver:20130706'
}

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

@ -22,6 +22,7 @@ import java.net.URI; @@ -22,6 +22,7 @@ import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static feign.Util.checkState;
import static feign.Util.emptyToNull;
@ -165,14 +166,28 @@ public interface Contract { @@ -165,14 +166,28 @@ public interface Contract {
checkState(emptyToNull(name) != null, "Named annotation was empty on param %s.", paramIndex);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
if (data.template().url().indexOf('{' + name + '}') == -1 && //
!(data.template().queries().containsKey(name)
|| data.template().headers().containsKey(name))) {
String varName = '{' + name + '}';
if (data.template().url().indexOf(varName) == -1 &&
!searchMapValues(data.template().queries(), varName) &&
!searchMapValues(data.template().headers(), varName)) {
data.formParams().add(name);
}
}
}
return isHttpAnnotation;
}
private <K, V> boolean searchMapValues(Map<K, Collection<V>> map, V search) {
Collection<Collection<V>> values = map.values();
if (values == null)
return false;
for (Collection<V> entry : values) {
if (entry.contains(search))
return true;
}
return false;
}
}
}

17
core/src/main/java/feign/MethodHandler.java

@ -136,15 +136,16 @@ interface MethodHandler { @@ -136,15 +136,16 @@ interface MethodHandler {
if (logLevel.get() != Logger.Level.NONE) {
response = logger.logAndRebufferResponse(metadata.configKey(), logLevel.get(), response, elapsedTime);
}
if (Response.class == metadata.returnType()) {
if (response.body() == null) {
return response;
}
// Ensure the response body is disconnected
byte[] bodyData = Util.toByteArray(response.body().asInputStream());
return Response.create(response.status(), response.reason(), response.headers(), bodyData);
}
if (response.status() >= 200 && response.status() < 300) {
if (Response.class == metadata.returnType()) {
if (response.body() == null) {
return response;
}
// Ensure the response body is disconnected
byte[] bodyData = Util.toByteArray(response.body().asInputStream());
return Response.create(response.status(), response.reason(), response.headers(), bodyData);
} else if (void.class == metadata.returnType()) {
if (void.class == metadata.returnType()) {
return null;
} else {
return decode(response);

160
core/src/main/java/feign/auth/Base64.java

@ -0,0 +1,160 @@ @@ -0,0 +1,160 @@
/*
* Copyright 2013 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package feign.auth;
import java.io.UnsupportedEncodingException;
/**
* copied from <a href="https://github.com/square/okhttp/blob/master/okhttp-protocols/src/main/java/com/squareup/okhttp/internal/Base64.java">okhttp</a>
* @author Alexander Y. Kleymenov
*/
final class Base64 {
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
private Base64() {
}
public static byte[] decode(byte[] in) {
return decode(in, in.length);
}
public static byte[] decode(byte[] in, int len) {
// approximate output length
int length = len / 4 * 3;
// return an empty array on empty or short input without padding
if (length == 0) {
return EMPTY_BYTE_ARRAY;
}
// temporary array
byte[] out = new byte[length];
// number of padding characters ('=')
int pad = 0;
byte chr;
// compute the number of the padding characters
// and adjust the length of the input
for (; ; len--) {
chr = in[len - 1];
// skip the neutral characters
if ((chr == '\n') || (chr == '\r') || (chr == ' ') || (chr == '\t')) {
continue;
}
if (chr == '=') {
pad++;
} else {
break;
}
}
// index in the output array
int outIndex = 0;
// index in the input array
int inIndex = 0;
// holds the value of the input character
int bits = 0;
// holds the value of the input quantum
int quantum = 0;
for (int i = 0; i < len; i++) {
chr = in[i];
// skip the neutral characters
if ((chr == '\n') || (chr == '\r') || (chr == ' ') || (chr == '\t')) {
continue;
}
if ((chr >= 'A') && (chr <= 'Z')) {
// char ASCII value
// A 65 0
// Z 90 25 (ASCII - 65)
bits = chr - 65;
} else if ((chr >= 'a') && (chr <= 'z')) {
// char ASCII value
// a 97 26
// z 122 51 (ASCII - 71)
bits = chr - 71;
} else if ((chr >= '0') && (chr <= '9')) {
// char ASCII value
// 0 48 52
// 9 57 61 (ASCII + 4)
bits = chr + 4;
} else if (chr == '+') {
bits = 62;
} else if (chr == '/') {
bits = 63;
} else {
return null;
}
// append the value to the quantum
quantum = (quantum << 6) | (byte) bits;
if (inIndex % 4 == 3) {
// 4 characters were read, so make the output:
out[outIndex++] = (byte) (quantum >> 16);
out[outIndex++] = (byte) (quantum >> 8);
out[outIndex++] = (byte) quantum;
}
inIndex++;
}
if (pad > 0) {
// adjust the quantum value according to the padding
quantum = quantum << (6 * pad);
// make output
out[outIndex++] = (byte) (quantum >> 16);
if (pad == 1) {
out[outIndex++] = (byte) (quantum >> 8);
}
}
// create the resulting array
byte[] result = new byte[outIndex];
System.arraycopy(out, 0, result, 0, outIndex);
return result;
}
private static final byte[] MAP = new byte[] {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4',
'5', '6', '7', '8', '9', '+', '/'
};
public static String encode(byte[] in) {
int length = (in.length + 2) * 4 / 3;
byte[] out = new byte[length];
int index = 0, end = in.length - in.length % 3;
for (int i = 0; i < end; i += 3) {
out[index++] = MAP[(in[i] & 0xff) >> 2];
out[index++] = MAP[((in[i] & 0x03) << 4) | ((in[i + 1] & 0xff) >> 4)];
out[index++] = MAP[((in[i + 1] & 0x0f) << 2) | ((in[i + 2] & 0xff) >> 6)];
out[index++] = MAP[(in[i + 2] & 0x3f)];
}
switch (in.length % 3) {
case 1:
out[index++] = MAP[(in[end] & 0xff) >> 2];
out[index++] = MAP[(in[end] & 0x03) << 4];
out[index++] = '=';
out[index++] = '=';
break;
case 2:
out[index++] = MAP[(in[end] & 0xff) >> 2];
out[index++] = MAP[((in[end] & 0x03) << 4) | ((in[end + 1] & 0xff) >> 4)];
out[index++] = MAP[((in[end + 1] & 0x0f) << 2)];
out[index++] = '=';
break;
}
try {
return new String(out, 0, index, "US-ASCII");
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
}
}

4
core/src/main/java/feign/auth/BasicAuthRequestInterceptor.java

@ -17,7 +17,6 @@ package feign.auth; @@ -17,7 +17,6 @@ package feign.auth;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import sun.misc.BASE64Encoder;
import java.nio.charset.Charset;
@ -64,6 +63,7 @@ public class BasicAuthRequestInterceptor implements RequestInterceptor { @@ -64,6 +63,7 @@ public class BasicAuthRequestInterceptor implements RequestInterceptor {
* response would be to pull the necessary portions of Guava's BaseEncoding class into Util.
*/
private static String base64Encode(byte[] bytes) {
return new BASE64Encoder().encode(bytes);
return Base64.encode(bytes);
}
}

12
core/src/test/java/feign/FeignTest.java

@ -536,4 +536,16 @@ public class FeignTest { @@ -536,4 +536,16 @@ public class FeignTest {
server.shutdown();
}
}
@Test
public void responseTypeGetsReturnedDirectlyEvenWithErrorResponseCode() throws Exception {
final MockWebServer server = new MockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
server.play();
TestInterface testInterface = Feign.builder().options(new Request.Options(1000, 1000))
.target(TestInterface.class, "http://localhost:" + server.getPort());
Response response = testInterface.response();
assertEquals(response.status(), 404);
}
}

14
core/src/test/java/feign/auth/BasicAuthRequestInterceptorTest.java

@ -38,4 +38,18 @@ public class BasicAuthRequestInterceptorTest { @@ -38,4 +38,18 @@ public class BasicAuthRequestInterceptorTest {
Collection<String> expectedValue = Collections.singletonList("Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
assertEquals(actualValue, expectedValue);
}
/**
* Tests that requests headers are added as expected when user and pass are too long
*/
@Test public void testAuthenticationWhenUserPassAreTooLong() {
RequestTemplate template = new RequestTemplate();
BasicAuthRequestInterceptor interceptor = new BasicAuthRequestInterceptor("IOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIO",
"101010101010101010101010101010101010101010");
interceptor.apply(template);
Collection<String> actualValue = template.headers().get("Authorization");
Collection<String> expectedValue = Collections.
singletonList("Basic SU9JT0lPSU9JT0lPSU9JT0lPSU9JT0lPSU9JT0lPSU9JT0lPSU86MTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEw");
assertEquals(actualValue, expectedValue);
}
}

4
dagger.gradle

@ -92,7 +92,7 @@ rootProject.idea.project.ipr.withXml { projectXml -> @@ -92,7 +92,7 @@ rootProject.idea.project.ipr.withXml { projectXml ->
tasks.ideaModule.dependsOn(prepareAnnotationGeneratedSourceDirs)
idea.module {
scopes.PROVIDED.plus += project.configurations.daggerCompiler
scopes.PROVIDED.plus += [project.configurations.daggerCompiler]
iml.withXml { xml->
def moduleSource = xml.asNode().component.find { it.@name = 'NewModuleRootManager' }.content[0]
moduleSource.appendNode('sourceFolder', [url: "file://\$MODULE_DIR\$/${relativePath(annotationGeneratedSources)}", isTestSource: false])
@ -103,7 +103,7 @@ idea.module { @@ -103,7 +103,7 @@ idea.module {
tasks.eclipseClasspath.dependsOn(prepareAnnotationGeneratedSourceDirs)
eclipse.classpath {
plusConfigurations += project.configurations.daggerCompiler
plusConfigurations += [project.configurations.daggerCompiler]
}
tasks.eclipseClasspath {

10
example-github/build.gradle

@ -1,8 +1,14 @@ @@ -1,8 +1,14 @@
plugins {
id 'nebula.provided-base' version '2.0.1'
}
apply plugin: 'java'
sourceCompatibility = 1.6
dependencies {
compile 'com.netflix.feign:feign-core:5.0.0'
compile 'com.netflix.feign:feign-gson:5.0.0'
compile project(':feign-core')
compile project(':feign-gson')
provided 'com.squareup.dagger:dagger-compiler:1.1.0'
}

10
example-wikipedia/build.gradle

@ -1,8 +1,14 @@ @@ -1,8 +1,14 @@
plugins {
id 'nebula.provided-base' version '2.0.1'
}
apply plugin: 'java'
sourceCompatibility = 1.6
dependencies {
compile 'com.netflix.feign:feign-core:5.0.0'
compile 'com.netflix.feign:feign-gson:5.0.0'
compile project(':feign-core')
compile project(':feign-gson')
provided 'com.squareup.dagger:dagger-compiler:1.1.0'
}

1
gradle.properties

@ -1 +0,0 @@ @@ -1 +0,0 @@
version=6.0.0-SNAPSHOT

11
gradle/buildscript.gradle

@ -1,11 +0,0 @@ @@ -1,11 +0,0 @@
// Executed in context of buildscript
repositories {
// Repo in addition to maven central
repositories { maven { url 'http://dl.bintray.com/content/netflixoss/external-gradle-plugins/' } } // For gradle-release
}
dependencies {
classpath 'nl.javadude.gradle.plugins:license-gradle-plugin:0.6.1'
classpath 'com.mapvine:gradle-cobertura-plugin:0.1'
classpath 'gradle-release:gradle-release:1.1.5'
classpath 'org.ajoberstar:gradle-git:0.5.0'
}

26
gradle/check.gradle

@ -1,26 +0,0 @@ @@ -1,26 +0,0 @@
subprojects {
// Checkstyle
apply plugin: 'checkstyle'
checkstyle {
ignoreFailures = true
configFile = rootProject.file('codequality/checkstyle.xml')
}
// FindBugs
apply plugin: 'findbugs'
findbugs {
ignoreFailures = true
}
// PMD
apply plugin: 'pmd'
//tasks.withType(Pmd) { reports.html.enabled true }
apply plugin: 'cobertura'
cobertura {
sourceDirs = sourceSets.main.java.srcDirs
format = 'html'
includes = ['**/*.java', '**/*.groovy']
excludes = []
}
}

101
gradle/convention.gradle

@ -1,101 +0,0 @@ @@ -1,101 +0,0 @@
// GRADLE-2087 workaround, perform after java plugin
status = project.hasProperty('preferredStatus')?project.preferredStatus:(version.contains('SNAPSHOT')?'snapshot':'release')
subprojects { project ->
apply plugin: 'java' // Plugin as major conventions
sourceCompatibility = 1.6
// Restore status after Java plugin
status = rootProject.status
task sourcesJar(type: Jar, dependsOn:classes) {
from sourceSets.main.allSource
classifier 'sources'
extension 'jar'
}
task javadocJar(type: Jar, dependsOn:javadoc) {
from javadoc.destinationDir
classifier 'javadoc'
extension 'jar'
}
configurations.add('sources')
configurations.add('javadoc')
configurations.archives {
extendsFrom configurations.sources
extendsFrom configurations.javadoc
}
// When outputing to an Ivy repo, we want to use the proper type field
gradle.taskGraph.whenReady {
def isNotMaven = !it.hasTask(project.uploadMavenCentral)
if (isNotMaven) {
def artifacts = project.configurations.sources.artifacts
def sourceArtifact = artifacts.iterator().next()
sourceArtifact.type = 'sources'
}
}
artifacts {
sources(sourcesJar) {
// Weird Gradle quirk where type will be used for the extension, but only for sources
type 'jar'
}
javadoc(javadocJar) {
type 'javadoc'
}
}
configurations {
provided {
description = 'much like compile, but indicates you expect the JDK or a container to provide it. It is only available on the compilation classpath, and is not transitive.'
transitive = true
visible = true
}
}
project.sourceSets {
main.compileClasspath += project.configurations.provided
main.runtimeClasspath -= project.configurations.provided
test.compileClasspath += project.configurations.provided
test.runtimeClasspath += project.configurations.provided
}
}
apply plugin: 'github-pages' // Used to create publishGhPages task
def docTasks = [:]
[Javadoc,ScalaDoc,Groovydoc].each{ Class docClass ->
def allSources = allprojects.tasks*.withType(docClass).flatten()*.source
if (allSources) {
def shortName = docClass.simpleName.toLowerCase()
def docTask = task "aggregate${shortName.capitalize()}"(type: docClass, description: "Aggregate subproject ${shortName}s") {
source = allSources
destinationDir = file("${project.buildDir}/docs/${shortName}")
doFirst {
def classpaths = allprojects.findAll { it.plugins.hasPlugin(JavaPlugin) }.collect { it.sourceSets.main.compileClasspath }
classpath = files(classpaths)
}
}
docTasks[shortName] = docTask
processGhPages.dependsOn(docTask)
}
}
githubPages {
repoUri = "git@github.com:Netflix/${rootProject.githubProjectName}.git"
pages {
docTasks.each { shortName, docTask ->
from(docTask.outputs.files) {
into "docs/${shortName}"
}
}
}
}
// Generate wrapper, which is distributed as part of source to alleviate the need of installing gradle
task createWrapper(type: Wrapper) {
gradleVersion = '1.5'
}

10
gradle/license.gradle

@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
// Dependency for plugin was set in buildscript.gradle
subprojects {
apply plugin: 'license' //nl.javadude.gradle.plugins.license.LicensePlugin
license {
header rootProject.file('codequality/HEADER')
ext.year = Calendar.getInstance().get(Calendar.YEAR)
skipExistingHeaders true
}
}

70
gradle/maven.gradle

@ -1,70 +0,0 @@ @@ -1,70 +0,0 @@
// Maven side of things
subprojects {
apply plugin: 'maven' // Java plugin has to have been already applied for the conf2scope mappings to work
apply plugin: 'signing'
signing {
required { gradle.taskGraph.hasTask(uploadMavenCentral) }
sign configurations.archives
}
/**
* Publishing to Maven Central example provided from http://jedicoder.blogspot.com/2011/11/automated-gradle-project-deployment-to.html
* artifactory will execute uploadArchives to force generation of ivy.xml, and we don't want that to trigger an upload to maven
* central, so using custom upload task.
*/
task uploadMavenCentral(type:Upload, dependsOn: signArchives) {
configuration = configurations.archives
onlyIf { ['release', 'snapshot'].contains(project.status) }
repositories.mavenDeployer {
beforeDeployment { signing.signPom(it) }
// To test deployment locally, use the following instead of oss.sonatype.org
//repository(url: "file://localhost/${rootProject.rootDir}/repo")
def sonatypeUsername = rootProject.hasProperty('sonatypeUsername')?rootProject.sonatypeUsername:''
def sonatypePassword = rootProject.hasProperty('sonatypePassword')?rootProject.sonatypePassword:''
repository(url: 'https://oss.sonatype.org/service/local/staging/deploy/maven2') {
authentication(userName: sonatypeUsername, password: sonatypePassword)
}
snapshotRepository(url: 'https://oss.sonatype.org/content/repositories/snapshots/') {
authentication(userName: sonatypeUsername, password: sonatypePassword)
}
// Prevent datastamp from being appending to artifacts during deployment
uniqueVersion = false
// Closure to configure all the POM with extra info, common to all projects
pom.project {
name "${project.name}"
description "${project.name} developed by Netflix"
developers {
developer {
id 'netflixgithub'
name 'Netflix Open Source Development'
email 'talent@netflix.com'
}
}
licenses {
license {
name 'The Apache Software License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
distribution 'repo'
}
}
url "https://github.com/Netflix/${rootProject.githubProjectName}"
scm {
connection "scm:git:git@github.com:Netflix/${rootProject.githubProjectName}.git"
url "scm:git:git@github.com:Netflix/${rootProject.githubProjectName}.git"
developerConnection "scm:git:git@github.com:Netflix/${rootProject.githubProjectName}.git"
}
issueManagement {
system 'github'
url "https://github.com/Netflix/${rootProject.githubProjectName}/issues"
}
}
}
}
}

1
gradle/netflix-oss.gradle

@ -1 +0,0 @@ @@ -1 +0,0 @@
apply from: 'http://artifacts.netflix.com/gradle-netflix-local/artifactory.gradle'

61
gradle/release.gradle

@ -1,61 +0,0 @@ @@ -1,61 +0,0 @@
apply plugin: 'release'
[ uploadIvyLocal: 'uploadLocal', uploadArtifactory: 'artifactoryPublish', buildWithArtifactory: 'build' ].each { key, value ->
// Call out to compile against internal repository
task "${key}"(type: GradleBuild) {
startParameter = project.gradle.startParameter.newInstance()
doFirst {
startParameter.projectProperties = [status: project.status, preferredStatus: project.status]
}
startParameter.addInitScript( file('gradle/netflix-oss.gradle') )
startParameter.getExcludedTaskNames().add('check')
tasks = [ 'build', value ]
}
}
// Marker task for following code to key in on
task releaseCandidate(dependsOn: release)
task forceCandidate {
onlyIf { gradle.taskGraph.hasTask(releaseCandidate) }
doFirst { project.status = 'candidate' }
}
task forceRelease {
onlyIf { !gradle.taskGraph.hasTask(releaseCandidate) }
doFirst { project.status = 'release' }
}
release.dependsOn([forceCandidate, forceRelease])
task uploadMavenCentral(dependsOn: subprojects.tasks.uploadMavenCentral)
task releaseSnapshot(dependsOn: [uploadArtifactory, uploadMavenCentral])
// Ensure our versions look like the project status before publishing
task verifyStatus << {
def hasSnapshot = version.contains('-SNAPSHOT')
if (project.status == 'snapshot' && !hasSnapshot) {
throw new GradleException("Version (${version}) needs -SNAPSHOT if publishing snapshot")
}
}
uploadArtifactory.dependsOn(verifyStatus)
uploadMavenCentral.dependsOn(verifyStatus)
// Ensure upload happens before taggging, hence upload failures will leave repo in a revertable state
preTagCommit.dependsOn([uploadArtifactory, uploadMavenCentral])
gradle.taskGraph.whenReady { taskGraph ->
def hasRelease = taskGraph.hasTask('commitNewVersion')
def indexOf = { return taskGraph.allTasks.indexOf(it) }
if (hasRelease) {
assert indexOf(build) < indexOf(unSnapshotVersion), 'build target has to be after unSnapshotVersion'
assert indexOf(uploadMavenCentral) < indexOf(preTagCommit), 'preTagCommit has to be after uploadMavenCentral'
assert indexOf(uploadArtifactory) < indexOf(preTagCommit), 'preTagCommit has to be after uploadArtifactory'
}
}
// Prevent plugin from asking for a version number interactively
ext.'gradle.release.useAutomaticVersion' = "true"
release {
git.requireBranch = null
}

BIN
gradle/wrapper/gradle-wrapper.jar vendored

Binary file not shown.

4
gradle/wrapper/gradle-wrapper.properties vendored

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
#Tue Apr 02 11:45:56 PDT 2013
#Fri Jan 02 13:14:58 PST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-bin.zip

13
gson/build.gradle

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
apply plugin: 'java'
sourceCompatibility = 1.6
test {
useTestNG()
}
dependencies {
compile project(':feign-core')
compile 'com.google.code.gson:gson:2.2.4'
testCompile 'org.testng:testng:6.8.5'
}

14
jackson/build.gradle

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
apply plugin: 'java'
sourceCompatibility = 1.6
test {
useTestNG()
}
dependencies {
compile project(':feign-core')
compile 'com.fasterxml.jackson.core:jackson-databind:2.2.2'
testCompile 'org.testng:testng:6.8.5'
testCompile 'com.google.guava:guava:14.0.1'
}

15
jaxrs/build.gradle

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
apply plugin: 'java'
sourceCompatibility = 1.6
test {
useTestNG()
}
dependencies {
compile project(':feign-core')
compile 'javax.ws.rs:jsr311-api:1.1.1'
testCompile project(':feign-gson')
testCompile 'com.google.guava:guava:14.0.1'
testCompile 'org.testng:testng:6.8.5'
}

14
ribbon/build.gradle

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
apply plugin: 'java'
sourceCompatibility = 1.6
test {
useTestNG()
}
dependencies {
compile project(':feign-core')
compile 'com.netflix.ribbon:ribbon-loadbalancer:2.0-RC5'
testCompile 'org.testng:testng:6.8.5'
testCompile 'com.google.mockwebserver:mockwebserver:20130706'
}

76
ribbon/src/main/java/feign/ribbon/LBClient.java

@ -19,64 +19,61 @@ import com.netflix.client.AbstractLoadBalancerAwareClient; @@ -19,64 +19,61 @@ import com.netflix.client.AbstractLoadBalancerAwareClient;
import com.netflix.client.ClientException;
import com.netflix.client.ClientRequest;
import com.netflix.client.IResponse;
import com.netflix.client.RequestSpecificRetryHandler;
import com.netflix.client.RetryHandler;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.util.Pair;
import java.io.IOException;
import java.net.URI;
import java.util.Collection;
import java.util.Map;
import feign.Client;
import feign.Request;
import feign.RequestTemplate;
import feign.Response;
import feign.RetryableException;
import static com.netflix.client.config.CommonClientConfigKey.ConnectTimeout;
import static com.netflix.client.config.CommonClientConfigKey.ReadTimeout;
import java.io.IOException;
import java.net.URI;
import java.util.Collection;
import java.util.Map;
class LBClient extends AbstractLoadBalancerAwareClient<LBClient.RibbonRequest, LBClient.RibbonResponse> {
private final Client delegate;
private final int connectTimeout;
private final int readTimeout;
private final IClientConfig clientConfig;
LBClient(Client delegate, ILoadBalancer lb, IClientConfig clientConfig) {
super(lb, clientConfig);
this.setRetryHandler(RetryHandler.DEFAULT);
this.clientConfig = clientConfig;
this.delegate = delegate;
this.connectTimeout = Integer.valueOf(clientConfig.getProperty(ConnectTimeout).toString());
this.readTimeout = Integer.valueOf(clientConfig.getProperty(ReadTimeout).toString());
setLoadBalancer(lb);
initWithNiwsConfig(clientConfig);
connectTimeout = clientConfig.get(CommonClientConfigKey.ConnectTimeout);
readTimeout = clientConfig.get(CommonClientConfigKey.ReadTimeout);
}
@Override
public RibbonResponse execute(RibbonRequest request) throws IOException {
int connectTimeout = config(request, ConnectTimeout, this.connectTimeout);
int readTimeout = config(request, ReadTimeout, this.readTimeout);
Request.Options options = new Request.Options(connectTimeout, readTimeout);
public RibbonResponse execute(RibbonRequest request, IClientConfig configOverride) throws IOException {
Request.Options options;
if (configOverride != null) {
options = new Request.Options(configOverride.get(CommonClientConfigKey.ConnectTimeout, connectTimeout),
(configOverride.get(CommonClientConfigKey.ReadTimeout, readTimeout)));
} else {
options = new Request.Options(connectTimeout, readTimeout);
}
Response response = delegate.execute(request.toRequest(), options);
return new RibbonResponse(request.getUri(), response);
}
@Override protected boolean isCircuitBreakerException(Exception e) {
return e instanceof IOException;
}
@Override protected boolean isRetriableException(Exception e) {
return e instanceof RetryableException;
}
@Override
protected Pair<String, Integer> deriveSchemeAndPortFromPartialUri(RibbonRequest task) {
return new Pair<String, Integer>(URI.create(task.request.url()).getScheme(), task.getUri().getPort());
}
@Override protected int getDefaultPort() {
return 443;
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
RibbonRequest request, IClientConfig requestConfig) {
if (clientConfig.get(CommonClientConfigKey.OkToRetryOnAllOperations, false)) {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig);
}
if (!request.toRequest().method().equals("GET")) {
return new RequestSpecificRetryHandler(true, false, this.getRetryHandler(), requestConfig);
} else {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig);
}
}
static class RibbonRequest extends ClientRequest implements Cloneable {
@ -135,11 +132,14 @@ class LBClient extends AbstractLoadBalancerAwareClient<LBClient.RibbonRequest, L @@ -135,11 +132,14 @@ class LBClient extends AbstractLoadBalancerAwareClient<LBClient.RibbonRequest, L
Response toResponse() {
return response;
}
}
static int config(RibbonRequest request, CommonClientConfigKey key, int defaultValue) {
if (request.getOverrideConfig() != null && request.getOverrideConfig().containsProperty(key))
return Integer.valueOf(request.getOverrideConfig().getProperty(key).toString());
return defaultValue;
@Override
public void close() throws IOException {
if (response != null && response.body() != null) {
response.body().close();
}
}
}
}

13
sax/build.gradle

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
apply plugin: 'java'
sourceCompatibility = 1.6
test {
useTestNG()
}
dependencies {
compile project(':feign-core')
testCompile 'com.google.guava:guava:14.0.1'
testCompile 'org.testng:testng:6.8.5'
}
Loading…
Cancel
Save