19
19
20
20
import java .io .File ;
21
21
import java .io .IOException ;
22
+ import java .io .UnsupportedEncodingException ;
23
+ import java .lang .annotation .Documented ;
24
+ import java .lang .annotation .ElementType ;
25
+ import java .lang .annotation .Repeatable ;
26
+ import java .lang .annotation .Retention ;
27
+ import java .lang .annotation .RetentionPolicy ;
28
+ import java .lang .annotation .Target ;
22
29
import java .net .Socket ;
23
30
import java .net .URI ;
31
+ import java .net .URLDecoder ;
24
32
import java .nio .charset .Charset ;
25
33
import java .nio .charset .UnsupportedCharsetException ;
26
34
import java .nio .file .FileSystemException ;
@@ -88,6 +96,7 @@ public class SFTPEnvironment implements Map<String, Object> {
88
96
private static final String SOCKET_FACTORY = "socketFactory" ; //$NON-NLS-1$
89
97
// timeOut should have been timeout, but that's a breaking change...
90
98
private static final String TIMEOUT = "timeOut" ; //$NON-NLS-1$
99
+ private static final String TIMEOUT_QUERY_PARAM = "timeout" ; //$NON-NLS-1$
91
100
private static final String CLIENT_VERSION = "clientVersion" ; //$NON-NLS-1$
92
101
private static final String HOST_KEY_ALIAS = "hostKeyAlias" ; //$NON-NLS-1$
93
102
private static final String SERVER_ALIVE_INTERVAL = "serverAliveInterval" ; //$NON-NLS-1$
@@ -107,6 +116,10 @@ public class SFTPEnvironment implements Map<String, Object> {
107
116
108
117
private static final String DEFAULT_DIR = "defaultDir" ; //$NON-NLS-1$
109
118
private static final String POOL_CONFIG = "poolConfig" ; //$NON-NLS-1$
119
+ private static final String POOL_CONFIG_MAX_WAIT_TIME = POOL_CONFIG + ".maxWaitTime" ; //$NON-NLS-1$
120
+ private static final String POOL_CONFIG_MAX_IDLE_TIME = POOL_CONFIG + ".maxIdleTime" ; //$NON-NLS-1$
121
+ private static final String POOL_CONFIG_INITIAL_SIZE = POOL_CONFIG + ".initialSize" ; //$NON-NLS-1$
122
+ private static final String POOL_CONFIG_MAX_SIZE = POOL_CONFIG + ".maxSize" ; //$NON-NLS-1$
110
123
private static final String FILE_SYSTEM_EXCEPTION_FACTORY = "fileSystemExceptionFactory" ; //$NON-NLS-1$
111
124
112
125
private final Map <String , Object > map ;
@@ -148,6 +161,7 @@ public SFTPEnvironment withUsername(String username) {
148
161
* @param timeout The connection timeout in milliseconds.
149
162
* @return This object.
150
163
*/
164
+ @ QueryParam (CONNECT_TIMEOUT )
151
165
public SFTPEnvironment withConnectTimeout (int timeout ) {
152
166
put (CONNECT_TIMEOUT , timeout );
153
167
return this ;
@@ -211,6 +225,7 @@ public SFTPEnvironment withConfig(Properties config) {
211
225
* @throws NullPointerException if the given key or value is {@code null}.
212
226
* @see #withConfig(Properties)
213
227
*/
228
+ @ QueryParam (CONFIG + ".<key>" )
214
229
public SFTPEnvironment withConfig (String key , String value ) {
215
230
getConfig ().setProperty (key , value );
216
231
return this ;
@@ -250,6 +265,7 @@ private Properties getConfig() {
250
265
* @throws NullPointerException If the given key or value is {@code null}.
251
266
* @since 3.2
252
267
*/
268
+ @ QueryParam (APPENDED_CONFIG + ".<key>" )
253
269
public SFTPEnvironment withAppendedConfig (String key , String value ) {
254
270
return withAppendedConfig (key , value , AppendedConfig .DEFAULT_APPENDER );
255
271
}
@@ -302,6 +318,7 @@ public SFTPEnvironment withSocketFactory(SocketFactory factory) {
302
318
* @return This object.
303
319
* @see Socket#setSoTimeout(int)
304
320
*/
321
+ @ QueryParam (TIMEOUT_QUERY_PARAM )
305
322
public SFTPEnvironment withTimeout (int timeout ) {
306
323
put (TIMEOUT , timeout );
307
324
return this ;
@@ -313,6 +330,7 @@ public SFTPEnvironment withTimeout(int timeout) {
313
330
* @param version The client version.
314
331
* @return This object.
315
332
*/
333
+ @ QueryParam (CLIENT_VERSION )
316
334
public SFTPEnvironment withClientVersion (String version ) {
317
335
put (CLIENT_VERSION , version );
318
336
return this ;
@@ -324,6 +342,7 @@ public SFTPEnvironment withClientVersion(String version) {
324
342
* @param alias The host key alias.
325
343
* @return This object.
326
344
*/
345
+ @ QueryParam (HOST_KEY_ALIAS )
327
346
public SFTPEnvironment withHostKeyAlias (String alias ) {
328
347
put (HOST_KEY_ALIAS , alias );
329
348
return this ;
@@ -335,6 +354,7 @@ public SFTPEnvironment withHostKeyAlias(String alias) {
335
354
* @param interval The server alive interval in milliseconds.
336
355
* @return This object.
337
356
*/
357
+ @ QueryParam (SERVER_ALIVE_INTERVAL )
338
358
public SFTPEnvironment withServerAliveInterval (int interval ) {
339
359
put (SERVER_ALIVE_INTERVAL , interval );
340
360
return this ;
@@ -346,6 +366,7 @@ public SFTPEnvironment withServerAliveInterval(int interval) {
346
366
* @param count The maximum number of server alive messages.
347
367
* @return This object.
348
368
*/
369
+ @ QueryParam (SERVER_ALIVE_COUNT_MAX )
349
370
public SFTPEnvironment withServerAliveCountMax (int count ) {
350
371
put (SERVER_ALIVE_COUNT_MAX , count );
351
372
return this ;
@@ -471,6 +492,7 @@ public SFTPEnvironment withConfigRepository(ConfigRepository repository) {
471
492
* @param agentForwarding {@code true} to enable strict agent forwarding, or {@code false} to disable it.
472
493
* @return This object.
473
494
*/
495
+ @ QueryParam (AGENT_FORWARDING )
474
496
public SFTPEnvironment withAgentForwarding (boolean agentForwarding ) {
475
497
put (AGENT_FORWARDING , agentForwarding );
476
498
return this ;
@@ -482,6 +504,7 @@ public SFTPEnvironment withAgentForwarding(boolean agentForwarding) {
482
504
* @param encoding The filename encoding to use.
483
505
* @return This object.
484
506
*/
507
+ @ QueryParam (FILENAME_ENCODING )
485
508
public SFTPEnvironment withFilenameEncoding (Charset encoding ) {
486
509
put (FILENAME_ENCODING , encoding );
487
510
return this ;
@@ -496,6 +519,7 @@ public SFTPEnvironment withFilenameEncoding(Charset encoding) {
496
519
* @param pathname The default directory to use.
497
520
* @return This object.
498
521
*/
522
+ @ QueryParam (DEFAULT_DIR )
499
523
public SFTPEnvironment withDefaultDirectory (String pathname ) {
500
524
put (DEFAULT_DIR , pathname );
501
525
return this ;
@@ -513,6 +537,10 @@ public SFTPEnvironment withDefaultDirectory(String pathname) {
513
537
* @return This object.
514
538
* @since 3.0
515
539
*/
540
+ @ QueryParam (POOL_CONFIG_MAX_WAIT_TIME )
541
+ @ QueryParam (POOL_CONFIG_MAX_IDLE_TIME )
542
+ @ QueryParam (POOL_CONFIG_INITIAL_SIZE )
543
+ @ QueryParam (POOL_CONFIG_MAX_SIZE )
516
544
public SFTPEnvironment withPoolConfig (SFTPPoolConfig poolConfig ) {
517
545
put (POOL_CONFIG , poolConfig );
518
546
return this ;
@@ -529,6 +557,11 @@ public SFTPEnvironment withFileSystemExceptionFactory(FileSystemExceptionFactory
529
557
return this ;
530
558
}
531
559
560
+ SFTPEnvironment withQueryString (String rawQueryString ) {
561
+ new QueryParamProcessor (this ).processQueryString (rawQueryString );
562
+ return this ;
563
+ }
564
+
532
565
boolean hasUsername () {
533
566
return containsKey (USERNAME );
534
567
}
@@ -984,4 +1017,143 @@ public String toString() {
984
1017
return value ;
985
1018
}
986
1019
}
1020
+
1021
+ /**
1022
+ * Indicates which query parameters can be used to define environment values.
1023
+ *
1024
+ * @author Rob Spoor
1025
+ * @since 3.3
1026
+ */
1027
+ @ Target (ElementType .METHOD )
1028
+ @ Retention (RetentionPolicy .SOURCE )
1029
+ @ Documented
1030
+ @ Repeatable (QueryParams .class )
1031
+ public @interface QueryParam {
1032
+
1033
+ /**
1034
+ * The name of the query parameter.
1035
+ */
1036
+ String value ();
1037
+ }
1038
+
1039
+ /**
1040
+ * A container for {@link QueryParam} annotations.
1041
+ *
1042
+ * @author Rob Spoor
1043
+ * @since 3.3
1044
+ */
1045
+ @ Target (ElementType .METHOD )
1046
+ @ Retention (RetentionPolicy .SOURCE )
1047
+ @ Documented
1048
+ public @interface QueryParams {
1049
+
1050
+ /**
1051
+ * The contained {@link QueryParam} annotations.
1052
+ */
1053
+ QueryParam [] value ();
1054
+ }
1055
+
1056
+ static final class QueryParamProcessor {
1057
+
1058
+ private final SFTPEnvironment env ;
1059
+ private SFTPPoolConfig .Builder poolConfigBuilder ;
1060
+
1061
+ private QueryParamProcessor (SFTPEnvironment env ) {
1062
+ this .env = env ;
1063
+ }
1064
+
1065
+ private void processQueryString (String rawQueryString ) {
1066
+ int start = 0 ;
1067
+ int indexOfAmp = rawQueryString .indexOf ('&' , start );
1068
+ while (indexOfAmp != -1 ) {
1069
+ processQueryParam (rawQueryString , start , indexOfAmp );
1070
+ start = indexOfAmp + 1 ;
1071
+ indexOfAmp = rawQueryString .indexOf ('&' , start );
1072
+ }
1073
+ processQueryParam (rawQueryString , start , rawQueryString .length ());
1074
+
1075
+ if (poolConfigBuilder != null ) {
1076
+ env .withPoolConfig (poolConfigBuilder .build ());
1077
+ }
1078
+ }
1079
+
1080
+ private void processQueryParam (String rawQueryString , int start , int end ) {
1081
+ int indexOfEquals = rawQueryString .indexOf ('=' , start );
1082
+ if (indexOfEquals == -1 || indexOfEquals > end ) {
1083
+ String key = decode (rawQueryString .substring (start , end ));
1084
+ processQueryParam (key , "" ); //$NON-NLS-1$
1085
+ } else {
1086
+ String key = decode (rawQueryString .substring (start , indexOfEquals ));
1087
+ String value = decode (rawQueryString .substring (indexOfEquals + 1 , end ));
1088
+ processQueryParam (key , value );
1089
+ }
1090
+ }
1091
+
1092
+ private void processQueryParam (String key , String value ) {
1093
+ switch (key ) {
1094
+ case CONNECT_TIMEOUT :
1095
+ env .withConnectTimeout (Integer .parseInt (value ));
1096
+ break ;
1097
+ case TIMEOUT_QUERY_PARAM :
1098
+ env .withTimeout (Integer .parseInt (value ));
1099
+ break ;
1100
+ case CLIENT_VERSION :
1101
+ env .withClientVersion (value );
1102
+ break ;
1103
+ case HOST_KEY_ALIAS :
1104
+ env .withHostKeyAlias (value );
1105
+ break ;
1106
+ case SERVER_ALIVE_INTERVAL :
1107
+ env .withServerAliveInterval (Integer .parseInt (value ));
1108
+ break ;
1109
+ case SERVER_ALIVE_COUNT_MAX :
1110
+ env .withServerAliveCountMax (Integer .parseInt (value ));
1111
+ break ;
1112
+ case AGENT_FORWARDING :
1113
+ env .withAgentForwarding (Boolean .parseBoolean (value ));
1114
+ break ;
1115
+ case FILENAME_ENCODING :
1116
+ env .withFilenameEncoding (Charset .forName (value ));
1117
+ break ;
1118
+ case DEFAULT_DIR :
1119
+ env .withDefaultDirectory (value );
1120
+ break ;
1121
+ case POOL_CONFIG_MAX_WAIT_TIME :
1122
+ poolConfigBuilder ().withMaxWaitTime (Duration .parse (value ));
1123
+ break ;
1124
+ case POOL_CONFIG_MAX_IDLE_TIME :
1125
+ poolConfigBuilder ().withMaxIdleTime (Duration .parse (value ));
1126
+ break ;
1127
+ case POOL_CONFIG_INITIAL_SIZE :
1128
+ poolConfigBuilder ().withInitialSize (Integer .parseInt (value ));
1129
+ break ;
1130
+ case POOL_CONFIG_MAX_SIZE :
1131
+ poolConfigBuilder ().withMaxSize (Integer .parseInt (value ));
1132
+ break ;
1133
+ default :
1134
+ if (key .startsWith (CONFIG + "." )) { //$NON-NLS-1$
1135
+ env .withConfig (key .substring (CONFIG .length () + 1 ), value );
1136
+ } else if (key .startsWith (APPENDED_CONFIG + "." )) { //$NON-NLS-1$
1137
+ env .withAppendedConfig (key .substring (APPENDED_CONFIG .length () + 1 ), value );
1138
+ }
1139
+ // else ignore
1140
+ break ;
1141
+ }
1142
+ }
1143
+
1144
+ private String decode (String value ) {
1145
+ try {
1146
+ return URLDecoder .decode (value , "UTF-8" ); //$NON-NLS-1$
1147
+ } catch (UnsupportedEncodingException e ) {
1148
+ throw new IllegalStateException (e );
1149
+ }
1150
+ }
1151
+
1152
+ private SFTPPoolConfig .Builder poolConfigBuilder () {
1153
+ if (poolConfigBuilder == null ) {
1154
+ poolConfigBuilder = env .getPoolConfig ().toBuilder ();
1155
+ }
1156
+ return poolConfigBuilder ;
1157
+ }
1158
+ }
987
1159
}
0 commit comments