Skip to content

Commit 0e0508c

Browse files
committed
Merge pull request #1998 from WoodWing/master
Support file downloading in Java jersey2 client
2 parents 2471163 + eee441b commit 0e0508c

File tree

18 files changed

+187
-31
lines changed

18 files changed

+187
-31
lines changed

modules/swagger-codegen/src/main/resources/Java/libraries/jersey2/ApiClient.mustache

Lines changed: 85 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
2020
import org.glassfish.jersey.media.multipart.MultiPart;
2121
import org.glassfish.jersey.media.multipart.MultiPartFeature;
2222

23+
import java.io.IOException;
24+
import java.io.InputStream;
25+
import java.nio.file.Files;
2326
import java.util.Collection;
2427
import java.util.Collections;
2528
import java.util.Map;
@@ -37,6 +40,8 @@ import java.io.UnsupportedEncodingException;
3740

3841
import java.text.DateFormat;
3942
import java.text.SimpleDateFormat;
43+
import java.util.regex.Matcher;
44+
import java.util.regex.Pattern;
4045

4146
import {{invokerPackage}}.auth.Authentication;
4247
import {{invokerPackage}}.auth.HttpBasicAuth;
@@ -52,6 +57,7 @@ public class ApiClient {
5257
5358
private Client httpClient;
5459
private JSON json;
60+
private String tempFolderPath = null;
5561
5662
private Map<String, Authentication> authentications;
5763
@@ -236,8 +242,24 @@ public class ApiClient {
236242
}
237243

238244
/**
239-
* Connect timeout (in milliseconds).
240-
*/
245+
* The path of temporary folder used to store downloaded files from endpoints
246+
* with file response. The default value is <code>null</code>, i.e. using
247+
* the system's default tempopary folder.
248+
*
249+
* @see https://docs.oracle.com/javase/7/docs/api/java/io/File.html#createTempFile(java.lang.String,%20java.lang.String,%20java.io.File)
250+
*/
251+
public String getTempFolderPath() {
252+
return tempFolderPath;
253+
}
254+
255+
public ApiClient setTempFolderPath(String tempFolderPath) {
256+
this.tempFolderPath = tempFolderPath;
257+
return this;
258+
}
259+
260+
/**
261+
* Connect timeout (in milliseconds).
262+
*/
241263
public int getConnectTimeout() {
242264
return connectionTimeout;
243265
}
@@ -247,11 +269,11 @@ public class ApiClient {
247269
* A value of 0 means no timeout, otherwise values must be between 1 and
248270
* {@link Integer#MAX_VALUE}.
249271
*/
250-
public ApiClient setConnectTimeout(int connectionTimeout) {
251-
this.connectionTimeout = connectionTimeout;
252-
httpClient.property(ClientProperties.CONNECT_TIMEOUT, connectionTimeout);
253-
return this;
254-
}
272+
public ApiClient setConnectTimeout(int connectionTimeout) {
273+
this.connectionTimeout = connectionTimeout;
274+
httpClient.property(ClientProperties.CONNECT_TIMEOUT, connectionTimeout);
275+
return this;
276+
}
255277

256278
/**
257279
* Get the date format used to parse/format date parameters.
@@ -467,6 +489,13 @@ public class ApiClient {
467489
* Deserialize response body to Java object according to the Content-Type.
468490
*/
469491
public <T> T deserialize(Response response, GenericType<T> returnType) throws ApiException {
492+
// Handle file downloading.
493+
if (returnType.equals(File.class)) {
494+
@SuppressWarnings("unchecked")
495+
T file = (T) downloadFileFromResponse(response);
496+
return file;
497+
}
498+
470499
String contentType = null;
471500
List<Object> contentTypes = response.getHeaders().get("Content-Type");
472501
if (contentTypes != null && !contentTypes.isEmpty())
@@ -477,6 +506,55 @@ public class ApiClient {
477506
return response.readEntity(returnType);
478507
}
479508

509+
/**
510+
* Download file from the given response.
511+
* @throws ApiException If fail to read file content from response and write to disk
512+
*/
513+
public File downloadFileFromResponse(Response response) throws ApiException {
514+
try {
515+
File file = prepareDownloadFile(response);
516+
Files.copy(response.readEntity(InputStream.class), file.toPath());
517+
return file;
518+
} catch (IOException e) {
519+
throw new ApiException(e);
520+
}
521+
}
522+
523+
public File prepareDownloadFile(Response response) throws IOException {
524+
String filename = null;
525+
String contentDisposition = (String) response.getHeaders().getFirst("Content-Disposition");
526+
if (contentDisposition != null && !"".equals(contentDisposition)) {
527+
// Get filename from the Content-Disposition header.
528+
Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?");
529+
Matcher matcher = pattern.matcher(contentDisposition);
530+
if (matcher.find())
531+
filename = matcher.group(1);
532+
}
533+
534+
String prefix = null;
535+
String suffix = null;
536+
if (filename == null) {
537+
prefix = "download-";
538+
suffix = "";
539+
} else {
540+
int pos = filename.lastIndexOf(".");
541+
if (pos == -1) {
542+
prefix = filename + "-";
543+
} else {
544+
prefix = filename.substring(0, pos) + "-";
545+
suffix = filename.substring(pos);
546+
}
547+
// File.createTempFile requires the prefix to be at least three characters long
548+
if (prefix.length() < 3)
549+
prefix = "download-";
550+
}
551+
552+
if (tempFolderPath == null)
553+
return File.createTempFile(prefix, suffix);
554+
else
555+
return File.createTempFile(prefix, suffix, new File(tempFolderPath));
556+
}
557+
480558
/**
481559
* Invoke API by sending HTTP request with the given options.
482560
*

samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/ApiClient.java

Lines changed: 86 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
import org.glassfish.jersey.media.multipart.MultiPart;
2121
import org.glassfish.jersey.media.multipart.MultiPartFeature;
2222

23+
import java.io.IOException;
24+
import java.io.InputStream;
25+
import java.nio.file.Files;
2326
import java.util.Collection;
2427
import java.util.Collections;
2528
import java.util.Map;
@@ -37,13 +40,15 @@
3740

3841
import java.text.DateFormat;
3942
import java.text.SimpleDateFormat;
43+
import java.util.regex.Matcher;
44+
import java.util.regex.Pattern;
4045

4146
import io.swagger.client.auth.Authentication;
4247
import io.swagger.client.auth.HttpBasicAuth;
4348
import io.swagger.client.auth.ApiKeyAuth;
4449
import io.swagger.client.auth.OAuth;
4550

46-
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-15T19:00:52.199+08:00")
51+
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-28T16:23:25.238+01:00")
4752
public class ApiClient {
4853
private Map<String, String> defaultHeaderMap = new HashMap<String, String>();
4954
private String basePath = "http://petstore.swagger.io/v2";
@@ -52,6 +57,7 @@ public class ApiClient {
5257

5358
private Client httpClient;
5459
private JSON json;
60+
private String tempFolderPath = null;
5561

5662
private Map<String, Authentication> authentications;
5763

@@ -235,8 +241,24 @@ public ApiClient setDebugging(boolean debugging) {
235241
}
236242

237243
/**
238-
* Connect timeout (in milliseconds).
239-
*/
244+
* The path of temporary folder used to store downloaded files from endpoints
245+
* with file response. The default value is <code>null</code>, i.e. using
246+
* the system's default tempopary folder.
247+
*
248+
* @see https://docs.oracle.com/javase/7/docs/api/java/io/File.html#createTempFile(java.lang.String,%20java.lang.String,%20java.io.File)
249+
*/
250+
public String getTempFolderPath() {
251+
return tempFolderPath;
252+
}
253+
254+
public ApiClient setTempFolderPath(String tempFolderPath) {
255+
this.tempFolderPath = tempFolderPath;
256+
return this;
257+
}
258+
259+
/**
260+
* Connect timeout (in milliseconds).
261+
*/
240262
public int getConnectTimeout() {
241263
return connectionTimeout;
242264
}
@@ -246,11 +268,11 @@ public int getConnectTimeout() {
246268
* A value of 0 means no timeout, otherwise values must be between 1 and
247269
* {@link Integer#MAX_VALUE}.
248270
*/
249-
public ApiClient setConnectTimeout(int connectionTimeout) {
250-
this.connectionTimeout = connectionTimeout;
251-
httpClient.property(ClientProperties.CONNECT_TIMEOUT, connectionTimeout);
252-
return this;
253-
}
271+
public ApiClient setConnectTimeout(int connectionTimeout) {
272+
this.connectionTimeout = connectionTimeout;
273+
httpClient.property(ClientProperties.CONNECT_TIMEOUT, connectionTimeout);
274+
return this;
275+
}
254276

255277
/**
256278
* Get the date format used to parse/format date parameters.
@@ -466,6 +488,13 @@ public Entity<?> serialize(Object obj, Map<String, Object> formParams, String co
466488
* Deserialize response body to Java object according to the Content-Type.
467489
*/
468490
public <T> T deserialize(Response response, GenericType<T> returnType) throws ApiException {
491+
// Handle file downloading.
492+
if (returnType.equals(File.class)) {
493+
@SuppressWarnings("unchecked")
494+
T file = (T) downloadFileFromResponse(response);
495+
return file;
496+
}
497+
469498
String contentType = null;
470499
List<Object> contentTypes = response.getHeaders().get("Content-Type");
471500
if (contentTypes != null && !contentTypes.isEmpty())
@@ -476,6 +505,55 @@ public <T> T deserialize(Response response, GenericType<T> returnType) throws Ap
476505
return response.readEntity(returnType);
477506
}
478507

508+
/**
509+
* Download file from the given response.
510+
* @throws ApiException If fail to read file content from response and write to disk
511+
*/
512+
public File downloadFileFromResponse(Response response) throws ApiException {
513+
try {
514+
File file = prepareDownloadFile(response);
515+
Files.copy(response.readEntity(InputStream.class), file.toPath());
516+
return file;
517+
} catch (IOException e) {
518+
throw new ApiException(e);
519+
}
520+
}
521+
522+
public File prepareDownloadFile(Response response) throws IOException {
523+
String filename = null;
524+
String contentDisposition = (String) response.getHeaders().getFirst("Content-Disposition");
525+
if (contentDisposition != null && !"".equals(contentDisposition)) {
526+
// Get filename from the Content-Disposition header.
527+
Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?");
528+
Matcher matcher = pattern.matcher(contentDisposition);
529+
if (matcher.find())
530+
filename = matcher.group(1);
531+
}
532+
533+
String prefix = null;
534+
String suffix = null;
535+
if (filename == null) {
536+
prefix = "download-";
537+
suffix = "";
538+
} else {
539+
int pos = filename.lastIndexOf(".");
540+
if (pos == -1) {
541+
prefix = filename + "-";
542+
} else {
543+
prefix = filename.substring(0, pos) + "-";
544+
suffix = filename.substring(pos);
545+
}
546+
// File.createTempFile requires the prefix to be at least three characters long
547+
if (prefix.length() < 3)
548+
prefix = "download-";
549+
}
550+
551+
if (tempFolderPath == null)
552+
return File.createTempFile(prefix, suffix);
553+
else
554+
return File.createTempFile(prefix, suffix, new File(tempFolderPath));
555+
}
556+
479557
/**
480558
* Invoke API by sending HTTP request with the given options.
481559
*

samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/ApiException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import java.util.Map;
44
import java.util.List;
55

6-
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-05T14:39:17.660+08:00")
6+
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-28T16:23:25.238+01:00")
77
public class ApiException extends Exception {
88
private int code = 0;
99
private Map<String, List<String>> responseHeaders = null;

samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/Configuration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.swagger.client;
22

3-
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-05T14:39:17.660+08:00")
3+
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-28T16:23:25.238+01:00")
44
public class Configuration {
55
private static ApiClient defaultApiClient = new ApiClient();
66

samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/JSON.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import javax.ws.rs.ext.ContextResolver;
1010

11-
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-05T14:39:17.660+08:00")
11+
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-28T16:23:25.238+01:00")
1212
public class JSON implements ContextResolver<ObjectMapper> {
1313
private ObjectMapper mapper;
1414

samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/Pair.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.swagger.client;
22

3-
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-05T14:39:17.660+08:00")
3+
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-28T16:23:25.238+01:00")
44
public class Pair {
55
private String name = "";
66
private String value = "";

samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/StringUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.swagger.client;
22

3-
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-05T14:39:17.660+08:00")
3+
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-28T16:23:25.238+01:00")
44
public class StringUtil {
55
/**
66
* Check if the given array contains the given value (with case-insensitive comparison).

samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/api/PetApi.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import java.util.*;
1414

15-
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-15T19:00:52.199+08:00")
15+
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-28T16:23:25.238+01:00")
1616
public class PetApi {
1717
private ApiClient apiClient;
1818

samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/api/StoreApi.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import java.util.*;
1414

15-
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-05T14:39:17.660+08:00")
15+
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-28T16:23:25.238+01:00")
1616
public class StoreApi {
1717
private ApiClient apiClient;
1818

samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/api/UserApi.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import java.util.*;
1414

15-
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-05T14:39:17.660+08:00")
15+
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-28T16:23:25.238+01:00")
1616
public class UserApi {
1717
private ApiClient apiClient;
1818

samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/auth/ApiKeyAuth.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import java.util.Map;
66
import java.util.List;
77

8-
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-05T14:39:17.660+08:00")
8+
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-28T16:23:25.238+01:00")
99
public class ApiKeyAuth implements Authentication {
1010
private final String location;
1111
private final String paramName;

samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/auth/HttpBasicAuth.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import java.io.UnsupportedEncodingException;
1111

12-
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-05T14:39:17.660+08:00")
12+
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-28T16:23:25.238+01:00")
1313
public class HttpBasicAuth implements Authentication {
1414
private String username;
1515
private String password;

samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/auth/OAuth.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import java.util.Map;
66
import java.util.List;
77

8-
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-05T14:39:17.660+08:00")
8+
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-28T16:23:25.238+01:00")
99
public class OAuth implements Authentication {
1010
private String accessToken;
1111

samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/model/Category.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212

13-
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-15T19:00:52.199+08:00")
13+
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-01-28T16:23:25.238+01:00")
1414
public class Category {
1515

1616
private Long id = null;

0 commit comments

Comments
 (0)