1919import java .io .IOException ;
2020import java .util .Arrays ;
2121import java .util .Properties ;
22- import java .util .concurrent .locks .ReadWriteLock ;
23- import java .util .concurrent .locks .ReentrantReadWriteLock ;
22+ import java .util .concurrent .locks .Lock ;
23+ import java .util .concurrent .locks .ReentrantLock ;
2424
2525import org .apache .commons .logging .Log ;
2626import org .apache .commons .logging .LogFactory ;
@@ -64,51 +64,51 @@ public class DefaultSftpSessionFactory implements SessionFactory<LsEntry>, Share
6464 JSch .setLogger (new JschLogger ());
6565 }
6666
67- private final ReadWriteLock sharedSessionLock = new ReentrantReadWriteLock ();
68-
6967 private final UserInfo userInfoWrapper = new UserInfoWrapper ();
7068
7169 private final JSch jsch ;
7270
7371 private final boolean isSharedSession ;
7472
75- private volatile String host ;
73+ private final Lock sharedSessionLock ;
7674
77- private volatile int port = 22 ; // the default
75+ private String host ;
7876
79- private volatile String user ;
77+ private int port = 22 ; // the default
8078
81- private volatile String password ;
79+ private String user ;
8280
83- private volatile String knownHosts ;
81+ private String password ;
8482
85- private volatile Resource privateKey ;
83+ private String knownHosts ;
8684
87- private volatile String privateKeyPassphrase ;
85+ private Resource privateKey ;
8886
89- private volatile Properties sessionConfig ;
87+ private String privateKeyPassphrase ;
9088
91- private volatile Proxy proxy ;
89+ private Properties sessionConfig ;
9290
93- private volatile SocketFactory socketFactory ;
91+ private Proxy proxy ;
9492
95- private volatile Integer timeout ;
93+ private SocketFactory socketFactory ;
9694
97- private volatile String clientVersion ;
95+ private Integer timeout ;
9896
99- private volatile String hostKeyAlias ;
97+ private String clientVersion ;
10098
101- private volatile Integer serverAliveInterval ;
99+ private String hostKeyAlias ;
102100
103- private volatile Integer serverAliveCountMax ;
101+ private Integer serverAliveInterval ;
104102
105- private volatile Boolean enableDaemonThread ;
103+ private Integer serverAliveCountMax ;
106104
107- private volatile JSchSessionWrapper sharedJschSession ;
105+ private Boolean enableDaemonThread ;
108106
109- private volatile UserInfo userInfo ;
107+ private UserInfo userInfo ;
110108
111- private volatile boolean allowUnknownKeys = false ;
109+ private boolean allowUnknownKeys = false ;
110+
111+ private volatile JSchSessionWrapper sharedJschSession ;
112112
113113
114114 public DefaultSftpSessionFactory () {
@@ -130,6 +130,12 @@ public DefaultSftpSessionFactory(boolean isSharedSession) {
130130 public DefaultSftpSessionFactory (JSch jsch , boolean isSharedSession ) {
131131 this .jsch = jsch ;
132132 this .isSharedSession = isSharedSession ;
133+ if (this .isSharedSession ) {
134+ this .sharedSessionLock = new ReentrantLock ();
135+ }
136+ else {
137+ this .sharedSessionLock = null ;
138+ }
133139 }
134140
135141 /**
@@ -349,57 +355,41 @@ public void setAllowUnknownKeys(boolean allowUnknownKeys) {
349355
350356 @ Override
351357 public SftpSession getSession () {
352- Assert .hasText (this .host , "host must not be empty" );
353- Assert .hasText (this .user , "user must not be empty" );
354- Assert .isTrue (StringUtils .hasText (this .userInfoWrapper .getPassword ()) || this .privateKey != null ,
355- "either a password or a private key is required" );
358+ JSchSessionWrapper jschSession = this .sharedJschSession ;
359+ SftpSession sftpSession ;
360+ if (this .sharedSessionLock != null ) {
361+ this .sharedSessionLock .lock ();
362+ }
356363 try {
357- JSchSessionWrapper jschSession ;
358- SftpSession sftpSession ;
359- if (this .isSharedSession ) {
360- this .sharedSessionLock .readLock ().lock ();
361- try {
362- if (this .sharedJschSession == null || !this .sharedJschSession .isConnected ()) {
363- this .sharedSessionLock .readLock ().unlock ();
364- this .sharedSessionLock .writeLock ().lock ();
365- try {
366- if (this .sharedJschSession == null || !this .sharedJschSession .isConnected ()) {
367- this .sharedJschSession = new JSchSessionWrapper (initJschSession ());
368- try {
369- this .sharedJschSession .getSession ().connect ();
370- }
371- catch (JSchException e ) {
372- throw new IllegalStateException ("failed to connect" , e );
373- }
374- }
375- }
376- finally {
377- this .sharedSessionLock .readLock ().lock ();
378- this .sharedSessionLock .writeLock ().unlock ();
379- }
380- }
381- jschSession = this .sharedJschSession ;
382- sftpSession = new SftpSession (jschSession );
383- sftpSession .connect ();
384- }
385- finally {
386- this .sharedSessionLock .readLock ().unlock ();
387- }
388- }
389- else {
364+ boolean freshJschSession = false ;
365+ if (jschSession == null || !jschSession .isConnected ()) {
390366 jschSession = new JSchSessionWrapper (initJschSession ());
391- sftpSession = new SftpSession (jschSession );
392- sftpSession .connect ();
367+ freshJschSession = true ;
368+ }
369+ sftpSession = new SftpSession (jschSession );
370+ sftpSession .connect ();
371+ if (this .isSharedSession && freshJschSession ) {
372+ this .sharedJschSession = jschSession ;
393373 }
394- jschSession .addChannel ();
395- return sftpSession ;
396374 }
397375 catch (Exception e ) {
398376 throw new IllegalStateException ("failed to create SFTP Session" , e );
399377 }
378+ finally {
379+ if (this .sharedSessionLock != null ) {
380+ this .sharedSessionLock .unlock ();
381+ }
382+ }
383+ jschSession .addChannel ();
384+ return sftpSession ;
400385 }
401386
402387 private com .jcraft .jsch .Session initJschSession () throws JSchException , IOException {
388+ Assert .hasText (this .host , "host must not be empty" );
389+ Assert .hasText (this .user , "user must not be empty" );
390+ Assert .isTrue (StringUtils .hasText (this .userInfoWrapper .getPassword ()) || this .privateKey != null ,
391+ "either a password or a private key is required" );
392+
403393 if (this .port <= 0 ) {
404394 this .port = 22 ;
405395 }
@@ -564,18 +554,20 @@ public void showMessage(String message) {
564554 @ Override
565555 public String [] promptKeyboardInteractive (String destination , String name , String instruction , String [] prompt ,
566556 boolean [] echo ) {
557+
567558 if (hasDelegate () && getDelegate () instanceof UIKeyboardInteractive ) {
568559 return ((UIKeyboardInteractive ) getDelegate ()).promptKeyboardInteractive (destination , name ,
569560 instruction , prompt , echo );
570561 }
571562 else {
572563 if (logger .isDebugEnabled ()) {
573564 logger .debug ("No UIKeyboardInteractive provided - " + destination + ":" + name + ":" + instruction
574- + ":" + Arrays .asList (prompt ) + ":" + Arrays .asList (echo ));
565+ + ":" + Arrays .asList (prompt ) + ":" + Arrays .toString (echo ));
575566 }
576567 return null ;
577568 }
578569 }
570+
579571 }
580572
581573}
0 commit comments