summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.ssh.jsch
diff options
context:
space:
mode:
authorMatthias Sohn <matthias.sohn@sap.com>2020-04-24 22:41:39 +0200
committerMatthias Sohn <matthias.sohn@sap.com>2020-06-01 01:46:59 +0200
commit8d2d683655e2de17cf465fa46af10e0e56b3aaed (patch)
tree52491eb0da64433efa2d41004dafd7933ddae8ee /org.eclipse.jgit.ssh.jsch
parent77848d635b76d8294697ffaf11acf51256df2a5b (diff)
downloadjgit-8d2d683655e2de17cf465fa46af10e0e56b3aaed.tar.gz
jgit-8d2d683655e2de17cf465fa46af10e0e56b3aaed.zip
Decouple JSch from JGit Core
Motivation: JSch serves as 'default' implementations of the SSH transport. If a client application does not use it then there is no need to pull in this dependency. Move the classes depending on JSch to an OSGi fragment extending the org.eclipse.jgit bundle and keep them in the same package as before since moving them to another package would break API. Defer moving them to a separate package to the next major release. Add a new feature org.eclipse.jgit.ssh.jsch feature to enable installation. With that users can now decide which of the ssh client integrations (JCraft JSch or Apache Mina SSHD) they want to install. We will remove the JCraft JSch integration in a later step due to the reasons discussed in bug 520927. Bug: 553625 Change-Id: I5979c8a9dbbe878a2e8ac0fbfde7230059d74dc2 Also-by: Michael Dardis <git@md-5.net> Signed-off-by: Michael Dardis <git@md-5.net> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com> Signed-off-by: David Ostrovsky <david@ostrovsky.org>
Diffstat (limited to 'org.eclipse.jgit.ssh.jsch')
-rw-r--r--org.eclipse.jgit.ssh.jsch/.classpath8
-rw-r--r--org.eclipse.jgit.ssh.jsch/.fbprefs125
-rw-r--r--org.eclipse.jgit.ssh.jsch/.gitignore2
-rw-r--r--org.eclipse.jgit.ssh.jsch/.project34
-rw-r--r--org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.core.resources.prefs2
-rw-r--r--org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.core.runtime.prefs2
-rw-r--r--org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.jdt.core.prefs399
-rw-r--r--org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.jdt.ui.prefs66
-rw-r--r--org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.mylyn.tasks.ui.prefs3
-rw-r--r--org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.mylyn.team.ui.prefs2
-rw-r--r--org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.pde.api.tools.prefs104
-rw-r--r--org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.pde.core.prefs2
-rw-r--r--org.eclipse.jgit.ssh.jsch/BUILD20
-rw-r--r--org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF26
-rw-r--r--org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF7
-rw-r--r--org.eclipse.jgit.ssh.jsch/about.html96
-rw-r--r--org.eclipse.jgit.ssh.jsch/build.properties7
-rw-r--r--org.eclipse.jgit.ssh.jsch/plugin.properties2
-rw-r--r--org.eclipse.jgit.ssh.jsch/pom.xml218
-rw-r--r--org.eclipse.jgit.ssh.jsch/resources/META-INF/services/org.eclipse.jgit.transport.SshSessionFactory1
-rw-r--r--org.eclipse.jgit.ssh.jsch/resources/org/eclipse/jgit/internal/transport/jsch/JSchText.properties4
-rw-r--r--org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/internal/transport/jsch/JSchText.java35
-rw-r--r--org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/CredentialsProviderUserInfo.java133
-rw-r--r--org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java541
-rw-r--r--org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschSession.java373
-rw-r--r--org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/OpenSshConfig.java346
26 files changed, 2558 insertions, 0 deletions
diff --git a/org.eclipse.jgit.ssh.jsch/.classpath b/org.eclipse.jgit.ssh.jsch/.classpath
new file mode 100644
index 0000000000..110168ffa1
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="resources"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.jgit.ssh.jsch/.fbprefs b/org.eclipse.jgit.ssh.jsch/.fbprefs
new file mode 100644
index 0000000000..81a0767ff6
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/.fbprefs
@@ -0,0 +1,125 @@
+#FindBugs User Preferences
+#Mon May 04 16:24:13 PDT 2009
+detectorAppendingToAnObjectOutputStream=AppendingToAnObjectOutputStream|true
+detectorBadAppletConstructor=BadAppletConstructor|false
+detectorBadResultSetAccess=BadResultSetAccess|true
+detectorBadSyntaxForRegularExpression=BadSyntaxForRegularExpression|true
+detectorBadUseOfReturnValue=BadUseOfReturnValue|true
+detectorBadlyOverriddenAdapter=BadlyOverriddenAdapter|true
+detectorBooleanReturnNull=BooleanReturnNull|true
+detectorCallToUnsupportedMethod=CallToUnsupportedMethod|true
+detectorCheckImmutableAnnotation=CheckImmutableAnnotation|true
+detectorCheckTypeQualifiers=CheckTypeQualifiers|true
+detectorCloneIdiom=CloneIdiom|false
+detectorComparatorIdiom=ComparatorIdiom|true
+detectorConfusedInheritance=ConfusedInheritance|true
+detectorConfusionBetweenInheritedAndOuterMethod=ConfusionBetweenInheritedAndOuterMethod|true
+detectorCrossSiteScripting=CrossSiteScripting|true
+detectorDoInsideDoPrivileged=DoInsideDoPrivileged|true
+detectorDontCatchIllegalMonitorStateException=DontCatchIllegalMonitorStateException|true
+detectorDontUseEnum=DontUseEnum|true
+detectorDroppedException=DroppedException|true
+detectorDumbMethodInvocations=DumbMethodInvocations|true
+detectorDumbMethods=DumbMethods|true
+detectorDuplicateBranches=DuplicateBranches|true
+detectorEmptyZipFileEntry=EmptyZipFileEntry|true
+detectorEqualsOperandShouldHaveClassCompatibleWithThis=EqualsOperandShouldHaveClassCompatibleWithThis|true
+detectorFinalizerNullsFields=FinalizerNullsFields|true
+detectorFindBadCast2=FindBadCast2|true
+detectorFindBadForLoop=FindBadForLoop|true
+detectorFindCircularDependencies=FindCircularDependencies|false
+detectorFindDeadLocalStores=FindDeadLocalStores|true
+detectorFindDoubleCheck=FindDoubleCheck|true
+detectorFindEmptySynchronizedBlock=FindEmptySynchronizedBlock|true
+detectorFindFieldSelfAssignment=FindFieldSelfAssignment|true
+detectorFindFinalizeInvocations=FindFinalizeInvocations|true
+detectorFindFloatEquality=FindFloatEquality|true
+detectorFindHEmismatch=FindHEmismatch|true
+detectorFindInconsistentSync2=FindInconsistentSync2|true
+detectorFindJSR166LockMonitorenter=FindJSR166LockMonitorenter|true
+detectorFindLocalSelfAssignment2=FindLocalSelfAssignment2|true
+detectorFindMaskedFields=FindMaskedFields|true
+detectorFindMismatchedWaitOrNotify=FindMismatchedWaitOrNotify|true
+detectorFindNakedNotify=FindNakedNotify|true
+detectorFindNonSerializableStoreIntoSession=FindNonSerializableStoreIntoSession|true
+detectorFindNonSerializableValuePassedToWriteObject=FindNonSerializableValuePassedToWriteObject|true
+detectorFindNonShortCircuit=FindNonShortCircuit|true
+detectorFindNullDeref=FindNullDeref|true
+detectorFindNullDerefsInvolvingNonShortCircuitEvaluation=FindNullDerefsInvolvingNonShortCircuitEvaluation|true
+detectorFindOpenStream=FindOpenStream|true
+detectorFindPuzzlers=FindPuzzlers|true
+detectorFindRefComparison=FindRefComparison|true
+detectorFindReturnRef=FindReturnRef|true
+detectorFindRunInvocations=FindRunInvocations|true
+detectorFindSelfComparison=FindSelfComparison|true
+detectorFindSelfComparison2=FindSelfComparison2|true
+detectorFindSleepWithLockHeld=FindSleepWithLockHeld|true
+detectorFindSpinLoop=FindSpinLoop|true
+detectorFindSqlInjection=FindSqlInjection|true
+detectorFindTwoLockWait=FindTwoLockWait|true
+detectorFindUncalledPrivateMethods=FindUncalledPrivateMethods|true
+detectorFindUnconditionalWait=FindUnconditionalWait|true
+detectorFindUninitializedGet=FindUninitializedGet|true
+detectorFindUnrelatedTypesInGenericContainer=FindUnrelatedTypesInGenericContainer|true
+detectorFindUnreleasedLock=FindUnreleasedLock|true
+detectorFindUnsatisfiedObligation=FindUnsatisfiedObligation|true
+detectorFindUnsyncGet=FindUnsyncGet|true
+detectorFindUselessControlFlow=FindUselessControlFlow|true
+detectorFormatStringChecker=FormatStringChecker|true
+detectorHugeSharedStringConstants=HugeSharedStringConstants|true
+detectorIDivResultCastToDouble=IDivResultCastToDouble|true
+detectorIncompatMask=IncompatMask|true
+detectorInconsistentAnnotations=InconsistentAnnotations|true
+detectorInefficientMemberAccess=InefficientMemberAccess|false
+detectorInefficientToArray=InefficientToArray|true
+detectorInfiniteLoop=InfiniteLoop|true
+detectorInfiniteRecursiveLoop=InfiniteRecursiveLoop|true
+detectorInfiniteRecursiveLoop2=InfiniteRecursiveLoop2|false
+detectorInheritanceUnsafeGetResource=InheritanceUnsafeGetResource|true
+detectorInitializationChain=InitializationChain|true
+detectorInstantiateStaticClass=InstantiateStaticClass|true
+detectorInvalidJUnitTest=InvalidJUnitTest|true
+detectorIteratorIdioms=IteratorIdioms|true
+detectorLazyInit=LazyInit|true
+detectorLoadOfKnownNullValue=LoadOfKnownNullValue|true
+detectorMethodReturnCheck=MethodReturnCheck|true
+detectorMultithreadedInstanceAccess=MultithreadedInstanceAccess|true
+detectorMutableLock=MutableLock|true
+detectorMutableStaticFields=MutableStaticFields|true
+detectorNaming=Naming|true
+detectorNumberConstructor=NumberConstructor|true
+detectorOverridingEqualsNotSymmetrical=OverridingEqualsNotSymmetrical|true
+detectorPreferZeroLengthArrays=PreferZeroLengthArrays|true
+detectorPublicSemaphores=PublicSemaphores|false
+detectorQuestionableBooleanAssignment=QuestionableBooleanAssignment|true
+detectorReadReturnShouldBeChecked=ReadReturnShouldBeChecked|true
+detectorRedundantInterfaces=RedundantInterfaces|true
+detectorRepeatedConditionals=RepeatedConditionals|true
+detectorRuntimeExceptionCapture=RuntimeExceptionCapture|true
+detectorSerializableIdiom=SerializableIdiom|true
+detectorStartInConstructor=StartInConstructor|true
+detectorStaticCalendarDetector=StaticCalendarDetector|true
+detectorStringConcatenation=StringConcatenation|true
+detectorSuperfluousInstanceOf=SuperfluousInstanceOf|true
+detectorSuspiciousThreadInterrupted=SuspiciousThreadInterrupted|true
+detectorSwitchFallthrough=SwitchFallthrough|true
+detectorSynchronizeAndNullCheckField=SynchronizeAndNullCheckField|true
+detectorSynchronizeOnClassLiteralNotGetClass=SynchronizeOnClassLiteralNotGetClass|true
+detectorSynchronizingOnContentsOfFieldToProtectField=SynchronizingOnContentsOfFieldToProtectField|true
+detectorURLProblems=URLProblems|true
+detectorUncallableMethodOfAnonymousClass=UncallableMethodOfAnonymousClass|true
+detectorUnnecessaryMath=UnnecessaryMath|true
+detectorUnreadFields=UnreadFields|true
+detectorUseObjectEquals=UseObjectEquals|false
+detectorUselessSubclassMethod=UselessSubclassMethod|false
+detectorVarArgsProblems=VarArgsProblems|true
+detectorVolatileUsage=VolatileUsage|true
+detectorWaitInLoop=WaitInLoop|true
+detectorWrongMapIterator=WrongMapIterator|true
+detectorXMLFactoryBypass=XMLFactoryBypass|true
+detector_threshold=2
+effort=default
+excludefilter0=findBugs/FindBugsExcludeFilter.xml
+filter_settings=Medium|BAD_PRACTICE,CORRECTNESS,MT_CORRECTNESS,PERFORMANCE,STYLE|false
+filter_settings_neg=MALICIOUS_CODE,NOISE,I18N,SECURITY,EXPERIMENTAL|
+run_at_full_build=true
diff --git a/org.eclipse.jgit.ssh.jsch/.gitignore b/org.eclipse.jgit.ssh.jsch/.gitignore
new file mode 100644
index 0000000000..934e0e06ff
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/.gitignore
@@ -0,0 +1,2 @@
+/bin
+/target
diff --git a/org.eclipse.jgit.ssh.jsch/.project b/org.eclipse.jgit.ssh.jsch/.project
new file mode 100644
index 0000000000..c29a38cb54
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.jgit.ssh.jsch</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.core.resources.prefs b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000000..99f26c0203
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000000..5a0ad22d2a
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..15ef2aad5d
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,399 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jgit.annotations.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jgit.annotations.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jgit.annotations.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=warning
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=error
+org.eclipse.jdt.core.compiler.problem.deadCode=error
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=error
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=error
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=error
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
+org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=1
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000..fef3713825
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,66 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_JGit Format
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.mylyn.tasks.ui.prefs b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.mylyn.tasks.ui.prefs
new file mode 100644
index 0000000000..3dec4d97c7
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.mylyn.tasks.ui.prefs
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+project.repository.kind=bugzilla
+project.repository.url=https\://bugs.eclipse.org/bugs
diff --git a/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.mylyn.team.ui.prefs b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.mylyn.team.ui.prefs
new file mode 100644
index 0000000000..ce7a0f0478
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.mylyn.team.ui.prefs
@@ -0,0 +1,2 @@
+commit.comment.template=${task.description} \n\nBug\: ${task.key}
+eclipse.preferences.version=1
diff --git a/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.pde.api.tools.prefs b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.pde.api.tools.prefs
new file mode 100644
index 0000000000..c0030ded71
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.pde.api.tools.prefs
@@ -0,0 +1,104 @@
+ANNOTATION_ELEMENT_TYPE_ADDED_FIELD=Error
+ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
+ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+API_USE_SCAN_FIELD_SEVERITY=Error
+API_USE_SCAN_METHOD_SEVERITY=Error
+API_USE_SCAN_TYPE_SEVERITY=Error
+CLASS_ELEMENT_TYPE_ADDED_FIELD=Error
+CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
+CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error
+CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error
+CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error
+CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error
+ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error
+ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error
+ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+FIELD_ELEMENT_TYPE_ADDED_VALUE=Error
+FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error
+FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error
+FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error
+FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error
+ILLEGAL_EXTEND=Warning
+ILLEGAL_IMPLEMENT=Warning
+ILLEGAL_INSTANTIATE=Warning
+ILLEGAL_OVERRIDE=Warning
+ILLEGAL_REFERENCE=Warning
+INTERFACE_ELEMENT_TYPE_ADDED_DEFAULT_METHOD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_ANNOTATION=Ignore
+INVALID_JAVADOC_TAG=Ignore
+INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error
+LEAK_EXTEND=Warning
+LEAK_FIELD_DECL=Warning
+LEAK_IMPLEMENT=Warning
+LEAK_METHOD_PARAM=Warning
+LEAK_METHOD_RETURN_TYPE=Warning
+METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
+METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+MISSING_EE_DESCRIPTIONS=Warning
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
+UNUSED_PROBLEM_FILTERS=Warning
+automatically_removed_unused_problem_filters=false
+changed_execution_env=Error
+eclipse.preferences.version=1
+incompatible_api_component_version=Error
+incompatible_api_component_version_include_major_without_breaking_change=Disabled
+incompatible_api_component_version_include_minor_without_api_change=Disabled
+incompatible_api_component_version_report_major_without_breaking_change=Warning
+incompatible_api_component_version_report_minor_without_api_change=Ignore
+invalid_since_tag_version=Error
+malformed_since_tag=Error
+missing_since_tag=Error
+report_api_breakage_when_major_version_incremented=Disabled
+report_resolution_errors_api_component=Warning
diff --git a/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.pde.core.prefs b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 0000000000..923c37fb8d
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+resolve.requirebundle=false
diff --git a/org.eclipse.jgit.ssh.jsch/BUILD b/org.eclipse.jgit.ssh.jsch/BUILD
new file mode 100644
index 0000000000..4917e28e04
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/BUILD
@@ -0,0 +1,20 @@
+load("@rules_java//java:defs.bzl", "java_library")
+
+package(default_visibility = ["//visibility:public"])
+
+SRCS = glob(["src/**/*.java"])
+
+RESOURCES = glob(["resources/**"])
+
+java_library(
+ name = "ssh-jsch",
+ srcs = SRCS,
+ resource_strip_prefix = "org.eclipse.jgit.ssh.jsch/resources",
+ resources = RESOURCES,
+ deps = [
+ "//lib:jsch",
+ "//lib:jzlib",
+ "//lib:slf4j-api",
+ "//org.eclipse.jgit:jgit",
+ ],
+)
diff --git a/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..5ae5d4b303
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF
@@ -0,0 +1,26 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Automatic-Module-Name: org.eclipse.jgit.ssh.jsch
+Bundle-SymbolicName: org.eclipse.jgit.ssh.jsch;singleton:=true
+Fragment-Host: org.eclipse.jgit;bundle-version="5.8.0.qualifier"
+Bundle-Vendor: %Bundle-Vendor
+Bundle-Localization: plugin
+Bundle-ActivationPolicy: lazy
+Bundle-Version: 5.8.0.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Export-Package: org.eclipse.jgit.internal.transport.jsch;version="5.8.0";x-friends:="org.eclipse.egit.core",
+ org.eclipse.jgit.transport;version="5.8.0";
+ uses:="org.eclipse.jgit.transport,
+ org.eclipse.jgit.internal.transport.ssh,
+ org.eclipse.jgit.util,
+ com.jcraft.jsch"
+Import-Package: com.jcraft.jsch;version="[0.1.37,0.2.0)",
+ org.eclipse.jgit.errors;version="[5.8.0,5.9.0)",
+ org.eclipse.jgit.internal;version="[5.8.0,5.9.0)",
+ org.eclipse.jgit.internal.transport.ssh;version="[5.8.0,5.9.0)",
+ org.eclipse.jgit.nls;version="[5.8.0,5.9.0)",
+ org.eclipse.jgit.transport;version="[5.8.0,5.9.0)",
+ org.eclipse.jgit.util;version="[5.8.0,5.9.0)",
+ org.eclipse.jgit.util.io;version="[5.8.0,5.9.0)",
+ org.slf4j;version="[1.7.0,2.0.0)"
diff --git a/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF
new file mode 100644
index 0000000000..35b27810c5
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF
@@ -0,0 +1,7 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: org.eclipse.jgit.ssh.jsch - Sources
+Bundle-SymbolicName: org.eclipse.jgit.ssh.jsch.source
+Bundle-Vendor: Eclipse.org - JGit
+Bundle-Version: 5.8.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.ssh.jsch;version="5.8.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.ssh.jsch/about.html b/org.eclipse.jgit.ssh.jsch/about.html
new file mode 100644
index 0000000000..f971af18d0
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/about.html
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Distribution License - Version 1.0</title>
+<style type="text/css">
+ body {
+ size: 8.5in 11.0in;
+ margin: 0.25in 0.5in 0.25in 0.5in;
+ tab-interval: 0.5in;
+ }
+ p {
+ margin-left: auto;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ }
+ p.list {
+ margin-left: 0.5in;
+ margin-top: 0.05em;
+ margin-bottom: 0.05em;
+ }
+ .ubc-name {
+ margin-left: 0.5in;
+ white-space: pre;
+ }
+ </style>
+
+</head>
+
+<body lang="EN-US">
+
+<p><b>Eclipse Distribution License - v 1.0</b></p>
+
+<p>Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors. </p>
+
+<p>All rights reserved.</p>
+<p>Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+<ul><li>Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer. </li>
+<li>Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution. </li>
+<li>Neither the name of the Eclipse Foundation, Inc. nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission. </li></ul>
+</p>
+<p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.</p>
+
+<hr>
+<p><b>SHA-1 UbcCheck - MIT</b></p>
+
+<p>Copyright (c) 2017:</p>
+<div class="ubc-name">
+Marc Stevens
+Cryptology Group
+Centrum Wiskunde & Informatica
+P.O. Box 94079, 1090 GB Amsterdam, Netherlands
+marc@marc-stevens.nl
+</div>
+<div class="ubc-name">
+Dan Shumow
+Microsoft Research
+danshu@microsoft.com
+</div>
+<p>Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+</p>
+<ul><li>The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.</li></ul>
+<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.</p>
+
+</body>
+
+</html>
diff --git a/org.eclipse.jgit.ssh.jsch/build.properties b/org.eclipse.jgit.ssh.jsch/build.properties
new file mode 100644
index 0000000000..8148271ef3
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/build.properties
@@ -0,0 +1,7 @@
+source.. = src/,\
+ resources/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.properties,\
+ about.html
diff --git a/org.eclipse.jgit.ssh.jsch/plugin.properties b/org.eclipse.jgit.ssh.jsch/plugin.properties
new file mode 100644
index 0000000000..126709b961
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/plugin.properties
@@ -0,0 +1,2 @@
+Bundle-Name=JGit SSH support based on JSch
+Bundle-Vendor=Eclipse JGit
diff --git a/org.eclipse.jgit.ssh.jsch/pom.xml b/org.eclipse.jgit.ssh.jsch/pom.xml
new file mode 100644
index 0000000000..142ea28b1d
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/pom.xml
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2018, Thomas Wolf <thomas.wolf@paranor.ch> and others
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Distribution License v. 1.0 which is available at
+ http://www.eclipse.org/org/documents/edl-v10.php.
+
+ SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.eclipse.jgit</groupId>
+ <artifactId>org.eclipse.jgit-parent</artifactId>
+ <version>5.8.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.eclipse.jgit.ssh.jsch</artifactId>
+ <name>JGit - JSch-based SSH support</name>
+
+ <description>
+ SSH support for JGit based on JSch
+ </description>
+
+ <properties>
+ <translate-qualifier/>
+ <source-bundle-manifest>${project.build.directory}/META-INF/SOURCE-MANIFEST.MF</source-bundle-manifest>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jgit</groupId>
+ <artifactId>org.eclipse.jgit</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.jcraft</groupId>
+ <artifactId>jsch</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.jcraft</groupId>
+ <artifactId>jzlib</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <sourceDirectory>src/</sourceDirectory>
+
+ <resources>
+ <resource>
+ <directory>.</directory>
+ <includes>
+ <include>plugin.properties</include>
+ <include>about.html</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>resources/</directory>
+ </resource>
+ </resources>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>translate-source-qualifier</id>
+ <phase>generate-resources</phase>
+ <configuration>
+ <target>
+ <copy file="META-INF/SOURCE-MANIFEST.MF" tofile="${source-bundle-manifest}" overwrite="true" />
+ <replace file="${source-bundle-manifest}">
+ <replacefilter token=".qualifier" value=".${maven.build.timestamp}" />
+ </replace>
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <inherited>true</inherited>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <archive>
+ <manifestFile>${source-bundle-manifest}</manifestFile>
+ </archive>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifestFile>${bundle-manifest}</manifestFile>
+ </archive>
+ </configuration>
+ </plugin>
+
+ <!-- No previous version to compare to
+ <plugin>
+ <groupId>com.github.siom79.japicmp</groupId>
+ <artifactId>japicmp-maven-plugin</artifactId>
+ <version>${japicmp-version}</version>
+ <configuration>
+ <oldVersion>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>${project.artifactId}</artifactId>
+ <version>${jgit-last-release-version}</version>
+ </dependency>
+ </oldVersion>
+ <newVersion>
+ <file>
+ <path>${project.build.directory}/${project.artifactId}-${project.version}.jar</path>
+ </file>
+ </newVersion>
+ <parameter>
+ <onlyModified>true</onlyModified>
+ <includes>
+ <include>org.eclipse.jgit.*</include>
+ </includes>
+ <accessModifier>public</accessModifier>
+ <breakBuildOnModifications>false</breakBuildOnModifications>
+ <breakBuildOnBinaryIncompatibleModifications>false</breakBuildOnBinaryIncompatibleModifications>
+ <onlyBinaryIncompatible>false</onlyBinaryIncompatible>
+ <includeSynthetic>false</includeSynthetic>
+ <ignoreMissingClasses>false</ignoreMissingClasses>
+ <skipPomModules>true</skipPomModules>
+ </parameter>
+ <skip>false</skip>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>verify</phase>
+ <goals>
+ <goal>cmp</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ -->
+ </plugins>
+ </build>
+
+ <reporting>
+ <plugins>
+ <!-- No previous version to compare to
+ <plugin>
+ <groupId>com.github.siom79.japicmp</groupId>
+ <artifactId>japicmp-maven-plugin</artifactId>
+ <version>${japicmp-version}</version>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>cmp-report</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ <configuration>
+ <oldVersion>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>${project.artifactId}</artifactId>
+ <version>${jgit-last-release-version}</version>
+ </dependency>
+ </oldVersion>
+ <newVersion>
+ <file>
+ <path>${project.build.directory}/${project.artifactId}-${project.version}.jar</path>
+ </file>
+ </newVersion>
+ <parameter>
+ <onlyModified>true</onlyModified>
+ <includes>
+ <include>org.eclipse.jgit.*</include>
+ </includes>
+ <accessModifier>public</accessModifier>
+ <breakBuildOnModifications>false</breakBuildOnModifications>
+ <breakBuildOnBinaryIncompatibleModifications>false</breakBuildOnBinaryIncompatibleModifications>
+ <onlyBinaryIncompatible>false</onlyBinaryIncompatible>
+ <includeSynthetic>false</includeSynthetic>
+ <ignoreMissingClasses>false</ignoreMissingClasses>
+ <skipPomModules>true</skipPomModules>
+ </parameter>
+ <skip>false</skip>
+ </configuration>
+ </plugin>
+ -->
+ </plugins>
+ </reporting>
+</project>
diff --git a/org.eclipse.jgit.ssh.jsch/resources/META-INF/services/org.eclipse.jgit.transport.SshSessionFactory b/org.eclipse.jgit.ssh.jsch/resources/META-INF/services/org.eclipse.jgit.transport.SshSessionFactory
new file mode 100644
index 0000000000..81927466bb
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/resources/META-INF/services/org.eclipse.jgit.transport.SshSessionFactory
@@ -0,0 +1 @@
+org.eclipse.jgit.transport.JschConfigSessionFactory
diff --git a/org.eclipse.jgit.ssh.jsch/resources/org/eclipse/jgit/internal/transport/jsch/JSchText.properties b/org.eclipse.jgit.ssh.jsch/resources/org/eclipse/jgit/internal/transport/jsch/JSchText.properties
new file mode 100644
index 0000000000..529e9f488c
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/resources/org/eclipse/jgit/internal/transport/jsch/JSchText.properties
@@ -0,0 +1,4 @@
+connectionFailed=connection failed
+sshUserNameError=Jsch error: failed to set SSH user name correctly to ''{0}''; using ''{1}'' picked up from SSH config file.
+transportSSHRetryInterrupt=Interrupted while waiting for retry
+unknownHost=unknown host
diff --git a/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/internal/transport/jsch/JSchText.java b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/internal/transport/jsch/JSchText.java
new file mode 100644
index 0000000000..4d4c9cb250
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/internal/transport/jsch/JSchText.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020, Michael Dardis <git@md-5.net> and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.transport.jsch;
+
+import org.eclipse.jgit.nls.NLS;
+import org.eclipse.jgit.nls.TranslationBundle;
+
+/**
+ * Externalized text messages for localization.
+ */
+public final class JSchText extends TranslationBundle {
+
+ /**
+ * Get an instance of this translation bundle.
+ *
+ * @return an instance of this translation bundle
+ */
+ public static JSchText get() {
+ return NLS.getBundleFor(JSchText.class);
+ }
+
+ // @formatter:off
+ /***/ public String connectionFailed;
+ /***/ public String sshUserNameError;
+ /***/ public String transportSSHRetryInterrupt;
+ /***/ public String unknownHost;
+
+}
diff --git a/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/CredentialsProviderUserInfo.java b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/CredentialsProviderUserInfo.java
new file mode 100644
index 0000000000..01adcf30b0
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/CredentialsProviderUserInfo.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2010, Google Inc. and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+//TODO(ms): move to org.eclipse.jgit.ssh.jsch in 6.0
+package org.eclipse.jgit.transport;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.UIKeyboardInteractive;
+import com.jcraft.jsch.UserInfo;
+
+/**
+ * A JSch {@link com.jcraft.jsch.UserInfo} adapter for a
+ * {@link org.eclipse.jgit.transport.CredentialsProvider}.
+ */
+public class CredentialsProviderUserInfo implements UserInfo,
+ UIKeyboardInteractive {
+ private final URIish uri;
+
+ private final CredentialsProvider provider;
+
+ private String password;
+
+ private String passphrase;
+
+ /**
+ * Wrap a CredentialsProvider to make it suitable for use with JSch.
+ *
+ * @param session
+ * the JSch session this UserInfo will support authentication on.
+ * @param credentialsProvider
+ * the provider that will perform the authentication.
+ */
+ public CredentialsProviderUserInfo(Session session,
+ CredentialsProvider credentialsProvider) {
+ this.uri = createURI(session);
+ this.provider = credentialsProvider;
+ }
+
+ private static URIish createURI(Session session) {
+ URIish uri = new URIish();
+ uri = uri.setScheme("ssh"); //$NON-NLS-1$
+ uri = uri.setUser(session.getUserName());
+ uri = uri.setHost(session.getHost());
+ uri = uri.setPort(session.getPort());
+ return uri;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getPassword() {
+ return password;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getPassphrase() {
+ return passphrase;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean promptPassphrase(String msg) {
+ CredentialItem.StringType v = newPrompt(msg);
+ if (provider.get(uri, v)) {
+ passphrase = v.getValue();
+ return true;
+ }
+ passphrase = null;
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean promptPassword(String msg) {
+ CredentialItem.Password p = new CredentialItem.Password(msg);
+ if (provider.get(uri, p)) {
+ password = new String(p.getValue());
+ return true;
+ }
+ password = null;
+ return false;
+ }
+
+ private CredentialItem.StringType newPrompt(String msg) {
+ return new CredentialItem.StringType(msg, true);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean promptYesNo(String msg) {
+ CredentialItem.YesNoType v = new CredentialItem.YesNoType(msg);
+ return provider.get(uri, v) && v.getValue();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void showMessage(String msg) {
+ provider.get(uri, new CredentialItem.InformationalMessage(msg));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String[] promptKeyboardInteractive(String destination, String name,
+ String instruction, String[] prompt, boolean[] echo) {
+ CredentialItem.StringType[] v = new CredentialItem.StringType[prompt.length];
+ for (int i = 0; i < prompt.length; i++)
+ v[i] = new CredentialItem.StringType(prompt[i], !echo[i]);
+
+ List<CredentialItem> items = new ArrayList<>();
+ if (instruction != null && instruction.length() > 0)
+ items.add(new CredentialItem.InformationalMessage(instruction));
+ items.addAll(Arrays.asList(v));
+
+ if (!provider.get(uri, items))
+ return null; // cancel
+
+ String[] result = new String[v.length];
+ for (int i = 0; i < v.length; i++)
+ result[i] = v[i].getValue();
+ return result;
+ }
+}
diff --git a/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java
new file mode 100644
index 0000000000..88202dd2d6
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschConfigSessionFactory.java
@@ -0,0 +1,541 @@
+/*
+ * Copyright (C) 2018, Sasa Zivkov <sasa.zivkov@sap.com>
+ * Copyright (C) 2016, Mark Ingram <markdingram@gmail.com>
+ * Copyright (C) 2009, Constantine Plotnikov <constantine.plotnikov@gmail.com>
+ * Copyright (C) 2008-2009, Google Inc.
+ * Copyright (C) 2009, Google, Inc.
+ * Copyright (C) 2009, JetBrains s.r.o.
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+//TODO(ms): move to org.eclipse.jgit.ssh.jsch in 6.0
+package org.eclipse.jgit.transport;
+
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toList;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.ConnectException;
+import java.net.UnknownHostException;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
+
+import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.internal.transport.jsch.JSchText;
+import org.eclipse.jgit.util.FS;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.jcraft.jsch.ConfigRepository;
+import com.jcraft.jsch.ConfigRepository.Config;
+import com.jcraft.jsch.HostKey;
+import com.jcraft.jsch.HostKeyRepository;
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+
+/**
+ * The base session factory that loads known hosts and private keys from
+ * <code>$HOME/.ssh</code>.
+ * <p>
+ * This is the default implementation used by JGit and provides most of the
+ * compatibility necessary to match OpenSSH, a popular implementation of SSH
+ * used by C Git.
+ * <p>
+ * The factory does not provide UI behavior. Override the method
+ * {@link #configure(org.eclipse.jgit.transport.OpenSshConfig.Host, Session)} to
+ * supply appropriate {@link com.jcraft.jsch.UserInfo} to the session.
+ */
+public class JschConfigSessionFactory extends SshSessionFactory {
+
+ private static final String JSCH = "jsch"; //$NON-NLS-1$
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(JschConfigSessionFactory.class);
+
+ /**
+ * We use different Jsch instances for hosts that have an IdentityFile
+ * configured in ~/.ssh/config. Jsch by default would cache decrypted keys
+ * only per session, which results in repeated password prompts. Using
+ * different Jsch instances, we can cache the keys on these instances so
+ * that they will be re-used for successive sessions, and thus the user is
+ * prompted for a key password only once while Eclipse runs.
+ */
+ private final Map<String, JSch> byIdentityFile = new HashMap<>();
+
+ private JSch defaultJSch;
+
+ private OpenSshConfig config;
+
+ /** {@inheritDoc} */
+ @Override
+ public synchronized RemoteSession getSession(URIish uri,
+ CredentialsProvider credentialsProvider, FS fs, int tms)
+ throws TransportException {
+
+ String user = uri.getUser();
+ final String pass = uri.getPass();
+ String host = uri.getHost();
+ int port = uri.getPort();
+
+ try {
+ if (config == null)
+ config = OpenSshConfig.get(fs);
+
+ final OpenSshConfig.Host hc = config.lookup(host);
+ if (port <= 0)
+ port = hc.getPort();
+ if (user == null)
+ user = hc.getUser();
+
+ Session session = createSession(credentialsProvider, fs, user,
+ pass, host, port, hc);
+
+ int retries = 0;
+ while (!session.isConnected()) {
+ try {
+ retries++;
+ session.connect(tms);
+ } catch (JSchException e) {
+ session.disconnect();
+ session = null;
+ // Make sure our known_hosts is not outdated
+ knownHosts(getJSch(hc, fs), fs);
+
+ if (isAuthenticationCanceled(e)) {
+ throw e;
+ } else if (isAuthenticationFailed(e)
+ && credentialsProvider != null) {
+ // if authentication failed maybe credentials changed at
+ // the remote end therefore reset credentials and retry
+ if (retries < 3) {
+ credentialsProvider.reset(uri);
+ session = createSession(credentialsProvider, fs,
+ user, pass, host, port, hc);
+ } else
+ throw e;
+ } else if (retries >= hc.getConnectionAttempts()) {
+ throw e;
+ } else {
+ try {
+ Thread.sleep(1000);
+ session = createSession(credentialsProvider, fs,
+ user, pass, host, port, hc);
+ } catch (InterruptedException e1) {
+ throw new TransportException(
+ JSchText.get().transportSSHRetryInterrupt,
+ e1);
+ }
+ }
+ }
+ }
+
+ return new JschSession(session, uri);
+
+ } catch (JSchException je) {
+ final Throwable c = je.getCause();
+ if (c instanceof UnknownHostException) {
+ throw new TransportException(uri,
+ JSchText.get().unknownHost,
+ je);
+ }
+ if (c instanceof ConnectException) {
+ throw new TransportException(uri, c.getMessage(), je);
+ }
+ throw new TransportException(uri, je.getMessage(), je);
+ }
+
+ }
+
+ @Override
+ public String getType() {
+ return JSCH;
+ }
+
+ private static boolean isAuthenticationFailed(JSchException e) {
+ return e.getCause() == null && e.getMessage().equals("Auth fail"); //$NON-NLS-1$
+ }
+
+ private static boolean isAuthenticationCanceled(JSchException e) {
+ return e.getCause() == null && e.getMessage().equals("Auth cancel"); //$NON-NLS-1$
+ }
+
+ // Package visibility for tests
+ Session createSession(CredentialsProvider credentialsProvider,
+ FS fs, String user, final String pass, String host, int port,
+ final OpenSshConfig.Host hc) throws JSchException {
+ final Session session = createSession(hc, user, host, port, fs);
+ // Jsch will have overridden the explicit user by the one from the SSH
+ // config file...
+ setUserName(session, user);
+ // Jsch will also have overridden the port.
+ if (port > 0 && port != session.getPort()) {
+ session.setPort(port);
+ }
+ // We retry already in getSession() method. JSch must not retry
+ // on its own.
+ session.setConfig("MaxAuthTries", "1"); //$NON-NLS-1$ //$NON-NLS-2$
+ if (pass != null)
+ session.setPassword(pass);
+ final String strictHostKeyCheckingPolicy = hc
+ .getStrictHostKeyChecking();
+ if (strictHostKeyCheckingPolicy != null)
+ session.setConfig("StrictHostKeyChecking", //$NON-NLS-1$
+ strictHostKeyCheckingPolicy);
+ final String pauth = hc.getPreferredAuthentications();
+ if (pauth != null)
+ session.setConfig("PreferredAuthentications", pauth); //$NON-NLS-1$
+ if (credentialsProvider != null
+ && (!hc.isBatchMode() || !credentialsProvider.isInteractive())) {
+ session.setUserInfo(new CredentialsProviderUserInfo(session,
+ credentialsProvider));
+ }
+ safeConfig(session, hc.getConfig());
+ if (hc.getConfig().getValue("HostKeyAlgorithms") == null) { //$NON-NLS-1$
+ setPreferredKeyTypesOrder(session);
+ }
+ configure(hc, session);
+ return session;
+ }
+
+ private void safeConfig(Session session, Config cfg) {
+ // Ensure that Jsch checks all configured algorithms, not just its
+ // built-in ones. Otherwise it may propose an algorithm for which it
+ // doesn't have an implementation, and then run into an NPE if that
+ // algorithm ends up being chosen.
+ copyConfigValueToSession(session, cfg, "Ciphers", "CheckCiphers"); //$NON-NLS-1$ //$NON-NLS-2$
+ copyConfigValueToSession(session, cfg, "KexAlgorithms", "CheckKexes"); //$NON-NLS-1$ //$NON-NLS-2$
+ copyConfigValueToSession(session, cfg, "HostKeyAlgorithms", //$NON-NLS-1$
+ "CheckSignatures"); //$NON-NLS-1$
+ }
+
+ private static void setPreferredKeyTypesOrder(Session session) {
+ HostKeyRepository hkr = session.getHostKeyRepository();
+ HostKey[] hostKeys = hkr.getHostKey(hostName(session), null);
+
+ if (hostKeys == null) {
+ return;
+ }
+
+ List<String> known = Stream.of(hostKeys)
+ .map(HostKey::getType)
+ .collect(toList());
+
+ if (!known.isEmpty()) {
+ String serverHostKey = "server_host_key"; //$NON-NLS-1$
+ String current = session.getConfig(serverHostKey);
+ if (current == null) {
+ session.setConfig(serverHostKey, String.join(",", known)); //$NON-NLS-1$
+ return;
+ }
+
+ String knownFirst = Stream.concat(
+ known.stream(),
+ Stream.of(current.split(",")) //$NON-NLS-1$
+ .filter(s -> !known.contains(s)))
+ .collect(joining(",")); //$NON-NLS-1$
+ session.setConfig(serverHostKey, knownFirst);
+ }
+ }
+
+ private static String hostName(Session s) {
+ if (s.getPort() == SshConstants.SSH_DEFAULT_PORT) {
+ return s.getHost();
+ }
+ return String.format("[%s]:%d", s.getHost(), //$NON-NLS-1$
+ Integer.valueOf(s.getPort()));
+ }
+
+ private void copyConfigValueToSession(Session session, Config cfg,
+ String from, String to) {
+ String value = cfg.getValue(from);
+ if (value != null) {
+ session.setConfig(to, value);
+ }
+ }
+
+ private void setUserName(Session session, String userName) {
+ // Jsch 0.1.54 picks up the user name from the ssh config, even if an
+ // explicit user name was given! We must correct that if ~/.ssh/config
+ // has a different user name.
+ if (userName == null || userName.isEmpty()
+ || userName.equals(session.getUserName())) {
+ return;
+ }
+ try {
+ Class<?>[] parameterTypes = { String.class };
+ Method method = Session.class.getDeclaredMethod("setUserName", //$NON-NLS-1$
+ parameterTypes);
+ method.setAccessible(true);
+ method.invoke(session, userName);
+ } catch (NullPointerException | IllegalAccessException
+ | IllegalArgumentException | InvocationTargetException
+ | NoSuchMethodException | SecurityException e) {
+ LOG.error(MessageFormat.format(JSchText.get().sshUserNameError,
+ userName, session.getUserName()), e);
+ }
+ }
+
+ /**
+ * Create a new remote session for the requested address.
+ *
+ * @param hc
+ * host configuration
+ * @param user
+ * login to authenticate as.
+ * @param host
+ * server name to connect to.
+ * @param port
+ * port number of the SSH daemon (typically 22).
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
+ * @return new session instance, but otherwise unconfigured.
+ * @throws com.jcraft.jsch.JSchException
+ * the session could not be created.
+ */
+ protected Session createSession(final OpenSshConfig.Host hc,
+ final String user, final String host, final int port, FS fs)
+ throws JSchException {
+ return getJSch(hc, fs).getSession(user, host, port);
+ }
+
+ /**
+ * Provide additional configuration for the JSch instance. This method could
+ * be overridden to supply a preferred
+ * {@link com.jcraft.jsch.IdentityRepository}.
+ *
+ * @param jsch
+ * jsch instance
+ * @since 4.5
+ */
+ protected void configureJSch(JSch jsch) {
+ // No additional configuration required.
+ }
+
+ /**
+ * Provide additional configuration for the session based on the host
+ * information. This method could be used to supply
+ * {@link com.jcraft.jsch.UserInfo}.
+ *
+ * @param hc
+ * host configuration
+ * @param session
+ * session to configure
+ */
+ protected void configure(OpenSshConfig.Host hc, Session session) {
+ // No additional configuration required.
+ }
+
+ /**
+ * Obtain the JSch used to create new sessions.
+ *
+ * @param hc
+ * host configuration
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
+ * @return the JSch instance to use.
+ * @throws com.jcraft.jsch.JSchException
+ * the user configuration could not be created.
+ */
+ protected JSch getJSch(OpenSshConfig.Host hc, FS fs) throws JSchException {
+ if (defaultJSch == null) {
+ defaultJSch = createDefaultJSch(fs);
+ if (defaultJSch.getConfigRepository() == null) {
+ defaultJSch.setConfigRepository(
+ new JschBugFixingConfigRepository(config));
+ }
+ for (Object name : defaultJSch.getIdentityNames())
+ byIdentityFile.put((String) name, defaultJSch);
+ }
+
+ final File identityFile = hc.getIdentityFile();
+ if (identityFile == null)
+ return defaultJSch;
+
+ final String identityKey = identityFile.getAbsolutePath();
+ JSch jsch = byIdentityFile.get(identityKey);
+ if (jsch == null) {
+ jsch = new JSch();
+ configureJSch(jsch);
+ if (jsch.getConfigRepository() == null) {
+ jsch.setConfigRepository(defaultJSch.getConfigRepository());
+ }
+ jsch.setHostKeyRepository(defaultJSch.getHostKeyRepository());
+ jsch.addIdentity(identityKey);
+ byIdentityFile.put(identityKey, jsch);
+ }
+ return jsch;
+ }
+
+ /**
+ * Create default instance of jsch
+ *
+ * @param fs
+ * the file system abstraction which will be necessary to perform
+ * certain file system operations.
+ * @return the new default JSch implementation.
+ * @throws com.jcraft.jsch.JSchException
+ * known host keys cannot be loaded.
+ */
+ protected JSch createDefaultJSch(FS fs) throws JSchException {
+ final JSch jsch = new JSch();
+ JSch.setConfig("ssh-rsa", JSch.getConfig("signature.rsa")); //$NON-NLS-1$ //$NON-NLS-2$
+ JSch.setConfig("ssh-dss", JSch.getConfig("signature.dss")); //$NON-NLS-1$ //$NON-NLS-2$
+ configureJSch(jsch);
+ knownHosts(jsch, fs);
+ identities(jsch, fs);
+ return jsch;
+ }
+
+ private static void knownHosts(JSch sch, FS fs) throws JSchException {
+ final File home = fs.userHome();
+ if (home == null)
+ return;
+ final File known_hosts = new File(new File(home, ".ssh"), "known_hosts"); //$NON-NLS-1$ //$NON-NLS-2$
+ try (FileInputStream in = new FileInputStream(known_hosts)) {
+ sch.setKnownHosts(in);
+ } catch (FileNotFoundException none) {
+ // Oh well. They don't have a known hosts in home.
+ } catch (IOException err) {
+ // Oh well. They don't have a known hosts in home.
+ }
+ }
+
+ private static void identities(JSch sch, FS fs) {
+ final File home = fs.userHome();
+ if (home == null)
+ return;
+ final File sshdir = new File(home, ".ssh"); //$NON-NLS-1$
+ if (sshdir.isDirectory()) {
+ loadIdentity(sch, new File(sshdir, "identity")); //$NON-NLS-1$
+ loadIdentity(sch, new File(sshdir, "id_rsa")); //$NON-NLS-1$
+ loadIdentity(sch, new File(sshdir, "id_dsa")); //$NON-NLS-1$
+ }
+ }
+
+ private static void loadIdentity(JSch sch, File priv) {
+ if (priv.isFile()) {
+ try {
+ sch.addIdentity(priv.getAbsolutePath());
+ } catch (JSchException e) {
+ // Instead, pretend the key doesn't exist.
+ }
+ }
+ }
+
+ private static class JschBugFixingConfigRepository
+ implements ConfigRepository {
+
+ private final ConfigRepository base;
+
+ public JschBugFixingConfigRepository(ConfigRepository base) {
+ this.base = base;
+ }
+
+ @Override
+ public Config getConfig(String host) {
+ return new JschBugFixingConfig(base.getConfig(host));
+ }
+
+ /**
+ * A {@link com.jcraft.jsch.ConfigRepository.Config} that transforms
+ * some values from the config file into the format Jsch 0.1.54 expects.
+ * This is a work-around for bugs in Jsch.
+ * <p>
+ * Additionally, this config hides the IdentityFile config entries from
+ * Jsch; we manage those ourselves. Otherwise Jsch would cache passwords
+ * (or rather, decrypted keys) only for a single session, resulting in
+ * multiple password prompts for user operations that use several Jsch
+ * sessions.
+ */
+ private static class JschBugFixingConfig implements Config {
+
+ private static final String[] NO_IDENTITIES = {};
+
+ private final Config real;
+
+ public JschBugFixingConfig(Config delegate) {
+ real = delegate;
+ }
+
+ @Override
+ public String getHostname() {
+ return real.getHostname();
+ }
+
+ @Override
+ public String getUser() {
+ return real.getUser();
+ }
+
+ @Override
+ public int getPort() {
+ return real.getPort();
+ }
+
+ @Override
+ public String getValue(String key) {
+ String k = key.toUpperCase(Locale.ROOT);
+ if ("IDENTITYFILE".equals(k)) { //$NON-NLS-1$
+ return null;
+ }
+ String result = real.getValue(key);
+ if (result != null) {
+ if ("SERVERALIVEINTERVAL".equals(k) //$NON-NLS-1$
+ || "CONNECTTIMEOUT".equals(k)) { //$NON-NLS-1$
+ // These values are in seconds. Jsch 0.1.54 passes them
+ // on as is to java.net.Socket.setSoTimeout(), which
+ // expects milliseconds. So convert here to
+ // milliseconds.
+ try {
+ int timeout = Integer.parseInt(result);
+ result = Long.toString(
+ TimeUnit.SECONDS.toMillis(timeout));
+ } catch (NumberFormatException e) {
+ // Ignore
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public String[] getValues(String key) {
+ String k = key.toUpperCase(Locale.ROOT);
+ if ("IDENTITYFILE".equals(k)) { //$NON-NLS-1$
+ return NO_IDENTITIES;
+ }
+ return real.getValues(key);
+ }
+ }
+ }
+
+ /**
+ * Set the {@link OpenSshConfig} to use. Intended for use in tests.
+ *
+ * @param config
+ * to use
+ */
+ synchronized void setConfig(OpenSshConfig config) {
+ this.config = config;
+ }
+}
diff --git a/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschSession.java b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschSession.java
new file mode 100644
index 0000000000..300e03d798
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/JschSession.java
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2009, Constantine Plotnikov <constantine.plotnikov@gmail.com>
+ * Copyright (C) 2008-2009, Google Inc.
+ * Copyright (C) 2009, Google, Inc.
+ * Copyright (C) 2009, JetBrains s.r.o.
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+//TODO(ms): move to org.eclipse.jgit.ssh.jsch in 6.0
+package org.eclipse.jgit.transport;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.internal.transport.jsch.JSchText;
+import org.eclipse.jgit.util.io.IsolatedOutputStream;
+
+import com.jcraft.jsch.Channel;
+import com.jcraft.jsch.ChannelExec;
+import com.jcraft.jsch.ChannelSftp;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.SftpException;
+
+/**
+ * Run remote commands using Jsch.
+ * <p>
+ * This class is the default session implementation using Jsch. Note that
+ * {@link org.eclipse.jgit.transport.JschConfigSessionFactory} is used to create
+ * the actual session passed to the constructor.
+ */
+public class JschSession implements RemoteSession {
+ final Session sock;
+ final URIish uri;
+
+ /**
+ * Create a new session object by passing the real Jsch session and the URI
+ * information.
+ *
+ * @param session
+ * the real Jsch session created elsewhere.
+ * @param uri
+ * the URI information for the remote connection
+ */
+ public JschSession(Session session, URIish uri) {
+ sock = session;
+ this.uri = uri;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Process exec(String command, int timeout) throws IOException {
+ return new JschProcess(command, timeout);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void disconnect() {
+ if (sock.isConnected())
+ sock.disconnect();
+ }
+
+ /**
+ * A kludge to allow {@link org.eclipse.jgit.transport.TransportSftp} to get
+ * an Sftp channel from Jsch. Ideally, this method would be generic, which
+ * would require implementing generic Sftp channel operations in the
+ * RemoteSession class.
+ *
+ * @return a channel suitable for Sftp operations.
+ * @throws com.jcraft.jsch.JSchException
+ * on problems getting the channel.
+ * @deprecated since 5.2; use {@link #getFtpChannel()} instead
+ */
+ @Deprecated
+ public Channel getSftpChannel() throws JSchException {
+ return sock.openChannel("sftp"); //$NON-NLS-1$
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 5.2
+ */
+ @Override
+ public FtpChannel getFtpChannel() {
+ return new JschFtpChannel();
+ }
+
+ /**
+ * Implementation of Process for running a single command using Jsch.
+ * <p>
+ * Uses the Jsch session to do actual command execution and manage the
+ * execution.
+ */
+ private class JschProcess extends Process {
+ private ChannelExec channel;
+
+ final int timeout;
+
+ private InputStream inputStream;
+
+ private OutputStream outputStream;
+
+ private InputStream errStream;
+
+ /**
+ * Opens a channel on the session ("sock") for executing the given
+ * command, opens streams, and starts command execution.
+ *
+ * @param commandName
+ * the command to execute
+ * @param tms
+ * the timeout value, in seconds, for the command.
+ * @throws TransportException
+ * on problems opening a channel or connecting to the remote
+ * host
+ * @throws IOException
+ * on problems opening streams
+ */
+ JschProcess(String commandName, int tms)
+ throws TransportException, IOException {
+ timeout = tms;
+ try {
+ channel = (ChannelExec) sock.openChannel("exec"); //$NON-NLS-1$
+ channel.setCommand(commandName);
+ setupStreams();
+ channel.connect(timeout > 0 ? timeout * 1000 : 0);
+ if (!channel.isConnected()) {
+ closeOutputStream();
+ throw new TransportException(uri,
+ JSchText.get().connectionFailed);
+ }
+ } catch (JSchException e) {
+ closeOutputStream();
+ throw new TransportException(uri, e.getMessage(), e);
+ }
+ }
+
+ private void closeOutputStream() {
+ if (outputStream != null) {
+ try {
+ outputStream.close();
+ } catch (IOException ioe) {
+ // ignore
+ }
+ }
+ }
+
+ private void setupStreams() throws IOException {
+ inputStream = channel.getInputStream();
+
+ // JSch won't let us interrupt writes when we use our InterruptTimer
+ // to break out of a long-running write operation. To work around
+ // that we spawn a background thread to shuttle data through a pipe,
+ // as we can issue an interrupted write out of that. Its slower, so
+ // we only use this route if there is a timeout.
+ OutputStream out = channel.getOutputStream();
+ if (timeout <= 0) {
+ outputStream = out;
+ } else {
+ IsolatedOutputStream i = new IsolatedOutputStream(out);
+ outputStream = new BufferedOutputStream(i, 16 * 1024);
+ }
+
+ errStream = channel.getErrStream();
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ return inputStream;
+ }
+
+ @Override
+ public OutputStream getOutputStream() {
+ return outputStream;
+ }
+
+ @Override
+ public InputStream getErrorStream() {
+ return errStream;
+ }
+
+ @Override
+ public int exitValue() {
+ if (isRunning())
+ throw new IllegalStateException();
+ return channel.getExitStatus();
+ }
+
+ private boolean isRunning() {
+ return channel.getExitStatus() < 0 && channel.isConnected();
+ }
+
+ @Override
+ public void destroy() {
+ if (channel.isConnected())
+ channel.disconnect();
+ closeOutputStream();
+ }
+
+ @Override
+ public int waitFor() throws InterruptedException {
+ while (isRunning())
+ Thread.sleep(100);
+ return exitValue();
+ }
+ }
+
+ private class JschFtpChannel implements FtpChannel {
+
+ private ChannelSftp ftp;
+
+ @Override
+ public void connect(int timeout, TimeUnit unit) throws IOException {
+ try {
+ ftp = (ChannelSftp) sock.openChannel("sftp"); //$NON-NLS-1$
+ ftp.connect((int) unit.toMillis(timeout));
+ } catch (JSchException e) {
+ ftp = null;
+ throw new IOException(e.getLocalizedMessage(), e);
+ }
+ }
+
+ @Override
+ public void disconnect() {
+ ftp.disconnect();
+ ftp = null;
+ }
+
+ private <T> T map(Callable<T> op) throws IOException {
+ try {
+ return op.call();
+ } catch (Exception e) {
+ if (e instanceof SftpException) {
+ throw new FtpChannel.FtpException(e.getLocalizedMessage(),
+ ((SftpException) e).id, e);
+ }
+ throw new IOException(e.getLocalizedMessage(), e);
+ }
+ }
+
+ @Override
+ public boolean isConnected() {
+ return ftp != null && sock.isConnected();
+ }
+
+ @Override
+ public void cd(String path) throws IOException {
+ map(() -> {
+ ftp.cd(path);
+ return null;
+ });
+ }
+
+ @Override
+ public String pwd() throws IOException {
+ return map(() -> ftp.pwd());
+ }
+
+ @Override
+ public Collection<DirEntry> ls(String path) throws IOException {
+ return map(() -> {
+ List<DirEntry> result = new ArrayList<>();
+ for (Object e : ftp.ls(path)) {
+ ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) e;
+ result.add(new DirEntry() {
+
+ @Override
+ public String getFilename() {
+ return entry.getFilename();
+ }
+
+ @Override
+ public long getModifiedTime() {
+ return entry.getAttrs().getMTime();
+ }
+
+ @Override
+ public boolean isDirectory() {
+ return entry.getAttrs().isDir();
+ }
+ });
+ }
+ return result;
+ });
+ }
+
+ @Override
+ public void rmdir(String path) throws IOException {
+ map(() -> {
+ ftp.rm(path);
+ return null;
+ });
+ }
+
+ @Override
+ public void mkdir(String path) throws IOException {
+ map(() -> {
+ ftp.mkdir(path);
+ return null;
+ });
+ }
+
+ @Override
+ public InputStream get(String path) throws IOException {
+ return map(() -> ftp.get(path));
+ }
+
+ @Override
+ public OutputStream put(String path) throws IOException {
+ return map(() -> ftp.put(path));
+ }
+
+ @Override
+ public void rm(String path) throws IOException {
+ map(() -> {
+ ftp.rm(path);
+ return null;
+ });
+ }
+
+ @Override
+ public void rename(String from, String to) throws IOException {
+ map(() -> {
+ // Plain FTP rename will fail if "to" exists. Jsch knows about
+ // the FTP extension "posix-rename@openssh.com", which will
+ // remove "to" first if it exists.
+ if (hasPosixRename()) {
+ ftp.rename(from, to);
+ } else if (!to.equals(from)) {
+ // Try to remove "to" first. With git, we typically get this
+ // when a lock file is moved over the file locked. Note that
+ // the check for to being equal to from may still fail in
+ // the general case, but for use with JGit's TransportSftp
+ // it should be good enough.
+ delete(to);
+ ftp.rename(from, to);
+ }
+ return null;
+ });
+ }
+
+ /**
+ * Determine whether the server has the posix-rename extension.
+ *
+ * @return {@code true} if it is supported, {@code false} otherwise
+ * @see <a href=
+ * "https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL?annotate=HEAD">OpenSSH
+ * deviations and extensions to the published SSH protocol</a>
+ * @see <a href=
+ * "http://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html">stdio.h:
+ * rename()</a>
+ */
+ private boolean hasPosixRename() {
+ return "1".equals(ftp.getExtension("posix-rename@openssh.com")); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ }
+}
diff --git a/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/OpenSshConfig.java b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/OpenSshConfig.java
new file mode 100644
index 0000000000..5c6c80c768
--- /dev/null
+++ b/org.eclipse.jgit.ssh.jsch/src/org/eclipse/jgit/transport/OpenSshConfig.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2008, 2018, Google Inc. and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+//TODO(ms): move to org.eclipse.jgit.ssh.jsch in 6.0
+package org.eclipse.jgit.transport;
+
+import static org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile.positive;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile;
+import org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile.HostEntry;
+import org.eclipse.jgit.util.FS;
+
+import com.jcraft.jsch.ConfigRepository;
+
+/**
+ * Fairly complete configuration parser for the OpenSSH ~/.ssh/config file.
+ * <p>
+ * JSch does have its own config file parser
+ * {@link com.jcraft.jsch.OpenSSHConfig} since version 0.1.50, but it has a
+ * number of problems:
+ * <ul>
+ * <li>it splits lines of the format "keyword = value" wrongly: you'd end up
+ * with the value "= value".
+ * <li>its "Host" keyword is not case insensitive.
+ * <li>it doesn't handle quoted values.
+ * <li>JSch's OpenSSHConfig doesn't monitor for config file changes.
+ * </ul>
+ * <p>
+ * This parser makes the critical options available to
+ * {@link org.eclipse.jgit.transport.SshSessionFactory} via
+ * {@link org.eclipse.jgit.transport.OpenSshConfig.Host} objects returned
+ * by {@link #lookup(String)}, and implements a fully conforming
+ * {@link com.jcraft.jsch.ConfigRepository} providing
+ * {@link com.jcraft.jsch.ConfigRepository.Config}s via
+ * {@link #getConfig(String)}.
+ * </p>
+ *
+ * @see OpenSshConfigFile
+ */
+public class OpenSshConfig implements ConfigRepository {
+
+ /**
+ * Obtain the user's configuration data.
+ * <p>
+ * The configuration file is always returned to the caller, even if no file
+ * exists in the user's home directory at the time the call was made. Lookup
+ * requests are cached and are automatically updated if the user modifies
+ * the configuration file since the last time it was cached.
+ *
+ * @param fs
+ * the file system abstraction which will be necessary to
+ * perform certain file system operations.
+ * @return a caching reader of the user's configuration file.
+ */
+ public static OpenSshConfig get(FS fs) {
+ File home = fs.userHome();
+ if (home == null)
+ home = new File(".").getAbsoluteFile(); //$NON-NLS-1$
+
+ final File config = new File(new File(home, SshConstants.SSH_DIR),
+ SshConstants.CONFIG);
+ return new OpenSshConfig(home, config);
+ }
+
+ /** The base file. */
+ private OpenSshConfigFile configFile;
+
+ OpenSshConfig(File h, File cfg) {
+ configFile = new OpenSshConfigFile(h, cfg,
+ SshSessionFactory.getLocalUserName());
+ }
+
+ /**
+ * Locate the configuration for a specific host request.
+ *
+ * @param hostName
+ * the name the user has supplied to the SSH tool. This may be a
+ * real host name, or it may just be a "Host" block in the
+ * configuration file.
+ * @return r configuration for the requested name. Never null.
+ */
+ public Host lookup(String hostName) {
+ HostEntry entry = configFile.lookup(hostName, -1, null);
+ return new Host(entry, hostName, configFile.getLocalUserName());
+ }
+
+ /**
+ * Configuration of one "Host" block in the configuration file.
+ * <p>
+ * If returned from {@link OpenSshConfig#lookup(String)} some or all of the
+ * properties may not be populated. The properties which are not populated
+ * should be defaulted by the caller.
+ * <p>
+ * When returned from {@link OpenSshConfig#lookup(String)} any wildcard
+ * entries which appear later in the configuration file will have been
+ * already merged into this block.
+ */
+ public static class Host {
+ String hostName;
+
+ int port;
+
+ File identityFile;
+
+ String user;
+
+ String preferredAuthentications;
+
+ Boolean batchMode;
+
+ String strictHostKeyChecking;
+
+ int connectionAttempts;
+
+ private HostEntry entry;
+
+ private Config config;
+
+ // See com.jcraft.jsch.OpenSSHConfig. Translates some command-line keys
+ // to ssh-config keys.
+ private static final Map<String, String> KEY_MAP = new TreeMap<>(
+ String.CASE_INSENSITIVE_ORDER);
+
+ static {
+ KEY_MAP.put("kex", SshConstants.KEX_ALGORITHMS); //$NON-NLS-1$
+ KEY_MAP.put("server_host_key", SshConstants.HOST_KEY_ALGORITHMS); //$NON-NLS-1$
+ KEY_MAP.put("cipher.c2s", SshConstants.CIPHERS); //$NON-NLS-1$
+ KEY_MAP.put("cipher.s2c", SshConstants.CIPHERS); //$NON-NLS-1$
+ KEY_MAP.put("mac.c2s", SshConstants.MACS); //$NON-NLS-1$
+ KEY_MAP.put("mac.s2c", SshConstants.MACS); //$NON-NLS-1$
+ KEY_MAP.put("compression.s2c", SshConstants.COMPRESSION); //$NON-NLS-1$
+ KEY_MAP.put("compression.c2s", SshConstants.COMPRESSION); //$NON-NLS-1$
+ KEY_MAP.put("compression_level", "CompressionLevel"); //$NON-NLS-1$ //$NON-NLS-2$
+ KEY_MAP.put("MaxAuthTries", //$NON-NLS-1$
+ SshConstants.NUMBER_OF_PASSWORD_PROMPTS);
+ }
+
+ private static String mapKey(String key) {
+ String k = KEY_MAP.get(key);
+ return k != null ? k : key;
+ }
+
+ /**
+ * Creates a new uninitialized {@link Host}.
+ */
+ public Host() {
+ // For API backwards compatibility with pre-4.9 JGit
+ }
+
+ Host(HostEntry entry, String hostName, String localUserName) {
+ this.entry = entry;
+ complete(hostName, localUserName);
+ }
+
+ /**
+ * @return the value StrictHostKeyChecking property, the valid values
+ * are "yes" (unknown hosts are not accepted), "no" (unknown
+ * hosts are always accepted), and "ask" (user should be asked
+ * before accepting the host)
+ */
+ public String getStrictHostKeyChecking() {
+ return strictHostKeyChecking;
+ }
+
+ /**
+ * @return the real IP address or host name to connect to; never null.
+ */
+ public String getHostName() {
+ return hostName;
+ }
+
+ /**
+ * @return the real port number to connect to; never 0.
+ */
+ public int getPort() {
+ return port;
+ }
+
+ /**
+ * @return path of the private key file to use for authentication; null
+ * if the caller should use default authentication strategies.
+ */
+ public File getIdentityFile() {
+ return identityFile;
+ }
+
+ /**
+ * @return the real user name to connect as; never null.
+ */
+ public String getUser() {
+ return user;
+ }
+
+ /**
+ * @return the preferred authentication methods, separated by commas if
+ * more than one authentication method is preferred.
+ */
+ public String getPreferredAuthentications() {
+ return preferredAuthentications;
+ }
+
+ /**
+ * @return true if batch (non-interactive) mode is preferred for this
+ * host connection.
+ */
+ public boolean isBatchMode() {
+ return batchMode != null && batchMode.booleanValue();
+ }
+
+ /**
+ * @return the number of tries (one per second) to connect before
+ * exiting. The argument must be an integer. This may be useful
+ * in scripts if the connection sometimes fails. The default is
+ * 1.
+ * @since 3.4
+ */
+ public int getConnectionAttempts() {
+ return connectionAttempts;
+ }
+
+
+ private void complete(String initialHostName, String localUserName) {
+ // Try to set values from the options.
+ hostName = entry.getValue(SshConstants.HOST_NAME);
+ user = entry.getValue(SshConstants.USER);
+ port = positive(entry.getValue(SshConstants.PORT));
+ connectionAttempts = positive(
+ entry.getValue(SshConstants.CONNECTION_ATTEMPTS));
+ strictHostKeyChecking = entry
+ .getValue(SshConstants.STRICT_HOST_KEY_CHECKING);
+ batchMode = Boolean.valueOf(OpenSshConfigFile
+ .flag(entry.getValue(SshConstants.BATCH_MODE)));
+ preferredAuthentications = entry
+ .getValue(SshConstants.PREFERRED_AUTHENTICATIONS);
+ // Fill in defaults if still not set
+ if (hostName == null || hostName.isEmpty()) {
+ hostName = initialHostName;
+ }
+ if (user == null || user.isEmpty()) {
+ user = localUserName;
+ }
+ if (port <= 0) {
+ port = SshConstants.SSH_DEFAULT_PORT;
+ }
+ if (connectionAttempts <= 0) {
+ connectionAttempts = 1;
+ }
+ List<String> identityFiles = entry
+ .getValues(SshConstants.IDENTITY_FILE);
+ if (identityFiles != null && !identityFiles.isEmpty()) {
+ identityFile = new File(identityFiles.get(0));
+ }
+ }
+
+ Config getConfig() {
+ if (config == null) {
+ config = new Config() {
+
+ @Override
+ public String getHostname() {
+ return Host.this.getHostName();
+ }
+
+ @Override
+ public String getUser() {
+ return Host.this.getUser();
+ }
+
+ @Override
+ public int getPort() {
+ return Host.this.getPort();
+ }
+
+ @Override
+ public String getValue(String key) {
+ // See com.jcraft.jsch.OpenSSHConfig.MyConfig.getValue()
+ // for this special case.
+ if (key.equals("compression.s2c") //$NON-NLS-1$
+ || key.equals("compression.c2s")) { //$NON-NLS-1$
+ if (!OpenSshConfigFile.flag(
+ Host.this.entry.getValue(mapKey(key)))) {
+ return "none,zlib@openssh.com,zlib"; //$NON-NLS-1$
+ }
+ return "zlib@openssh.com,zlib,none"; //$NON-NLS-1$
+ }
+ return Host.this.entry.getValue(mapKey(key));
+ }
+
+ @Override
+ public String[] getValues(String key) {
+ List<String> values = Host.this.entry
+ .getValues(mapKey(key));
+ if (values == null) {
+ return new String[0];
+ }
+ return values.toArray(new String[0]);
+ }
+ };
+ }
+ return config;
+ }
+
+ @Override
+ @SuppressWarnings("nls")
+ public String toString() {
+ return "Host [hostName=" + hostName + ", port=" + port
+ + ", identityFile=" + identityFile + ", user=" + user
+ + ", preferredAuthentications=" + preferredAuthentications
+ + ", batchMode=" + batchMode + ", strictHostKeyChecking="
+ + strictHostKeyChecking + ", connectionAttempts="
+ + connectionAttempts + ", entry=" + entry + "]";
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Retrieves the full {@link com.jcraft.jsch.ConfigRepository.Config Config}
+ * for the given host name. Should be called only by Jsch and tests.
+ *
+ * @since 4.9
+ */
+ @Override
+ public Config getConfig(String hostName) {
+ Host host = lookup(hostName);
+ return host.getConfig();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "OpenSshConfig [configFile=" + configFile + ']'; //$NON-NLS-1$
+ }
+}