diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java index 770294cac..92584cbe1 100644 --- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java +++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/HttpClientTests.java @@ -60,6 +60,7 @@ import org.eclipse.jgit.http.server.GitServlet; import org.eclipse.jgit.http.server.resolver.RepositoryResolver; import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException; import org.eclipse.jgit.http.test.util.AccessEvent; +import org.eclipse.jgit.http.test.util.AppServer; import org.eclipse.jgit.http.test.util.HttpTestCase; import org.eclipse.jgit.junit.TestRepository; import org.eclipse.jgit.lib.Constants; @@ -71,6 +72,7 @@ import org.eclipse.jgit.storage.file.FileRepository; import org.eclipse.jgit.transport.FetchConnection; import org.eclipse.jgit.transport.Transport; import org.eclipse.jgit.transport.URIish; +import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; public class HttpClientTests extends HttpTestCase { private TestRepository remoteRepository; @@ -290,6 +292,31 @@ public class HttpClientTests extends HttpTestCase { } } + public void testListRemote_Dumb_Auth() throws Exception { + Repository dst = createBareRepository(); + Transport t = Transport.open(dst, dumbAuthBasicURI); + t.setCredentialsProvider(new UsernamePasswordCredentialsProvider( + AppServer.username, AppServer.password)); + try { + t.openFetch(); + } finally { + t.close(); + } + t = Transport.open(dst, dumbAuthBasicURI); + t.setCredentialsProvider(new UsernamePasswordCredentialsProvider( + AppServer.username, "")); + try { + t.openFetch(); + fail("connection opened even info/refs needs auth basic and we provide wrong password"); + } catch (TransportException err) { + String exp = dumbAuthBasicURI + ": " + + JGitText.get().notAuthorized; + assertEquals(exp, err.getMessage()); + } finally { + t.close(); + } + } + public void testListRemote_Smart_UploadPackNeedsAuth() throws Exception { Repository dst = createBareRepository(); Transport t = Transport.open(dst, smartAuthBasicURI); diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties index 8af6e315f..ab4ec6132 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties @@ -124,7 +124,8 @@ couldNotWriteFile=Could not write file {0} countingObjects=Counting objects createBranchFailedUnknownReason=Create branch failed for unknown reason createBranchUnexpectedResult=Create branch returned unexpected result {0} -creatingDeltasIsNotImplemented=creating deltas is not implemented +credentialPassword=Password +credentialUsername=Username daemonAlreadyRunning=Daemon already running deleteBranchUnexpectedResult=Delete branch returned unexpected result {0} deletingNotSupported=Deleting {0} not supported. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java index 6a75a9eb8..2eb316e85 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java @@ -184,7 +184,8 @@ public class JGitText extends TranslationBundle { /***/ public String countingObjects; /***/ public String createBranchFailedUnknownReason; /***/ public String createBranchUnexpectedResult; - /***/ public String creatingDeltasIsNotImplemented; + /***/ public String credentialPassword; + /***/ public String credentialUsername; /***/ public String daemonAlreadyRunning; /***/ public String deleteBranchUnexpectedResult; /***/ public String deletingNotSupported; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/errors/UnsupportedCredentialItem.java b/org.eclipse.jgit/src/org/eclipse/jgit/errors/UnsupportedCredentialItem.java new file mode 100644 index 000000000..eb09588fb --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/errors/UnsupportedCredentialItem.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010, Christian Halstrick , + * Copyright (C) 2010, Stefan Lay + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * - 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. + * + * 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. + */ +package org.eclipse.jgit.errors; + +import org.eclipse.jgit.transport.CredentialItem; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.URIish; + +/** + * An exception thrown when a {@link CredentialItem} is requested from a + * {@link CredentialsProvider} which is not supported by this provider. + */ +public class UnsupportedCredentialItem extends RuntimeException { + private static final long serialVersionUID = 1L; + + /** + * Constructs an UnsupportedCredentialItem with the specified detail message + * prefixed with provided URI. + * + * @param uri + * URI used for transport + * @param s + * message + */ + public UnsupportedCredentialItem(final URIish uri, final String s) { + super(uri.setPass(null) + ": " + s); + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/CredentialItem.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/CredentialItem.java new file mode 100644 index 000000000..eacc1ddec --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/CredentialItem.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2010, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * - 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. + * + * 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. + */ + +package org.eclipse.jgit.transport; + +import java.util.Arrays; + +import org.eclipse.jgit.JGitText; + +/** + * A credential requested from a {@link CredentialsProvider}. + * + * Most users should work with the specialized subclasses: + *
    + *
  • {@link Username} for usernames
  • + *
  • {@link Password} for passwords
  • + *
  • {@link StringType} for other general string information
  • + *
  • {@link CharArrayType} for other general secret information
  • + *
+ * + * This class is not thread-safe. Applications should construct their own + * instance for each use, as the value is held within the CredentialItem object. + */ +public abstract class CredentialItem { + private final String promptText; + + private final boolean valueSecure; + + /** + * Initialize a prompt. + * + * @param promptText + * prompt to display to the user alongside of the input field. + * Should be sufficient text to indicate what to supply for this + * item. + * @param maskValue + * true if the value should be masked from displaying during + * input. This should be true for passwords and other secrets, + * false for names and other public data. + */ + public CredentialItem(String promptText, boolean maskValue) { + this.promptText = promptText; + this.valueSecure = maskValue; + } + + /** @return prompt to display to the user. */ + public String getPromptText() { + return promptText; + } + + /** @return true if the value should be masked when entered. */ + public boolean isValueSecure() { + return valueSecure; + } + + /** Clear the stored value, destroying it as much as possible. */ + public abstract void clear(); + + /** + * An item whose value is stored as a string. + * + * When working with secret data, consider {@link CharArrayType} instead, as + * the internal members of the array can be cleared, reducing the chances + * that the password is left in memory after authentication is completed. + */ + public static class StringType extends CredentialItem { + private String value; + + /** + * Initialize a prompt for a single string. + * + * @param promptText + * prompt to display to the user alongside of the input + * field. Should be sufficient text to indicate what to + * supply for this item. + * @param maskValue + * true if the value should be masked from displaying during + * input. This should be true for passwords and other + * secrets, false for names and other public data. + */ + public StringType(String promptText, boolean maskValue) { + super(promptText, maskValue); + } + + @Override + public void clear() { + value = null; + } + + /** @return the current value */ + public String getValue() { + return value; + } + + /** + * + * @param newValue + */ + public void setValue(String newValue) { + value = newValue; + } + } + + /** An item whose value is stored as a char[] and is therefore clearable. */ + public static class CharArrayType extends CredentialItem { + private char[] value; + + /** + * Initialize a prompt for a secure value stored in a character array. + * + * @param promptText + * prompt to display to the user alongside of the input + * field. Should be sufficient text to indicate what to + * supply for this item. + * @param maskValue + * true if the value should be masked from displaying during + * input. This should be true for passwords and other + * secrets, false for names and other public data. + */ + public CharArrayType(String promptText, boolean maskValue) { + super(promptText, maskValue); + } + + /** Destroys the current value, clearing the internal array. */ + @Override + public void clear() { + if (value != null) { + Arrays.fill(value, (char) 0); + value = null; + } + } + + /** + * Get the current value. + * + * The returned array will be cleared out when {@link #clear()} is + * called. Callers that need the array elements to survive should delay + * invoking {@code clear()} until the value is no longer necessary. + * + * @return the current value array. The actual internal array is + * returned, reducing the number of copies present in memory. + */ + public char[] getValue() { + return value; + } + + /** + * Set the new value, clearing the old value array. + * + * @param newValue + * if not null, the array is copied. + */ + public void setValue(char[] newValue) { + clear(); + + if (newValue != null) { + value = new char[newValue.length]; + System.arraycopy(newValue, 0, value, 0, newValue.length); + } + } + + /** + * Set the new value, clearing the old value array. + * + * @param newValue + * the new internal array. The array is NOT copied. + */ + public void setValueNoCopy(char[] newValue) { + clear(); + value = newValue; + } + } + + /** Prompt for a username, which is not masked on input. */ + public static class Username extends StringType { + /** Initialize a new username item, with a default username prompt. */ + public Username() { + super(JGitText.get().credentialUsername, false); + } + } + + /** Prompt for a password, which is masked on input. */ + public static class Password extends CharArrayType { + /** Initialize a new password item, with a default password prompt. */ + public Password() { + super(JGitText.get().credentialPassword, true); + } + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/CredentialsProvider.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/CredentialsProvider.java new file mode 100644 index 000000000..d2130ad30 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/CredentialsProvider.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2010, Christian Halstrick , + * Copyright (C) 2010, Stefan Lay + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * - 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. + * + * 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. + */ + +package org.eclipse.jgit.transport; + +import java.util.List; + +import org.eclipse.jgit.errors.UnsupportedCredentialItem; + +/** + * Provide credentials for use in connecting to Git repositories. + * + * Implementors are strongly encouraged to support at least the minimal + * {@link CredentialItem.Username} and {@link CredentialItem.Password} items. + * More sophisticated implementors may implement additional types, such as + * {@link CredentialItem.StringType}. + * + * CredentialItems are usually presented in bulk, allowing implementors to + * combine them into a single UI widget and streamline the authentication + * process for an end-user. + * + * @see UsernamePasswordCredentialsProvider + */ +public abstract class CredentialsProvider { + /** + * Check if the provider can supply the necessary {@link CredentialItem}s. + * + * @param items + * the items the application requires to complete authentication. + * @return {@code true} if this {@link CredentialsProvider} supports all of + * the items supplied. + */ + public abstract boolean supports(CredentialItem... items); + + /** + * Ask for the credential items to be populated. + * + * @param uri + * the URI of the remote resource that needs authentication. + * @param items + * the items the application requires to complete authentication. + * @return {@code true} if the request was successful and values were + * supplied; {@code false} if the user canceled the request and did + * not supply all requested values. + * @throws UnsupportedCredentialItem + * if one of the items supplied is not supported. + */ + public abstract boolean get(URIish uri, CredentialItem... items) + throws UnsupportedCredentialItem; + + /** + * Ask for the credential items to be populated. + * + * @param uri + * the URI of the remote resource that needs authentication. + * @param items + * the items the application requires to complete authentication. + * @return {@code true} if the request was successful and values were + * supplied; {@code false} if the user canceled the request and did + * not supply all requested values. + * @throws UnsupportedCredentialItem + * if one of the items supplied is not supported. + */ + public boolean get(URIish uri, List items) + throws UnsupportedCredentialItem { + return get(uri, items.toArray(new CredentialItem[items.size()])); + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java index 11178fc72..926661667 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java @@ -98,9 +98,37 @@ abstract class HttpAuthMethod { * * @param uri * the URI used to create the connection. + * @param credentialsProvider + * the credentials provider, or null. If provided, + * {@link URIish#getPass() credentials in the URI} are ignored. + * + * @return true if the authentication method is able to provide + * authorization for the given URI */ - void authorize(URIish uri) { - authorize(uri.getUser(), uri.getPass()); + boolean authorize(URIish uri, CredentialsProvider credentialsProvider) { + String username; + String password; + + if (credentialsProvider != null) { + CredentialItem.Username u = new CredentialItem.Username(); + CredentialItem.Password p = new CredentialItem.Password(); + + if (credentialsProvider.supports(u, p) + && credentialsProvider.get(uri, u, p)) { + username = u.getValue(); + password = new String(p.getValue()); + p.clear(); + } else + return false; + } else { + username = uri.getUser(); + password = uri.getPass(); + } + if (username != null) { + authorize(username, password); + return true; + } + return false; } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java index 500cf0cff..5895f7f37 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java @@ -558,6 +558,9 @@ public abstract class Transport { /** Pack configuration used by this transport to make pack file. */ private PackConfig packConfig; + /** Assists with authentication the connection. */ + private CredentialsProvider credentialsProvider; + /** * Create a new transport instance. * @@ -821,6 +824,26 @@ public abstract class Transport { packConfig = pc; } + /** + * A credentials provider to assist with authentication connections.. + * + * @param credentialsProvider + * the credentials provider, or null if there is none + */ + public void setCredentialsProvider(CredentialsProvider credentialsProvider) { + this.credentialsProvider = credentialsProvider; + } + + /** + * The configured credentials provider. + * + * @return the credentials provider, or null if no credentials provider is + * associated with this transport. + */ + public CredentialsProvider getCredentialsProvider() { + return credentialsProvider; + } + /** * Fetch objects and refs from the remote repository to the local one. *

diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java index 39dedc6a6..9eb1d2db5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java @@ -367,10 +367,12 @@ public class TransportHttp extends HttpTransport implements WalkTransport, if (authMethod == HttpAuthMethod.NONE) throw new TransportException(uri, MessageFormat.format( JGitText.get().authenticationNotSupported, uri)); - if (1 < authAttempts || uri.getUser() == null) + if (1 < authAttempts + || !authMethod.authorize(uri, + getCredentialsProvider())) { throw new TransportException(uri, JGitText.get().notAuthorized); - authMethod.authorize(uri); + } authAttempts++; continue; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UsernamePasswordCredentialsProvider.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UsernamePasswordCredentialsProvider.java new file mode 100644 index 000000000..68cf96cf3 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UsernamePasswordCredentialsProvider.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2010, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - 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. + * + * - 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. + * + * 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. + */ + +package org.eclipse.jgit.transport; + +import java.util.Arrays; + +import org.eclipse.jgit.errors.UnsupportedCredentialItem; + +/** + * Simple {@link CredentialsProvider} that always uses the same information. + */ +public class UsernamePasswordCredentialsProvider extends CredentialsProvider { + private String username; + + private char[] password; + + /** + * Initialize the provider with a single username and password. + * + * @param username + * @param password + */ + public UsernamePasswordCredentialsProvider(String username, String password) { + this(username, password.toCharArray()); + } + + /** + * Initialize the provider with a single username and password. + * + * @param username + * @param password + */ + public UsernamePasswordCredentialsProvider(String username, char[] password) { + this.username = username; + this.password = password; + } + + @Override + public boolean supports(CredentialItem... items) { + for (CredentialItem i : items) { + if (i instanceof CredentialItem.Username) + continue; + + else if (i instanceof CredentialItem.Password) + continue; + + else + return false; + } + return true; + } + + @Override + public boolean get(URIish uri, CredentialItem... items) + throws UnsupportedCredentialItem { + for (CredentialItem i : items) { + if (i instanceof CredentialItem.Username) + ((CredentialItem.Username) i).setValue(username); + + else if (i instanceof CredentialItem.Password) + ((CredentialItem.Password) i).setValue(password); + + else + throw new UnsupportedCredentialItem(uri, i.getPromptText()); + } + return true; + } + + /** Destroy the saved username and password.. */ + public void clear() { + username = null; + + if (password != null) { + Arrays.fill(password, (char) 0); + password = null; + } + } +}