svn: Refactor "SvnAuthenticationNotifier"

This commit is contained in:
Konstantin Kolosovsky
2018-11-21 16:56:48 +03:00
parent 60ffd8454c
commit 33d32069bf
@@ -1,10 +1,8 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.svn.auth;
import com.intellij.concurrency.JobScheduler;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
@@ -18,9 +16,7 @@ import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.NamedRunnable;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.impl.GenericNotifierImpl;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.ex.WindowManagerEx;
@@ -30,7 +26,10 @@ import com.intellij.util.net.HttpConfigurable;
import com.intellij.util.proxy.CommonProxy;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.*;
import org.jetbrains.idea.svn.RootsToWorkingCopies;
import org.jetbrains.idea.svn.SvnConfiguration;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.WorkingCopy;
import org.jetbrains.idea.svn.api.ClientFactory;
import org.jetbrains.idea.svn.api.Revision;
import org.jetbrains.idea.svn.api.Target;
@@ -43,11 +42,17 @@ import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.net.*;
import java.util.*;
import java.util.List;
import java.util.*;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import static com.intellij.openapi.application.ApplicationManager.getApplication;
import static com.intellij.openapi.util.text.StringUtil.isEmptyOrSpaces;
import static com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier.showOverChangesView;
import static java.util.Collections.synchronizedMap;
import static org.jetbrains.idea.svn.SvnBundle.message;
import static org.jetbrains.idea.svn.SvnConfigurable.selectConfigurationDirectory;
import static org.jetbrains.idea.svn.SvnUtil.isAuthError;
public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthenticationNotifier.AuthenticationRequest, Url> {
@@ -66,7 +71,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
super(svnVcs.getProject(), svnVcs.getDisplayName(), "Not Logged In to Subversion", NotificationType.ERROR);
myVcs = svnVcs;
myRootsToWorkingCopies = myVcs.getRootsToWorkingCopies();
myCopiesPassiveResults = Collections.synchronizedMap(new HashMap<Url, Boolean>());
myCopiesPassiveResults = synchronizedMap(new HashMap<>());
myVerificationInProgress = false;
}
@@ -74,9 +79,8 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
if (myTimer != null) {
stop();
}
myTimer =
// every 10 minutes
JobScheduler.getScheduler().scheduleWithFixedDelay(myCopiesPassiveResults::clear, 10, 10 * 60, TimeUnit.SECONDS);
myTimer = JobScheduler.getScheduler().scheduleWithFixedDelay(myCopiesPassiveResults::clear, 10, 10 * 60, TimeUnit.SECONDS);
}
public void stop() {
@@ -86,18 +90,14 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
@Override
protected boolean ask(final AuthenticationRequest obj, String description) {
if (myVerificationInProgress) {
return showAlreadyChecking();
}
if (myVerificationInProgress) return showAlreadyChecking();
myVerificationInProgress = true;
final Ref<Boolean> resultRef = new Ref<>();
final Runnable checker = () -> {
try {
final boolean result =
interactiveValidation(obj.myProject, obj.getUrl(), obj.getRealm(), obj.getKind());
log("ask result for: " + obj.getUrl() + " is: " + result);
final boolean result = interactiveValidation(obj.myProject, obj.getUrl(), obj.getRealm(), obj.getKind());
LOG.debug("ask result for: " + obj.getUrl() + " is: " + result);
resultRef.set(result);
if (result) {
onStateChangedToSuccess(obj);
@@ -107,10 +107,9 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
myVerificationInProgress = false;
}
};
final Application application = ApplicationManager.getApplication();
// also do not show auth if thread does not have progress indicator
if (application.isReadAccessAllowed() || !ProgressManager.getInstance().hasProgressIndicator()) {
application.executeOnPooledThread(checker);
if (getApplication().isReadAccessAllowed() || !ProgressManager.getInstance().hasProgressIndicator()) {
getApplication().executeOnPooledThread(checker);
}
else {
checker.run();
@@ -138,20 +137,15 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
myCopiesPassiveResults.put(getKey(obj), true);
myVcs.invokeRefreshSvnRoots();
final List<Url> outdatedRequests = new LinkedList<>();
final Collection<Url> keys = getAllCurrentKeys();
for (Url key : keys) {
final List<Url> outdatedRequests = new ArrayList<>();
for (Url key : getAllCurrentKeys()) {
final Url commonURLAncestor = key.commonAncestorWith(obj.getUrl());
if ((commonURLAncestor != null) && (! StringUtil.isEmptyOrSpaces(commonURLAncestor.getHost())) &&
(! StringUtil.isEmptyOrSpaces(commonURLAncestor.getPath()))) {
//final AuthenticationRequest currObj = getObj(key);
//if ((currObj != null) && passiveValidation(myVcs.getProject(), key, true, currObj.getRealm(), currObj.getKind())) {
outdatedRequests.add(key);
//}
if (commonURLAncestor != null && !isEmptyOrSpaces(commonURLAncestor.getHost()) && !isEmptyOrSpaces(commonURLAncestor.getPath())) {
outdatedRequests.add(key);
}
}
log("on state changed ");
ApplicationManager.getApplication().invokeLater(() -> {
LOG.debug("on state changed ");
getApplication().invokeLater(() -> {
for (Url key : outdatedRequests) {
removeLazyNotificationByKey(key);
}
@@ -160,26 +154,18 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
@Override
public boolean ensureNotify(AuthenticationRequest obj) {
final Url key = getKey(obj);
myCopiesPassiveResults.remove(key);
/*VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), "You are not authenticated to '" + obj.getRealm() + "'." +
"To login, see pending notifications.", MessageType.ERROR);*/
myCopiesPassiveResults.remove(getKey(obj));
return super.ensureNotify(obj);
}
@Override
protected boolean onFirstNotification(AuthenticationRequest obj) {
if (ProgressManager.getInstance().hasProgressIndicator()) {
return ask(obj, null); // TODO
} else {
return false;
}
return ProgressManager.getInstance().hasProgressIndicator() && ask(obj, null);
}
@NotNull
@Override
public Url getKey(final AuthenticationRequest obj) {
// !!! wc's URL
return obj.getWcUrl();
}
@@ -249,7 +235,6 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
private Url myWcUrl;
private boolean myOutsideCopies;
private boolean myForceSaving;
public AuthenticationRequest(Project project, String kind, Url url, String realm) {
myProject = project;
@@ -258,14 +243,6 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
myRealm = realm;
}
public boolean isForceSaving() {
return myForceSaving;
}
public void setForceSaving(boolean forceSaving) {
myForceSaving = forceSaving;
}
public boolean isOutsideCopies() {
return myOutsideCopies;
}
@@ -295,14 +272,6 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
}
}
static void log(final Throwable t) {
LOG.debug(t);
}
static void log(final String s) {
LOG.debug(s);
}
public static boolean passiveValidation(@NotNull SvnVcs vcs, final Url url) {
SvnConfiguration configuration = vcs.getSvnConfiguration();
SvnAuthenticationManager passiveManager = configuration.getPassiveAuthenticationManager(vcs);
@@ -324,8 +293,9 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
Proxy proxyToRelease = null;
if (! interactive && configuration.isIsUseDefaultProxy()) {
final HttpConfigurable instance = HttpConfigurable.getInstance();
if (instance.USE_HTTP_PROXY && instance.PROXY_AUTHENTICATION && (StringUtil.isEmptyOrSpaces(instance.getProxyLogin()) ||
StringUtil.isEmptyOrSpaces(instance.getPlainProxyPassword()))) {
if (instance.USE_HTTP_PROXY &&
instance.PROXY_AUTHENTICATION &&
(isEmptyOrSpaces(instance.getProxyLogin()) || isEmptyOrSpaces(instance.getPlainProxyPassword()))) {
return false;
}
if (instance.USE_PROXY_PAC) {
@@ -362,7 +332,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
}
catch (SvnBindException e) {
if (isAuthError(e)) {
log(e);
LOG.debug(e);
return false;
}
LOG.info("some other exc", e);
@@ -377,12 +347,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
}
}
if (! checkWrite) {
return true;
}
/*if (passive) {
return SvnInteractiveAuthenticationProvider.wasCalled();
}*/
if (!checkWrite) return true;
if (SvnInteractiveAuthenticationProvider.wasCalled() && SvnInteractiveAuthenticationProvider.wasCancelled()) return false;
if (SvnInteractiveAuthenticationProvider.wasCalled()) return true;
@@ -402,35 +367,33 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
private static void showAuthenticationFailedWithHotFixes(final Project project,
final SvnConfiguration configuration,
final SvnBindException e) {
ApplicationManager.getApplication().invokeLater(() -> VcsBalloonProblemNotifier
.showOverChangesView(project, "Authentication failed: " + e.getMessage(), MessageType.ERROR, new NamedRunnable(
SvnBundle.message("confirmation.title.clear.authentication.cache")) {
@Override
public void run() {
clearAuthenticationCache(project, null, configuration
.getConfigurationDirectory());
}
}, new NamedRunnable(
SvnBundle.message("action.title.select.configuration.directory")) {
@Override
public void run() {
SvnConfigurable.selectConfigurationDirectory(configuration.getConfigurationDirectory(),
s -> configuration.setConfigurationDirParameters(false, s), project, null);
}
}
), ModalityState.NON_MODAL, project.getDisposed());
getApplication().invokeLater(() -> showOverChangesView(
project, "Authentication failed: " + e.getMessage(), MessageType.ERROR,
new NamedRunnable(message("confirmation.title.clear.authentication.cache")) {
@Override
public void run() {
clearAuthenticationCache(project, null, configuration.getConfigurationDirectory());
}
}, new NamedRunnable(message("action.title.select.configuration.directory")) {
@Override
public void run() {
selectConfigurationDirectory(configuration.getConfigurationDirectory(),
s -> configuration.setConfigurationDirParameters(false, s), project, null);
}
}
), ModalityState.NON_MODAL, project.getDisposed());
}
public static void clearAuthenticationCache(@NotNull final Project project, final Component component, final String configDirPath) {
if (configDirPath != null) {
int result;
if (component == null) {
result = Messages.showYesNoDialog(project, SvnBundle.message("confirmation.text.delete.stored.authentication.information"),
SvnBundle.message("confirmation.title.clear.authentication.cache"),
result = Messages.showYesNoDialog(project, message("confirmation.text.delete.stored.authentication.information"),
message("confirmation.title.clear.authentication.cache"),
Messages.getWarningIcon());
} else {
result = Messages.showYesNoDialog(component, SvnBundle.message("confirmation.text.delete.stored.authentication.information"),
SvnBundle.message("confirmation.title.clear.authentication.cache"),
result = Messages.showYesNoDialog(component, message("confirmation.text.delete.stored.authentication.information"),
message("confirmation.title.clear.authentication.cache"),
Messages.getWarningIcon());
}
if (result == Messages.YES) {
@@ -458,8 +421,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
FileUtil.delete(dir);
}
};
final Application application = ApplicationManager.getApplication();
if (application.isUnitTestMode() || !application.isDispatchThread()) {
if (getApplication().isUnitTestMode() || !getApplication().isDispatchThread()) {
process.run();
}
else {