SVN: proper way of getting to be asked/notified on credentials saving + svnkit 1.3.5.7455

This commit is contained in:
irengrig
2011-01-26 00:22:33 +03:00
parent fc1370eaac
commit 08e71f4045
7 changed files with 312 additions and 157 deletions
+1 -1
View File
@@ -531,4 +531,4 @@
= build 20041105
+ switch and relocate operations
+ bugfixes
+ bugfixes
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,58 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed 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.
*/
package org.jetbrains.idea.svn;
import org.tmatesoft.svn.core.auth.*;
/**
* @author irengrig
* Date: 1/24/11
* Time: 6:14 PM
*/
public class ProxySvnAuthentication {
private ProxySvnAuthentication() {
}
public static SVNAuthentication proxy(final SVNAuthentication in, final boolean storeAuth) {
if (in.isStorageAllowed() == storeAuth || (! in.isStorageAllowed())) return in;
final String userName = in.getUserName();
if (in instanceof SVNPasswordAuthentication) {
return new SVNPasswordAuthentication(userName, ((SVNPasswordAuthentication)in).getPassword(),
storeAuth, in.getURL(), in.isPartial());
} else if (in instanceof SVNSSHAuthentication) {
final SVNSSHAuthentication svnsshAuthentication = (SVNSSHAuthentication)in;
if (svnsshAuthentication.hasPrivateKey()) {
return new SVNSSHAuthentication(userName, svnsshAuthentication.getPrivateKeyFile(), svnsshAuthentication.getPassphrase(),
svnsshAuthentication.getPortNumber(), storeAuth, in.getURL(), in.isPartial());
} else {
return new SVNSSHAuthentication(userName, svnsshAuthentication.getPassword(), svnsshAuthentication.getPortNumber(),
storeAuth, in.getURL(), in.isPartial());
}
} else if (in instanceof SVNSSLAuthentication) {
final SVNSSLAuthentication svnsslAuthentication = (SVNSSLAuthentication)in;
if (SVNSSLAuthentication.MSCAPI.equals(svnsslAuthentication.getSSLKind())) {
return new SVNSSLAuthentication(SVNSSLAuthentication.MSCAPI, svnsslAuthentication.getAlias(), storeAuth, in.getURL(), in.isPartial());
} else {
return new SVNSSLAuthentication(svnsslAuthentication.getCertificateFile(), svnsslAuthentication.getPassword(),
storeAuth, svnsslAuthentication.getURL(), svnsslAuthentication.isPartial());
}
} else if (in instanceof SVNUserNameAuthentication) {
return new SVNUserNameAuthentication(in.getUserName(), storeAuth, in.getURL(), in.isPartial());
}
return in;
}
}
@@ -29,7 +29,6 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.CalledInAwt;
import com.intellij.openapi.vcs.changes.committed.AbstractCalledLater;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.util.Consumer;
import com.intellij.util.EventDispatcher;
import com.intellij.util.net.HttpConfigurable;
import org.jetbrains.idea.svn.auth.ProviderType;
@@ -37,9 +36,12 @@ import org.jetbrains.idea.svn.auth.SvnAuthenticationInteraction;
import org.jetbrains.idea.svn.auth.SvnAuthenticationListener;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.*;
import org.tmatesoft.svn.core.internal.util.jna.SVNJNAUtil;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationProvider;
import org.tmatesoft.svn.core.auth.ISVNProxyManager;
import org.tmatesoft.svn.core.auth.SVNAuthentication;
import org.tmatesoft.svn.core.auth.SVNSSLAuthentication;
import org.tmatesoft.svn.core.internal.wc.*;
import org.tmatesoft.svn.core.io.SVNRepository;
@@ -52,7 +54,6 @@ import java.util.*;
*/
public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager implements SvnAuthenticationListener {
// while Mac storage not working for IDEA, we use this key to check whether to prompt abt plaintext or just store
private static final String ourMacPlaintextNicht = "svn.ourMacPlaintextNicht";
private static final Logger LOG = Logger.getInstance(SvnAuthenticationManager.class.getName());
private final Project myProject;
private File myConfigDirectory;
@@ -60,17 +61,16 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
private SvnConfiguration myConfig;
private static final ThreadLocal<Boolean> ourJustEntered = new ThreadLocal<Boolean>();
private SvnAuthenticationInteraction myInteraction;
private final EventDispatcher<SvnAuthenticationListener> myListener;
private EventDispatcher<SvnAuthenticationListener> myListener;
private IdeaSVNHostOptionsProvider myLocalHostOptionsProvider;
private ThreadLocalSavePermissions mySavePermissions;
private boolean myMacCryptIsOk;
private final ThreadLocalSavePermissions mySavePermissions;
public SvnAuthenticationManager(final Project project, final File configDirectory) {
super(configDirectory, true, null, null);
myProject = project;
myConfigDirectory = configDirectory;
myMacCryptIsOk = Boolean.getBoolean(ourMacPlaintextNicht);
myListener = EventDispatcher.create(SvnAuthenticationListener.class);
ensureListenerCreated();
mySavePermissions = new ThreadLocalSavePermissions();
myConfig = SvnConfiguration.getInstance(myProject);
if (myPersistentAuthenticationProviderProxy != null) {
myPersistentAuthenticationProviderProxy.setProject(myProject);
@@ -78,11 +78,16 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
myInteraction = new MySvnAuthenticationInteraction(myProject);
}
private void ensureListenerCreated() {
if (myListener == null) {
myListener = EventDispatcher.create(SvnAuthenticationListener.class);
}
}
@Override
public IdeaSVNHostOptionsProvider getHostOptionsProvider() {
if (myLocalHostOptionsProvider == null) {
mySavePermissions = new ThreadLocalSavePermissions();
myLocalHostOptionsProvider = new IdeaSVNHostOptionsProvider(mySavePermissions);
myLocalHostOptionsProvider = new IdeaSVNHostOptionsProvider();
}
return myLocalHostOptionsProvider;
}
@@ -92,8 +97,18 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
}
@Override
public void actualSaveWillBeTried(ProviderType type, SVNURL url, String realm, String kind, boolean withCredentials) {
myListener.getMulticaster().actualSaveWillBeTried(type, url, realm, kind, withCredentials);
public void actualSaveWillBeTried(ProviderType type, SVNURL url, String realm, String kind) {
myListener.getMulticaster().actualSaveWillBeTried(type, url, realm, kind);
}
@Override
public void saveAttemptStarted(ProviderType type, SVNURL url, String realm, String kind) {
myListener.getMulticaster().saveAttemptStarted(type, url, realm, kind);
}
@Override
public void saveAttemptFinished(ProviderType type, SVNURL url, String realm, String kind) {
myListener.getMulticaster().saveAttemptFinished(type, url, realm, kind);
}
@Override
@@ -108,8 +123,7 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
protected ISVNAuthenticationProvider createCacheAuthenticationProvider(File authDir, String userName) {
// this is a hack due to the fact this method is called from super() constructor
myConfigDirectory = new File(authDir.getParent());
myPersistentAuthenticationProviderProxy = new PersistentAuthenticationProviderProxy(
super.createCacheAuthenticationProvider(authDir, userName), authDir);
myPersistentAuthenticationProviderProxy = new PersistentAuthenticationProviderProxy(authDir, userName);
return myPersistentAuthenticationProviderProxy;
}
@@ -120,7 +134,9 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
SVNErrorMessage errorMessage,
SVNAuthentication authentication) throws SVNException {
try {
super.acknowledgeAuthentication(accepted, kind, realm, errorMessage, authentication);
final boolean authStorageEnabled = getHostOptionsProvider().getHostOptions(authentication.getURL()).isAuthStorageEnabled();
final SVNAuthentication proxy = ProxySvnAuthentication.proxy(authentication, authStorageEnabled);
super.acknowledgeAuthentication(accepted, kind, realm, errorMessage, proxy);
} finally {
mySavePermissions.remove();
}
@@ -131,8 +147,34 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
private final File myAuthDir;
private Project myProject;
private PersistentAuthenticationProviderProxy(final ISVNAuthenticationProvider delegate, final File authDir) {
myDelegate = delegate;
private PersistentAuthenticationProviderProxy(File authDir, String userName) {
ISVNAuthenticationStorageOptions delegatingOptions = new ISVNAuthenticationStorageOptions() {
public boolean isNonInteractive() throws SVNException {
return getAuthenticationStorageOptions().isNonInteractive();
}
public ISVNAuthStoreHandler getAuthStoreHandler() throws SVNException {
return getAuthenticationStorageOptions().getAuthStoreHandler();
}
@Override
public boolean isSSLPassphrasePromptSupported() {
return false;
}
};
ensureListenerCreated();
myDelegate = new DefaultSVNPersistentAuthenticationProvider(authDir, userName, delegatingOptions, getDefaultOptions(), getHostOptionsProvider()) {
@Override
protected IPasswordStorage[] createPasswordStorages(DefaultSVNOptions options) {
final IPasswordStorage[] passwordStorages = super.createPasswordStorages(options);
final IPasswordStorage[] proxied = new IPasswordStorage[passwordStorages.length];
for (int i = 0; i < passwordStorages.length; i++) {
final IPasswordStorage storage = passwordStorages[i];
proxied[i] = new ProxyPasswordStorageForDebug(storage, myListener);
}
return proxied;
}
};
myAuthDir = authDir;
}
@@ -152,24 +194,12 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
return ACCEPTED_TEMPORARY;
}
public void saveAuthentication(final SVNAuthentication auth, final String kind, final String realm) throws SVNException {
final Boolean fromInteractive = ourJustEntered.get();
ourJustEntered.set(null);
if (! Boolean.TRUE.equals(fromInteractive)) {
// not what user entered
return;
}
private void actualSavePermissions(String realm, SVNAuthentication auth) {
final String actualKind = auth.getKind();
final Consumer<Boolean> actualSave = new Consumer<Boolean>() {
@Override
public void consume(final Boolean withCredentials) {
File dir = new File(myAuthDir, actualKind);
String fileName = SVNFileUtil.computeChecksum(realm);
File authFile = new File(dir, fileName);
myListener.getMulticaster().actualSaveWillBeTried(ProviderType.persistent, auth.getURL(), realm, actualKind,
Boolean.TRUE.equals(withCredentials));
try {
((ISVNPersistentAuthenticationProvider) myDelegate).saveAuthentication(auth, actualKind, realm);
}
@@ -183,14 +213,19 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
// do not make password file readonly
setWriteable(authFile);
}
}
};
if (USERNAME.equals(actualKind)) {
actualSave.consume(true);
}
public void saveAuthentication(final SVNAuthentication auth, final String kind, final String realm) throws SVNException {
final Boolean fromInteractive = ourJustEntered.get();
ourJustEntered.set(null);
if (! Boolean.TRUE.equals(fromInteractive)) {
// not what user entered
return;
}
if (!auth.isStorageAllowed()) return;
saveCredentialsIfAllowed(auth, actualKind, realm, actualSave);
myListener.getMulticaster().saveAttemptStarted(ProviderType.persistent, auth.getURL(), realm, auth.getKind());
((ISVNPersistentAuthenticationProvider) myDelegate).saveAuthentication(auth, kind, realm);
myListener.getMulticaster().saveAttemptFinished(ProviderType.persistent, auth.getURL(), realm, auth.getKind());
}
@Override
@@ -425,62 +460,6 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
return value == null || "yes".equalsIgnoreCase(value) || "on".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value);
}
public void saveCredentialsIfAllowed(final SVNAuthentication auth, final String kind, final String realm,
final Consumer<Boolean> saveRunnable) {
final SVNURL url = auth.getURL();
final IdeaSVNHostOptionsProvider hostOptionsProvider = getHostOptionsProvider();
final ISVNHostOptions hostOptions = hostOptionsProvider.getHostOptions(url);
if (! hostOptions.isAuthStorageEnabled()) {
myInteraction.warnOnAuthStorageDisabled(url);
return;
}
boolean passwordWillBeSaved = true;
// check can store
if ((! ISVNAuthenticationManager.SSL.equals(kind)) && (! hostOptions.isStorePasswords())) {
// but it should be
myInteraction.warnOnPasswordStorageDisabled(url);
passwordWillBeSaved = false;
}
if (ISVNAuthenticationManager.SSL.equals(kind) && (! hostOptionsProvider.getHostOptions(url).isStoreSSLClientCertificatePassphrases())) {
myInteraction.warnOnSSLPassphraseStorageDisabled(url);
passwordWillBeSaved = false;
}
// check can encrypt
if (passwordWillBeSaved && (! ((SystemInfo.isWindows && SVNJNAUtil.isWinCryptEnabled()) ||
(SystemInfo.isMacOSLeopard || SystemInfo.isMacOSSnowLeopard || isLion()) && SVNJNAUtil.isMacOsKeychainEnabled() && myMacCryptIsOk))) {
try {
if (ISVNAuthenticationManager.SSL.equals(kind)) {
if (! hostOptionsProvider.getHostOptions(auth.getURL()).isStorePlainTextPassphrases(realm, auth)) {
promptAndSaveWhenWeLackEncryption(saveRunnable,
new Getter<Boolean>() {
@Override
public Boolean get() {
return myInteraction.promptForSSLPlaintextPassphraseSaving(url, realm, ((SVNSSLAuthentication)auth).getCertificateFile());
}
});
return;
}
} else {
if (! hostOptionsProvider.getHostOptions(auth.getURL()).isStorePlainTextPasswords(realm, auth)) {
promptAndSaveWhenWeLackEncryption(saveRunnable,
new Getter<Boolean>() {
@Override
public Boolean get() {
return myInteraction.promptForPlaintextPasswordSaving(url, realm);
}
});
return;
}
}
} catch (SVNException e) {
LOG.info(e);
return;
}
}
saveRunnable.consume(passwordWillBeSaved);
}
private ModalityState getCurrent() {
if (ApplicationManager.getApplication().isDispatchThread()) {
return ModalityState.current();
@@ -492,38 +471,6 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
return pi.getModalityState();
}
private void promptAndSaveWhenWeLackEncryption(
final Consumer<Boolean> saveRunnable,
final Getter<Boolean> prompt) {
final Boolean[] saveOnce = new Boolean[1];
final Runnable actualSave = new Runnable() {
@Override
public void run() {
mySavePermissions.put(Boolean.TRUE.equals(saveOnce[0]));
try {
saveRunnable.consume(saveOnce[0]);
}
finally {
mySavePermissions.remove();
}
}
};
if (myInteraction.promptInAwt()) {
new AbstractCalledLater(myProject, getCurrent()) {
@Override
public void run() {
saveOnce[0] = Boolean.TRUE.equals(prompt.get());
ApplicationManager.getApplication().executeOnPooledThread(actualSave);
}
}.callMe();
} else {
saveOnce[0] = Boolean.TRUE.equals(prompt.get());
actualSave.run();
}
}
/**
* Shows a yes/no question whether user wants to store his password in plain text and returns his answer.
* @param title title of the questioning dialog.
@@ -589,11 +536,8 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
}
public class IdeaSVNHostOptionsProvider extends DefaultSVNHostOptionsProvider {
private final ThreadLocalSavePermissions mySavePermissions;
public IdeaSVNHostOptionsProvider(ThreadLocalSavePermissions savePermissions) {
public IdeaSVNHostOptionsProvider() {
super(myConfigDirectory);
mySavePermissions = savePermissions;
}
@Override
@@ -603,7 +547,7 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
@Override
public ISVNHostOptions getHostOptions(SVNURL url) {
return new IdeaSVNHostOptions(getServersFile(), url, mySavePermissions);
return new IdeaSVNHostOptions(getServersFile(), url);
}
}
@@ -618,6 +562,10 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
myPlainTextAllowed.put(Thread.currentThread(), value);
}
public boolean have() {
return myPlainTextAllowed.containsKey(Thread.currentThread());
}
public void remove() {
myPlainTextAllowed.remove(Thread.currentThread());
}
@@ -628,50 +576,85 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
}
private class IdeaSVNHostOptions extends DefaultSVNHostOptions {
private final ThreadLocalSavePermissions mySavePermissions;
private SVNCompositeConfigFile myConfigFile;
private final SVNURL myUrl;
private IdeaSVNHostOptions(SVNCompositeConfigFile serversFile,
SVNURL url,
ThreadLocalSavePermissions savePermissions) {
private IdeaSVNHostOptions(SVNCompositeConfigFile serversFile, SVNURL url) {
super(serversFile, url);
mySavePermissions = savePermissions;
}
public void put(final boolean value) {
mySavePermissions.put(value);
}
public void remove() {
mySavePermissions.remove();
myUrl = url;
}
@Override
public boolean isStorePlainTextPasswords(String realm, SVNAuthentication auth) throws SVNException {
return mySavePermissions.allowed() || super.isStorePlainTextPasswords(realm, auth);
public boolean isStorePlainTextPasswords(final String realm, SVNAuthentication auth) throws SVNException {
if (USERNAME.equals(auth.getKind())) return true;
final boolean superValue = super.isStorePlainTextPasswords(realm, auth);
final boolean value = mySavePermissions.allowed() || superValue;
if ((! value) && (! mySavePermissions.have())) {
promptAndSaveWhenWeLackEncryption(realm, auth, new Getter<Boolean>() {
@Override
public Boolean get() {
return myInteraction.promptForPlaintextPasswordSaving(myUrl, realm);
}
});
}
return value;
}
@Override
public boolean isStorePlainTextPassphrases(String realm, SVNAuthentication auth) throws SVNException {
return mySavePermissions.allowed() || super.isStorePlainTextPassphrases(realm, auth);
public boolean isStorePlainTextPassphrases(final String realm, final SVNAuthentication auth) throws SVNException {
if (USERNAME.equals(auth.getKind())) return true;
final boolean value = mySavePermissions.allowed() || super.isStorePlainTextPassphrases(realm, auth);
if ((! value) && (! mySavePermissions.have())) {
promptAndSaveWhenWeLackEncryption(realm, auth, new Getter<Boolean>() {
@Override
public Boolean get() {
return myInteraction.promptForSSLPlaintextPassphraseSaving(myUrl, realm,
((SVNSSLAuthentication) auth).getCertificateFile());
}
});
}
return value;
}
@Override
public boolean isAuthStorageEnabled() {
final boolean value;
if (hasAuthStorageEnabledOption()) {
return super.isAuthStorageEnabled();
value = super.isAuthStorageEnabled();
} else {
value = isTurned(getConfigFile().getPropertyValue("auth", "store-auth-creds"));
}
return isTurned(getConfigFile().getPropertyValue("auth", "store-auth-creds"));
if (! value) {
myInteraction.warnOnAuthStorageDisabled(myUrl);
}
return value;
}
@Override
public boolean isStorePasswords() {
final String storePasswords = getStorePasswords();
final boolean value;
if (storePasswords != null) {
return isTurned(storePasswords);
value = isTurned(storePasswords);
} else {
final String configValue = getConfigFile().getPropertyValue("auth", "store-passwords");
value = isTurned(configValue);
}
final String configValue = getConfigFile().getPropertyValue("auth", "store-passwords");
return isTurned(configValue);
if (! value) {
myInteraction.warnOnPasswordStorageDisabled(myUrl);
}
return value;
}
@Override
public boolean isStoreSSLClientCertificatePassphrases() {
final boolean value = super.isStoreSSLClientCertificatePassphrases();
if (! value) {
myInteraction.warnOnSSLPassphraseStorageDisabled(myUrl);
}
return value;
}
public String getStorePasswords() {
@@ -688,5 +671,81 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
}
return myConfigFile;
}
private void promptAndSaveWhenWeLackEncryption(final String realm, final SVNAuthentication auth, final Getter<Boolean> prompt) {
final Boolean[] saveOnce = new Boolean[1];
final Runnable actualSave = new Runnable() {
@Override
public void run() {
mySavePermissions.put(Boolean.TRUE.equals(saveOnce[0]));
try {
myPersistentAuthenticationProviderProxy.actualSavePermissions(realm, auth);
}
finally {
mySavePermissions.remove();
}
}
};
if (myInteraction.promptInAwt()) {
new AbstractCalledLater(myProject, getCurrent()) {
@Override
public void run() {
saveOnce[0] = Boolean.TRUE.equals(prompt.get());
ApplicationManager.getApplication().executeOnPooledThread(actualSave);
}
}.callMe();
} else {
saveOnce[0] = Boolean.TRUE.equals(prompt.get());
actualSave.run();
}
}
}
private static class ProxyPasswordStorageForDebug implements DefaultSVNPersistentAuthenticationProvider.IPasswordStorage {
private final DefaultSVNPersistentAuthenticationProvider.IPasswordStorage myDelegate;
private final EventDispatcher<SvnAuthenticationListener> myListener;
public ProxyPasswordStorageForDebug(final DefaultSVNPersistentAuthenticationProvider.IPasswordStorage delegate,
final EventDispatcher<SvnAuthenticationListener> listener) {
myDelegate = delegate;
myListener = listener;
}
@Override
public String getPassType() {
return myDelegate.getPassType();
}
@Override
public boolean savePassword(String realm, String password, SVNAuthentication auth, SVNProperties authParameters) throws SVNException {
final boolean saved = myDelegate.savePassword(realm, password, auth, authParameters);
if (saved) {
myListener.getMulticaster().actualSaveWillBeTried(ProviderType.persistent, auth.getURL(), realm, auth.getKind()
);
}
return saved;
}
@Override
public String readPassword(String realm, String userName, SVNProperties authParameters) throws SVNException {
return myDelegate.readPassword(realm, userName, authParameters);
}
@Override
public boolean savePassphrase(String realm, String passphrase, SVNAuthentication auth, SVNProperties authParameters, boolean force)
throws SVNException {
final boolean saved = myDelegate.savePassphrase(realm, passphrase, auth, authParameters, force);
if (saved) {
myListener.getMulticaster().actualSaveWillBeTried(ProviderType.persistent, auth.getURL(), realm, auth.getKind()
);
}
return saved;
}
@Override
public String readPassphrase(String realm, SVNProperties authParameters) throws SVNException {
return myDelegate.readPassphrase(realm, authParameters);
}
}
}
@@ -21,5 +21,7 @@ import java.util.EventListener;
public interface SvnAuthenticationListener extends EventListener {
void requested(final ProviderType type, final SVNURL url, String realm, String kind, boolean canceled);
void actualSaveWillBeTried(final ProviderType type, final SVNURL url, String realm, String kind, boolean withCredentials);
void actualSaveWillBeTried(final ProviderType type, final SVNURL url, String realm, String kind);
void saveAttemptStarted(final ProviderType type, final SVNURL url, String realm, String kind);
void saveAttemptFinished(final ProviderType type, final SVNURL url, String realm, String kind);
}
@@ -1040,6 +1040,7 @@ public class SvnAuthenticationTest extends PlatformTestCase {
private int myCnt;
private final Object mySynchObject;
private boolean mySuccess;
private boolean mySaved;
private TestListener(final Object synchObject) {
mySynchObject = synchObject;
@@ -1057,9 +1058,26 @@ public class SvnAuthenticationTest extends PlatformTestCase {
}
@Override
public void actualSaveWillBeTried(ProviderType type, SVNURL url, String realm, String kind, boolean withCredentials) {
public void saveAttemptStarted(ProviderType type, SVNURL url, String realm, String kind) {
mySaved = false;
}
@Override
public void saveAttemptFinished(ProviderType type, SVNURL url, String realm, String kind) {
if (! mySuccess) return;
if (! mySaved) {
saveRegistration(type, url, false);
}
}
@Override
public void actualSaveWillBeTried(ProviderType type, SVNURL url, String realm, String kind) {
if (! mySuccess) return;
mySaved = true;
saveRegistration(type, url, true);
}
private void saveRegistration(ProviderType type, SVNURL url, boolean withCredentials) {
mySuccess = myExpectedSequence.get(myCnt).equals(new Trinity<ProviderType, SVNURL, Type>(type, url, withCredentials ? Type.save : Type.without_pasword_save));
if (mySuccess) {
++ myCnt;
@@ -1097,6 +1115,7 @@ public class SvnAuthenticationTest extends PlatformTestCase {
private final Set<Pair<SVNURL, String>> myClientRequested;
private final Set<Pair<SVNURL, String>> mySaved;
private String myCause;
private boolean mySaveCalled;
private SavedOnceListener() {
myClientRequested = new HashSet<Pair<SVNURL, String>>();
@@ -1109,7 +1128,24 @@ public class SvnAuthenticationTest extends PlatformTestCase {
}
@Override
public void actualSaveWillBeTried(ProviderType type, SVNURL url, String realm, String kind, boolean withCredentials) {
public void saveAttemptStarted(ProviderType type, SVNURL url, String realm, String kind) {
mySaveCalled = false;
}
@Override
public void saveAttemptFinished(ProviderType type, SVNURL url, String realm, String kind) {
if (! mySaveCalled) {
saveRegistration(url, kind);
}
}
@Override
public void actualSaveWillBeTried(ProviderType type, SVNURL url, String realm, String kind) {
mySaveCalled = true;
saveRegistration(url, kind);
}
private void saveRegistration(SVNURL url, String kind) {
final Pair<SVNURL, String> pair = new Pair<SVNURL, String>(url, kind);
if (mySaved.contains(pair)) {
myCause = "saved twice";