From c8b7fa9339f6fa0e467e3dfd490546cd3245c097 Mon Sep 17 00:00:00 2001 From: Konrad Windszus Date: Tue, 12 Jul 2022 10:21:10 +0200 Subject: [PATCH] [SCM-994] Add credentials provider for JGit This closes #154 --- .../maven/scm/provider/ScmProvider.java | 9 ++ .../maven-scm-provider-jgit/pom.xml | 11 ++ .../provider/git/jgit/JGitScmProvider.java | 19 +++ ...lexusInteractivityCredentialsProvider.java | 133 ++++++++++++++++++ 4 files changed, 172 insertions(+) create mode 100644 maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/PlexusInteractivityCredentialsProvider.java diff --git a/maven-scm-api/src/main/java/org/apache/maven/scm/provider/ScmProvider.java b/maven-scm-api/src/main/java/org/apache/maven/scm/provider/ScmProvider.java index af247e2e5..2f96f5d91 100644 --- a/maven-scm-api/src/main/java/org/apache/maven/scm/provider/ScmProvider.java +++ b/maven-scm-api/src/main/java/org/apache/maven/scm/provider/ScmProvider.java @@ -71,6 +71,15 @@ ScmProviderRepository makeProviderScmRepository( String scmSpecificUrl, char del ScmProviderRepository makeProviderScmRepository( File path ) throws ScmRepositoryException, UnknownRepositoryStructure; + /** + * Sets the interactive mode. + * @param interactive either {@code true} in case user may be prompted for information, otherwise {@code false} + * @since 2.0.0-M2 + */ + default void setInteractive( boolean interactive ) + { + } + /** * Validate the scm url. * diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/pom.xml b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/pom.xml index 29efbf3b6..d343e513a 100644 --- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/pom.xml +++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/pom.xml @@ -47,6 +47,17 @@ org.apache.maven.scm maven-scm-provider-git-commons + + org.codehaus.plexus + plexus-interactivity-api + 1.1 + + + org.codehaus.plexus + plexus-container-default + + + org.eclipse.jgit org.eclipse.jgit diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/JGitScmProvider.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/JGitScmProvider.java index 952ebc7a7..f95f9d14a 100644 --- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/JGitScmProvider.java +++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/JGitScmProvider.java @@ -19,6 +19,7 @@ * under the License. */ +import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; @@ -29,6 +30,7 @@ import org.apache.maven.scm.command.info.InfoScmResult; import org.apache.maven.scm.provider.git.AbstractGitScmProvider; import org.apache.maven.scm.provider.git.command.GitCommand; +import org.apache.maven.scm.provider.git.jgit.command.PlexusInteractivityCredentialsProvider; import org.apache.maven.scm.provider.git.jgit.command.add.JGitAddCommand; import org.apache.maven.scm.provider.git.jgit.command.blame.JGitBlameCommand; import org.apache.maven.scm.provider.git.jgit.command.branch.JGitBranchCommand; @@ -43,6 +45,8 @@ import org.apache.maven.scm.provider.git.jgit.command.tag.JGitTagCommand; import org.apache.maven.scm.provider.git.jgit.command.untag.JGitUntagCommand; import org.apache.maven.scm.repository.ScmRepositoryException; +import org.codehaus.plexus.components.interactivity.Prompter; +import org.eclipse.jgit.transport.CredentialsProvider; /** * @author Mark Struberg @@ -54,6 +58,21 @@ public class JGitScmProvider extends AbstractGitScmProvider { + private final PlexusInteractivityCredentialsProvider credentialsProvider; + + @Inject + public JGitScmProvider( Prompter prompter ) + { + credentialsProvider = new PlexusInteractivityCredentialsProvider( prompter ); + CredentialsProvider.setDefault( credentialsProvider ); + } + + @Override + public void setInteractive( boolean interactive ) + { + credentialsProvider.setInteractive( interactive ); + } + /** * {@inheritDoc} */ diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/PlexusInteractivityCredentialsProvider.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/PlexusInteractivityCredentialsProvider.java new file mode 100644 index 000000000..91a474fe3 --- /dev/null +++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/PlexusInteractivityCredentialsProvider.java @@ -0,0 +1,133 @@ +package org.apache.maven.scm.provider.git.jgit.command; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +import java.util.Arrays; + +import org.codehaus.plexus.components.interactivity.Prompter; +import org.codehaus.plexus.components.interactivity.PrompterException; +import org.eclipse.jgit.errors.UnsupportedCredentialItem; +import org.eclipse.jgit.transport.CredentialItem; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.URIish; + +/** + * {@link CredentialsProvider} leveraging the {@link Prompter} component. + * + */ +public class PlexusInteractivityCredentialsProvider extends CredentialsProvider +{ + private boolean interactive; + private final Prompter prompter; + + public PlexusInteractivityCredentialsProvider( Prompter prompter ) + { + this.interactive = true; + this.prompter = prompter; + } + + @Override + public boolean get( URIish uri, CredentialItem... items ) throws UnsupportedCredentialItem + { + for ( CredentialItem item : items ) + { + try + { + get( uri, item ); + } + catch ( PrompterException e ) + { + throw new IllegalStateException( "Cannot prompt user", e ); + } + } + return true; + } + + private void get( URIish uri, CredentialItem item ) throws PrompterException + { + if ( item instanceof CredentialItem.InformationalMessage ) + { + // works even in non-interactive mode + prompter.showMessage( item.getPromptText() ); + } + else + { + if ( !interactive ) + { + throw new UnsupportedCredentialItem( uri, + "Cannot provide '" + item.getClass() + "' in non-interactive mode" ); + } + if ( item instanceof CredentialItem.YesNoType ) + { + CredentialItem.YesNoType yesNoItem = ( CredentialItem.YesNoType ) item; + String value = prompter.prompt( item.getPromptText(), Arrays.asList( "yes", "no" ) ); + yesNoItem.setValue( value.equals( "yes" ) ); + } + else if ( item instanceof CredentialItem.Password ) + { + CredentialItem.Password passwordItem = ( CredentialItem.Password ) item; + String password = prompter.promptForPassword( passwordItem.getPromptText() ); + passwordItem.setValue( password.toCharArray() ); + } + else if ( item instanceof CredentialItem.Username ) + { + CredentialItem.Username usernameItem = ( CredentialItem.Username ) item; + String username = prompter.prompt( usernameItem.getPromptText() ); + usernameItem.setValue( username ); + } + else if ( item instanceof CredentialItem.StringType ) + { + CredentialItem.StringType stringItem = ( CredentialItem.StringType ) item; + String value = prompter.prompt( stringItem.getPromptText() ); + stringItem.setValue( value ); + } + else if ( item instanceof CredentialItem.CharArrayType ) + { + CredentialItem.CharArrayType charArrayItem = ( CredentialItem.CharArrayType ) item; + String value = prompter.prompt( charArrayItem.getPromptText() ); + charArrayItem.setValue( value.toCharArray() ); + } + else + { + throw new UnsupportedCredentialItem( uri, "This provider does not support items of type '" + + item.getClass().toString() + "'" ); + } + } + } + + public void setInteractive( boolean interactive ) + { + this.interactive = interactive; + } + + @Override + public boolean isInteractive() + { + return interactive; + } + + @Override + public boolean supports( CredentialItem... items ) + { + return true; + } + +}